Cleanup ACPI code, find lower tables
This commit is contained in:
parent
d383cfb595
commit
7b2acdd79c
5
Makefile
5
Makefile
|
@ -10,7 +10,10 @@ bochs: build/harddrive.bin
|
|||
bochs -f bochs.$(ARCH)
|
||||
|
||||
qemu: build/harddrive.bin
|
||||
qemu-system-$(ARCH) -serial mon:stdio -drive file=$<,format=raw,index=0,media=disk -nographic -d guest_errors
|
||||
qemu-system-$(ARCH) -enable-kvm -cpu host -machine q35 \
|
||||
-serial mon:stdio -drive file=$<,format=raw,index=0,media=disk \
|
||||
-nographic -d guest_errors
|
||||
#-device intel-iommu
|
||||
|
||||
FORCE:
|
||||
|
||||
|
|
|
@ -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,23 +24,55 @@ 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) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Search for RSDP
|
||||
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) };
|
||||
let rxsdt = get_sdt(rsdp.sdt_address());
|
||||
|
||||
for &c in rxsdt.signature.iter() {
|
||||
print!("{}", c as char);
|
||||
}
|
||||
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!(" {:?}", sdt);
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
41
arch/x86_64/src/acpi/rsdt.rs
Normal file
41
arch/x86_64/src/acpi/rsdt.rs
Normal file
|
@ -0,0 +1,41 @@
|
|||
use core::mem;
|
||||
|
||||
use super::sdt::SDT;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct RSDT(&'static SDT);
|
||||
|
||||
impl RSDT {
|
||||
pub fn new(sdt: &'static SDT) -> Option<RSDT> {
|
||||
if &sdt.signature == b"RSDT" {
|
||||
Some(RSDT(sdt))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> RSDTIter {
|
||||
RSDTIter {
|
||||
sdt: self.0,
|
||||
i: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RSDTIter {
|
||||
sdt: &'static SDT,
|
||||
i: usize
|
||||
}
|
||||
|
||||
impl Iterator for RSDTIter {
|
||||
type Item = usize;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.i < self.sdt.data_len()/mem::size_of::<u32>() {
|
||||
let item = unsafe { *(self.sdt.data_address() as *const u32).offset(self.i as isize) };
|
||||
self.i += 1;
|
||||
Some(item as usize)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
use core::mem;
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[repr(packed)]
|
||||
pub struct SDTHeader {
|
||||
pub struct SDT {
|
||||
pub signature: [u8; 4],
|
||||
pub length: u32,
|
||||
pub revision: u8,
|
||||
|
@ -9,5 +11,23 @@ pub struct SDTHeader {
|
|||
pub oem_table_id: [u8; 8],
|
||||
pub oem_revision: u32,
|
||||
pub creator_id: u32,
|
||||
pub creator_revision: u32,
|
||||
pub creator_revision: u32
|
||||
}
|
||||
|
||||
impl SDT {
|
||||
/// Get the address of this tables data
|
||||
pub fn data_address(&'static self) -> usize {
|
||||
self as *const _ as usize + mem::size_of::<SDT>()
|
||||
}
|
||||
|
||||
/// Get the length of this tables data
|
||||
pub fn data_len(&'static self) -> usize {
|
||||
let total_size = self.length as usize;
|
||||
let header_size = mem::size_of::<SDT>();
|
||||
if total_size >= header_size {
|
||||
total_size - header_size
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
41
arch/x86_64/src/acpi/xsdt.rs
Normal file
41
arch/x86_64/src/acpi/xsdt.rs
Normal file
|
@ -0,0 +1,41 @@
|
|||
use core::mem;
|
||||
|
||||
use super::sdt::SDT;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct XSDT(&'static SDT);
|
||||
|
||||
impl XSDT {
|
||||
pub fn new(sdt: &'static SDT) -> Option<XSDT> {
|
||||
if &sdt.signature == b"XSDT" {
|
||||
Some(XSDT(sdt))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> XSDTIter {
|
||||
XSDTIter {
|
||||
sdt: self.0,
|
||||
i: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct XSDTIter {
|
||||
sdt: &'static SDT,
|
||||
i: usize
|
||||
}
|
||||
|
||||
impl Iterator for XSDTIter {
|
||||
type Item = usize;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.i < self.sdt.data_len()/mem::size_of::<u64>() {
|
||||
let item = unsafe { *(self.sdt.data_address() as *const u64).offset(self.i as isize) };
|
||||
self.i += 1;
|
||||
Some(item as usize)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue