From 4b43dac16b46a8f94a8b349764ce3efdfab64269 Mon Sep 17 00:00:00 2001 From: Patrick Rudolph Date: Tue, 18 Jun 2024 09:18:44 +0200 Subject: 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 Reviewed-on: https://review.coreboot.org/c/coreboot/+/83116 Reviewed-by: Angel Pons Reviewed-by: Arthur Heymans Reviewed-by: Paul Menzel Tested-by: build bot (Jenkins) --- src/acpi/acpi.c | 13 +++++++++++-- 1 file 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); -- cgit v1.2.3