diff --git a/src/lib.rs b/src/lib.rs index feb69593..a898f5cd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -112,15 +112,12 @@ where } let rsdp_revision = rsdp_mapping.revision(); - let rsdt_address = if rsdp_revision == 0 { - // We're running on ACPI Version 1.0. We should use the 32-bit RSDT address. - rsdp_mapping.rsdt_address() as usize - } else { - /* - * We're running on ACPI Version 2.0+. We should use the 64-bit XSDT address, truncated - * to 32 bits on x86. - */ + // Use XSDT only when revision > 1, following Linux (tbutils.c). + // revision == 0 and revision == 1 both use the 32-bit RSDT address. + let rsdt_address = if rsdp_revision > 1 { rsdp_mapping.xsdt_address() as usize + } else { + rsdp_mapping.rsdt_address() as usize }; unsafe { Self::from_rsdt(handler, rsdp_revision, rsdt_address) } diff --git a/src/rsdp.rs b/src/rsdp.rs index 6cc37c2c..61c522a2 100644 --- a/src/rsdp.rs +++ b/src/rsdp.rs @@ -3,6 +3,8 @@ use core::{mem, ops::Range, slice, str}; /// The size in bytes of the ACPI 1.0 RSDP. const RSDP_V1_LENGTH: usize = 20; +/// The size in bytes covered by the ACPI 2.0+ extended checksum (mirrors Linux ACPI_RSDP_XCHECKSUM_LENGTH). +const RSDP_XCHECKSUM_LENGTH: usize = 36; /// The total size in bytes of the RSDP fields introduced in ACPI 2.0. const RSDP_V2_EXT_LENGTH: usize = mem::size_of::() - RSDP_V1_LENGTH; @@ -114,10 +116,11 @@ impl Rsdp { /* * `self.length` doesn't exist on ACPI version 1.0, so we mustn't rely on it. Instead, * check for version 1.0 and use a hard-coded length instead. + * + * For Version 2.0+, use the Linux's ACPI_RSDP_XCHECKSUM_LENGTH. */ - let length = if self.revision > 0 { - // For Version 2.0+, include the number of bytes specified by `length` - self.length as usize + let length = if self.revision > 1 { + RSDP_XCHECKSUM_LENGTH } else { RSDP_V1_LENGTH };