diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-20 09:45:38 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-20 09:45:38 -0700 |
commit | 04afb40593f9a3007e5ea817d009529ef10fb685 (patch) | |
tree | de5a16c2b1e5f2d97a7c2eccea4677719817f282 /drivers/acpi/acpica/tbutils.c | |
parent | 7f06a8b26aba1dc03b42272dc0089a800372c575 (diff) | |
parent | cce4f632db200aef147c59084437168174b23f11 (diff) | |
download | blackbird-op-linux-04afb40593f9a3007e5ea817d009529ef10fb685.tar.gz blackbird-op-linux-04afb40593f9a3007e5ea817d009529ef10fb685.zip |
Merge branch 'acpica' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6
* 'acpica' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6: (22 commits)
ACPI: fix early DSDT dmi check warnings on ia64
ACPICA: Update version to 20100428.
ACPICA: Update/clarify some parameter names associated with acpi_handle
ACPICA: Rename acpi_ex_system_do_suspend->acpi_ex_system_do_sleep
ACPICA: Prevent possible allocation overrun during object copy
ACPICA: Split large file, evgpeblk
ACPICA: Add GPE support for dynamically loaded ACPI tables
ACPICA: Clarify/rename some root table descriptor fields
ACPICA: Update version to 20100331.
ACPICA: Minimize the differences between linux GPE code and ACPICA code base
ACPI: add boot option acpi=copy_dsdt to fix corrupt DSDT
ACPICA: Update DSDT copy/detection.
ACPICA: Add subsystem option to force copy of DSDT to local memory
ACPICA: Add detection of corrupted/replaced DSDT
ACPICA: Add write support for DataTable operation regions
ACPICA: Fix for acpi_reallocate_root_table for incorrect root table copy
ACPICA: Update comments/headers, no functional change
ACPICA: Update version to 20100304
ACPICA: Fix for possible fault in acpi_ex_release_mutex
ACPICA: Standardize integer output for ACPICA warnings/errors
...
Diffstat (limited to 'drivers/acpi/acpica/tbutils.c')
-rw-r--r-- | drivers/acpi/acpica/tbutils.c | 101 |
1 files changed, 90 insertions, 11 deletions
diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c index 02723a9fb10c..34f9c2bc5e1f 100644 --- a/drivers/acpi/acpica/tbutils.c +++ b/drivers/acpi/acpica/tbutils.c @@ -158,7 +158,7 @@ acpi_status acpi_tb_initialize_facs(void) u8 acpi_tb_tables_loaded(void) { - if (acpi_gbl_root_table_list.count >= 3) { + if (acpi_gbl_root_table_list.current_table_count >= 3) { return (TRUE); } @@ -309,7 +309,7 @@ acpi_status acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length) if (checksum) { ACPI_WARNING((AE_INFO, - "Incorrect checksum in table [%4.4s] - %2.2X, should be %2.2X", + "Incorrect checksum in table [%4.4s] - 0x%2.2X, should be 0x%2.2X", table->signature, table->checksum, (u8) (table->checksum - checksum))); @@ -349,6 +349,84 @@ u8 acpi_tb_checksum(u8 *buffer, u32 length) /******************************************************************************* * + * FUNCTION: acpi_tb_check_dsdt_header + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Quick compare to check validity of the DSDT. This will detect + * if the DSDT has been replaced from outside the OS and/or if + * the DSDT header has been corrupted. + * + ******************************************************************************/ + +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->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(0, acpi_gbl_DSDT); + + ACPI_ERROR((AE_INFO, + "Please send DMI info to linux-acpi@vger.kernel.org\n" + "If system does not work as expected, please boot with acpi=copy_dsdt")); + + /* Disable further error messages */ + + acpi_gbl_original_dsdt_header.length = acpi_gbl_DSDT->length; + acpi_gbl_original_dsdt_header.checksum = + acpi_gbl_DSDT->checksum; + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_copy_dsdt + * + * PARAMETERS: table_desc - Installed table to copy + * + * RETURN: None + * + * DESCRIPTION: Implements a subsystem option to copy the DSDT to local memory. + * Some very bad BIOSs are known to either corrupt the DSDT or + * install a new, bad DSDT. This copy works around the problem. + * + ******************************************************************************/ + +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 (NULL); + } + + ACPI_MEMCPY(new_table, table_desc->pointer, table_desc->length); + acpi_tb_delete_table(table_desc); + table_desc->pointer = new_table; + table_desc->flags = ACPI_TABLE_ORIGIN_ALLOCATED; + + ACPI_INFO((AE_INFO, + "Forced DSDT copy: length 0x%05X copied locally, original unmapped", + new_table->length)); + + return (new_table); +} + +/******************************************************************************* + * * FUNCTION: acpi_tb_install_table * * PARAMETERS: Address - Physical address of DSDT or FACS @@ -496,7 +574,7 @@ acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size) /* Will truncate 64-bit address to 32 bits, issue warning */ ACPI_WARNING((AE_INFO, - "64-bit Physical Address in XSDT is too large (%8.8X%8.8X)," + "64-bit Physical Address in XSDT is too large (0x%8.8X%8.8X)," " truncating", ACPI_FORMAT_UINT64(address64))); } @@ -629,14 +707,14 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address) */ table_entry = ACPI_CAST_PTR(u8, table) + sizeof(struct acpi_table_header); - acpi_gbl_root_table_list.count = 2; + acpi_gbl_root_table_list.current_table_count = 2; /* * Initialize the root table array from the RSDT/XSDT */ for (i = 0; i < table_count; i++) { - if (acpi_gbl_root_table_list.count >= - acpi_gbl_root_table_list.size) { + if (acpi_gbl_root_table_list.current_table_count >= + acpi_gbl_root_table_list.max_table_count) { /* There is no more room in the root table array, attempt resize */ @@ -646,19 +724,20 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address) "Truncating %u table entries!", (unsigned) (table_count - (acpi_gbl_root_table_list. - count - 2)))); + current_table_count - + 2)))); break; } } /* Get the table physical address (32-bit for RSDT, 64-bit for XSDT) */ - acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count]. - address = + acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list. + current_table_count].address = acpi_tb_get_root_table_entry(table_entry, table_entry_size); table_entry += table_entry_size; - acpi_gbl_root_table_list.count++; + acpi_gbl_root_table_list.current_table_count++; } /* @@ -671,7 +750,7 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address) * Complete the initialization of the root table array by examining * the header of each table */ - for (i = 2; i < acpi_gbl_root_table_list.count; i++) { + for (i = 2; i < acpi_gbl_root_table_list.current_table_count; i++) { acpi_tb_install_table(acpi_gbl_root_table_list.tables[i]. address, NULL, i); |