diff options
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 02723a9fb10..34f9c2bc5e1 100644 --- a/drivers/acpi/acpica/tbutils.c +++ b/drivers/acpi/acpica/tbutils.c | |||
@@ -158,7 +158,7 @@ acpi_status acpi_tb_initialize_facs(void) | |||
158 | u8 acpi_tb_tables_loaded(void) | 158 | u8 acpi_tb_tables_loaded(void) |
159 | { | 159 | { |
160 | 160 | ||
161 | if (acpi_gbl_root_table_list.count >= 3) { | 161 | if (acpi_gbl_root_table_list.current_table_count >= 3) { |
162 | return (TRUE); | 162 | return (TRUE); |
163 | } | 163 | } |
164 | 164 | ||
@@ -309,7 +309,7 @@ acpi_status acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length) | |||
309 | 309 | ||
310 | if (checksum) { | 310 | if (checksum) { |
311 | ACPI_WARNING((AE_INFO, | 311 | ACPI_WARNING((AE_INFO, |
312 | "Incorrect checksum in table [%4.4s] - %2.2X, should be %2.2X", | 312 | "Incorrect checksum in table [%4.4s] - 0x%2.2X, should be 0x%2.2X", |
313 | table->signature, table->checksum, | 313 | table->signature, table->checksum, |
314 | (u8) (table->checksum - checksum))); | 314 | (u8) (table->checksum - checksum))); |
315 | 315 | ||
@@ -349,6 +349,84 @@ u8 acpi_tb_checksum(u8 *buffer, u32 length) | |||
349 | 349 | ||
350 | /******************************************************************************* | 350 | /******************************************************************************* |
351 | * | 351 | * |
352 | * FUNCTION: acpi_tb_check_dsdt_header | ||
353 | * | ||
354 | * PARAMETERS: None | ||
355 | * | ||
356 | * RETURN: None | ||
357 | * | ||
358 | * DESCRIPTION: Quick compare to check validity of the DSDT. This will detect | ||
359 | * if the DSDT has been replaced from outside the OS and/or if | ||
360 | * the DSDT header has been corrupted. | ||
361 | * | ||
362 | ******************************************************************************/ | ||
363 | |||
364 | void acpi_tb_check_dsdt_header(void) | ||
365 | { | ||
366 | |||
367 | /* Compare original length and checksum to current values */ | ||
368 | |||
369 | if (acpi_gbl_original_dsdt_header.length != acpi_gbl_DSDT->length || | ||
370 | acpi_gbl_original_dsdt_header.checksum != acpi_gbl_DSDT->checksum) { | ||
371 | ACPI_ERROR((AE_INFO, | ||
372 | "The DSDT has been corrupted or replaced - old, new headers below")); | ||
373 | acpi_tb_print_table_header(0, &acpi_gbl_original_dsdt_header); | ||
374 | acpi_tb_print_table_header(0, acpi_gbl_DSDT); | ||
375 | |||
376 | ACPI_ERROR((AE_INFO, | ||
377 | "Please send DMI info to linux-acpi@vger.kernel.org\n" | ||
378 | "If system does not work as expected, please boot with acpi=copy_dsdt")); | ||
379 | |||
380 | /* Disable further error messages */ | ||
381 | |||
382 | acpi_gbl_original_dsdt_header.length = acpi_gbl_DSDT->length; | ||
383 | acpi_gbl_original_dsdt_header.checksum = | ||
384 | acpi_gbl_DSDT->checksum; | ||
385 | } | ||
386 | } | ||
387 | |||
388 | /******************************************************************************* | ||
389 | * | ||
390 | * FUNCTION: acpi_tb_copy_dsdt | ||
391 | * | ||
392 | * PARAMETERS: table_desc - Installed table to copy | ||
393 | * | ||
394 | * RETURN: None | ||
395 | * | ||
396 | * DESCRIPTION: Implements a subsystem option to copy the DSDT to local memory. | ||
397 | * Some very bad BIOSs are known to either corrupt the DSDT or | ||
398 | * install a new, bad DSDT. This copy works around the problem. | ||
399 | * | ||
400 | ******************************************************************************/ | ||
401 | |||
402 | struct acpi_table_header *acpi_tb_copy_dsdt(u32 table_index) | ||
403 | { | ||
404 | struct acpi_table_header *new_table; | ||
405 | struct acpi_table_desc *table_desc; | ||
406 | |||
407 | table_desc = &acpi_gbl_root_table_list.tables[table_index]; | ||
408 | |||
409 | new_table = ACPI_ALLOCATE(table_desc->length); | ||
410 | if (!new_table) { | ||
411 | ACPI_ERROR((AE_INFO, "Could not copy DSDT of length 0x%X", | ||
412 | table_desc->length)); | ||
413 | return (NULL); | ||
414 | } | ||
415 | |||
416 | ACPI_MEMCPY(new_table, table_desc->pointer, table_desc->length); | ||
417 | acpi_tb_delete_table(table_desc); | ||
418 | table_desc->pointer = new_table; | ||
419 | table_desc->flags = ACPI_TABLE_ORIGIN_ALLOCATED; | ||
420 | |||
421 | ACPI_INFO((AE_INFO, | ||
422 | "Forced DSDT copy: length 0x%05X copied locally, original unmapped", | ||
423 | new_table->length)); | ||
424 | |||
425 | return (new_table); | ||
426 | } | ||
427 | |||
428 | /******************************************************************************* | ||
429 | * | ||
352 | * FUNCTION: acpi_tb_install_table | 430 | * FUNCTION: acpi_tb_install_table |
353 | * | 431 | * |
354 | * PARAMETERS: Address - Physical address of DSDT or FACS | 432 | * 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) | |||
496 | /* Will truncate 64-bit address to 32 bits, issue warning */ | 574 | /* Will truncate 64-bit address to 32 bits, issue warning */ |
497 | 575 | ||
498 | ACPI_WARNING((AE_INFO, | 576 | ACPI_WARNING((AE_INFO, |
499 | "64-bit Physical Address in XSDT is too large (%8.8X%8.8X)," | 577 | "64-bit Physical Address in XSDT is too large (0x%8.8X%8.8X)," |
500 | " truncating", | 578 | " truncating", |
501 | ACPI_FORMAT_UINT64(address64))); | 579 | ACPI_FORMAT_UINT64(address64))); |
502 | } | 580 | } |
@@ -629,14 +707,14 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address) | |||
629 | */ | 707 | */ |
630 | table_entry = | 708 | table_entry = |
631 | ACPI_CAST_PTR(u8, table) + sizeof(struct acpi_table_header); | 709 | ACPI_CAST_PTR(u8, table) + sizeof(struct acpi_table_header); |
632 | acpi_gbl_root_table_list.count = 2; | 710 | acpi_gbl_root_table_list.current_table_count = 2; |
633 | 711 | ||
634 | /* | 712 | /* |
635 | * Initialize the root table array from the RSDT/XSDT | 713 | * Initialize the root table array from the RSDT/XSDT |
636 | */ | 714 | */ |
637 | for (i = 0; i < table_count; i++) { | 715 | for (i = 0; i < table_count; i++) { |
638 | if (acpi_gbl_root_table_list.count >= | 716 | if (acpi_gbl_root_table_list.current_table_count >= |
639 | acpi_gbl_root_table_list.size) { | 717 | acpi_gbl_root_table_list.max_table_count) { |
640 | 718 | ||
641 | /* There is no more room in the root table array, attempt resize */ | 719 | /* There is no more room in the root table array, attempt resize */ |
642 | 720 | ||
@@ -646,19 +724,20 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address) | |||
646 | "Truncating %u table entries!", | 724 | "Truncating %u table entries!", |
647 | (unsigned) (table_count - | 725 | (unsigned) (table_count - |
648 | (acpi_gbl_root_table_list. | 726 | (acpi_gbl_root_table_list. |
649 | count - 2)))); | 727 | current_table_count - |
728 | 2)))); | ||
650 | break; | 729 | break; |
651 | } | 730 | } |
652 | } | 731 | } |
653 | 732 | ||
654 | /* Get the table physical address (32-bit for RSDT, 64-bit for XSDT) */ | 733 | /* Get the table physical address (32-bit for RSDT, 64-bit for XSDT) */ |
655 | 734 | ||
656 | acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count]. | 735 | acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list. |
657 | address = | 736 | current_table_count].address = |
658 | acpi_tb_get_root_table_entry(table_entry, table_entry_size); | 737 | acpi_tb_get_root_table_entry(table_entry, table_entry_size); |
659 | 738 | ||
660 | table_entry += table_entry_size; | 739 | table_entry += table_entry_size; |
661 | acpi_gbl_root_table_list.count++; | 740 | acpi_gbl_root_table_list.current_table_count++; |
662 | } | 741 | } |
663 | 742 | ||
664 | /* | 743 | /* |
@@ -671,7 +750,7 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address) | |||
671 | * Complete the initialization of the root table array by examining | 750 | * Complete the initialization of the root table array by examining |
672 | * the header of each table | 751 | * the header of each table |
673 | */ | 752 | */ |
674 | for (i = 2; i < acpi_gbl_root_table_list.count; i++) { | 753 | for (i = 2; i < acpi_gbl_root_table_list.current_table_count; i++) { |
675 | acpi_tb_install_table(acpi_gbl_root_table_list.tables[i]. | 754 | acpi_tb_install_table(acpi_gbl_root_table_list.tables[i]. |
676 | address, NULL, i); | 755 | address, NULL, i); |
677 | 756 | ||