diff options
author | Len Brown <len.brown@intel.com> | 2007-11-23 20:08:02 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2007-12-14 02:36:24 -0500 |
commit | 239665a3bb0a2234980f918913add31bc536cfd1 (patch) | |
tree | 260262706ce5223bf3d1cec0e8083ea42260f2fb | |
parent | 2ffbb8377c7a0713baf6644e285adc27a5654582 (diff) |
ACPI: tables: complete searching upon RSDP w/ bad checksum.
ACPI tables follow a tree structure in memory.
The root of the tree is the RSDP (Root System Description Pointer).
To find the RSDP, the OS searches for the signature "RSD PTR "
in well known physical memory locations. Then the OS computes
a table checksum to verify that the signature is really part
of a valid table header.
Some systems have a proper signature but an invalid checksum;
followed elsewhere by a proper signature with valid checksum.
http://bugzilla.kernel.org/show_bug.cgi?id=9444
The Linux RSDP scanning code bailed out on those systems
and as a result they booted with ACPI disabled.
Fix this by deleting the Linux RSDP scanning code and
plugging in the ACPICA RSDP scanning code.
Signed-off-by: Len Brown <len.brown@intel.com>
-rw-r--r-- | arch/ia64/kernel/acpi.c | 26 | ||||
-rw-r--r-- | arch/x86/kernel/acpi/boot.c | 40 | ||||
-rw-r--r-- | arch/x86/kernel/srat_32.c | 2 | ||||
-rw-r--r-- | drivers/acpi/osl.c | 8 | ||||
-rw-r--r-- | drivers/acpi/tables/Makefile | 2 | ||||
-rw-r--r-- | drivers/acpi/tables/tbxfroot.c | 4 | ||||
-rw-r--r-- | include/linux/acpi.h | 1 |
7 files changed, 23 insertions, 60 deletions
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index 897e2083a3b1..63d6dcdc2e2a 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c | |||
@@ -69,6 +69,20 @@ unsigned int acpi_cpei_phys_cpuid; | |||
69 | 69 | ||
70 | unsigned long acpi_wakeup_address = 0; | 70 | unsigned long acpi_wakeup_address = 0; |
71 | 71 | ||
72 | #ifdef CONFIG_IA64_GENERIC | ||
73 | static unsigned long __init acpi_find_rsdp(void) | ||
74 | { | ||
75 | unsigned long rsdp_phys = 0; | ||
76 | |||
77 | if (efi.acpi20 != EFI_INVALID_TABLE_ADDR) | ||
78 | rsdp_phys = efi.acpi20; | ||
79 | else if (efi.acpi != EFI_INVALID_TABLE_ADDR) | ||
80 | printk(KERN_WARNING PREFIX | ||
81 | "v1.0/r0.71 tables no longer supported\n"); | ||
82 | return rsdp_phys; | ||
83 | } | ||
84 | #endif | ||
85 | |||
72 | const char __init * | 86 | const char __init * |
73 | acpi_get_sysname(void) | 87 | acpi_get_sysname(void) |
74 | { | 88 | { |
@@ -631,18 +645,6 @@ static int __init acpi_parse_fadt(struct acpi_table_header *table) | |||
631 | return 0; | 645 | return 0; |
632 | } | 646 | } |
633 | 647 | ||
634 | unsigned long __init acpi_find_rsdp(void) | ||
635 | { | ||
636 | unsigned long rsdp_phys = 0; | ||
637 | |||
638 | if (efi.acpi20 != EFI_INVALID_TABLE_ADDR) | ||
639 | rsdp_phys = efi.acpi20; | ||
640 | else if (efi.acpi != EFI_INVALID_TABLE_ADDR) | ||
641 | printk(KERN_WARNING PREFIX | ||
642 | "v1.0/r0.71 tables no longer supported\n"); | ||
643 | return rsdp_phys; | ||
644 | } | ||
645 | |||
646 | int __init acpi_boot_init(void) | 648 | int __init acpi_boot_init(void) |
647 | { | 649 | { |
648 | 650 | ||
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 0ca27c7b0e8d..719c74b0141a 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c | |||
@@ -581,25 +581,6 @@ int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base) | |||
581 | 581 | ||
582 | EXPORT_SYMBOL(acpi_unregister_ioapic); | 582 | EXPORT_SYMBOL(acpi_unregister_ioapic); |
583 | 583 | ||
584 | static unsigned long __init | ||
585 | acpi_scan_rsdp(unsigned long start, unsigned long length) | ||
586 | { | ||
587 | unsigned long offset = 0; | ||
588 | unsigned long sig_len = sizeof("RSD PTR ") - 1; | ||
589 | |||
590 | /* | ||
591 | * Scan all 16-byte boundaries of the physical memory region for the | ||
592 | * RSDP signature. | ||
593 | */ | ||
594 | for (offset = 0; offset < length; offset += 16) { | ||
595 | if (strncmp((char *)(phys_to_virt(start) + offset), "RSD PTR ", sig_len)) | ||
596 | continue; | ||
597 | return (start + offset); | ||
598 | } | ||
599 | |||
600 | return 0; | ||
601 | } | ||
602 | |||
603 | static int __init acpi_parse_sbf(struct acpi_table_header *table) | 584 | static int __init acpi_parse_sbf(struct acpi_table_header *table) |
604 | { | 585 | { |
605 | struct acpi_table_boot *sb; | 586 | struct acpi_table_boot *sb; |
@@ -742,27 +723,6 @@ static int __init acpi_parse_fadt(struct acpi_table_header *table) | |||
742 | return 0; | 723 | return 0; |
743 | } | 724 | } |
744 | 725 | ||
745 | unsigned long __init acpi_find_rsdp(void) | ||
746 | { | ||
747 | unsigned long rsdp_phys = 0; | ||
748 | |||
749 | if (efi_enabled) { | ||
750 | if (efi.acpi20 != EFI_INVALID_TABLE_ADDR) | ||
751 | return efi.acpi20; | ||
752 | else if (efi.acpi != EFI_INVALID_TABLE_ADDR) | ||
753 | return efi.acpi; | ||
754 | } | ||
755 | /* | ||
756 | * Scan memory looking for the RSDP signature. First search EBDA (low | ||
757 | * memory) paragraphs and then search upper memory (E0000-FFFFF). | ||
758 | */ | ||
759 | rsdp_phys = acpi_scan_rsdp(0, 0x400); | ||
760 | if (!rsdp_phys) | ||
761 | rsdp_phys = acpi_scan_rsdp(0xE0000, 0x20000); | ||
762 | |||
763 | return rsdp_phys; | ||
764 | } | ||
765 | |||
766 | #ifdef CONFIG_X86_LOCAL_APIC | 726 | #ifdef CONFIG_X86_LOCAL_APIC |
767 | /* | 727 | /* |
768 | * Parse LAPIC entries in MADT | 728 | * Parse LAPIC entries in MADT |
diff --git a/arch/x86/kernel/srat_32.c b/arch/x86/kernel/srat_32.c index 2a8713ec0f9a..b3b2c95f19d3 100644 --- a/arch/x86/kernel/srat_32.c +++ b/arch/x86/kernel/srat_32.c | |||
@@ -276,7 +276,7 @@ int __init get_memcfg_from_srat(void) | |||
276 | int tables = 0; | 276 | int tables = 0; |
277 | int i = 0; | 277 | int i = 0; |
278 | 278 | ||
279 | rsdp_address = acpi_find_rsdp(); | 279 | rsdp_address = acpi_os_get_root_pointer(); |
280 | if (!rsdp_address) { | 280 | if (!rsdp_address) { |
281 | printk("%s: System description tables not found\n", | 281 | printk("%s: System description tables not found\n", |
282 | __FUNCTION__); | 282 | __FUNCTION__); |
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index aabc6ca4a81c..101691ef66cb 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
@@ -207,8 +207,12 @@ acpi_physical_address __init acpi_os_get_root_pointer(void) | |||
207 | "System description tables not found\n"); | 207 | "System description tables not found\n"); |
208 | return 0; | 208 | return 0; |
209 | } | 209 | } |
210 | } else | 210 | } else { |
211 | return acpi_find_rsdp(); | 211 | acpi_physical_address pa = 0; |
212 | |||
213 | acpi_find_root_pointer(&pa); | ||
214 | return pa; | ||
215 | } | ||
212 | } | 216 | } |
213 | 217 | ||
214 | void __iomem *acpi_os_map_memory(acpi_physical_address phys, acpi_size size) | 218 | void __iomem *acpi_os_map_memory(acpi_physical_address phys, acpi_size size) |
diff --git a/drivers/acpi/tables/Makefile b/drivers/acpi/tables/Makefile index 0a7d7afac255..7385efa61622 100644 --- a/drivers/acpi/tables/Makefile +++ b/drivers/acpi/tables/Makefile | |||
@@ -2,6 +2,6 @@ | |||
2 | # Makefile for all Linux ACPI interpreter subdirectories | 2 | # Makefile for all Linux ACPI interpreter subdirectories |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y := tbxface.o tbinstal.o tbutils.o tbfind.o tbfadt.o | 5 | obj-y := tbxface.o tbinstal.o tbutils.o tbfind.o tbfadt.o tbxfroot.o |
6 | 6 | ||
7 | EXTRA_CFLAGS += $(ACPI_CFLAGS) | 7 | EXTRA_CFLAGS += $(ACPI_CFLAGS) |
diff --git a/drivers/acpi/tables/tbxfroot.c b/drivers/acpi/tables/tbxfroot.c index cf8fa514189f..9ecb4b6c1e7d 100644 --- a/drivers/acpi/tables/tbxfroot.c +++ b/drivers/acpi/tables/tbxfroot.c | |||
@@ -100,7 +100,7 @@ static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp) | |||
100 | 100 | ||
101 | /******************************************************************************* | 101 | /******************************************************************************* |
102 | * | 102 | * |
103 | * FUNCTION: acpi_tb_find_rsdp | 103 | * FUNCTION: acpi_find_root_pointer |
104 | * | 104 | * |
105 | * PARAMETERS: table_address - Where the table pointer is returned | 105 | * PARAMETERS: table_address - Where the table pointer is returned |
106 | * | 106 | * |
@@ -219,8 +219,6 @@ acpi_status acpi_find_root_pointer(acpi_native_uint * table_address) | |||
219 | return_ACPI_STATUS(AE_NOT_FOUND); | 219 | return_ACPI_STATUS(AE_NOT_FOUND); |
220 | } | 220 | } |
221 | 221 | ||
222 | ACPI_EXPORT_SYMBOL(acpi_find_root_pointer) | ||
223 | |||
224 | /******************************************************************************* | 222 | /******************************************************************************* |
225 | * | 223 | * |
226 | * FUNCTION: acpi_tb_scan_memory_for_rsdp | 224 | * FUNCTION: acpi_tb_scan_memory_for_rsdp |
diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 8ccedf7a0a5a..8deb61171558 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h | |||
@@ -79,7 +79,6 @@ typedef int (*acpi_table_handler) (struct acpi_table_header *table); | |||
79 | typedef int (*acpi_table_entry_handler) (struct acpi_subtable_header *header, const unsigned long end); | 79 | typedef int (*acpi_table_entry_handler) (struct acpi_subtable_header *header, const unsigned long end); |
80 | 80 | ||
81 | char * __acpi_map_table (unsigned long phys_addr, unsigned long size); | 81 | char * __acpi_map_table (unsigned long phys_addr, unsigned long size); |
82 | unsigned long acpi_find_rsdp (void); | ||
83 | int acpi_boot_init (void); | 82 | int acpi_boot_init (void); |
84 | int acpi_boot_table_init (void); | 83 | int acpi_boot_table_init (void); |
85 | int acpi_numa_init (void); | 84 | int acpi_numa_init (void); |