|
@@ -1,4 +1,5 @@
|
|
-use core::mem;
|
|
|
|
|
|
+use core::{str,mem};
|
|
|
|
+use super::AcpiError;
|
|
|
|
|
|
/// The first structure found in ACPI. It just tells us where the RSDT is.
|
|
/// The first structure found in ACPI. It just tells us where the RSDT is.
|
|
///
|
|
///
|
|
@@ -8,14 +9,25 @@ use core::mem;
|
|
///
|
|
///
|
|
/// The recommended way of locating the RSDP is to let the bootloader do it - Multiboot2 can pass a
|
|
/// The recommended way of locating the RSDP is to let the bootloader do it - Multiboot2 can pass a
|
|
/// tag with the physical address of it. If this is not possible, a manual scan can be done.
|
|
/// tag with the physical address of it. If this is not possible, a manual scan can be done.
|
|
|
|
+///
|
|
|
|
+/// If `revision > 0`, (the hardware ACPI version is Version 2.0 or greater), the RSDP contains
|
|
|
|
+/// some new fields. For ACPI Version 1.0, these fields are not valid and should not be accessed.
|
|
#[repr(C, packed)]
|
|
#[repr(C, packed)]
|
|
-pub struct Rsdp
|
|
|
|
|
|
+pub(crate) struct Rsdp
|
|
{
|
|
{
|
|
- pub(crate) signature : [u8; 8],
|
|
|
|
- pub(crate) checksum : u8,
|
|
|
|
- pub(crate) oem_id : [u8; 6],
|
|
|
|
- pub(crate) revision : u8,
|
|
|
|
- pub(crate) rsdt_address : u32,
|
|
|
|
|
|
+ signature : [u8; 8],
|
|
|
|
+ checksum : u8,
|
|
|
|
+ oem_id : [u8; 6],
|
|
|
|
+ revision : u8,
|
|
|
|
+ rsdt_address : u32,
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * These fields are only valid for ACPI Version 2.0 and greater
|
|
|
|
+ */
|
|
|
|
+ length : u32,
|
|
|
|
+ xsdt_address : u64,
|
|
|
|
+ ext_checksum : u8,
|
|
|
|
+ reserved : [u8; 3],
|
|
}
|
|
}
|
|
|
|
|
|
impl Rsdp
|
|
impl Rsdp
|
|
@@ -24,7 +36,7 @@ impl Rsdp
|
|
/// 1) The signature is correct
|
|
/// 1) The signature is correct
|
|
/// 2) The checksum is correct
|
|
/// 2) The checksum is correct
|
|
/// 3) For Version 2.0+, that the extension checksum is correct
|
|
/// 3) For Version 2.0+, that the extension checksum is correct
|
|
- pub(crate) fn validate(&self) -> Result<(), &str>
|
|
|
|
|
|
+ pub(crate) fn validate(&self) -> Result<(), AcpiError>
|
|
{
|
|
{
|
|
// FIXME: Check what version of ACPI this is. This works for Version 1.0 (revision=0), but
|
|
// FIXME: Check what version of ACPI this is. This works for Version 1.0 (revision=0), but
|
|
// for subsequent versions, we also need to check the checksum for the extension fields.
|
|
// for subsequent versions, we also need to check the checksum for the extension fields.
|
|
@@ -34,7 +46,13 @@ impl Rsdp
|
|
// Check the signature
|
|
// Check the signature
|
|
if &self.signature != b"RSD PTR "
|
|
if &self.signature != b"RSD PTR "
|
|
{
|
|
{
|
|
- return Err("RSDP has incorrect signature");
|
|
|
|
|
|
+ return Err(AcpiError::RsdpIncorrectSignature);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Check the OEM id is valid UTF8 (allows use of unwrap)
|
|
|
|
+ if str::from_utf8(&self.oem_id).is_err()
|
|
|
|
+ {
|
|
|
|
+ return Err(AcpiError::RsdpInvalidOemId);
|
|
}
|
|
}
|
|
|
|
|
|
// Sum all bytes in the structure
|
|
// Sum all bytes in the structure
|
|
@@ -47,9 +65,30 @@ impl Rsdp
|
|
// Check that the lowest byte is 0
|
|
// Check that the lowest byte is 0
|
|
if sum & 0b1111_1111 != 0
|
|
if sum & 0b1111_1111 != 0
|
|
{
|
|
{
|
|
- return Err("RSDP has incorrect checksum");
|
|
|
|
|
|
+ return Err(AcpiError::RsdpInvalidChecksum);
|
|
}
|
|
}
|
|
|
|
|
|
Ok(())
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ pub(crate) fn oem_id<'a>(&'a self) -> &'a str
|
|
|
|
+ {
|
|
|
|
+ str::from_utf8(&self.oem_id).unwrap()
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ pub(crate) fn revision(&self) -> u8
|
|
|
|
+ {
|
|
|
|
+ self.revision
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ pub(crate) fn rsdt_address(&self) -> u32
|
|
|
|
+ {
|
|
|
|
+ self.rsdt_address
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ pub(crate) fn xsdt_address(&self) -> u64
|
|
|
|
+ {
|
|
|
|
+ assert!(self.revision > 0, "Tried to read extended RSDP field with ACPI Version 1.0");
|
|
|
|
+ self.xsdt_address
|
|
|
|
+ }
|
|
}
|
|
}
|