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>
This commit is contained in:
Len Brown 2007-11-23 20:08:02 -05:00
parent 2ffbb8377c
commit 239665a3bb
7 changed files with 23 additions and 60 deletions

View file

@ -69,6 +69,20 @@ unsigned int acpi_cpei_phys_cpuid;
unsigned long acpi_wakeup_address = 0; unsigned long acpi_wakeup_address = 0;
#ifdef CONFIG_IA64_GENERIC
static unsigned long __init acpi_find_rsdp(void)
{
unsigned long rsdp_phys = 0;
if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
rsdp_phys = efi.acpi20;
else if (efi.acpi != EFI_INVALID_TABLE_ADDR)
printk(KERN_WARNING PREFIX
"v1.0/r0.71 tables no longer supported\n");
return rsdp_phys;
}
#endif
const char __init * const char __init *
acpi_get_sysname(void) acpi_get_sysname(void)
{ {
@ -631,18 +645,6 @@ static int __init acpi_parse_fadt(struct acpi_table_header *table)
return 0; return 0;
} }
unsigned long __init acpi_find_rsdp(void)
{
unsigned long rsdp_phys = 0;
if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
rsdp_phys = efi.acpi20;
else if (efi.acpi != EFI_INVALID_TABLE_ADDR)
printk(KERN_WARNING PREFIX
"v1.0/r0.71 tables no longer supported\n");
return rsdp_phys;
}
int __init acpi_boot_init(void) int __init acpi_boot_init(void)
{ {

View file

@ -581,25 +581,6 @@ int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base)
EXPORT_SYMBOL(acpi_unregister_ioapic); EXPORT_SYMBOL(acpi_unregister_ioapic);
static unsigned long __init
acpi_scan_rsdp(unsigned long start, unsigned long length)
{
unsigned long offset = 0;
unsigned long sig_len = sizeof("RSD PTR ") - 1;
/*
* Scan all 16-byte boundaries of the physical memory region for the
* RSDP signature.
*/
for (offset = 0; offset < length; offset += 16) {
if (strncmp((char *)(phys_to_virt(start) + offset), "RSD PTR ", sig_len))
continue;
return (start + offset);
}
return 0;
}
static int __init acpi_parse_sbf(struct acpi_table_header *table) static int __init acpi_parse_sbf(struct acpi_table_header *table)
{ {
struct acpi_table_boot *sb; struct acpi_table_boot *sb;
@ -742,27 +723,6 @@ static int __init acpi_parse_fadt(struct acpi_table_header *table)
return 0; return 0;
} }
unsigned long __init acpi_find_rsdp(void)
{
unsigned long rsdp_phys = 0;
if (efi_enabled) {
if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
return efi.acpi20;
else if (efi.acpi != EFI_INVALID_TABLE_ADDR)
return efi.acpi;
}
/*
* Scan memory looking for the RSDP signature. First search EBDA (low
* memory) paragraphs and then search upper memory (E0000-FFFFF).
*/
rsdp_phys = acpi_scan_rsdp(0, 0x400);
if (!rsdp_phys)
rsdp_phys = acpi_scan_rsdp(0xE0000, 0x20000);
return rsdp_phys;
}
#ifdef CONFIG_X86_LOCAL_APIC #ifdef CONFIG_X86_LOCAL_APIC
/* /*
* Parse LAPIC entries in MADT * Parse LAPIC entries in MADT

View file

@ -276,7 +276,7 @@ int __init get_memcfg_from_srat(void)
int tables = 0; int tables = 0;
int i = 0; int i = 0;
rsdp_address = acpi_find_rsdp(); rsdp_address = acpi_os_get_root_pointer();
if (!rsdp_address) { if (!rsdp_address) {
printk("%s: System description tables not found\n", printk("%s: System description tables not found\n",
__FUNCTION__); __FUNCTION__);

View file

@ -207,8 +207,12 @@ acpi_physical_address __init acpi_os_get_root_pointer(void)
"System description tables not found\n"); "System description tables not found\n");
return 0; return 0;
} }
} else } else {
return acpi_find_rsdp(); acpi_physical_address pa = 0;
acpi_find_root_pointer(&pa);
return pa;
}
} }
void __iomem *acpi_os_map_memory(acpi_physical_address phys, acpi_size size) void __iomem *acpi_os_map_memory(acpi_physical_address phys, acpi_size size)

View file

@ -2,6 +2,6 @@
# Makefile for all Linux ACPI interpreter subdirectories # Makefile for all Linux ACPI interpreter subdirectories
# #
obj-y := tbxface.o tbinstal.o tbutils.o tbfind.o tbfadt.o obj-y := tbxface.o tbinstal.o tbutils.o tbfind.o tbfadt.o tbxfroot.o
EXTRA_CFLAGS += $(ACPI_CFLAGS) EXTRA_CFLAGS += $(ACPI_CFLAGS)

View file

@ -100,7 +100,7 @@ static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp)
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_tb_find_rsdp * FUNCTION: acpi_find_root_pointer
* *
* PARAMETERS: table_address - Where the table pointer is returned * PARAMETERS: table_address - Where the table pointer is returned
* *
@ -219,8 +219,6 @@ acpi_status acpi_find_root_pointer(acpi_native_uint * table_address)
return_ACPI_STATUS(AE_NOT_FOUND); return_ACPI_STATUS(AE_NOT_FOUND);
} }
ACPI_EXPORT_SYMBOL(acpi_find_root_pointer)
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_tb_scan_memory_for_rsdp * FUNCTION: acpi_tb_scan_memory_for_rsdp

View file

@ -79,7 +79,6 @@ typedef int (*acpi_table_handler) (struct acpi_table_header *table);
typedef int (*acpi_table_entry_handler) (struct acpi_subtable_header *header, const unsigned long end); typedef int (*acpi_table_entry_handler) (struct acpi_subtable_header *header, const unsigned long end);
char * __acpi_map_table (unsigned long phys_addr, unsigned long size); char * __acpi_map_table (unsigned long phys_addr, unsigned long size);
unsigned long acpi_find_rsdp (void);
int acpi_boot_init (void); int acpi_boot_init (void);
int acpi_boot_table_init (void); int acpi_boot_table_init (void);
int acpi_numa_init (void); int acpi_numa_init (void);