From e9d89576a371285e023fa76c90049adf575a8bab Mon Sep 17 00:00:00 2001 From: WangRunji Date: Sat, 7 Apr 2018 22:40:22 +0800 Subject: [PATCH] Port acpiinit() --- src/arch/x86_64/driver/acpi/mod.rs | 53 +++++++++++++++++++++++--- src/arch/x86_64/driver/acpi/structs.rs | 17 +++++++-- src/lib.rs | 2 +- 3 files changed, 63 insertions(+), 9 deletions(-) diff --git a/src/arch/x86_64/driver/acpi/mod.rs b/src/arch/x86_64/driver/acpi/mod.rs index e065a95..b286501 100644 --- a/src/arch/x86_64/driver/acpi/mod.rs +++ b/src/arch/x86_64/driver/acpi/mod.rs @@ -4,15 +4,58 @@ mod structs; use self::structs::*; /// See https://wiki.osdev.org/RSDP -- Detecting the RSDP -pub fn find_rdsp() -> Option<*const rsdp> { +pub fn find_rsdp() -> Option<&'static rsdp> { use util::{Checkable, find_in_memory}; let ebda = unsafe { *(0x40E as *const u16) as usize } << 4; debug!("EBDA at {:#x}", ebda); + + macro_rules! return_if_find_in { + ($begin:expr, $end:expr) => ( + if let Some(addr) = unsafe{ find_in_memory::($begin, $end, 4) } { + return Some(unsafe{ &*(addr as *const rsdp) }); + } + ) + } + if ebda != 0 { - if let Some(addr) = unsafe{ find_in_memory::(ebda as usize, 1024, 4) } { - return Some(addr as *const rsdp); - } + return_if_find_in!(ebda as usize, 1024); } - unsafe{ find_in_memory::(0xE0000, 0x20000, 4).map(|addr| addr as *const rsdp) } + return_if_find_in!(0xE0000, 0x20000); + None } +#[cfg(target_arch="x86")] +const PHYSICAL_MEMORY_LIMIT: u32 = 0x0E000000; +#[cfg(target_arch="x86_64")] +const PHYSICAL_MEMORY_LIMIT: u32 = 0x80000000; + +#[derive(Debug)] +pub enum ACPI_Error { + NotMapped +} + +pub fn init() -> Result<(), ACPI_Error> { + use core::mem::size_of; + use util::Checkable; + let rsdp = find_rsdp().expect("acpi: rsdp not found."); + if rsdp.RsdtPhysicalAddress > PHYSICAL_MEMORY_LIMIT { + return Err(ACPI_Error::NotMapped); + } + let rsdt = unsafe{ &*(rsdp.RsdtPhysicalAddress as *const rsdt) }; + let entry_count = (rsdt.Header.Length as usize - size_of::
()) / 4; + let mut madt: Option<&'static madt> = None; + for i in 0 .. entry_count { + let entry = unsafe{ rsdt.entry_at(i) }; + if entry > PHYSICAL_MEMORY_LIMIT { + return Err(ACPI_Error::NotMapped); + } + let header = unsafe{ &*(entry as *const header) }; + debug!("{:?}", header); + if &header.Signature == b"APIC" { + madt = Some(unsafe{ &*(entry as *const madt) }); + } + } + debug!("{:?}", madt); + // return acpi_config_smp(madt); + Ok(()) +} diff --git a/src/arch/x86_64/driver/acpi/structs.rs b/src/arch/x86_64/driver/acpi/structs.rs index 96c55fb..51dd777 100644 --- a/src/arch/x86_64/driver/acpi/structs.rs +++ b/src/arch/x86_64/driver/acpi/structs.rs @@ -26,7 +26,7 @@ impl Checkable for rsdp { #[repr(C)] #[derive(Debug)] pub struct header { - pub Signature: [i8; 4], + pub Signature: [u8; 4], pub Length: u32, pub Revision: u8, pub Checksum: u8, @@ -41,7 +41,13 @@ pub struct header { #[derive(Debug)] pub struct rsdt { pub Header: header, - pub TableOffsetEntry: [u32; 1], + TableOffsetEntry: [u32; 0], +} + +impl rsdt { + pub unsafe fn entry_at(&self, id: usize) -> u32 { + *(self.TableOffsetEntry.as_ptr().offset(id as isize)) + } } #[repr(C)] @@ -50,9 +56,14 @@ pub struct madt { pub Header: header, pub Address: u32, pub Flags: u32, + Table: [u32; 0], } -const MADT_SIGNATURE: [u8; 4] = *b"APIC"; +impl Checkable for madt { + fn check(&self) -> bool { + &self.Header.Signature == b"APIC" + } +} #[repr(C)] #[derive(Debug)] diff --git a/src/lib.rs b/src/lib.rs index 3139708..968ae21 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -46,7 +46,7 @@ mod arch; pub extern "C" fn rust_main(multiboot_information_address: usize) { // ATTENTION: we have a very small stack and no guard page println!("MP = {:?}", arch::driver::mp::find_mp()); - println!("RDSP = {:?}", arch::driver::acpi::find_rdsp()); + arch::driver::acpi::init(); loop { }