Print this page
12195 acpidump failed under EFI
@@ -24,11 +24,11 @@
* Use is subject to license terms.
*
* Copyright (c) 2010, Intel Corporation.
* All rights reserved.
*
- * Copyright (c) 2019, Joyent, Inc.
+ * Copyright 2020 Joyent, Inc.
*/
/*
* This file contains the functionality that mimics the boot operations
* on SPARC systems or the old boot.bin/multiboot programs on x86 systems.
@@ -2269,66 +2269,94 @@
/*
* Scan memory range for an RSDP;
* see ACPI 3.0 Spec, 5.2.5.1
*/
static ACPI_TABLE_RSDP *
-scan_rsdp(paddr_t start, paddr_t end)
+scan_rsdp(paddr_t *paddrp, size_t len)
{
- ssize_t len = end - start;
+ paddr_t paddr = *paddrp;
caddr_t ptr;
- ptr = vmap_phys(len, start);
+ ptr = vmap_phys(len, paddr);
+
while (len > 0) {
if (strncmp(ptr, ACPI_SIG_RSDP, strlen(ACPI_SIG_RSDP)) == 0 &&
- valid_rsdp((ACPI_TABLE_RSDP *)ptr))
+ valid_rsdp((ACPI_TABLE_RSDP *)ptr)) {
+ *paddrp = paddr;
return ((ACPI_TABLE_RSDP *)ptr);
+ }
ptr += ACPI_RSDP_SCAN_STEP;
+ paddr += ACPI_RSDP_SCAN_STEP;
len -= ACPI_RSDP_SCAN_STEP;
}
return (NULL);
}
/*
- * Refer to ACPI 3.0 Spec, section 5.2.5.1 to understand this function
+ * Locate the ACPI RSDP. We search in a particular order:
+ *
+ * - If the bootloader told us the location of the RSDP (via the EFI system
+ * table), try that first.
+ * - Otherwise, look in the EBDA and BIOS memory as per ACPI 5.2.5.1 (legacy
+ * case).
+ * - Finally, our bootloader may have a copy of the RSDP in its info: this might
+ * get freed after boot, so we always prefer to find the original RSDP first.
+ *
+ * Once found, we set acpi-root-tab property (a physical address) for the
+ * benefit of acpica, acpidump etc.
*/
+
static ACPI_TABLE_RSDP *
-find_rsdp()
+find_rsdp(struct xboot_info *xbp)
{
- ACPI_TABLE_RSDP *rsdp;
- uint64_t rsdp_val = 0;
- uint16_t *ebda_seg;
- paddr_t ebda_addr;
+ ACPI_TABLE_RSDP *rsdp = NULL;
+ paddr_t paddr = 0;
- /* check for "acpi-root-tab" property */
if (do_bsys_getproplen(NULL, "acpi-root-tab") == sizeof (uint64_t)) {
- (void) do_bsys_getprop(NULL, "acpi-root-tab", &rsdp_val);
- if (rsdp_val != 0) {
- rsdp = scan_rsdp(rsdp_val, rsdp_val + sizeof (*rsdp));
- if (rsdp != NULL) {
- if (kbm_debug) {
- bop_printf(NULL,
- "Using RSDP from bootloader: "
- "0x%p\n", (void *)rsdp);
+ (void) do_bsys_getprop(NULL, "acpi-root-tab", &paddr);
+ rsdp = scan_rsdp(&paddr, sizeof (*rsdp));
}
- return (rsdp);
+
+#ifndef __xpv
+ if (rsdp == NULL && xbp->bi_acpi_rsdp != NULL) {
+ paddr = (uintptr_t)xbp->bi_acpi_rsdp;
+ rsdp = scan_rsdp(&paddr, sizeof (*rsdp));
}
+#endif
+
+ if (rsdp == NULL) {
+ uint16_t *ebda_seg = (uint16_t *)vmap_phys(sizeof (uint16_t),
+ ACPI_EBDA_PTR_LOCATION);
+ paddr = *ebda_seg << 4;
+ rsdp = scan_rsdp(&paddr, ACPI_EBDA_WINDOW_SIZE);
}
+
+ if (rsdp == NULL) {
+ paddr = ACPI_HI_RSDP_WINDOW_BASE;
+ rsdp = scan_rsdp(&paddr, ACPI_HI_RSDP_WINDOW_SIZE);
}
- /*
- * Get the EBDA segment and scan the first 1K
- */
- ebda_seg = (uint16_t *)vmap_phys(sizeof (uint16_t),
- ACPI_EBDA_PTR_LOCATION);
- ebda_addr = *ebda_seg << 4;
- rsdp = scan_rsdp(ebda_addr, ebda_addr + ACPI_EBDA_WINDOW_SIZE);
- if (rsdp == NULL)
- /* if EBDA doesn't contain RSDP, look in BIOS memory */
- rsdp = scan_rsdp(ACPI_HI_RSDP_WINDOW_BASE,
- ACPI_HI_RSDP_WINDOW_BASE + ACPI_HI_RSDP_WINDOW_SIZE);
+#ifndef __xpv
+ if (rsdp == NULL && xbp->bi_acpi_rsdp_copy != NULL) {
+ paddr = (uintptr_t)xbp->bi_acpi_rsdp_copy;
+ rsdp = scan_rsdp(&paddr, sizeof (*rsdp));
+ }
+#endif
+
+ if (rsdp == NULL) {
+ bop_printf(NULL, "no RSDP found!\n");
+ return (NULL);
+ }
+
+ if (kbm_debug)
+ bop_printf(NULL, "RSDP found at physical 0x%lx\n", paddr);
+
+ if (do_bsys_getproplen(NULL, "acpi-root-tab") != sizeof (uint64_t))
+ bsetprop64("acpi-root-tab", paddr);
+
return (rsdp);
}
static ACPI_TABLE_HEADER *
map_fw_table(paddr_t table_addr)
@@ -2344,17 +2372,16 @@
tp = (ACPI_TABLE_HEADER *)vmap_phys(tp->Length, table_addr);
return (tp);
}
static ACPI_TABLE_HEADER *
-find_fw_table(char *signature)
+find_fw_table(ACPI_TABLE_RSDP *rsdp, char *signature)
{
static int revision = 0;
static ACPI_TABLE_XSDT *xsdt;
static int len;
paddr_t xsdt_addr;
- ACPI_TABLE_RSDP *rsdp;
ACPI_TABLE_HEADER *tp;
paddr_t table_addr;
int n;
if (strlen(signature) != ACPI_NAME_SIZE)
@@ -2368,11 +2395,13 @@
* 0 or 1, use the RSDT and set internal revision to 1; if it is 2,
* use the XSDT. If the XSDT address is 0, though, fall back to
* revision 1 and use the RSDT.
*/
if (revision == 0) {
- if ((rsdp = find_rsdp()) != NULL) {
+ if (rsdp == NULL)
+ return (NULL);
+
revision = rsdp->Revision;
/*
* ACPI 6.0 states that current revision is 2
* from acpi_table_rsdp definition:
* Must be (0) for ACPI 1.0 or (2) for ACPI 2.0+
@@ -2401,11 +2430,11 @@
default:
/* unknown revision */
revision = 0;
break;
}
- }
+
if (revision == 0)
return (NULL);
/* cache the XSDT info */
xsdt = (ACPI_TABLE_XSDT *)map_fw_table(xsdt_addr);
@@ -2838,10 +2867,11 @@
/*ARGSUSED*/
static void
build_firmware_properties(struct xboot_info *xbp)
{
ACPI_TABLE_HEADER *tp = NULL;
+ ACPI_TABLE_RSDP *rsdp;
#ifndef __xpv
if (xbp->bi_uefi_arch == XBI_UEFI_ARCH_64) {
bsetprops("efi-systype", "64");
bsetprop64("efi-systab",
@@ -2854,40 +2884,37 @@
(uint64_t)(uintptr_t)xbp->bi_uefi_systab);
if (kbm_debug)
bop_printf(NULL, "32-bit UEFI detected.\n");
}
- if (xbp->bi_acpi_rsdp != NULL) {
- bsetprop64("acpi-root-tab",
- (uint64_t)(uintptr_t)xbp->bi_acpi_rsdp);
- }
-
if (xbp->bi_smbios != NULL) {
bsetprop64("smbios-address",
(uint64_t)(uintptr_t)xbp->bi_smbios);
}
- if ((tp = find_fw_table(ACPI_SIG_MSCT)) != NULL)
+ rsdp = find_rsdp(xbp);
+
+ if ((tp = find_fw_table(rsdp, ACPI_SIG_MSCT)) != NULL)
msct_ptr = process_msct((ACPI_TABLE_MSCT *)tp);
else
msct_ptr = NULL;
- if ((tp = find_fw_table(ACPI_SIG_MADT)) != NULL)
+ if ((tp = find_fw_table(rsdp, ACPI_SIG_MADT)) != NULL)
process_madt((ACPI_TABLE_MADT *)tp);
if ((srat_ptr = (ACPI_TABLE_SRAT *)
- find_fw_table(ACPI_SIG_SRAT)) != NULL)
+ find_fw_table(rsdp, ACPI_SIG_SRAT)) != NULL)
process_srat(srat_ptr);
- if (slit_ptr = (ACPI_TABLE_SLIT *)find_fw_table(ACPI_SIG_SLIT))
+ if (slit_ptr = (ACPI_TABLE_SLIT *)find_fw_table(rsdp, ACPI_SIG_SLIT))
process_slit(slit_ptr);
- tp = find_fw_table(ACPI_SIG_MCFG);
+ tp = find_fw_table(rsdp, ACPI_SIG_MCFG);
#else /* __xpv */
enumerate_xen_cpus();
if (DOMAIN_IS_INITDOMAIN(xen_info))
- tp = find_fw_table(ACPI_SIG_MCFG);
+ tp = find_fw_table(rsdp, ACPI_SIG_MCFG);
#endif /* __xpv */
if (tp != NULL)
process_mcfg((ACPI_TABLE_MCFG *)tp);
}