xref: /titanic_52/usr/src/boot/sys/boot/i386/libi386/biosacpi.c (revision 6feb9af90381719e3e30d6f0566dec8664195d0a)
14a5d661aSToomas Soome /*-
24a5d661aSToomas Soome  * Copyright (c) 2001 Michael Smith <msmith@freebsd.org>
34a5d661aSToomas Soome  * All rights reserved.
44a5d661aSToomas Soome  *
54a5d661aSToomas Soome  * Redistribution and use in source and binary forms, with or without
64a5d661aSToomas Soome  * modification, are permitted provided that the following conditions
74a5d661aSToomas Soome  * are met:
84a5d661aSToomas Soome  * 1. Redistributions of source code must retain the above copyright
94a5d661aSToomas Soome  *    notice, this list of conditions and the following disclaimer.
104a5d661aSToomas Soome  * 2. Redistributions in binary form must reproduce the above copyright
114a5d661aSToomas Soome  *    notice, this list of conditions and the following disclaimer in the
124a5d661aSToomas Soome  *    documentation and/or other materials provided with the distribution.
134a5d661aSToomas Soome  *
144a5d661aSToomas Soome  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
154a5d661aSToomas Soome  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
164a5d661aSToomas Soome  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
174a5d661aSToomas Soome  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
184a5d661aSToomas Soome  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
194a5d661aSToomas Soome  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
204a5d661aSToomas Soome  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
214a5d661aSToomas Soome  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
224a5d661aSToomas Soome  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
234a5d661aSToomas Soome  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
244a5d661aSToomas Soome  * SUCH DAMAGE.
254a5d661aSToomas Soome  */
264a5d661aSToomas Soome 
274a5d661aSToomas Soome #include <sys/cdefs.h>
284a5d661aSToomas Soome 
294a5d661aSToomas Soome #include <stand.h>
304a5d661aSToomas Soome #include <machine/stdarg.h>
314a5d661aSToomas Soome #include <bootstrap.h>
324a5d661aSToomas Soome #include <btxv86.h>
334a5d661aSToomas Soome #include "libi386.h"
344a5d661aSToomas Soome 
354a5d661aSToomas Soome #include "platform/acfreebsd.h"
364a5d661aSToomas Soome #include "acconfig.h"
374a5d661aSToomas Soome #define ACPI_SYSTEM_XFACE
384a5d661aSToomas Soome #include "actypes.h"
394a5d661aSToomas Soome #include "actbl.h"
404a5d661aSToomas Soome 
414a5d661aSToomas Soome /*
424a5d661aSToomas Soome  * Detect ACPI and export information about the ACPI BIOS into the
434a5d661aSToomas Soome  * environment.
444a5d661aSToomas Soome  */
454a5d661aSToomas Soome 
46*6feb9af9SToomas Soome ACPI_TABLE_RSDP	*rsdp;
474a5d661aSToomas Soome static ACPI_TABLE_RSDP	*biosacpi_find_rsdp(void);
484a5d661aSToomas Soome static ACPI_TABLE_RSDP	*biosacpi_search_rsdp(char *base, int length);
494a5d661aSToomas Soome 
504a5d661aSToomas Soome #define RSDP_CHECKSUM_LENGTH 20
514a5d661aSToomas Soome 
524a5d661aSToomas Soome void
534a5d661aSToomas Soome biosacpi_detect(void)
544a5d661aSToomas Soome {
554a5d661aSToomas Soome     char		buf[24];
564a5d661aSToomas Soome     int			revision;
574a5d661aSToomas Soome 
584a5d661aSToomas Soome     /* locate and validate the RSDP */
594a5d661aSToomas Soome     if ((rsdp = biosacpi_find_rsdp()) == NULL)
604a5d661aSToomas Soome 	return;
614a5d661aSToomas Soome 
624a5d661aSToomas Soome     /* export values from the RSDP */
634a5d661aSToomas Soome     sprintf(buf, "0x%08x", (unsigned int)VTOP(rsdp));
644a5d661aSToomas Soome     setenv("acpi.rsdp", buf, 1);
654a5d661aSToomas Soome     revision = rsdp->Revision;
664a5d661aSToomas Soome     if (revision == 0)
674a5d661aSToomas Soome 	revision = 1;
684a5d661aSToomas Soome     sprintf(buf, "%d", revision);
694a5d661aSToomas Soome     setenv("acpi.revision", buf, 1);
704a5d661aSToomas Soome     strncpy(buf, rsdp->OemId, sizeof(rsdp->OemId));
714a5d661aSToomas Soome     buf[sizeof(rsdp->OemId)] = '\0';
724a5d661aSToomas Soome     setenv("acpi.oem", buf, 1);
734a5d661aSToomas Soome     sprintf(buf, "0x%08x", rsdp->RsdtPhysicalAddress);
744a5d661aSToomas Soome     setenv("acpi.rsdt", buf, 1);
754a5d661aSToomas Soome     if (revision >= 2) {
764a5d661aSToomas Soome 	/* XXX extended checksum? */
774a5d661aSToomas Soome 	sprintf(buf, "0x%016llx",
784a5d661aSToomas Soome 	    (unsigned long long)rsdp->XsdtPhysicalAddress);
794a5d661aSToomas Soome 	setenv("acpi.xsdt", buf, 1);
804a5d661aSToomas Soome 	sprintf(buf, "%d", rsdp->Length);
814a5d661aSToomas Soome 	setenv("acpi.xsdt_length", buf, 1);
824a5d661aSToomas Soome     }
834a5d661aSToomas Soome }
844a5d661aSToomas Soome 
854a5d661aSToomas Soome /*
864a5d661aSToomas Soome  * Find the RSDP in low memory.  See section 5.2.2 of the ACPI spec.
874a5d661aSToomas Soome  */
884a5d661aSToomas Soome static ACPI_TABLE_RSDP *
894a5d661aSToomas Soome biosacpi_find_rsdp(void)
904a5d661aSToomas Soome {
914a5d661aSToomas Soome     ACPI_TABLE_RSDP	*rsdp;
924a5d661aSToomas Soome     uint16_t		*addr;
934a5d661aSToomas Soome 
944a5d661aSToomas Soome     /* EBDA is the 1 KB addressed by the 16 bit pointer at 0x40E. */
954a5d661aSToomas Soome     addr = (uint16_t *)PTOV(0x40E);
964a5d661aSToomas Soome     rsdp = biosacpi_search_rsdp((char *)(intptr_t)(*addr << 4), 0x400);
974a5d661aSToomas Soome     if (rsdp != NULL)
984a5d661aSToomas Soome 	return (rsdp);
994a5d661aSToomas Soome 
1004a5d661aSToomas Soome     /* Check the upper memory BIOS space, 0xe0000 - 0xfffff. */
1014a5d661aSToomas Soome     if ((rsdp = biosacpi_search_rsdp((char *)0xe0000, 0x20000)) != NULL)
1024a5d661aSToomas Soome 	return (rsdp);
1034a5d661aSToomas Soome 
1044a5d661aSToomas Soome     return (NULL);
1054a5d661aSToomas Soome }
1064a5d661aSToomas Soome 
1074a5d661aSToomas Soome static ACPI_TABLE_RSDP *
1084a5d661aSToomas Soome biosacpi_search_rsdp(char *base, int length)
1094a5d661aSToomas Soome {
1104a5d661aSToomas Soome     ACPI_TABLE_RSDP	*rsdp;
1114a5d661aSToomas Soome     u_int8_t		*cp, sum;
1124a5d661aSToomas Soome     int			ofs, idx;
1134a5d661aSToomas Soome 
1144a5d661aSToomas Soome     /* search on 16-byte boundaries */
1154a5d661aSToomas Soome     for (ofs = 0; ofs < length; ofs += 16) {
1164a5d661aSToomas Soome 	rsdp = (ACPI_TABLE_RSDP *)PTOV(base + ofs);
1174a5d661aSToomas Soome 
1184a5d661aSToomas Soome 	/* compare signature, validate checksum */
1194a5d661aSToomas Soome 	if (!strncmp(rsdp->Signature, ACPI_SIG_RSDP, strlen(ACPI_SIG_RSDP))) {
1204a5d661aSToomas Soome 	    cp = (u_int8_t *)rsdp;
1214a5d661aSToomas Soome 	    sum = 0;
1224a5d661aSToomas Soome 	    for (idx = 0; idx < RSDP_CHECKSUM_LENGTH; idx++)
1234a5d661aSToomas Soome 		sum += *(cp + idx);
1244a5d661aSToomas Soome 	    if (sum != 0)
1254a5d661aSToomas Soome 		continue;
1264a5d661aSToomas Soome 	    return(rsdp);
1274a5d661aSToomas Soome 	}
1284a5d661aSToomas Soome     }
1294a5d661aSToomas Soome     return(NULL);
1304a5d661aSToomas Soome }
131