summaryrefslogtreecommitdiffstats
path: root/drivers/acpi/acpica
diff options
context:
space:
mode:
authorBob Moore <robert.moore@intel.com>2010-04-07 05:05:11 +0200
committerLen Brown <len.brown@intel.com>2010-04-20 16:43:16 +0200
commit43323cb4c4b619414913f54fef9d492aabadd033 (patch)
treef5b434b93688972995eeed01ec86260f24311925 /drivers/acpi/acpica
parentACPICA: Add subsystem option to force copy of DSDT to local memory (diff)
downloadlinux-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.h2
-rw-r--r--drivers/acpi/acpica/actables.h2
-rw-r--r--drivers/acpi/acpica/tbutils.c23
-rw-r--r--drivers/acpi/acpica/tbxface.c29
-rw-r--r--drivers/acpi/acpica/utglobal.c1
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;