diff options
author | Bob Moore <robert.moore@intel.com> | 2010-04-07 05:05:11 +0200 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2010-04-20 16:43:16 +0200 |
commit | 43323cb4c4b619414913f54fef9d492aabadd033 (patch) | |
tree | f5b434b93688972995eeed01ec86260f24311925 /drivers/acpi/acpica | |
parent | ACPICA: Add subsystem option to force copy of DSDT to local memory (diff) | |
download | linux-43323cb4c4b619414913f54fef9d492aabadd033.tar.xz linux-43323cb4c4b619414913f54fef9d492aabadd033.zip |
ACPICA: Update DSDT copy/detection.
Move initialization of DSDT pointer. Emit address of DSDT
in the dump of both table headers (good/bad DSDT).
Now handles the case where the root table can be reallocated,
which would invalidate the original pointer.
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/acpica')
-rw-r--r-- | drivers/acpi/acpica/acglobal.h | 2 | ||||
-rw-r--r-- | drivers/acpi/acpica/actables.h | 2 | ||||
-rw-r--r-- | drivers/acpi/acpica/tbutils.c | 23 | ||||
-rw-r--r-- | drivers/acpi/acpica/tbxface.c | 29 | ||||
-rw-r--r-- | drivers/acpi/acpica/utglobal.c | 1 |
5 files changed, 38 insertions, 19 deletions
diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index e3813d290b4f..87f21d9d2a66 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -175,7 +175,7 @@ ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1b_enable; /* DSDT information. Used to check for DSDT corruption */ -ACPI_EXTERN struct acpi_table_desc *acpi_gbl_DSDT; +ACPI_EXTERN struct acpi_table_header *acpi_gbl_DSDT; ACPI_EXTERN struct acpi_table_header acpi_gbl_original_dsdt_header; /* diff --git a/drivers/acpi/acpica/actables.h b/drivers/acpi/acpica/actables.h index b7197bf4af0b..62a576e34361 100644 --- a/drivers/acpi/acpica/actables.h +++ b/drivers/acpi/acpica/actables.h @@ -109,7 +109,7 @@ acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length); void acpi_tb_check_dsdt_header(void); -void acpi_tb_copy_dsdt(struct acpi_table_desc *table_desc); +struct acpi_table_header *acpi_tb_copy_dsdt(u32 table_index); void acpi_tb_install_table(acpi_physical_address address, diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c index 1efb0940e8b2..54a8712bae62 100644 --- a/drivers/acpi/acpica/tbutils.c +++ b/drivers/acpi/acpica/tbutils.c @@ -366,22 +366,18 @@ void acpi_tb_check_dsdt_header(void) /* Compare original length and checksum to current values */ - if (acpi_gbl_original_dsdt_header.length != - acpi_gbl_DSDT->pointer->length - || acpi_gbl_original_dsdt_header.checksum != - acpi_gbl_DSDT->pointer->checksum) { + if (acpi_gbl_original_dsdt_header.length != acpi_gbl_DSDT->length || + acpi_gbl_original_dsdt_header.checksum != acpi_gbl_DSDT->checksum) { ACPI_ERROR((AE_INFO, "The DSDT has been corrupted or replaced - old, new headers below")); acpi_tb_print_table_header(0, &acpi_gbl_original_dsdt_header); - acpi_tb_print_table_header(acpi_gbl_DSDT->address, - acpi_gbl_DSDT->pointer); + acpi_tb_print_table_header(0, acpi_gbl_DSDT); /* Disable further error messages */ - acpi_gbl_original_dsdt_header.length = - acpi_gbl_DSDT->pointer->length; + acpi_gbl_original_dsdt_header.length = acpi_gbl_DSDT->length; acpi_gbl_original_dsdt_header.checksum = - acpi_gbl_DSDT->pointer->checksum; + acpi_gbl_DSDT->checksum; } } @@ -399,15 +395,18 @@ void acpi_tb_check_dsdt_header(void) * ******************************************************************************/ -void acpi_tb_copy_dsdt(struct acpi_table_desc *table_desc) +struct acpi_table_header *acpi_tb_copy_dsdt(u32 table_index) { struct acpi_table_header *new_table; + struct acpi_table_desc *table_desc; + + table_desc = &acpi_gbl_root_table_list.tables[table_index]; new_table = ACPI_ALLOCATE(table_desc->length); if (!new_table) { ACPI_ERROR((AE_INFO, "Could not copy DSDT of length 0x%X", table_desc->length)); - return; + return (NULL); } ACPI_MEMCPY(new_table, table_desc->pointer, table_desc->length); @@ -418,6 +417,8 @@ void acpi_tb_copy_dsdt(struct acpi_table_desc *table_desc) ACPI_INFO((AE_INFO, "Forced DSDT copy: length 0x%05X copied locally, original unmapped", new_table->length)); + + return (new_table); } /******************************************************************************* diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c index f5378fc302b3..adb7f56b853e 100644 --- a/drivers/acpi/acpica/tbxface.c +++ b/drivers/acpi/acpica/tbxface.c @@ -513,39 +513,56 @@ static acpi_status acpi_tb_load_namespace(void) { acpi_status status; u32 i; + struct acpi_table_header *new_dsdt; ACPI_FUNCTION_TRACE(tb_load_namespace); (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - acpi_gbl_DSDT = &acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT]; - /* * Load the namespace. The DSDT is required, but any SSDT and * PSDT tables are optional. Verify the DSDT. */ if (!acpi_gbl_root_table_list.count || - !ACPI_COMPARE_NAME(&acpi_gbl_DSDT->signature, ACPI_SIG_DSDT) || - ACPI_FAILURE(acpi_tb_verify_table(acpi_gbl_DSDT))) { + !ACPI_COMPARE_NAME(& + (acpi_gbl_root_table_list. + tables[ACPI_TABLE_INDEX_DSDT].signature), + ACPI_SIG_DSDT) + || + ACPI_FAILURE(acpi_tb_verify_table + (&acpi_gbl_root_table_list. + tables[ACPI_TABLE_INDEX_DSDT]))) { status = AE_NO_ACPI_TABLES; goto unlock_and_exit; } /* + * Save the DSDT pointer for simple access. This is the mapped memory + * address. We must take care here because the address of the .Tables + * array can change dynamically as tables are loaded at run-time. Note: + * .Pointer field is not validated until after call to acpi_tb_verify_table. + */ + acpi_gbl_DSDT = + acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].pointer; + + /* * Optionally copy the entire DSDT to local memory (instead of simply * mapping it.) There are some BIOSs that corrupt or replace the original * DSDT, creating the need for this option. Default is FALSE, do not copy * the DSDT. */ if (acpi_gbl_copy_dsdt_locally) { - acpi_tb_copy_dsdt(acpi_gbl_DSDT); + new_dsdt = acpi_tb_copy_dsdt(ACPI_TABLE_INDEX_DSDT); + if (new_dsdt) { + acpi_gbl_DSDT = new_dsdt; + } } /* * Save the original DSDT header for detection of table corruption * and/or replacement of the DSDT from outside the OS. */ - ACPI_MEMCPY(&acpi_gbl_original_dsdt_header, acpi_gbl_DSDT->pointer, + ACPI_MEMCPY(&acpi_gbl_original_dsdt_header, acpi_gbl_DSDT, sizeof(struct acpi_table_header)); (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c index eda3e656c4af..66116750a0f9 100644 --- a/drivers/acpi/acpica/utglobal.c +++ b/drivers/acpi/acpica/utglobal.c @@ -785,6 +785,7 @@ acpi_status acpi_ut_init_globals(void) /* Miscellaneous variables */ + acpi_gbl_DSDT = NULL; acpi_gbl_cm_single_step = FALSE; acpi_gbl_db_terminate_threads = FALSE; acpi_gbl_shutdown = FALSE; |