浏览代码

Create internal manager object and generalise AML table

Isaac Woods 6 年之前
父节点
当前提交
e8d8994cf4
共有 5 个文件被更改,包括 104 次插入57 次删除
  1. 46 0
      src/aml/mod.rs
  2. 0 29
      src/dsdt.rs
  3. 13 9
      src/fadt.rs
  4. 31 9
      src/lib.rs
  5. 14 10
      src/sdt.rs

+ 46 - 0
src/aml/mod.rs

@@ -0,0 +1,46 @@
+use core::{mem, slice};
+use sdt::SdtHeader;
+use {Acpi, AcpiError, AcpiHandler, PhysicalMapping};
+
+/// Represents a table containing AML. For ACPI Version 2+, this is just the DSDT and SSDTs.
+/// Version 1.0 may also have a PSDT.
+#[repr(C, packed)]
+pub struct AmlTable {
+    header: SdtHeader,
+    // ...
+}
+
+pub struct AmlStream<'a> {
+    data: &'a [u8],
+    count: usize,
+}
+
+impl AmlTable {
+    /// Get the AML stream encoded in this table so it can be safely accessed
+    pub fn stream<'a>(&'a self) -> AmlStream<'a> {
+        assert!(self.header.length() as usize > mem::size_of::<SdtHeader>());
+        let stream_length = self.header.length() as usize - mem::size_of::<SdtHeader>();
+        let stream_ptr =
+            ((self as *const AmlTable as usize) + mem::size_of::<SdtHeader>()) as *const u8;
+
+        AmlStream {
+            data: unsafe { slice::from_raw_parts(stream_ptr, stream_length) },
+            count: 0,
+        }
+    }
+}
+
+pub(crate) fn parse_aml_table<'a, H>(
+    acpi: &mut Acpi<'a, H>,
+    mapping: &PhysicalMapping<AmlTable>,
+    signature: &[u8; 4],
+) -> Result<(), AcpiError>
+where
+    H: AcpiHandler + 'a,
+{
+    (*mapping).header.validate(signature)?;
+
+    let stream = (*mapping).stream();
+    // TODO: pass off to the AML parser
+    unimplemented!();
+}

+ 0 - 29
src/dsdt.rs

@@ -1,29 +0,0 @@
-use core::{mem, slice};
-use sdt::SdtHeader;
-use {AcpiError, PhysicalMapping};
-
-/// Represents the Differentiated Definition Block (DSDT). This table contains the standard header,
-/// then an AML-encoded definition block.
-#[repr(C, packed)]
-pub struct Dsdt {
-    header: SdtHeader,
-}
-
-impl Dsdt {
-    /// Get the AML stream encoded in this table so it can be safely accessed
-    pub fn stream(&self) -> &[u8] {
-        assert!(self.header.length() as usize > mem::size_of::<SdtHeader>());
-        let stream_length = self.header.length() as usize - mem::size_of::<SdtHeader>();
-        let stream_ptr =
-            ((self as *const Dsdt as usize) + mem::size_of::<SdtHeader>()) as *const u8;
-        unsafe { slice::from_raw_parts(stream_ptr, stream_length) }
-    }
-}
-
-pub fn parse_dsdt(mapping: &PhysicalMapping<Dsdt>) -> Result<(), AcpiError> {
-    (*mapping).header.validate(b"DSDT")?;
-
-    let stream = (*mapping).stream();
-    // TODO: pass off to the AML parser
-    unimplemented!();
-}

+ 13 - 9
src/fadt.rs

@@ -1,7 +1,7 @@
-use dsdt::{parse_dsdt, Dsdt};
+use aml::{parse_aml_table, AmlTable};
 use sdt;
 use sdt::SdtHeader;
-use {AcpiError, AcpiHandler, GenericAddress, PhysicalMapping};
+use {Acpi, AcpiError, AcpiHandler, GenericAddress, PhysicalMapping};
 
 /// Represents the Fixed ACPI Description Table (FADT). This table contains various fixed hardware
 /// details, such as the addresses of the hardware register blocks. It also contains a pointer to
@@ -74,9 +74,12 @@ pub struct Fadt {
     hypervisor_vendor_id: u64,
 }
 
-pub fn parse_fadt<H>(handler: &mut H, mapping: &PhysicalMapping<Fadt>) -> Result<(), AcpiError>
+pub(crate) fn parse_fadt<'a, H>(
+    acpi: &mut Acpi<'a, H>,
+    mapping: &PhysicalMapping<Fadt>,
+) -> Result<(), AcpiError>
 where
-    H: AcpiHandler,
+    H: AcpiHandler + 'a,
 {
     (*mapping).header.validate(b"FACP")?;
 
@@ -87,11 +90,12 @@ where
     };
 
     // Parse the DSDT
-    let dsdt_header = sdt::peek_at_sdt_header(handler, dsdt_physical_address);
-    let dsdt_mapping =
-        handler.map_physical_region::<Dsdt>(dsdt_physical_address, dsdt_header.length() as usize);
-    parse_dsdt(&dsdt_mapping)?;
-    handler.unmap_physical_region(dsdt_mapping);
+    let dsdt_header = sdt::peek_at_sdt_header(acpi.handler, dsdt_physical_address);
+    let dsdt_mapping = acpi
+        .handler
+        .map_physical_region::<AmlTable>(dsdt_physical_address, dsdt_header.length() as usize);
+    parse_aml_table(acpi, &dsdt_mapping, b"DSDT")?;
+    acpi.handler.unmap_physical_region(dsdt_mapping);
 
     Ok(())
 }

+ 31 - 9
src/lib.rs

@@ -1,4 +1,5 @@
 #![no_std]
+#![feature(alloc)]
 
 #[cfg(test)]
 #[macro_use]
