[PATCH] Fix FADT update in creation of fake FACS table.
jvohanka
jvohanka at redhat.com
Mon Nov 23 14:49:56 UTC 2015
If a FACS ACPI table is not found, a fake one is created and
a fake physical address is assigned to it. This fake physical
address is written to FIRMWARE_CTRL and X_FIRMWARE_CTRL fields
of FADT table. The problem is that the checksum of the FADT
table is not updated to reflect the change in FIRMWARE_CTRL
and X_FIRMWARE_CTRL fields. Thus, the 'checksum' test falsely
reports:
FAILED [MEDIUM] ACPITableChecksum: Test 1, Table FACP has
incorrect checksum, expected 0xe8, got 0xcf.
This patch changes the update of the FADT table. If one of
X_FIRMWARE_CTRL, FIRMWARE_CTRL fields is nonzero then that
value is used as physical address of FACS table. If both
fields are zero then a fake physical address is assigned
to FACS, written to FADT table and the checksum of the FADT
table is updated.
Signed-off-by: jvohanka <jvohanka at redhat.com>
---
src/lib/src/fwts_acpi_tables.c | 23 +++++++++++++++++------
1 file changed, 17 insertions(+), 6 deletions(-)
diff --git a/src/lib/src/fwts_acpi_tables.c b/src/lib/src/fwts_acpi_tables.c
index 0aab404..6dcf7f8 100644
--- a/src/lib/src/fwts_acpi_tables.c
+++ b/src/lib/src/fwts_acpi_tables.c
@@ -936,7 +936,7 @@ static int fwts_acpi_load_tables_fixup(fwts_framework *fw)
facs = (fwts_acpi_table_facs *)table->data;
else {
size_t size = 64;
- uint64_t facs_fake_addr;
+ uint64_t facs_addr;
/* This is most unexpected, so warn about it */
fwts_log_warning(fw, "No FACS found, fwts has faked one instead.");
@@ -949,12 +949,23 @@ static int fwts_acpi_load_tables_fixup(fwts_framework *fw)
facs->hardware_signature = 0xf000a200; /* Some signature */
facs->flags = 0;
facs->version = 2;
- facs_fake_addr = fwts_fake_physical_addr(size);
- fadt->firmware_control = (uint32_t)facs_fake_addr;
- if (fadt->header.length >= 140)
- fadt->x_firmware_ctrl = (uint64_t)facs_fake_addr;
- fwts_acpi_add_table("FACS", facs, (uint64_t)facs_fake_addr,
+ /* Get physical address of FACS, try to take it from FACS first,
+ and if that fails, create a fake one and update FACS */
+ if (fadt->header.length >= 140 && fadt->x_firmware_ctrl != 0) {
+ facs_addr = fadt->x_firmware_ctrl;
+ } else if (fadt->firmware_control != 0) {
+ facs_addr = (uint64_t)fadt->firmware_control;
+ } else {
+ facs_addr = (uint64_t)fwts_fake_physical_addr(size);
+ if (fadt->header.length >= 140)
+ fadt->x_firmware_ctrl = facs_addr;
+ else
+ fadt->firmware_control = (uint32_t)facs_addr;
+ fadt->header.checksum -= fwts_checksum((uint8_t*)&facs_addr, sizeof(facs_addr));
+ }
+
+ fwts_acpi_add_table("FACS", facs, (uint64_t)facs_addr,
size, FWTS_ACPI_TABLE_FROM_FIXUP);
}
--
2.4.3
More information about the fwts-devel
mailing list