[PATCH] lib: fwts_acpi_tables: update RSDP checksum on fixed-up RSDP (LP: #1287852)

Colin King colin.king at canonical.com
Tue Mar 4 18:56:20 UTC 2014


From: Colin Ian King <colin.king at canonical.com>

When loading the RSDP from a file sometimes the XSDT and/or RSDT
have been updated (fixed up) which requires clearing the old
checksums and re-calculating them for the updated RSDP. Currently
this is not occurring, causing fwts checksum tests to fail on the
RSDP on fixed up tables loaded from file. This patch fixes this.

Signed-off-by: Colin Ian King <colin.king at canonical.com>
---
 src/lib/src/fwts_acpi_tables.c | 21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/src/lib/src/fwts_acpi_tables.c b/src/lib/src/fwts_acpi_tables.c
index cccf9ba..9932da6 100644
--- a/src/lib/src/fwts_acpi_tables.c
+++ b/src/lib/src/fwts_acpi_tables.c
@@ -634,6 +634,7 @@ static int fwts_acpi_load_tables_fixup(fwts_framework *fw)
 	fwts_acpi_table_fadt *fadt = NULL;
 	fwts_acpi_table_facs *facs = NULL;
 	uint64_t rsdt_fake_addr = 0, xsdt_fake_addr = 0;
+	bool redo_rsdp_checksum = false;
 
 	/* Fetch the OEM Table ID */
 	if (fwts_acpi_find_table(fw, "FACP", 0, &table) != FWTS_OK) {
@@ -784,15 +785,29 @@ static int fwts_acpi_load_tables_fixup(fwts_framework *fw)
 		rsdp->reserved[2] = 0;
 
 		rsdp->checksum = 256 - fwts_checksum((uint8_t*)rsdp, 20);
-		rsdp->extended_checksum = 256 - fwts_checksum((uint8_t*)rsdp, sizeof(fwts_acpi_table_rsdp));
+		rsdp->extended_checksum = 256 - fwts_checksum((uint8_t*)rsdp, rsdp->length);
 
 		fwts_acpi_add_table("RSDP", rsdp, (uint64_t)fwts_fake_physical_addr(size),
 			sizeof(fwts_acpi_table_rsdp), FWTS_ACPI_TABLE_FROM_FIXUP);
 	}
 
 	/* Now we have all the tables, final fix up is required */
-	rsdp->rsdt_address = rsdt_fake_addr;
-	rsdp->xsdt_address = xsdt_fake_addr;
+	if (rsdp->rsdt_address != rsdt_fake_addr) {
+		rsdp->rsdt_address = rsdt_fake_addr;
+		redo_rsdp_checksum = true;
+	}
+	if ((rsdp->revision > 0) && (rsdp->length >= 36) &&
+	    (rsdp->xsdt_address != xsdt_fake_addr)) {
+		rsdp->xsdt_address = xsdt_fake_addr;
+		redo_rsdp_checksum = true;
+	}
+	/* And update checksum if we've updated the rsdp */
+	if (redo_rsdp_checksum) {
+		rsdp->checksum = 0;	/* Clear old checksum */
+		rsdp->checksum = 256 - fwts_checksum((uint8_t*)rsdp, 20);
+		rsdp->extended_checksum = 0;	/* Clear old checksum */
+		rsdp->extended_checksum = 256 - fwts_checksum((uint8_t*)rsdp, rsdp->length);
+	}
 
 	return FWTS_OK;
 }
-- 
1.9.0




More information about the fwts-devel mailing list