diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs
index f193575..cd94e70 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 e2cf184..549f686 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);
+ 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);
+ 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);
- },
- _ => ()
- }
+ 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 c6ff36c..6dd82d8 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;
- };
-
- 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 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;
+ };
- let mut fadt_t = ACPI_TABLE.fadt.write();
- *fadt_t = Some(fadt);
+ if let Some(fadt) = fadt {
+ println!(" FACP: {:X}", fadt.dsdt);
+
+ let dsdt_sdt = get_sdt(fadt.dsdt as usize, active_table);
+
+ 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 7b92648..d2e5ecf 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 501bba5..c4f922a 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);
+ println!(" XAPIC {}: {:>08X}", me, local_apic.address);
+ }
- let local_apic = unsafe { &mut LOCAL_APIC };
- let me = local_apic.id() as u8;
+ if cfg!(feature = "multi_core"){
+ let trampoline_frame = Frame::containing_address(PhysicalAddress::new(TRAMPOLINE));
+ let trampoline_page = Page::containing_address(VirtualAddress::new(TRAMPOLINE));
- if local_apic.x2 {
- println!(" X2APIC {}", me);
- } else {
- println!(" XAPIC {}: {:>08X}", me, local_apic.address);
- }
+ // Map trampoline
+ let result = active_table.map_to(trampoline_page, trampoline_frame, entry::PRESENT | entry::WRITABLE);
+ result.flush(active_table);
- if cfg!(feature = "multi_core"){
- let trampoline_frame = Frame::containing_address(PhysicalAddress::new(TRAMPOLINE));
- let trampoline_page = Page::containing_address(VirtualAddress::new(TRAMPOLINE));
+ 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);
- // Map trampoline
- let result = active_table.map_to(trampoline_page, trampoline_frame, entry::PRESENT | entry::WRITABLE);
- result.flush(active_table);
+ // 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;
- 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);
+ 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) };
- // 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;
+ // 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);
- 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) };
+ print!(" AP {}:", ap_local_apic.id);
- // 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 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;
}
-
- // 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;
- }
-
- print!(" SIPI...");
- local_apic.set_icr(icr);
- }
-
- // 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");
-
- active_table.flush_all();
- } else {
- println!(" CPU Disabled");
+ print!(" IPI...");
+ local_apic.set_icr(icr);
}
- },
- _ => ()
- }
- }
- // Unmap trampoline
- let (result, _frame) = active_table.unmap_return(trampoline_page, false);
- result.flush(active_table);
+ // 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;
+ }
+
+ print!(" SIPI...");
+ local_apic.set_icr(icr);
+ }
+
+ // 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");
+
+ 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 a1d5ecc..5902ebc 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