acpi.c: Add XSDT on QEMU

Since d8f2dce "acpi.c: Swap XSDT and RSDT for adding/finding tables"
XSDT is primarily used to add new tables or to find the S3 resume vector.
However with QEMU coreboot does not generate most ACPI tables but takes
them from whatever QEMU provides. Qemu only creates an RSDT and lacks an
XSDT.

To keep the codebase simple with the assumption that XSDT is always
present, create an XSDT based on the existing RSDT and update the
address in RSDP.

Signed-off-by: Arthur Heymans <arthur@aheymans.xyz>
Change-Id: Ia9b7f090f55e436de98afad6f23597c3d426bb88
Reviewed-on: https://review.coreboot.org/c/coreboot/+/77385
Reviewed-by: Tim Wawrzynczak <inforichland@gmail.com>
Reviewed-by: Eric Lai <eric_lai@quanta.corp-partner.google.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Arthur Heymans 2023-08-22 12:50:43 +02:00
parent 2189640786
commit c2830c9661
1 changed files with 26 additions and 3 deletions

View File

@ -48,7 +48,7 @@ void acpi_add_table(acpi_rsdp_t *rsdp, void *table)
{ {
int i, entries_num; int i, entries_num;
acpi_rsdt_t *rsdt; acpi_rsdt_t *rsdt;
acpi_xsdt_t *xsdt = NULL; acpi_xsdt_t *xsdt;
/* The 32bit RSDT may not be valid if tables live above 4GiB */ /* The 32bit RSDT may not be valid if tables live above 4GiB */
rsdt = (acpi_rsdt_t *)(uintptr_t)rsdp->rsdt_address; rsdt = (acpi_rsdt_t *)(uintptr_t)rsdp->rsdt_address;
@ -1408,10 +1408,33 @@ unsigned long write_acpi_tables(const unsigned long start)
if (!rsdp) if (!rsdp)
return fw; return fw;
current = fw;
current = acpi_align_current(current);
if (rsdp->xsdt_address == 0) {
xsdt = (acpi_xsdt_t *)current;
current += sizeof(acpi_xsdt_t);
current = acpi_align_current(current);
/*
* Qemu only creates an RSDT.
* Add an XSDT based on the existing RSDT entries.
*/
acpi_rsdt_t *existing_rsdt = (acpi_rsdt_t *)(uintptr_t)rsdp->rsdt_address;
acpi_write_rsdp(rsdp, existing_rsdt, xsdt, oem_id);
acpi_write_xsdt(xsdt, oem_id, oem_table_id);
/*
* Copy existing entries to the new XSDT. This will override existing
* RSDT entries with the same value.
*/
for (int i = 0; existing_rsdt->entry[i]; i++)
acpi_add_table(rsdp, (void *)(uintptr_t)existing_rsdt->entry[i]);
}
/* Add BOOT0000 for Linux google firmware driver */ /* Add BOOT0000 for Linux google firmware driver */
printk(BIOS_DEBUG, "ACPI: * SSDT\n"); printk(BIOS_DEBUG, "ACPI: * SSDT\n");
ssdt = (acpi_header_t *)fw; ssdt = (acpi_header_t *)current;
current = (unsigned long)ssdt + sizeof(acpi_header_t); current += sizeof(acpi_header_t);
memset((void *)ssdt, 0, sizeof(acpi_header_t)); memset((void *)ssdt, 0, sizeof(acpi_header_t));