summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Rudolph <patrick.rudolph@9elements.com>2024-06-18 09:18:44 +0200
committerFelix Held <felix-coreboot@felixheld.de>2024-06-24 17:12:48 +0000
commit4b43dac16b46a8f94a8b349764ce3efdfab64269 (patch)
tree1f73d11543facc6d52b5da98f4042f517b0fc37b
parentf78979007a744912e767c270b0a56b0547b1dbd0 (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.c13
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);