diff --git a/src/arch/x86_64/driver/acpi/mod.rs b/src/arch/x86_64/driver/acpi/mod.rs index b286501..6e0e313 100644 --- a/src/arch/x86_64/driver/acpi/mod.rs +++ b/src/arch/x86_64/driver/acpi/mod.rs @@ -42,20 +42,35 @@ pub fn init() -> Result<(), ACPI_Error> { 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) }; + for i in 0 .. rsdt.entry_count() { + let entry = rsdt.entry_at(i); if entry > PHYSICAL_MEMORY_LIMIT { return Err(ACPI_Error::NotMapped); } let header = unsafe{ &*(entry as *const header) }; - debug!("{:?}", header); + // debug!("{:?}", header); if &header.Signature == b"APIC" { madt = Some(unsafe{ &*(entry as *const madt) }); } } debug!("{:?}", madt); - // return acpi_config_smp(madt); + config_smp(madt.expect("acpi: madt not found.")); Ok(()) } + +fn config_smp(madt: &'static madt) { + let lapic_addr = madt.LapicAddress; + + for entry in madt.entry_iter() { + debug!("{:?}", entry); + match &entry { + &MadtEntry::LocalApic(ref lapic) => {}, + &MadtEntry::IoApic(ref ioapic) => { + }, + _ => {}, + } + } + // TODO + unimplemented!(); +} \ No newline at end of file diff --git a/src/arch/x86_64/driver/acpi/structs.rs b/src/arch/x86_64/driver/acpi/structs.rs index 51dd777..0ec80cf 100644 --- a/src/arch/x86_64/driver/acpi/structs.rs +++ b/src/arch/x86_64/driver/acpi/structs.rs @@ -2,6 +2,7 @@ // Copy from crate 'acpica-sys' use util::{Checkable, bytes_sum}; +use core::mem::size_of; #[repr(C)] #[derive(Debug)] @@ -45,8 +46,15 @@ pub struct rsdt { } impl rsdt { - pub unsafe fn entry_at(&self, id: usize) -> u32 { - *(self.TableOffsetEntry.as_ptr().offset(id as isize)) + pub fn entry_count(&self) -> usize { + (self.Header.Length as usize - size_of::()) / 4 + } + pub fn entry_at(&self, id: usize) -> u32 { + assert!(id < self.entry_count()); + unsafe { + let p = (self as *const Self).offset(1) as *const u32; + *(p.offset(id as isize)) + } } } @@ -54,34 +62,80 @@ impl rsdt { #[derive(Debug)] pub struct madt { pub Header: header, - pub Address: u32, + pub LapicAddress: u32, pub Flags: u32, Table: [u32; 0], } impl Checkable for madt { fn check(&self) -> bool { - &self.Header.Signature == b"APIC" + &self.Header.Signature == b"APIC" && self.Header.Length >= size_of::() as u32 } } -#[repr(C)] #[derive(Debug)] -pub struct madt_local_apic { - pub Type: u8, +pub enum MadtEntry { + Unknown(MadtEntry_Unknown), + LocalApic(MadtEntry_LocalApic), + IoApic(MadtEntry_IoApic), +} +#[repr(C)] +#[derive(Debug, Clone)] +pub struct MadtEntry_Unknown { + pub Type: u8, + pub Length: u8, +} +#[repr(C)] +#[derive(Debug, Clone)] +pub struct MadtEntry_LocalApic { + pub Type: u8, // 0 pub Length: u8, pub ProcessorId: u8, pub Id: u8, pub LapicFlags: u32, } - #[repr(C)] -#[derive(Debug)] -pub struct madt_io_apic { - pub Type: u8, +#[derive(Debug, Clone)] +pub struct MadtEntry_IoApic { + pub Type: u8, // 1 pub Length: u8, pub Id: u8, pub Reserved: u8, pub Address: u32, pub GlobalIrqBase: u32, +} + +#[derive(Debug)] +pub struct MadtEntryIter<'a> { + madt: &'a madt, + ptr: *const u8, + end_ptr: *const u8, +} + +impl madt { + pub fn entry_iter(&self) -> MadtEntryIter { + let ptr = unsafe{ (self as *const Self).offset(1) } as *const u8; + let end_ptr = unsafe{ ptr.offset(self.Header.Length as isize) }; + MadtEntryIter { madt: self, ptr, end_ptr } + } +} + +impl<'a> Iterator for MadtEntryIter<'a> { + type Item = MadtEntry; + fn next(&mut self) -> Option { + if self.ptr >= self.end_ptr { + return None; + } + unsafe { + let typeId = *self.ptr.offset(0); + let len = *self.ptr.offset(1); + let ret = Some(match typeId { + 0 => MadtEntry::LocalApic( (&*(self.ptr as *const MadtEntry_LocalApic)).clone() ), + 1 => MadtEntry::IoApic( (&*(self.ptr as *const MadtEntry_IoApic)).clone() ), + _ => MadtEntry::Unknown( (&*(self.ptr as *const MadtEntry_Unknown)).clone() ), + }); + self.ptr = self.ptr.offset(len as isize); + ret + } + } } \ No newline at end of file