Cleanup ACPI code, find lower tables

This commit is contained in:
Jeremy Soller 2016-08-16 12:16:32 -06:00
commit 7b2acdd79c

View file

@ -1,14 +1,16 @@
//! # ACPI
//! Code to parse the ACPI tables
use core::mem;
use memory::{Frame, FrameAllocator};
use paging::{entry, ActivePageTable, Page, PhysicalAddress, VirtualAddress};
use self::sdt::SDTHeader;
use self::rsdt::RSDT;
use self::sdt::SDT;
use self::xsdt::XSDT;
pub mod rsdt;
pub mod sdt;
pub mod xsdt;
/// Parse the ACPI tables to gather CPU, interrupt, and timer information
pub unsafe fn init<A>(allocator: &mut A, active_table: &mut ActivePageTable) -> Option<Acpi>
@ -22,7 +24,9 @@ pub unsafe fn init<A>(allocator: &mut A, active_table: &mut ActivePageTable) ->
let start_frame = Frame::containing_address(PhysicalAddress::new(start_addr));
let end_frame = Frame::containing_address(PhysicalAddress::new(end_addr));
for frame in Frame::range_inclusive(start_frame, end_frame) {
active_table.identity_map(frame, entry::PRESENT | entry::NO_EXECUTE, allocator);
if active_table.translate_page(Page::containing_address(VirtualAddress::new(frame.start_address().get()))).is_none() {
active_table.identity_map(frame, entry::PRESENT | entry::NO_EXECUTE, allocator);
}
}
}
@ -30,15 +34,45 @@ pub unsafe fn init<A>(allocator: &mut A, active_table: &mut ActivePageTable) ->
if let Some(rsdp) = RSDP::search(start_addr, end_addr) {
println!("{:?}", rsdp);
let rsdt_frame = Frame::containing_address(PhysicalAddress::new(rsdp.rsdt_address as usize));
active_table.identity_map(rsdt_frame, entry::PRESENT | entry::NO_EXECUTE, allocator);
let mut get_sdt = |sdt_address: usize| -> &'static SDT {
if active_table.translate_page(Page::containing_address(VirtualAddress::new(sdt_address))).is_none() {
let sdt_frame = Frame::containing_address(PhysicalAddress::new(sdt_address));
active_table.identity_map(sdt_frame, entry::PRESENT | entry::NO_EXECUTE, allocator);
}
unsafe { &*(sdt_address as *const SDT) }
};
let sdt = unsafe { &*(rsdp.rsdt_address as usize as *const SDTHeader) };
for &c in sdt.signature.iter() {
let rxsdt = get_sdt(rsdp.sdt_address());
for &c in rxsdt.signature.iter() {
print!("{}", c as char);
}
println!(" {:?}", sdt);
println!(":");
if let Some(rsdt) = RSDT::new(rxsdt) {
println!("{:?}", rsdt);
for sdt_address in rsdt.iter() {
let sdt = get_sdt(sdt_address);
for &c in sdt.signature.iter() {
print!("{}", c as char);
}
println!(":");
println!("{:?}", sdt);
}
} else if let Some(xsdt) = XSDT::new(rxsdt) {
println!("{:?}", xsdt);
for sdt_address in xsdt.iter() {
let sdt = get_sdt(sdt_address);
for &c in sdt.signature.iter() {
print!("{}", c as char);
}
println!(":");
println!("{:?}", sdt);
}
} else {
println!("UNKNOWN RSDT OR XSDT SIGNATURE");
}
} else {
println!("NO RSDP FOUND");
}
None
@ -56,19 +90,29 @@ pub struct RSDP {
revision: u8,
rsdt_address: u32,
length: u32,
xsdt_address: u32,
xsdt_address: u64,
extended_checksum: u8,
reserved: [u8; 3]
}
impl RSDP {
/// Search for the RSDP
pub fn search(start_addr: usize, end_addr: usize) -> Option<RSDP> {
for i in 0 .. (end_addr + 1 - start_addr)/mem::size_of::<RSDP>() {
let mut rsdp = unsafe { &*(start_addr as *const RSDP).offset(i as isize) };
for i in 0 .. (end_addr + 1 - start_addr)/16 {
let mut rsdp = unsafe { &*((start_addr + i * 16) as *const RSDP) };
if &rsdp.signature == b"RSD PTR " {
return Some(*rsdp);
}
}
None
}
/// Get the RSDT or XSDT address
pub fn sdt_address(&self) -> usize {
if self.revision >= 2 {
self.xsdt_address as usize
} else {
self.rsdt_address as usize
}
}
}