Lean Sheng Tan has submitted this change. ( https://review.coreboot.org/c/coreboot/+/76000?usp=email )
Change subject: acpi.c: Swap XSDT and RSDT for adding/finding tables ......................................................................
acpi.c: Swap XSDT and RSDT for adding/finding tables
If ACPI is above 4G it's not possible to have a valid RSDT pointer in RSDP, therefore swap RSDT and XSDT. Both are always generated on x86. On other architectures RSDT is often skipped, e.g. aarch64. On top of that the OS looks at XSDT first. So unconditionally using XSDT and not RSDT is fine.
This also deal with the ACPI pointer being above 4G. This currently never happens with x86 platforms.
Signed-off-by: Arthur Heymans arthur@aheymans.xyz Change-Id: I6588676186faa896b6076f871d7f8f633db21e70 Reviewed-on: https://review.coreboot.org/c/coreboot/+/76000 Tested-by: build bot (Jenkins) no-reply@coreboot.org Reviewed-by: Lean Sheng Tan sheng.tan@9elements.com Reviewed-by: Eric Lai eric_lai@quanta.corp-partner.google.com --- M src/acpi/acpi.c 1 file changed, 34 insertions(+), 34 deletions(-)
Approvals: Lean Sheng Tan: Looks good to me, approved build bot (Jenkins): Verified Eric Lai: Looks good to me, approved
diff --git a/src/acpi/acpi.c b/src/acpi/acpi.c index a2e9fdb..07ca408 100644 --- a/src/acpi/acpi.c +++ b/src/acpi/acpi.c @@ -49,18 +49,15 @@ acpi_rsdt_t *rsdt; acpi_xsdt_t *xsdt = NULL;
- /* The RSDT is mandatory... */ + /* The 32bit RSDT may not be valid if tables live above 4GiB */ rsdt = (acpi_rsdt_t *)(uintptr_t)rsdp->rsdt_address; - - /* ...while the XSDT is not. */ - if (rsdp->xsdt_address) - xsdt = (acpi_xsdt_t *)((uintptr_t)rsdp->xsdt_address); + xsdt = (acpi_xsdt_t *)(uintptr_t)rsdp->xsdt_address;
/* This should always be MAX_ACPI_TABLES. */ - entries_num = ARRAY_SIZE(rsdt->entry); + entries_num = ARRAY_SIZE(xsdt->entry);
for (i = 0; i < entries_num; i++) { - if (rsdt->entry[i] == 0) + if (xsdt->entry[i] == 0) break; }
@@ -70,36 +67,34 @@ return; }
- /* Add table to the RSDT. */ - rsdt->entry[i] = (uintptr_t)table; + /* Add table to the XSDT. */ + xsdt->entry[i] = (u64)(uintptr_t)table;
- /* Fix RSDT length or the kernel will assume invalid entries. */ - rsdt->header.length = sizeof(acpi_header_t) + (sizeof(u32) * (i + 1)); + /* Fix XSDT length or the kernel will assume invalid entries. */ + xsdt->header.length = sizeof(acpi_header_t) + (sizeof(u64) * (i + 1));
/* Re-calculate checksum. */ - rsdt->header.checksum = 0; /* Hope this won't get optimized away */ - rsdt->header.checksum = acpi_checksum((u8 *)rsdt, rsdt->header.length); + xsdt->header.checksum = 0; /* Hope this won't get optimized away */ + xsdt->header.checksum = acpi_checksum((u8 *)xsdt, xsdt->header.length);
/* - * And now the same thing for the XSDT. We use the same index as for + * And now the same thing for the RSDT. We use the same index as for * now we want the XSDT and RSDT to always be in sync in coreboot. */ - if (xsdt) { - /* Add table to the XSDT. */ - xsdt->entry[i] = (u64)(uintptr_t)table; + if (rsdt && (uintptr_t)table < UINT32_MAX) { + /* Add table to the RSDT. */ + rsdt->entry[i] = (u32)(uintptr_t)table;
- /* Fix XSDT length. */ - xsdt->header.length = sizeof(acpi_header_t) + - (sizeof(u64) * (i + 1)); + /* Fix RSDT length. */ + rsdt->header.length = sizeof(acpi_header_t) + (sizeof(u32) * (i + 1));
/* Re-calculate checksum. */ - xsdt->header.checksum = 0; - xsdt->header.checksum = acpi_checksum((u8 *)xsdt, - xsdt->header.length); + rsdt->header.checksum = 0; + rsdt->header.checksum = acpi_checksum((u8 *)rsdt, rsdt->header.length); }
printk(BIOS_DEBUG, "ACPI: added table %d/%d, length now %d\n", - i + 1, entries_num, rsdt->header.length); + i + 1, entries_num, xsdt->header.length); }
static enum cb_err acpi_fill_header(acpi_header_t *header, const char name[4], @@ -1451,14 +1446,19 @@
printk(BIOS_INFO, "ACPI: Writing ACPI tables at %lx.\n", start);
- /* We need at least an RSDP and an RSDT Table */ + /* We need at least an RSDP, RSDT for ACPI 1.0 compat, otherwise XSDT */ rsdp = (acpi_rsdp_t *)current; coreboot_rsdp = (uintptr_t)rsdp; current += sizeof(acpi_rsdp_t); current = acpi_align_current(current); - rsdt = (acpi_rsdt_t *)current; - current += sizeof(acpi_rsdt_t); - current = acpi_align_current(current); + if (current + sizeof(acpi_rsdt_t) - 1 <= UINT32_MAX) { + rsdt = (acpi_rsdt_t *)current; + current += sizeof(acpi_rsdt_t); + current = acpi_align_current(current); + } else { + printk(BIOS_INFO, "Not adding RSDT because tables reside above 4G."); + } + xsdt = (acpi_xsdt_t *)current; current += sizeof(acpi_xsdt_t); current = acpi_align_current(current); @@ -1554,7 +1554,7 @@ void *acpi_find_wakeup_vector(void) { char *p, *end; - acpi_rsdt_t *rsdt; + acpi_xsdt_t *xsdt; acpi_facs_t *facs; acpi_fadt_t *fadt = NULL; acpi_rsdp_t *rsdp = NULL; @@ -1580,13 +1580,13 @@ }
printk(BIOS_DEBUG, "RSDP found at %p\n", rsdp); - rsdt = (acpi_rsdt_t *)(uintptr_t)rsdp->rsdt_address; + xsdt = (acpi_xsdt_t *)(uintptr_t)rsdp->xsdt_address;
- end = (char *)rsdt + rsdt->header.length; - printk(BIOS_DEBUG, "RSDT found at %p ends at %p\n", rsdt, end); + end = (char *)xsdt + xsdt->header.length; + printk(BIOS_DEBUG, "XSDT found at %p ends at %p\n", xsdt, end);
- for (i = 0; ((char *)&rsdt->entry[i]) < end; i++) { - fadt = (acpi_fadt_t *)(uintptr_t)rsdt->entry[i]; + for (i = 0; ((char *)&xsdt->entry[i]) < end; i++) { + fadt = (acpi_fadt_t *)(uintptr_t)xsdt->entry[i]; if (strncmp((char *)fadt, "FACP", 4) == 0) break; fadt = NULL;