@@ -6,19 +7,23 @@ extern crate std;
 
 #[macro_use]
 extern crate log;
+extern crate alloc;
 
-mod dsdt;
+mod aml;
 mod fadt;
 mod hpet;
 mod rsdp;
 mod sdt;
 
+use alloc::{BTreeMap, String};
 use core::mem;
 use core::ops::Deref;
 use core::ptr::NonNull;
 use rsdp::Rsdp;
 use sdt::SdtHeader;
 
+pub struct AmlValue; // TODO: temp
+
 #[derive(Debug)]
 // TODO: manually implement Debug to print signatures correctly etc.
 pub enum AcpiError {
@@ -30,8 +35,6 @@ pub enum AcpiError {
     SdtInvalidOemId([u8; 4]),
     SdtInvalidTableId([u8; 4]),
     SdtInvalidChecksum([u8; 4]),
-
-    FadtIncorrectSignature,
 }
 
 #[repr(C, packed)]
@@ -82,6 +85,16 @@ pub trait AcpiHandler {
     fn unmap_physical_region<T>(&mut self, region: PhysicalMapping<T>);
 }
 
+/// This struct manages the internal state of `acpi`. It is not visible to the user of the library.
+pub(crate) struct Acpi<'a, H>
+where
+    H: AcpiHandler + 'a,
+{
+    handler: &'a mut H,
+    acpi_revision: u8,
+    namespace: BTreeMap<String, AmlValue>,
+}
+
 /// This is the entry point of `acpi` if you have the **physical** address of the RSDP. It maps
 /// the RSDP, works out what version of ACPI the hardware supports, and passes the physical
 /// address of the RSDT/XSDT to `parse_rsdt`.
@@ -127,9 +140,16 @@ pub fn parse_rsdt<H>(
 where
     H: AcpiHandler,
 {
-    let header = sdt::peek_at_sdt_header(handler, physical_address);
-    let mapping =
-        handler.map_physical_region::<SdtHeader>(physical_address, header.length() as usize);
+    let mut acpi = Acpi {
+        handler,
+        acpi_revision: revision,
+        namespace: BTreeMap::new(),
+    };
+
+    let header = sdt::peek_at_sdt_header(acpi.handler, physical_address);
+    let mapping = acpi
+        .handler
+        .map_physical_region::<SdtHeader>(physical_address, header.length() as usize);
 
     if revision == 0 {
         /*
@@ -143,7 +163,8 @@ where
             ((mapping.virtual_start.as_ptr() as usize) + mem::size_of::<SdtHeader>()) as *const u32;
 
         for i in 0..num_tables {
-            sdt::dispatch_sdt(handler, unsafe { *tables_base.offset(i as isize) } as usize)?;
+            sdt::dispatch_sdt(&mut acpi, unsafe { *tables_base.offset(i as isize) }
+                as usize)?;
         }
     } else {
         /*
@@ -157,11 +178,12 @@ where
             ((mapping.virtual_start.as_ptr() as usize) + mem::size_of::<SdtHeader>()) as *const u64;
 
         for i in 0..num_tables {
-            sdt::dispatch_sdt(handler, unsafe { *tables_base.offset(i as isize) } as usize)?;
+            sdt::dispatch_sdt(&mut acpi, unsafe { *tables_base.offset(i as isize) }
+                as usize)?;
         }
     }
 
-    handler.unmap_physical_region(mapping);
+    acpi.handler.unmap_physical_region(mapping);
     Ok(())
 }
 

+ 14 - 10
src/sdt.rs

@@ -1,7 +1,7 @@
 use core::{mem, str};
 use fadt::Fadt;
 use hpet::Hpet;
-use {AcpiError, AcpiHandler};
+use {Acpi, AcpiError, AcpiHandler};
 
 /// All SDTs share the same header, and are `length` bytes long. The signature tells us which SDT
 /// this is.
@@ -155,11 +155,14 @@ where
 
 /// This takes the physical address of an SDT, maps it correctly and dispatches it to whatever
 /// function parses that table.
-pub(crate) fn dispatch_sdt<H>(handler: &mut H, physical_address: usize) -> Result<(), AcpiError>
+pub(crate) fn dispatch_sdt<'a, H>(
+    acpi: &mut Acpi<'a, H>,
+    physical_address: usize,
+) -> Result<(), AcpiError>
 where
-    H: AcpiHandler,
+    H: AcpiHandler + 'a,
 {
-    let header = peek_at_sdt_header(handler, physical_address);
+    let header = peek_at_sdt_header(acpi.handler, physical_address);
     info!(
         "Dispatching SDT with signature {:?} and length {:?}",
         header.signature(),
@@ -172,16 +175,17 @@ where
      */
     match header.signature() {
         "FACP" => {
-            let fadt_mapping =
-                handler.map_physical_region::<Fadt>(physical_address, mem::size_of::<Fadt>());
-            ::fadt::parse_fadt(handler, &fadt_mapping)?;
-            handler.unmap_physical_region(fadt_mapping);
+            let fadt_mapping = acpi
+                .handler
+                .map_physical_region::<Fadt>(physical_address, mem::size_of::<Fadt>());
+            ::fadt::parse_fadt(acpi, &fadt_mapping)?;
+            acpi.handler.unmap_physical_region(fadt_mapping);
         }
 
         "HPET" => {
-            let hpet_mapping = handler.map_physical_region::<Hpet>(physical_address);
+            let hpet_mapping = acpi.handler.map_physical_region::<Hpet>(physical_address);
             ::hpet::parse_hpet(&hpet_mapping)?;
-            handler.unmap_physical_region(hpet_mapping);
+            acpi.handler.unmap_physical_region(hpet_mapping);
         }
 
         signature => {