123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288 |
- #![no_std]
- #![feature(nll)]
- #![feature(alloc)]
- #![feature(exclusive_range_pattern, range_contains)]
- #![feature(exhaustive_integer_patterns)]
- #[cfg_attr(test, macro_use)]
- #[cfg(test)]
- extern crate std;
- #[macro_use]
- extern crate log;
- extern crate alloc;
- extern crate bit_field;
- mod aml;
- mod fadt;
- mod hpet;
- pub mod interrupt;
- mod madt;
- mod rsdp;
- mod rsdp_search;
- mod sdt;
- pub use crate::aml::AmlError;
- pub use crate::madt::MadtError;
- pub use crate::rsdp_search::search_for_rsdp_bios;
- use crate::aml::AmlValue;
- use crate::interrupt::InterruptModel;
- use crate::rsdp::Rsdp;
- use crate::sdt::SdtHeader;
- use alloc::{collections::BTreeMap, string::String, vec::Vec};
- use core::mem;
- use core::ops::Deref;
- use core::ptr::NonNull;
- #[derive(Debug)]
- pub enum AcpiError {
- RsdpIncorrectSignature,
- RsdpInvalidOemId,
- RsdpInvalidChecksum,
- NoValidRsdp,
- SdtInvalidSignature([u8; 4]),
- SdtInvalidOemId([u8; 4]),
- SdtInvalidTableId([u8; 4]),
- SdtInvalidChecksum([u8; 4]),
- InvalidAmlTable([u8; 4], AmlError),
- InvalidMadt(MadtError),
- }
- #[repr(C, packed)]
- pub(crate) struct GenericAddress {
- address_space: u8,
- bit_width: u8,
- bit_offset: u8,
- access_size: u8,
- address: u64,
- }
- #[derive(Clone, Copy, Debug)]
- pub enum ProcessorState {
-
- Disabled,
-
-
- WaitingForSipi,
-
- Running,
- }
- #[derive(Clone, Copy, Debug)]
- pub struct Processor {
- pub processor_uid: u8,
- pub local_apic_id: u8,
-
-
- pub state: ProcessorState,
-
-
-
- pub is_ap: bool,
- }
- impl Processor {
- pub(crate) fn new(
- processor_uid: u8,
- local_apic_id: u8,
- state: ProcessorState,
- is_ap: bool,
- ) -> Processor {
- Processor {
- processor_uid,
- local_apic_id,
- state,
- is_ap,
- }
- }
- }
- pub struct PhysicalMapping<T> {
- pub physical_start: usize,
- pub virtual_start: NonNull<T>,
- pub region_length: usize,
- pub mapped_length: usize,
- }
- impl<T> Deref for PhysicalMapping<T> {
- type Target = T;
- fn deref(&self) -> &T {
- unsafe { self.virtual_start.as_ref() }
- }
- }
- pub trait AcpiHandler {
-
-
-
-
-
- fn map_physical_region<T>(
- &mut self,
- physical_address: usize,
- size: usize,
- ) -> PhysicalMapping<T>;
-
-
- fn unmap_physical_region<T>(&mut self, region: PhysicalMapping<T>);
- }
- #[derive(Debug)]
- pub struct Acpi {
- acpi_revision: u8,
- namespace: BTreeMap<String, AmlValue>,
- boot_processor: Option<Processor>,
- application_processors: Vec<Processor>,
-
-
-
- interrupt_model: Option<InterruptModel>,
- }
- impl Acpi {
-
-
- pub fn boot_processor<'a>(&'a self) -> &'a Option<Processor> {
- &self.boot_processor
- }
-
-
-
- pub fn application_processors<'a>(&'a self) -> &'a Vec<Processor> {
- &self.application_processors
- }
-
- pub fn interrupt_model<'a>(&'a self) -> &'a Option<InterruptModel> {
- &self.interrupt_model
- }
- }
- pub fn parse_rsdp<H>(handler: &mut H, rsdp_address: usize) -> Result<Acpi, AcpiError>
- where
- H: AcpiHandler,
- {
- let rsdp_mapping = handler.map_physical_region::<Rsdp>(rsdp_address, mem::size_of::<Rsdp>());
- (*rsdp_mapping).validate()?;
- parse_validated_rsdp(handler, rsdp_mapping)
- }
- fn parse_validated_rsdp<H>(
- handler: &mut H,
- rsdp_mapping: PhysicalMapping<Rsdp>,
- ) -> Result<Acpi, AcpiError>
- where
- H: AcpiHandler,
- {
- let revision = (*rsdp_mapping).revision();
- if revision == 0 {
-
- let rsdt_address = (*rsdp_mapping).rsdt_address();
- handler.unmap_physical_region(rsdp_mapping);
- parse_rsdt(handler, revision, rsdt_address as usize)
- } else {
-
- let xsdt_address = (*rsdp_mapping).xsdt_address();
- handler.unmap_physical_region(rsdp_mapping);
- parse_rsdt(handler, revision, xsdt_address as usize)
- }
- }
- pub fn parse_rsdt<H>(
- handler: &mut H,
- revision: u8,
- physical_address: usize,
- ) -> Result<Acpi, AcpiError>
- where
- H: AcpiHandler,
- {
- let mut acpi = Acpi {
- acpi_revision: revision,
- namespace: BTreeMap::new(),
- boot_processor: None,
- application_processors: Vec::new(),
- interrupt_model: None,
- };
- let header = sdt::peek_at_sdt_header(handler, physical_address);
- let mapping =
- handler.map_physical_region::<SdtHeader>(physical_address, header.length() as usize);
- if revision == 0 {
-
- (*mapping).validate(b"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;
- for i in 0..num_tables {
- sdt::dispatch_sdt(
- &mut acpi,
- handler,
- unsafe { *tables_base.offset(i as isize) } as usize,
- )?;
- }
- } else {
-
- (*mapping).validate(b"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;
- for i in 0..num_tables {
- sdt::dispatch_sdt(
- &mut acpi,
- handler,
- unsafe { *tables_base.offset(i as isize) } as usize,
- )?;
- }
- }
- info!("Parsed namespace: {:#?}", acpi.namespace);
- handler.unmap_physical_region(mapping);
- Ok(acpi)
- }
|