|  | @@ -3,11 +3,13 @@
 | 
	
		
			
				|  |  |  #[cfg(test)]
 | 
	
		
			
				|  |  |  extern crate std;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -#[macro_use] extern crate log;
 | 
	
		
			
				|  |  | +#[macro_use]
 | 
	
		
			
				|  |  | +extern crate log;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +#[cfg(test)]
 | 
	
		
			
				|  |  | +mod constructed_tables_test;
 | 
	
		
			
				|  |  |  mod rsdp;
 | 
	
		
			
				|  |  |  mod sdt;
 | 
	
		
			
				|  |  | -#[cfg(test)] mod constructed_tables_test;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  use core::mem;
 | 
	
		
			
				|  |  |  use core::ops::Deref;
 | 
	
	
		
			
				|  | @@ -16,8 +18,7 @@ use rsdp::Rsdp;
 | 
	
		
			
				|  |  |  use sdt::SdtHeader;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #[derive(Debug)]
 | 
	
		
			
				|  |  | -pub enum AcpiError
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | +pub enum AcpiError {
 | 
	
		
			
				|  |  |      RsdpIncorrectSignature,
 | 
	
		
			
				|  |  |      RsdpInvalidOemId,
 | 
	
		
			
				|  |  |      RsdpInvalidChecksum,
 | 
	
	
		
			
				|  | @@ -31,24 +32,18 @@ pub enum AcpiError
 | 
	
		
			
				|  |  |  /// Describes a physical mapping created by `AcpiHandler::map_physical_region` and unmapped by
 | 
	
		
			
				|  |  |  /// `AcpiHandler::unmap_physical_region`. The region mapped must be at least `size_of::<T>()`
 | 
	
		
			
				|  |  |  /// bytes, but may be bigger.
 | 
	
		
			
				|  |  | -pub struct PhysicalMapping<T>
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -    pub physical_start  : usize,
 | 
	
		
			
				|  |  | -    pub virtual_start   : NonNull<T>,
 | 
	
		
			
				|  |  | -    pub region_length   : usize,    // Can be equal or larger than size_of::<T>()
 | 
	
		
			
				|  |  | -    pub mapped_length   : usize,    // Differs from `region_length` if padding is added for alignment
 | 
	
		
			
				|  |  | +pub struct PhysicalMapping<T> {
 | 
	
		
			
				|  |  | +    pub physical_start: usize,
 | 
	
		
			
				|  |  | +    pub virtual_start: NonNull<T>,
 | 
	
		
			
				|  |  | +    pub region_length: usize, // Can be equal or larger than size_of::<T>()
 | 
	
		
			
				|  |  | +    pub mapped_length: usize, // Differs from `region_length` if padding is added for alignment
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -impl<T> Deref for PhysicalMapping<T>
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | +impl<T> Deref for PhysicalMapping<T> {
 | 
	
		
			
				|  |  |      type Target = T;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    fn deref(&self) -> &T
 | 
	
		
			
				|  |  | -    {
 | 
	
		
			
				|  |  | -        unsafe
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            self.virtual_start.as_ref()
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +    fn deref(&self) -> &T {
 | 
	
		
			
				|  |  | +        unsafe { self.virtual_start.as_ref() }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -56,40 +51,37 @@ impl<T> Deref for PhysicalMapping<T>
 | 
	
		
			
				|  |  |  /// utility methods `acpi` uses to for e.g. mapping physical memory, but also an interface for
 | 
	
		
			
				|  |  |  /// `acpi` to tell the kernel about the tables it's parsing, such as how the kernel should
 | 
	
		
			
				|  |  |  /// configure the APIC or PCI routing.
 | 
	
		
			
				|  |  | -pub trait AcpiHandler
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | +pub trait AcpiHandler {
 | 
	
		
			
				|  |  |      /// Given a starting physical address, map a region of physical memory that contains a `T`
 | 
	
		
			
				|  |  |      /// somewhere in the virtual address space. The address doesn't have to be page-aligned, so
 | 
	
		
			
				|  |  |      /// the implementation may have to add padding to either end. The supplied size must be large
 | 
	
		
			
				|  |  |      /// enough to hold a `T`, but may also be larger.
 | 
	
		
			
				|  |  | -    fn map_physical_region<T>(&mut self, physical_address : usize) -> PhysicalMapping<T>;
 | 
	
		
			
				|  |  | +    fn map_physical_region<T>(&mut self, physical_address: usize) -> PhysicalMapping<T>;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      /// Unmap the given physical mapping. Safe because we consume the mapping, and so it can't be
 | 
	
		
			
				|  |  |      /// used after being passed to this function.
 | 
	
		
			
				|  |  | -    fn unmap_physical_region<T>(&mut self, region : PhysicalMapping<T>);
 | 
	
		
			
				|  |  | +    fn unmap_physical_region<T>(&mut self, region: PhysicalMapping<T>);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /// 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`.
 | 
	
		
			
				|  |  | -pub fn parse_rsdp<H>(handler : &mut H, rsdp_address : usize) -> Result<(), AcpiError>
 | 
	
		
			
				|  |  | -    where H : AcpiHandler
 | 
	
		
			
				|  |  | +pub fn parse_rsdp<H>(handler: &mut H, rsdp_address: usize) -> Result<(), AcpiError>
 | 
	
		
			
				|  |  | +where
 | 
	
		
			
				|  |  | +    H: AcpiHandler,
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |      let rsdp_mapping = handler.map_physical_region::<Rsdp>(rsdp_address);
 | 
	
		
			
				|  |  |      (*rsdp_mapping).validate()?;
 | 
	
		
			
				|  |  |      let revision = (*rsdp_mapping).revision();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    if revision == 0
 | 
	
		
			
				|  |  | -    {
 | 
	
		
			
				|  |  | +    if revision == 0 {
 | 
	
		
			
				|  |  |          /*
 | 
	
		
			
				|  |  |           * We're running on ACPI Version 1.0. We should use the 32-bit RSDT address.
 | 
	
		
			
				|  |  |           */
 | 
	
		
			
				|  |  |          let rsdt_address = (*rsdp_mapping).rsdt_address();
 | 
	
		
			
				|  |  |          handler.unmap_physical_region(rsdp_mapping);
 | 
	
		
			
				|  |  |          parse_rsdt(handler, revision, rsdt_address as usize)?;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    else
 | 
	
		
			
				|  |  | -    {
 | 
	
		
			
				|  |  | +    } else {
 | 
	
		
			
				|  |  |          /*
 | 
	
		
			
				|  |  |           * We're running on ACPI Version 2.0+. We should use the 64-bit XSDT address, truncated
 | 
	
		
			
				|  |  |           * to 32 bits on x86.
 | 
	
	
		
			
				|  | @@ -108,10 +100,13 @@ pub fn parse_rsdp<H>(handler : &mut H, rsdp_address : usize) -> Result<(), AcpiE
 | 
	
		
			
				|  |  |  ///
 | 
	
		
			
				|  |  |  /// If the given revision is 0, an address to the RSDT is expected. Otherwise, an address to
 | 
	
		
			
				|  |  |  /// the XSDT is expected.
 | 
	
		
			
				|  |  | -pub fn parse_rsdt<H>(handler            : &mut H,
 | 
	
		
			
				|  |  | -                     revision           : u8,
 | 
	
		
			
				|  |  | -                     physical_address   : usize) -> Result<(), AcpiError>
 | 
	
		
			
				|  |  | -    where H : AcpiHandler
 | 
	
		
			
				|  |  | +pub fn parse_rsdt<H>(
 | 
	
		
			
				|  |  | +    handler: &mut H,
 | 
	
		
			
				|  |  | +    revision: u8,
 | 
	
		
			
				|  |  | +    physical_address: usize,
 | 
	
		
			
				|  |  | +) -> Result<(), AcpiError>
 | 
	
		
			
				|  |  | +where
 | 
	
		
			
				|  |  | +    H: AcpiHandler,
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |      let mapping = handler.map_physical_region::<SdtHeader>(physical_address);
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -119,29 +114,28 @@ pub fn parse_rsdt<H>(handler            : &mut H,
 | 
	
		
			
				|  |  |      // TODO: validate the signature and checksum (XXX: if it's a RSDT, the signature will be
 | 
	
		
			
				|  |  |      // "RSDT", whereas a XSDT will have a signature of "XSDT"
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    if revision == 0
 | 
	
		
			
				|  |  | -    {
 | 
	
		
			
				|  |  | +    if revision == 0 {
 | 
	
		
			
				|  |  |          /*
 | 
	
		
			
				|  |  |           * ACPI Version 1.0. It's a 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;
 | 
	
		
			
				|  |  | +        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;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        for i in 0..num_tables
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | +        for i in 0..num_tables {
 | 
	
		
			
				|  |  |              sdt::dispatch_sdt(handler, unsafe { *tables_base.offset(i as isize) } as usize)?;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    else
 | 
	
		
			
				|  |  | -    {
 | 
	
		
			
				|  |  | +    } else {
 | 
	
		
			
				|  |  |          /*
 | 
	
		
			
				|  |  |           * ACPI Version 2.0+. It's a 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;
 | 
	
		
			
				|  |  | +        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;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        for i in 0..num_tables
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | +        for i in 0..num_tables {
 | 
	
		
			
				|  |  |              sdt::dispatch_sdt(handler, unsafe { *tables_base.offset(i as isize) } as usize)?;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 |