ソースを参照

Make dealing with SDT signatures easier

Isaac Woods 5 年 前
コミット
2840529c19
6 ファイル変更59 行追加27 行削除
  1. 1 1
      acpi/src/fadt.rs
  2. 1 1
      acpi/src/hpet.rs
  3. 10 8
      acpi/src/lib.rs
  4. 1 1
      acpi/src/madt.rs
  5. 1 1
      acpi/src/mcfg.rs
  6. 45 15
      acpi/src/sdt.rs

+ 1 - 1
acpi/src/fadt.rs

@@ -88,7 +88,7 @@ where
     H: AcpiHandler,
 {
     let fadt = &*mapping;
-    fadt.header.validate(b"FACP")?;
+    fadt.header.validate(crate::sdt::Signature::FADT)?;
 
     let dsdt_address = unsafe {
         fadt.x_dsdt_address

+ 1 - 1
acpi/src/hpet.rs

@@ -34,7 +34,7 @@ pub(crate) struct HpetTable {
 }
 
 pub(crate) fn parse_hpet(acpi: &mut Acpi, mapping: &PhysicalMapping<HpetTable>) -> Result<(), AcpiError> {
-    (*mapping).header.validate(b"HPET")?;
+    (*mapping).header.validate(crate::sdt::Signature::HPET)?;
     let hpet = &*mapping;
 
     // Make sure the HPET's in system memory

+ 10 - 8
acpi/src/lib.rs

@@ -48,22 +48,24 @@ pub use crate::{
     rsdp_search::search_for_rsdp_bios,
 };
 
-use crate::{rsdp::Rsdp, sdt::SdtHeader};
+use crate::{
+    rsdp::Rsdp,
+    sdt::{SdtHeader, Signature},
+};
 use alloc::vec::Vec;
 use core::mem;
 
 #[derive(Debug)]
-// TODO: manually implement Debug to print signatures correctly etc.
 pub enum AcpiError {
     RsdpIncorrectSignature,
     RsdpInvalidOemId,
     RsdpInvalidChecksum,
     NoValidRsdp,
 
-    SdtInvalidSignature([u8; 4]),
-    SdtInvalidOemId([u8; 4]),
-    SdtInvalidTableId([u8; 4]),
-    SdtInvalidChecksum([u8; 4]),
+    SdtInvalidSignature(Signature),
+    SdtInvalidOemId(Signature),
+    SdtInvalidTableId(Signature),
+    SdtInvalidChecksum(Signature),
 
     InvalidMadt(MadtError),
 }
@@ -216,7 +218,7 @@ where
         /*
          * ACPI Version 1.0. It's a RSDT!
          */
-        (*mapping).validate(b"RSDT")?;
+        (*mapping).validate(sdt::Signature::RSDT)?;
 
         let num_tables = ((*mapping).length as usize - mem::size_of::<SdtHeader>()) / mem::size_of::<u32>();
         let tables_base = ((mapping.virtual_start.as_ptr() as usize) + mem::size_of::<SdtHeader>()) as *const u32;
@@ -228,7 +230,7 @@ where
         /*
          * ACPI Version 2.0+. It's a XSDT!
          */
-        (*mapping).validate(b"XSDT")?;
+        (*mapping).validate(sdt::Signature::XSDT)?;
 
         let num_tables = ((*mapping).length as usize - mem::size_of::<SdtHeader>()) / mem::size_of::<u64>();
         let tables_base = ((mapping.virtual_start.as_ptr() as usize) + mem::size_of::<SdtHeader>()) as *const u64;

+ 1 - 1
acpi/src/madt.rs

@@ -337,7 +337,7 @@ pub(crate) fn parse_madt<H>(
 where
     H: AcpiHandler,
 {
-    (*mapping).header.validate(b"APIC")?;
+    (*mapping).header.validate(crate::sdt::Signature::MADT)?;
 
     /*
      * If the MADT doesn't contain another supported interrupt model (either APIC, SAPIC, X2APIC

+ 1 - 1
acpi/src/mcfg.rs

@@ -66,7 +66,7 @@ struct McfgEntry {
 }
 
 pub(crate) fn parse_mcfg(acpi: &mut Acpi, mapping: &PhysicalMapping<Mcfg>) -> Result<(), AcpiError> {
-    (*mapping).header.validate(b"MCFG")?;
+    (*mapping).header.validate(crate::sdt::Signature::MCFG)?;
 
     acpi.pci_config_regions =
         Some(PciConfigRegions { regions: mapping.entries().iter().map(|&entry| entry).collect() });

+ 45 - 15
acpi/src/sdt.rs

@@ -1,5 +1,5 @@
 use crate::{fadt::Fadt, hpet::HpetTable, madt::Madt, mcfg::Mcfg, Acpi, AcpiError, AcpiHandler, AmlTable};
-use core::{mem, mem::MaybeUninit, str};
+use core::{fmt, mem, mem::MaybeUninit, str};
 use log::{trace, warn};
 
 pub const ACPI_VERSION_2_0: u8 = 20;
@@ -60,7 +60,7 @@ impl<T: Copy, const MIN_VERSION: u8> ExtendedField<T, MIN_VERSION> {
 #[derive(Clone, Copy)]
 #[repr(C, packed)]
 pub struct SdtHeader {
-    signature: [u8; 4],
+    pub signature: Signature,
     pub length: u32,
     pub revision: u8,
     pub checksum: u8,
@@ -77,20 +77,20 @@ impl SdtHeader {
     ///     b) The checksum of the SDT
     ///
     /// This assumes that the whole SDT is mapped.
-    pub fn validate(&self, signature: &[u8; 4]) -> Result<(), AcpiError> {
+    pub fn validate(&self, signature: Signature) -> Result<(), AcpiError> {
         // Check the signature
-        if &self.signature != signature {
-            return Err(AcpiError::SdtInvalidSignature(*signature));
+        if self.signature != signature {
+            return Err(AcpiError::SdtInvalidSignature(signature));
         }
 
         // Check the OEM id
         if str::from_utf8(&self.oem_id).is_err() {
-            return Err(AcpiError::SdtInvalidOemId(*signature));
+            return Err(AcpiError::SdtInvalidOemId(signature));
         }
 
         // Check the OEM table id
         if str::from_utf8(&self.oem_table_id).is_err() {
-            return Err(AcpiError::SdtInvalidTableId(*signature));
+            return Err(AcpiError::SdtInvalidTableId(signature));
         }
 
         // Validate the checksum
@@ -101,7 +101,7 @@ impl SdtHeader {
         }
 
         if sum > 0 {
-            return Err(AcpiError::SdtInvalidChecksum(*signature));
+            return Err(AcpiError::SdtInvalidChecksum(signature));
         }
 
         Ok(())
@@ -118,6 +118,36 @@ impl SdtHeader {
     }
 }
 
+#[derive(Clone, Copy, PartialEq, Eq)]
+#[repr(transparent)]
+pub struct Signature([u8; 4]);
+
+impl Signature {
+    pub const RSDT: Signature = Signature(*b"RSDT");
+    pub const XSDT: Signature = Signature(*b"XSDT");
+    pub const FADT: Signature = Signature(*b"FACP");
+    pub const HPET: Signature = Signature(*b"HPET");
+    pub const MADT: Signature = Signature(*b"APIC");
+    pub const MCFG: Signature = Signature(*b"MCFG");
+    pub const SSDT: Signature = Signature(*b"SSDT");
+
+    pub fn as_str(&self) -> &str {
+        str::from_utf8(&self.0).unwrap()
+    }
+}
+
+impl fmt::Display for Signature {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{}", self.as_str())
+    }
+}
+
+impl fmt::Debug for Signature {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "\"{}\"", self.as_str())
+    }
+}
+
 /// Takes the physical address of an SDT, and maps, clones and unmaps its header. Useful for
 /// finding out how big it is to map it correctly later.
 pub(crate) fn peek_at_sdt_header<H>(handler: &mut H, physical_address: usize) -> SdtHeader
@@ -144,33 +174,33 @@ where
      * For a recognised signature, a new physical mapping should be created with the correct type
      * and length, and then the dispatched to the correct function to actually parse the table.
      */
-        "FACP" => {
     match header.signature {
+        Signature::FADT => {
             let fadt_mapping = handler.map_physical_region::<Fadt>(physical_address, mem::size_of::<Fadt>());
             crate::fadt::parse_fadt(acpi, handler, &fadt_mapping)?;
             handler.unmap_physical_region(fadt_mapping);
         }
 
-        "HPET" => {
+        Signature::HPET => {
             let hpet_mapping =
                 handler.map_physical_region::<HpetTable>(physical_address, mem::size_of::<HpetTable>());
             crate::hpet::parse_hpet(acpi, &hpet_mapping)?;
             handler.unmap_physical_region(hpet_mapping);
         }
 
-        "APIC" => {
-            let madt_mapping = handler.map_physical_region::<Madt>(physical_address, header.length() as usize);
+        Signature::MADT => {
+            let madt_mapping = handler.map_physical_region::<Madt>(physical_address, header.length as usize);
             crate::madt::parse_madt(acpi, handler, &madt_mapping)?;
             handler.unmap_physical_region(madt_mapping);
         }
 
-        "MCFG" => {
-            let mcfg_mapping = handler.map_physical_region::<Mcfg>(physical_address, header.length() as usize);
+        Signature::MCFG => {
+            let mcfg_mapping = handler.map_physical_region::<Mcfg>(physical_address, header.length as usize);
             crate::mcfg::parse_mcfg(acpi, &mcfg_mapping)?;
             handler.unmap_physical_region(mcfg_mapping);
         }
 
-        "SSDT" => acpi.ssdts.push(AmlTable::new(physical_address, header.length())),
+        Signature::SSDT => acpi.ssdts.push(AmlTable::new(physical_address, header.length)),
 
         signature => {
             /*