* acpi_scan_rsdp() in arch/i386/kernel/acpi/boot.c
@ 2004-02-19 22:11 Jon TURNEY
0 siblings, 0 replies; only message in thread
From: Jon TURNEY @ 2004-02-19 22:11 UTC (permalink / raw)
To: acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
len.brown-ral2JQCrhuEAvxtiuMwx3w
Cc: jon-GrJqePx9RPPAJUdA+FbntA
[-- Attachment #1: Type: text/plain, Size: 1670 bytes --]
The implementation of acpi_scan_rsdp() in linux 2.6.3 does not correctly
locate the RSDP on an Acer TravelMate C100 with BIOS versions R01-A4F or
R01-A4K
BIOS version R01-A4K has an RSDP signature at 0xEC2D0, with zero
checksum and RSDT pointer, and another RSDP signature at 0xFE030,
with a valid checksum and RSDT pointer.
Currently acpi_scan_rsdp() in arch/i386/kernel/acpi/boot.c searches
for a RSDP signature, and returns the first one it finds. If this
does not have a valid checksum, acpi_table_init() will return an error
(and since 2.6.2, this causes ACPI not to be initialised)
ACPI spec 2.0c, section 5.4.2.1 says:
"OSPM finds the Root System Description Pointer (RSDP) structure by
searching physical memory ranges on 16-byte boundaries for a valid Root
System Description Pointer structure signature and checksum match"
It's at least arguably correct to contine the search until a RSDP
signature and valid checksum is found.
The attached patch against 2.6.3 demonstrates a (not-very-good) way of
doing this.
(It also adds a printk which reports when ACPI is disabled because the
RSDP is invalid)
extract from dmesg without patch:
ACPI: RSDP (v000 Acer ) @ 0x000ec2d0
>>> ERROR: Invalid checksum
extract from dmesg with patch:
ACPI: RSDP (v000 Acer ) @ 0x000fe030
ACPI: RSDT (v001 Acer TM100 0x00000001 MSFT 0x00000001) @ 0x0ffe0000
ACPI: FADT (v001 Acer TM100 0x00000001 MSFT 0x00000001) @ 0x0ffe0054
ACPI: BOOT (v001 Acer TM100 0x00000001 MSFT 0x00000001) @ 0x0ffe002c
ACPI: DSDT (v001 Acer AN100 0x00001000 MSFT 0x0100000e) @ 0x000000002
[-- Attachment #2: acpi_rsdp_check.diff --]
[-- Type: text/plain, Size: 3102 bytes --]
diff -Naur -X exclude linux-2.6.3/arch/i386/kernel/acpi/boot.c linux-2.6.3-acpi-table-fix/arch/i386/kernel/acpi/boot.c
--- linux-2.6.3/arch/i386/kernel/acpi/boot.c 2004-02-19 14:01:00.000000000 +0000
+++ linux-2.6.3-acpi-table-fix/arch/i386/kernel/acpi/boot.c 2004-02-19 20:41:03.000000000 +0000
@@ -341,7 +341,10 @@
for (offset = 0; offset < length; offset += 16) {
if (strncmp((char *) (start + offset), "RSD PTR ", sig_len))
continue;
- return (start + offset);
+
+ /* Check for valid checksum */
+ if (acpi_checksum_rsdp((struct acpi_table_rsdp *)(start+offset)) == 0)
+ return (start + offset);
}
return 0;
@@ -388,8 +391,9 @@
return __pa(efi.acpi);
}
/*
- * Scan memory looking for the RSDP signature. First search EBDA (low
- * memory) paragraphs and then search upper memory (E0000-FFFFF).
+ * Scan memory looking for the RSDP signature and valid checksum.
+ * First search EBDA (low memory) paragraphs and then search
+ * upper memory (E0000-FFFFF).
*/
rsdp_phys = acpi_scan_rsdp (0, 0x400);
if (!rsdp_phys)
@@ -437,6 +441,7 @@
*/
result = acpi_table_init();
if (result) {
+ printk(KERN_WARNING PREFIX "Malformed ACPI tables, disabling ACPI support\n");
acpi_disabled = 1;
return result;
}
diff -Naur -X exclude linux-2.6.3/drivers/acpi/tables.c linux-2.6.3-acpi-table-fix/drivers/acpi/tables.c
--- linux-2.6.3/drivers/acpi/tables.c 2004-02-19 14:01:09.000000000 +0000
+++ linux-2.6.3-acpi-table-fix/drivers/acpi/tables.c 2004-02-19 16:29:47.000000000 +0000
@@ -550,13 +550,24 @@
return 0;
}
+int __init
+acpi_checksum_rsdp(struct acpi_table_rsdp *rsdp)
+{
+ int result = 0;
+
+ if (rsdp->revision < 2)
+ result = acpi_table_compute_checksum(rsdp, sizeof(struct acpi_table_rsdp));
+ else
+ result = acpi_table_compute_checksum(rsdp, ((struct acpi20_table_rsdp *)rsdp)->length);
+
+ return result;
+}
int __init
acpi_table_init (void)
{
struct acpi_table_rsdp *rsdp = NULL;
unsigned long rsdp_phys = 0;
- int result = 0;
/* Locate and map the Root System Description Table (RSDP) */
@@ -575,12 +586,7 @@
printk(KERN_INFO PREFIX "RSDP (v%3.3d %6.6s ) @ 0x%p\n",
rsdp->revision, rsdp->oem_id, (void *) rsdp_phys);
- if (rsdp->revision < 2)
- result = acpi_table_compute_checksum(rsdp, sizeof(struct acpi_table_rsdp));
- else
- result = acpi_table_compute_checksum(rsdp, ((struct acpi20_table_rsdp *)rsdp)->length);
-
- if (result) {
+ if (acpi_checksum_rsdp(rsdp)) {
printk(KERN_WARNING " >>> ERROR: Invalid checksum\n");
return -ENODEV;
}
diff -Naur -X exclude linux-2.6.3/include/linux/acpi.h linux-2.6.3-acpi-table-fix/include/linux/acpi.h
--- linux-2.6.3/include/linux/acpi.h 2004-02-19 14:01:40.000000000 +0000
+++ linux-2.6.3-acpi-table-fix/include/linux/acpi.h 2004-02-19 18:13:11.000000000 +0000
@@ -349,6 +349,7 @@
char * __acpi_map_table (unsigned long phys_addr, unsigned long size);
unsigned long acpi_find_rsdp (void);
+int acpi_checksum_rsdp(struct acpi_table_rsdp *rsdp);
int acpi_boot_init (void);
int acpi_numa_init (void);
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2004-02-19 22:11 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-02-19 22:11 acpi_scan_rsdp() in arch/i386/kernel/acpi/boot.c Jon TURNEY
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox