[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