From 1bcd8530d254dbb5c2f76bcb376241424c01ee51 Mon Sep 17 00:00:00 2001 From: Connor Wood <connorwood71@gmail.com> Date: Thu, 31 Aug 2017 10:52:59 +0100 Subject: [PATCH] Stored signature to include OEM signature and OEM table ID --- src/acpi/aml/type2opcode.rs | 13 +-- src/acpi/dmar/mod.rs | 54 +++++----- src/acpi/fadt.rs | 35 ++++--- src/acpi/hpet.rs | 28 ++--- src/acpi/madt.rs | 204 ++++++++++++++++++------------------ src/acpi/mod.rs | 82 +++++++++------ 6 files changed, 220 insertions(+), 196 deletions(-) diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index f193575f..cd94e708 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -11,7 +11,7 @@ use super::namestring::{parse_super_name, parse_target, parse_name_string, parse use super::dataobj::parse_data_ref_obj; use time::monotonic; -use acpi::ACPI_TABLE; +use acpi::{ACPI_TABLE, SDT_POINTERS}; #[derive(Debug, Clone)] pub enum MatchOpcode { @@ -1346,11 +1346,10 @@ fn parse_def_load_table(data: &[u8], let parameter_path = parse_term_arg(&data[2 + signature.len + oem_id.len + oem_table_id.len + root_path.len..], ctx)?; let parameter_data = parse_term_arg(&data[2 + signature.len + oem_id.len + oem_table_id.len + root_path.len + parameter_path.len..], ctx)?; - let rxsdt_ptr = ACPI_TABLE.rxsdt.read(); - - if let Some(ref rxsdt) = *rxsdt_ptr { + if let Some(ref ptrs) = *(SDT_POINTERS.read()) { let sig_str = unsafe { - *(signature.val.get_as_string()?.as_bytes().as_ptr() as *const [u8; 4]) + let sig = *(signature.val.get_as_string()?.as_bytes().as_ptr() as *const [u8; 4]); + String::from_utf8(sig.to_vec()).expect("Error converting signature to string") }; let oem_str = unsafe { *(oem_id.val.get_as_string()?.as_bytes().as_ptr() as *const [u8; 6]) @@ -1358,8 +1357,10 @@ fn parse_def_load_table(data: &[u8], let oem_table_str = unsafe { *(oem_table_id.val.get_as_string()?.as_bytes().as_ptr() as *const [u8; 8]) }; + + let sdt_signature = (sig_str, oem_str, oem_table_str); - let sdt = rxsdt.find(sig_str, oem_str, oem_table_str); + let sdt = ptrs.get(&sdt_signature); if let Some(sdt) = sdt { let hdl = parse_aml_with_scope(sdt, root_path.val.get_as_string()?)?; diff --git a/src/acpi/dmar/mod.rs b/src/acpi/dmar/mod.rs index e2cf1848..549f6869 100644 --- a/src/acpi/dmar/mod.rs +++ b/src/acpi/dmar/mod.rs @@ -5,7 +5,7 @@ use self::drhd::Drhd; use memory::Frame; use paging::{entry, ActivePageTable, PhysicalAddress}; -use super::{ACPI_TABLE, SDT_POINTERS, get_sdt}; +use super::{ACPI_TABLE, SDT_POINTERS, get_sdt, find_sdt, load_table, get_sdt_signature}; pub mod drhd; @@ -20,32 +20,32 @@ pub struct Dmar { impl Dmar { pub fn init(active_table: &mut ActivePageTable) { - if let Some(ref ptrs) = *(SDT_POINTERS.read()) { - let dmar = if let Some(dmar_sdt) = ptrs.get("DMAR") { - Dmar::new(dmar_sdt) - } else { - println!("Unable to find DMAR"); - return; - }; - - if let Some(dmar) = dmar { - println!(" DMAR: {}: {}", dmar.addr_width, dmar.flags); - - for dmar_entry in dmar.iter() { - println!(" {:?}", dmar_entry); - match dmar_entry { - DmarEntry::Drhd(dmar_drhd) => { - let drhd = dmar_drhd.get(active_table); - - println!("VER: {:X}", drhd.version); - println!("CAP: {:X}", drhd.cap); - println!("EXT_CAP: {:X}", drhd.ext_cap); - println!("GCMD: {:X}", drhd.gl_cmd); - println!("GSTS: {:X}", drhd.gl_sts); - println!("RT: {:X}", drhd.root_table); - }, - _ => () - } + let dmar_sdt = find_sdt("DMAR"); + let dmar = if dmar_sdt.len() == 1 { + load_table(get_sdt_signature(dmar_sdt[0])); + Dmar::new(dmar_sdt[0]) + } else { + println!("Unable to find DMAR"); + return; + }; + + if let Some(dmar) = dmar { + println!(" DMAR: {}: {}", dmar.addr_width, dmar.flags); + + for dmar_entry in dmar.iter() { + println!(" {:?}", dmar_entry); + match dmar_entry { + DmarEntry::Drhd(dmar_drhd) => { + let drhd = dmar_drhd.get(active_table); + + println!("VER: {:X}", drhd.version); + println!("CAP: {:X}", drhd.cap); + println!("EXT_CAP: {:X}", drhd.ext_cap); + println!("GCMD: {:X}", drhd.gl_cmd); + println!("GSTS: {:X}", drhd.gl_sts); + println!("RT: {:X}", drhd.root_table); + }, + _ => () } } } diff --git a/src/acpi/fadt.rs b/src/acpi/fadt.rs index c6ff36c3..6dd82d86 100644 --- a/src/acpi/fadt.rs +++ b/src/acpi/fadt.rs @@ -2,7 +2,7 @@ use core::{mem, ptr}; use collections::string::String; use super::sdt::Sdt; -use super::{ACPI_TABLE, SDT_POINTERS, get_sdt}; +use super::{ACPI_TABLE, SDT_POINTERS, get_sdt, find_sdt, get_sdt_signature, load_table}; use paging::ActivePageTable; @@ -99,24 +99,27 @@ impl Fadt { } pub fn init(active_table: &mut ActivePageTable) { - if let Some(ref mut ptrs) = *(SDT_POINTERS.write()) { - let fadt = if let Some(fadt_sdt) = ptrs.get("FACP") { - Fadt::new(fadt_sdt) - } else { - println!("Unable to find FADT"); - return; - }; + let fadt_sdt = find_sdt("FACP"); + let fadt = if fadt_sdt.len() == 1 { + load_table(get_sdt_signature(fadt_sdt[0])); + Fadt::new(fadt_sdt[0]) + } else { + println!("Unable to find FADT"); + return; + }; + + if let Some(fadt) = fadt { + println!(" FACP: {:X}", fadt.dsdt); - if let Some(fadt) = fadt { - println!(" FACP: {:X}", fadt.dsdt); - - let dsdt_sdt = get_sdt(fadt.dsdt as usize, active_table); - let signature = String::from_utf8(dsdt_sdt.signature.to_vec()).expect("Error converting signature to string"); - ptrs.insert(signature, dsdt_sdt); + let dsdt_sdt = get_sdt(fadt.dsdt as usize, active_table); - let mut fadt_t = ACPI_TABLE.fadt.write(); - *fadt_t = Some(fadt); + let signature = get_sdt_signature(dsdt_sdt); + if let Some(ref mut ptrs) = *(SDT_POINTERS.write()) { + ptrs.insert(signature, dsdt_sdt); } + + let mut fadt_t = ACPI_TABLE.fadt.write(); + *fadt_t = Some(fadt); } } } diff --git a/src/acpi/hpet.rs b/src/acpi/hpet.rs index 7b926487..d2e5ecfb 100644 --- a/src/acpi/hpet.rs +++ b/src/acpi/hpet.rs @@ -6,7 +6,7 @@ use memory::Frame; use paging::{entry, ActivePageTable, PhysicalAddress, Page, VirtualAddress}; use super::sdt::Sdt; -use super::{ACPI_TABLE, SDT_POINTERS, get_sdt}; +use super::{ACPI_TABLE, SDT_POINTERS, get_sdt, find_sdt, load_table, get_sdt_signature}; #[repr(packed)] #[derive(Clone, Copy, Debug, Default)] @@ -36,20 +36,20 @@ pub struct Hpet { impl Hpet { pub fn init(active_table: &mut ActivePageTable) { - if let Some(ref ptrs) = *(SDT_POINTERS.read()) { - let hpet = if let Some(hpet_sdt) = ptrs.get("HPET") { - Hpet::new(hpet_sdt, active_table) - } else { - println!("Unable to find HPET"); - return; - }; + let hpet_sdt = find_sdt("HPET"); + let hpet = if hpet_sdt.len() == 1 { + load_table(get_sdt_signature(hpet_sdt[0])); + Hpet::new(hpet_sdt[0], active_table) + } else { + println!("Unable to find HPET"); + return; + }; + + if let Some(hpet) = hpet { + println!(" HPET: {:X}", hpet.hpet_number); - if let Some(hpet) = hpet { - println!(" HPET: {:X}", hpet.hpet_number); - - let mut hpet_t = ACPI_TABLE.hpet.write(); - *hpet_t = Some(hpet); - } + let mut hpet_t = ACPI_TABLE.hpet.write(); + *hpet_t = Some(hpet); } } diff --git a/src/acpi/madt.rs b/src/acpi/madt.rs index 501bba59..c4f922a5 100644 --- a/src/acpi/madt.rs +++ b/src/acpi/madt.rs @@ -4,7 +4,7 @@ use memory::{allocate_frames, Frame}; use paging::{entry, ActivePageTable, Page, PhysicalAddress, VirtualAddress}; use super::sdt::Sdt; -use super::{ACPI_TABLE, SDT_POINTERS, AP_STARTUP, TRAMPOLINE}; +use super::{ACPI_TABLE, SDT_POINTERS, AP_STARTUP, TRAMPOLINE, find_sdt, load_table, get_sdt_signature}; use core::intrinsics::{atomic_load, atomic_store}; use core::sync::atomic::Ordering; @@ -33,118 +33,118 @@ pub struct Madt { impl Madt { pub fn init(active_table: &mut ActivePageTable) { - if let Some(ref ptrs) = *(SDT_POINTERS.read()) { - let madt = if let Some(madt_sdt) = ptrs.get("APIC") { - Madt::new(madt_sdt) + let madt_sdt = find_sdt("APIC"); + let madt = if madt_sdt.len() == 1 { + load_table(get_sdt_signature(madt_sdt[0])); + Madt::new(madt_sdt[0]) + } else { + println!("Unable to find MADT"); + return; + }; + + if let Some(madt) = madt { + println!(" APIC: {:>08X}: {}", madt.local_address, madt.flags); + + let local_apic = unsafe { &mut LOCAL_APIC }; + let me = local_apic.id() as u8; + + if local_apic.x2 { + println!(" X2APIC {}", me); } else { - println!("Unable to find MADT"); - return; - }; - - if let Some(madt) = madt { - println!(" APIC: {:>08X}: {}", madt.local_address, madt.flags); - - let local_apic = unsafe { &mut LOCAL_APIC }; - let me = local_apic.id() as u8; - - if local_apic.x2 { - println!(" X2APIC {}", me); - } else { - println!(" XAPIC {}: {:>08X}", me, local_apic.address); - } - - if cfg!(feature = "multi_core"){ - let trampoline_frame = Frame::containing_address(PhysicalAddress::new(TRAMPOLINE)); - let trampoline_page = Page::containing_address(VirtualAddress::new(TRAMPOLINE)); - - // Map trampoline - let result = active_table.map_to(trampoline_page, trampoline_frame, entry::PRESENT | entry::WRITABLE); - result.flush(active_table); + println!(" XAPIC {}: {:>08X}", me, local_apic.address); + } - for madt_entry in madt.iter() { - println!(" {:?}", madt_entry); - match madt_entry { - MadtEntry::LocalApic(ap_local_apic) => if ap_local_apic.id == me { - println!(" This is my local APIC"); - } else { - if ap_local_apic.flags & 1 == 1 { - // Increase CPU ID - CPU_COUNT.fetch_add(1, Ordering::SeqCst); - - // Allocate a stack - let stack_start = allocate_frames(64).expect("no more frames in acpi stack_start").start_address().get() + ::KERNEL_OFFSET; - let stack_end = stack_start + 64 * 4096; - - let ap_ready = TRAMPOLINE as *mut u64; - let ap_cpu_id = unsafe { ap_ready.offset(1) }; - let ap_page_table = unsafe { ap_ready.offset(2) }; - let ap_stack_start = unsafe { ap_ready.offset(3) }; - let ap_stack_end = unsafe { ap_ready.offset(4) }; - let ap_code = unsafe { ap_ready.offset(5) }; - - // Set the ap_ready to 0, volatile - unsafe { atomic_store(ap_ready, 0) }; - unsafe { atomic_store(ap_cpu_id, ap_local_apic.id as u64) }; - unsafe { atomic_store(ap_page_table, active_table.address() as u64) }; - unsafe { atomic_store(ap_stack_start, stack_start as u64) }; - unsafe { atomic_store(ap_stack_end, stack_end as u64) }; - unsafe { atomic_store(ap_code, kstart_ap as u64) }; - AP_READY.store(false, Ordering::SeqCst); - - print!(" AP {}:", ap_local_apic.id); - - // Send INIT IPI - { - let mut icr = 0x4500; - if local_apic.x2 { - icr |= (ap_local_apic.id as u64) << 32; - } else { - icr |= (ap_local_apic.id as u64) << 56; - } - print!(" IPI..."); - local_apic.set_icr(icr); + if cfg!(feature = "multi_core"){ + let trampoline_frame = Frame::containing_address(PhysicalAddress::new(TRAMPOLINE)); + let trampoline_page = Page::containing_address(VirtualAddress::new(TRAMPOLINE)); + + // Map trampoline + let result = active_table.map_to(trampoline_page, trampoline_frame, entry::PRESENT | entry::WRITABLE); + result.flush(active_table); + + for madt_entry in madt.iter() { + println!(" {:?}", madt_entry); + match madt_entry { + MadtEntry::LocalApic(ap_local_apic) => if ap_local_apic.id == me { + println!(" This is my local APIC"); + } else { + if ap_local_apic.flags & 1 == 1 { + // Increase CPU ID + CPU_COUNT.fetch_add(1, Ordering::SeqCst); + + // Allocate a stack + let stack_start = allocate_frames(64).expect("no more frames in acpi stack_start").start_address().get() + ::KERNEL_OFFSET; + let stack_end = stack_start + 64 * 4096; + + let ap_ready = TRAMPOLINE as *mut u64; + let ap_cpu_id = unsafe { ap_ready.offset(1) }; + let ap_page_table = unsafe { ap_ready.offset(2) }; + let ap_stack_start = unsafe { ap_ready.offset(3) }; + let ap_stack_end = unsafe { ap_ready.offset(4) }; + let ap_code = unsafe { ap_ready.offset(5) }; + + // Set the ap_ready to 0, volatile + unsafe { atomic_store(ap_ready, 0) }; + unsafe { atomic_store(ap_cpu_id, ap_local_apic.id as u64) }; + unsafe { atomic_store(ap_page_table, active_table.address() as u64) }; + unsafe { atomic_store(ap_stack_start, stack_start as u64) }; + unsafe { atomic_store(ap_stack_end, stack_end as u64) }; + unsafe { atomic_store(ap_code, kstart_ap as u64) }; + AP_READY.store(false, Ordering::SeqCst); + + print!(" AP {}:", ap_local_apic.id); + + // Send INIT IPI + { + let mut icr = 0x4500; + if local_apic.x2 { + icr |= (ap_local_apic.id as u64) << 32; + } else { + icr |= (ap_local_apic.id as u64) << 56; } + print!(" IPI..."); + local_apic.set_icr(icr); + } - // Send START IPI - { - //Start at 0x0800:0000 => 0x8000. Hopefully the bootloader code is still there - let ap_segment = (AP_STARTUP >> 12) & 0xFF; - let mut icr = 0x4600 | ap_segment as u64; - - if local_apic.x2 { - icr |= (ap_local_apic.id as u64) << 32; - } else { - icr |= (ap_local_apic.id as u64) << 56; - } + // Send START IPI + { + //Start at 0x0800:0000 => 0x8000. Hopefully the bootloader code is still there + let ap_segment = (AP_STARTUP >> 12) & 0xFF; + let mut icr = 0x4600 | ap_segment as u64; - print!(" SIPI..."); - local_apic.set_icr(icr); + if local_apic.x2 { + icr |= (ap_local_apic.id as u64) << 32; + } else { + icr |= (ap_local_apic.id as u64) << 56; } - // Wait for trampoline ready - print!(" Wait..."); - while unsafe { atomic_load(ap_ready) } == 0 { - interrupt::pause(); - } - print!(" Trampoline..."); - while ! AP_READY.load(Ordering::SeqCst) { - interrupt::pause(); - } - println!(" Ready"); + print!(" SIPI..."); + local_apic.set_icr(icr); + } - active_table.flush_all(); - } else { - println!(" CPU Disabled"); + // Wait for trampoline ready + print!(" Wait..."); + while unsafe { atomic_load(ap_ready) } == 0 { + interrupt::pause(); } - }, - _ => () - } - } + print!(" Trampoline..."); + while ! AP_READY.load(Ordering::SeqCst) { + interrupt::pause(); + } + println!(" Ready"); - // Unmap trampoline - let (result, _frame) = active_table.unmap_return(trampoline_page, false); - result.flush(active_table); + active_table.flush_all(); + } else { + println!(" CPU Disabled"); + } + }, + _ => () + } } + + // Unmap trampoline + let (result, _frame) = active_table.unmap_return(trampoline_page, false); + result.flush(active_table); } } } diff --git a/src/acpi/mod.rs b/src/acpi/mod.rs index a1d5eccf..5902ebc5 100644 --- a/src/acpi/mod.rs +++ b/src/acpi/mod.rs @@ -97,34 +97,24 @@ fn init_namespace() { let mut namespace = ACPI_TABLE.namespace.write(); *namespace = Some(BTreeMap::new()); } - - let dsdt: &'static Sdt = if let Some(ref ptrs) = *(SDT_POINTERS.read()) { - if let Some(dsdt_sdt) = ptrs.get("DSDT") { - print!(" DSDT"); - dsdt_sdt - } else { - println!("No DSDT found"); - return; - } - } else { - return; - }; - - init_aml_table(dsdt); - let ssdt: &'static Sdt = if let Some(ref ptrs) = *(SDT_POINTERS.read()) { - if let Some(ssdt_sdt) = ptrs.get("SSDT") { - print!(" SSDT"); - ssdt_sdt - } else { - println!("No SSDT found"); - return; - } + let dsdt = find_sdt("DSDT"); + if dsdt.len() == 1 { + print!(" DSDT"); + load_table(get_sdt_signature(dsdt[0])); + init_aml_table(dsdt[0]); } else { + println!("Unable to find DSDT"); return; }; + + let ssdts = find_sdt("SSDT"); - init_aml_table(ssdt); + for ssdt in ssdts { + print!(" SSDT"); + load_table(get_sdt_signature(ssdt)); + init_aml_table(ssdt); + } } /// Parse the ACPI tables to gather CPU, interrupt, and timer information @@ -133,6 +123,11 @@ pub unsafe fn init(active_table: &mut ActivePageTable) { let mut sdt_ptrs = SDT_POINTERS.write(); *sdt_ptrs = Some(BTreeMap::new()); } + + { + let mut order = SDT_ORDER.write(); + *order = Some(vec!()); + } // Search for RSDP if let Some(rsdp) = RSDP::get_rsdp(active_table) { @@ -157,11 +152,9 @@ pub unsafe fn init(active_table: &mut ActivePageTable) { for sdt_address in rxsdt.iter() { let sdt = unsafe { &*(sdt_address as *const Sdt) }; - let signature = String::from_utf8(sdt.signature.to_vec()).expect("Error converting signature to string"); - { - if let Some(ref mut ptrs) = *(SDT_POINTERS.write()) { - ptrs.insert(signature, sdt); - } + let signature = get_sdt_signature(sdt); + if let Some(ref mut ptrs) = *(SDT_POINTERS.write()) { + ptrs.insert(signature, sdt); } } @@ -203,10 +196,38 @@ pub fn set_global_s_state(state: u8) { } } -pub static SDT_POINTERS: RwLock<Option<BTreeMap<String, &'static Sdt>>> = RwLock::new(None); +type SdtSignature = (String, [u8; 6], [u8; 8]); +pub static SDT_POINTERS: RwLock<Option<BTreeMap<SdtSignature, &'static Sdt>>> = RwLock::new(None); +pub static SDT_ORDER: RwLock<Option<Vec<SdtSignature>>> = RwLock::new(None); + +pub fn find_sdt(name: &str) -> Vec<&'static Sdt> { + let mut sdts: Vec<&'static Sdt> = vec!(); + + if let Some(ref ptrs) = *(SDT_POINTERS.read()) { + for (signature, sdt) in ptrs { + if signature.0 == name { + sdts.push(sdt); + } + } + } + + sdts +} + +pub fn get_sdt_signature(sdt: &'static Sdt) -> SdtSignature { + let signature = String::from_utf8(sdt.signature.to_vec()).expect("Error converting signature to string"); + (signature, sdt.oem_id, sdt.oem_table_id) +} + +pub fn load_table(signature: SdtSignature) { + let mut order = SDT_ORDER.write(); + + if let Some(ref mut o) = *order { + o.push(signature); + } +} pub struct Acpi { - pub rxsdt: RwLock<Option<Box<Rxsdt + Send + Sync>>>, pub fadt: RwLock<Option<Fadt>>, pub namespace: RwLock<Option<BTreeMap<String, AmlValue>>>, pub hpet: RwLock<Option<Hpet>>, @@ -214,7 +235,6 @@ pub struct Acpi { } pub static ACPI_TABLE: Acpi = Acpi { - rxsdt: RwLock::new(None), fadt: RwLock::new(None), namespace: RwLock::new(None), hpet: RwLock::new(None), -- GitLab