static ACPI_TABLE_RSDP * acpi_scan_rsd_ptr(void) { #if defined(__amd64__) || defined(__i386__) ACPI_TABLE_RSDP *rsdp; u_long addr, end; /* * On ia32, scan physical memory for the RSD PTR if above failed. * According to section 5.2.2 of the ACPI spec, we only consider * two regions for the base address: * 1. EBDA (1 KB area addressed by the 16 bit pointer at 0x40E * 2. High memory (0xE0000 - 0xFFFFF) */ addr = ACPI_EBDA_PTR_LOCATION; pread(acpi_mem_fd, &addr, sizeof(uint16_t), addr); addr <<= 4; end = addr + ACPI_EBDA_WINDOW_SIZE; for (; addr < end; addr += 16) if ((rsdp = acpi_get_rsdp(addr)) != NULL) return rsdp; addr = ACPI_HI_RSDP_WINDOW_BASE; end = addr + ACPI_HI_RSDP_WINDOW_SIZE; for (; addr < end; addr += 16) if ((rsdp = acpi_get_rsdp(addr)) != NULL) return rsdp; #endif /* __amd64__ || __i386__ */ return NULL; }
/* * Public interfaces */ ACPI_TABLE_RSDP * acpi_find_rsd_ptr(void) { ACPI_TABLE_RSDP *rsdp; char buf[20]; u_long addr; size_t len; acpi_user_init(); addr = 0; /* Attempt to use kenv or sysctl to find RSD PTR record. */ if (kenv(KENV_GET, hint_acpi_0_rsdp, buf, 20) == 0) addr = strtoul(buf, NULL, 0); if (addr == 0) { len = sizeof(addr); if (sysctlbyname(machdep_acpi_root, &addr, &len, NULL, 0) != 0) addr = 0; } if (addr != 0 && (rsdp = acpi_get_rsdp(addr)) != NULL) return (rsdp); return (acpi_scan_rsd_ptr()); }
int acpi_detect(void) { struct ACPIrsdp *rp; struct ACPIsdt *rsdp; u_long addr; size_t len; if (!acpi0_present()) { warnx("no acpi0 device located"); return -1; } acpi_user_init(); /* Attempt to use sysctl to find RSD PTR record. */ len = sizeof(addr); if (sysctlbyname(machdep_acpi_root, &addr, &len, NULL, 0) != 0) { warnx("cannot find ACPI information"); return -1; } rp = acpi_get_rsdp(addr); if (rp == NULL) { warnx("cannot find ACPI information: sysctl %s does not point to RSDP", machdep_acpi_root); return -1; } if (rp->revision < 2) { rsdp = (struct ACPIsdt *)acpi_map_sdt(rp->rsdt_addr); if (memcmp(rsdp->signature, "RSDT", 4) != 0 || acpi_checksum(rsdp, rsdp->len) != 0) errx(1, "RSDT is corrupted"); addr_size = sizeof(uint32_t); } else { rsdp = (struct ACPIsdt *)acpi_map_sdt(rp->xsdt_addr); if (memcmp(rsdp->signature, "XSDT", 4) != 0 || acpi_checksum(rsdp, rsdp->len) != 0) errx(1, "XSDT is corrupted"); addr_size = sizeof(uint64_t); } ncpu = 0; acpi_handle_rsdt(rsdp); return (ncpu == 0 ? 1 : ncpu); }