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