Selaa lähdekoodia

Add start of constructed-table test harness

Isaac Woods 7 vuotta sitten
vanhempi
commit
6fa81133b7
2 muutettua tiedostoa jossa 126 lisäystä ja 0 poistoa
  1. 86 0
      src/lib.rs
  2. 40 0
      src/rsdp.rs

+ 86 - 0
src/lib.rs

@@ -71,3 +71,89 @@ pub fn parse_acpi<T>(handler : &mut T, rsdp_address : usize) -> Result<(), AcpiE
     handler.unmap_physical_region(rsdp_mapping);
     Ok(())
 }
+
+/// This module tests against idealistic sets of ACPI tables, which we construct on the fly. This
+/// should cover all standard-compliant implementations eventually, but does not guarantee we can
+/// handle all hardware's tables, obviously.
+#[cfg(test)]
+mod constructed_table_tests
+{
+    use std::mem;
+    use std::ptr::NonNull;
+    use std::boxed::Box;
+    use {AcpiHandler, PhysicalMapping, parse_acpi, rsdp::Rsdp};
+
+    const OEM_ID : &[u8; 6] = b"RUST  ";
+
+    /*
+     * We use fake physical addresses to track what is being requested. When a particular table or
+     * resource is requested, we just allocate it on the heap and return the "virtual address"
+     * (a pointer onto the heap).
+     */
+    const RSDP_ADDRESS : usize = 0x0;
+    const RSDT_ADDRESS : usize = 0x1;
+
+    struct TestHandler { }
+
+    impl AcpiHandler for TestHandler
+    {
+        fn map_physical_region<T>(&mut self, physical_address : usize) -> PhysicalMapping<T>
+        {
+            match physical_address
+            {
+                RSDP_ADDRESS =>
+                {
+                    let rsdp = Rsdp::make_testcase(*b"RSD PTR ",
+                                                   None,
+                                                   *OEM_ID,
+                                                   0,
+                                                   RSDT_ADDRESS as u32,
+                                                   0,
+                                                   0x0,
+                                                   None,
+                                                   [0, 0, 0]
+                                                  );
+
+                    PhysicalMapping
+                    {
+                        physical_start  : RSDP_ADDRESS,
+                        virtual_start   : unsafe
+                                          {
+                                              NonNull::<T>::new_unchecked(Box::into_raw(Box::new(rsdp)) as *mut T)
+                                          },
+                        mapped_length   : mem::size_of::<Rsdp>(),
+                    }
+                },
+
+                _ => panic!("ACPI requested invalid physical address: {:#x}", physical_address),
+            }
+        }
+
+        fn unmap_physical_region<T>(&mut self, region : PhysicalMapping<T>)
+        {
+            match region.physical_start
+            {
+                RSDP_ADDRESS =>
+                {
+                    let _ = unsafe { Box::from_raw(region.virtual_start.as_ptr()) };
+                },
+
+                address => panic!("ACPI tried to unmap a region not created by test harness: {:#x}", address),
+            }
+        }
+    }
+
+    #[test]
+    fn test_constructed_tables()
+    {
+        let mut test_handler = TestHandler { };
+        match parse_acpi(&mut test_handler, RSDP_ADDRESS)
+        {
+            Ok(_) => (),
+            Err(err) =>
+            {
+                panic!("Failed to parse ACPI: {:#?}", err);
+            },
+        }
+    }
+}

+ 40 - 0
src/rsdp.rs

@@ -104,4 +104,44 @@ impl Rsdp
         assert!(self.revision > 0, "Tried to read extended RSDP field with ACPI Version 1.0");
         self.xsdt_address
     }
+
+    /// Create a test RSDP. Checksums are passed as `Option<u8>`; if `None` is passed, the correct
+    /// checksum is calculated and used.
+    #[cfg(test)]
+    pub fn make_testcase(signature      : [u8; 8],
+                         checksum       : Option<u8>,
+                         oem_id         : [u8; 6],
+                         revision       : u8,
+                         rsdt_address   : u32,
+                         length         : u32,
+                         xsdt_address   : u64,
+                         ext_checksum   : Option<u8>,
+                         reserved       : [u8; 3]) -> Rsdp
+    {
+        let checksum = checksum.unwrap_or(((0isize -
+                                            signature.iter().map(|&b| isize::from(b)).sum::<isize>() -
+                                            oem_id.iter().map(|&b| isize::from(b)).sum::<isize>() -
+                                            revision as isize -
+                                            rsdt_address as isize
+                                           ) & 0b1111_1111) as u8);
+
+        let ext_checksum = ext_checksum.unwrap_or(((0isize -
+                                                    length as isize -
+                                                    xsdt_address as isize -
+                                                    reserved.iter().map(|&b| isize::from(b)).sum::<isize>()
+                                                   ) & 0b1111_1111) as u8);
+
+        Rsdp
+        {
+            signature,
+            checksum,
+            oem_id,
+            revision,
+            rsdt_address,
+            length,
+            xsdt_address,
+            ext_checksum,
+            reserved,
+        }
+    }
 }