diff options
author | Patrick Rudolph <patrick.rudolph@9elements.com> | 2024-06-18 09:18:44 +0200 |
---|---|---|
committer | Felix Held <felix-coreboot@felixheld.de> | 2024-06-24 17:12:48 +0000 |
commit | 4b43dac16b46a8f94a8b349764ce3efdfab64269 (patch) | |
tree | 1f73d11543facc6d52b5da98f4042f517b0fc37b | |
parent | f78979007a744912e767c270b0a56b0547b1dbd0 (diff) |
acpi/acpi: Fix Qemu's XSDT patching code
Since Qemu doesn't provide an XSDT, coreboot adds one as separate ACPI
table. Qemu only provides the smaller ACPI 1.0 RSDP, but the XSDT can
only fit into the bigger ACPI 2.0 RSDP. Currently the exsting RSDP is
being reused, without a size check, which works fine on the first boot.
However after reboot the XSDT pointer seems to be valid, even though the
checksum isn't. Since the XSDT then isn't reserved again on reboot, the
memory it's pointing to is reused by other tables, causing the
payload/OS to see an invalid XSDT.
Instead of corrupting the smaller existing RSDP, allocate a new RSDP
structure and properly fill it with both, existing RSDT and XSDT.
In addition return the correct length of allocated ACPI tables to the
calling code. It was ommiting the size of the allocated XSDT and SSDT.
TEST: Run "qemu-system-x86_64 -M q35" and reboot the virtual machine.
With this patch applied XSDT is always valid from the OS
point of view.
Change-Id: Ie4972230c3654714f3dcbaab46a3f70152e75163
Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/83116
Reviewed-by: Angel Pons <th3fanbus@gmail.com>
Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
Reviewed-by: Paul Menzel <paulepanter@mailbox.org>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
-rw-r--r-- | src/acpi/acpi.c | 13 |
1 files changed, 11 insertions, 2 deletions
diff --git a/src/acpi/acpi.c b/src/acpi/acpi.c index 39eadc3a7f..06aa038caa 100644 --- a/src/acpi/acpi.c +++ b/src/acpi/acpi.c @@ -1489,6 +1489,16 @@ unsigned long write_acpi_tables(const unsigned long start) current = fw; current = acpi_align_current(current); if (rsdp->xsdt_address == 0) { + acpi_rsdt_t *existing_rsdt = (acpi_rsdt_t *)(uintptr_t)rsdp->rsdt_address; + + /* + * Qemu only provides a smaller ACPI 1.0 RSDP, thus + * allocate a bigger ACPI 2.0 RSDP structure. + */ + rsdp = (acpi_rsdp_t *)current; + current += sizeof(acpi_rsdp_t); + coreboot_rsdp = (uintptr_t)rsdp; + xsdt = (acpi_xsdt_t *)current; current += sizeof(acpi_xsdt_t); current = acpi_align_current(current); @@ -1497,7 +1507,6 @@ unsigned long write_acpi_tables(const unsigned long start) * 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); /* @@ -1537,7 +1546,7 @@ unsigned long write_acpi_tables(const unsigned long start) acpi_add_table(rsdp, ssdt); - return fw; + return current; } dsdt_file = cbfs_map(CONFIG_CBFS_PREFIX "/dsdt.aml", &dsdt_size); |