123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216 |
- #![no_std]
- #![deny(unsafe_op_in_unsafe_fn)]
- #[cfg(test)]
- extern crate std;
- pub mod handler;
- use core::{mem, ops::Range, slice, str};
- use handler::{AcpiHandler, PhysicalMapping};
- use log::warn;
- #[derive(Clone, Copy, PartialEq, Eq, Debug)]
- pub enum RsdpError {
- NoValidRsdp,
- IncorrectSignature,
- InvalidOemId,
- InvalidChecksum,
- }
- #[derive(Clone, Copy, Debug)]
- #[repr(C, packed)]
- pub struct Rsdp {
- signature: [u8; 8],
- checksum: u8,
- oem_id: [u8; 6],
- revision: u8,
- rsdt_address: u32,
-
- length: u32,
- xsdt_address: u64,
- ext_checksum: u8,
- reserved: [u8; 3],
- }
- impl Rsdp {
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- pub unsafe fn search_for_on_bios<H>(handler: H) -> Result<PhysicalMapping<H, Rsdp>, RsdpError>
- where
- H: AcpiHandler,
- {
- let rsdp_address = {
- let mut rsdp_address = None;
- let areas = find_search_areas(handler.clone());
- 'areas: for area in areas.iter() {
- let mapping = unsafe { handler.map_physical_region::<u8>(area.start, area.end - area.start) };
- for address in area.clone().step_by(16) {
- let ptr_in_mapping =
- unsafe { mapping.virtual_start().as_ptr().offset((address - area.start) as isize) };
- let signature = unsafe { *(ptr_in_mapping as *const [u8; 8]) };
- if signature == *RSDP_SIGNATURE {
- match unsafe { *(ptr_in_mapping as *const Rsdp) }.validate() {
- Ok(()) => {
- rsdp_address = Some(address);
- break 'areas;
- }
- Err(err) => warn!("Invalid RSDP found at {:#x}: {:?}", address, err),
- }
- }
- }
- }
- rsdp_address
- };
- match rsdp_address {
- Some(address) => {
- let rsdp_mapping = unsafe { handler.map_physical_region::<Rsdp>(address, mem::size_of::<Rsdp>()) };
- Ok(rsdp_mapping)
- }
- None => Err(RsdpError::NoValidRsdp),
- }
- }
-
-
-
-
- pub fn validate(&self) -> Result<(), RsdpError> {
- const RSDP_V1_LENGTH: usize = 20;
-
- if &self.signature != RSDP_SIGNATURE {
- return Err(RsdpError::IncorrectSignature);
- }
-
- if str::from_utf8(&self.oem_id).is_err() {
- return Err(RsdpError::InvalidOemId);
- }
-
- let length = if self.revision > 0 {
-
- self.length as usize
- } else {
- RSDP_V1_LENGTH
- };
- let bytes = unsafe { slice::from_raw_parts(self as *const Rsdp as *const u8, length) };
- let sum = bytes.iter().fold(0u8, |sum, &byte| sum.wrapping_add(byte));
- if sum != 0 {
- return Err(RsdpError::InvalidChecksum);
- }
- Ok(())
- }
- pub fn oem_id(&self) -> &str {
- str::from_utf8(&self.oem_id).unwrap()
- }
- pub fn revision(&self) -> u8 {
- self.revision
- }
- pub fn rsdt_address(&self) -> u32 {
- self.rsdt_address
- }
- pub fn xsdt_address(&self) -> u64 {
- assert!(self.revision > 0, "Tried to read extended RSDP field with ACPI Version 1.0");
- self.xsdt_address
- }
- }
- pub fn find_search_areas<H>(handler: H) -> [Range<usize>; 2]
- where
- H: AcpiHandler,
- {
-
- let ebda_start_mapping =
- unsafe { handler.map_physical_region::<u16>(EBDA_START_SEGMENT_PTR, mem::size_of::<u16>()) };
- let ebda_start = (*ebda_start_mapping as usize) << 4;
- [
-
- RSDP_BIOS_AREA_START..(RSDP_BIOS_AREA_END + 1),
-
- if (EBDA_EARLIEST_START..EBDA_END).contains(&ebda_start) {
-
- ebda_start..ebda_start + 1024
- } else {
-
- EBDA_EARLIEST_START..(EBDA_END + 1)
- },
- ]
- }
- const EBDA_START_SEGMENT_PTR: usize = 0x40e;
- const EBDA_EARLIEST_START: usize = 0x80000;
- const EBDA_END: usize = 0x9ffff;
- const RSDP_BIOS_AREA_START: usize = 0xe0000;
- const RSDP_BIOS_AREA_END: usize = 0xfffff;
- const RSDP_SIGNATURE: &'static [u8; 8] = b"RSD PTR ";
|