[PATCH 2/3] lib: fwts_acpi_tables: Add extra fix-up for FACS and DSDT table addresses
Colin King
colin.king at canonical.com
Fri Mar 24 16:10:14 UTC 2017
From: Colin Ian King <colin.king at canonical.com>
In the case where the FACS and DSDT are loaded from file and don't have
an address then fwts makes up a fake address for these tables to keep
ACPICA happy. However, the FACP (FADT) points to these tables so we
can actually fix up the FACS and DSDT table addresses to these known
addresses fiven by the FACP. We prefer 64 bit addresses from the FACP
but if they don't exist, use the 32 bit addresses.
Signed-off-by: Colin Ian King <colin.king at canonical.com>
---
src/lib/src/fwts_acpi_tables.c | 56 +++++++++++++++++++++++++++++++++++++-----
1 file changed, 50 insertions(+), 6 deletions(-)
diff --git a/src/lib/src/fwts_acpi_tables.c b/src/lib/src/fwts_acpi_tables.c
index 3d342299..1d4fc705 100644
--- a/src/lib/src/fwts_acpi_tables.c
+++ b/src/lib/src/fwts_acpi_tables.c
@@ -925,6 +925,38 @@ static bool fwts_acpi_table_fixable(fwts_acpi_table_info *table)
}
/*
+ * fwts_acpi_fixup_addr_from_fadt()
+ * fixup the ACPI table address of a given table if we have it defined
+ * in the FADT. This is only for fixed up tables loaded from file
+ * where these table addresses are unknown and hence are faked physical
+ * addresses to keep ACPICA happy.
+ */
+void fwts_acpi_fixup_addr_from_fadt(
+ fwts_framework *fw,
+ const char *name,
+ uint32_t addr32,
+ uint64_t addr64)
+{
+ fwts_acpi_table_info *table;
+
+ /* Fetch the table */
+ if (fwts_acpi_find_table(fw, name, 0, &table) != FWTS_OK)
+ return;
+ if (!table)
+ return;
+
+ /*
+ * OK, we have something to patch up, 64 bit addresses
+ * are used in preference to 32 bit. And only patch
+ * the addresses if they are non-zero.
+ */
+ if (addr64)
+ table->addr = addr64;
+ else if (addr32)
+ table->addr = addr32;
+}
+
+/*
* fwts_acpi_load_tables_fixup()
* tables loaded from file sometimes do not contain the original
* physical address of the tables, so these need faking. Also, some
@@ -938,6 +970,7 @@ static int fwts_acpi_load_tables_fixup(fwts_framework *fw)
fwts_acpi_table_info *table;
fwts_acpi_table_rsdp *rsdp = NULL;
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;
@@ -946,21 +979,22 @@ static int fwts_acpi_load_tables_fixup(fwts_framework *fw)
fwts_log_error(fw, "ACPI table find failure.");
return FWTS_ERROR;
}
- if (table) {
- fadt = (fwts_acpi_table_fadt *)table->data;
- oem_tbl_id = fadt->header.oem_tbl_id;
- } else {
+ if (!table) {
fwts_log_error(fw, "Cannot find FACP.");
return FWTS_ERROR;
}
+ fadt = (fwts_acpi_table_fadt *)table->data;
+ oem_tbl_id = fadt->header.oem_tbl_id;
+
/* Get FACS */
if (fwts_acpi_find_table(fw, "FACS", 0, &table) != FWTS_OK) {
fwts_log_error(fw, "ACPI table find failure.");
return FWTS_ERROR;
}
- if (!table) {
- fwts_acpi_table_facs *facs;
+ if (table) {
+ facs = (fwts_acpi_table_facs *)table->data;
+ } else {
size_t size = 64;
uint64_t facs_addr;
@@ -995,6 +1029,16 @@ static int fwts_acpi_load_tables_fixup(fwts_framework *fw)
size, FWTS_ACPI_TABLE_FROM_FIXUP);
}
+ /*
+ * In the case where the tables have be loaded from file
+ * and the address is not known we may have a valid FACP (FADT)
+ * that points to the FACS and DSDT, so we need to ensure
+ * fake addresses created by fwts for these are in-sync
+ * before we create RSDT and XSDTs
+ */
+ fwts_acpi_fixup_addr_from_fadt(fw, "FACS", fadt->firmware_control, fadt->x_firmware_ctrl);
+ fwts_acpi_fixup_addr_from_fadt(fw, "DSDT", fadt->dsdt, fadt->x_dsdt);
+
/* Figure out how many tables we need to put into RSDT and XSDT */
for (count = 0, i = 0; ; i++) {
if (fwts_acpi_get_table(fw, i, &table) != FWTS_OK)
--
2.11.0
More information about the fwts-devel
mailing list