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)
|
bochs -f bochs.$(ARCH)
|
||||||
|
|
||||||
qemu: build/harddrive.bin
|
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:
|
FORCE:
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
//! # ACPI
|
//! # ACPI
|
||||||
//! Code to parse the ACPI tables
|
//! Code to parse the ACPI tables
|
||||||
|
|
||||||
use core::mem;
|
|
||||||
|
|
||||||
use memory::{Frame, FrameAllocator};
|
use memory::{Frame, FrameAllocator};
|
||||||
use paging::{entry, ActivePageTable, Page, PhysicalAddress, VirtualAddress};
|
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 sdt;
|
||||||
|
pub mod xsdt;
|
||||||
|
|
||||||
/// Parse the ACPI tables to gather CPU, interrupt, and timer information
|
/// 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>
|
pub unsafe fn init<A>(allocator: &mut A, active_table: &mut ActivePageTable) -> Option<Acpi>
|
||||||
|
@ -22,24 +24,56 @@ pub unsafe fn init<A>(allocator: &mut A, active_table: &mut ActivePageTable) ->
|
||||||
let start_frame = Frame::containing_address(PhysicalAddress::new(start_addr));
|
let start_frame = Frame::containing_address(PhysicalAddress::new(start_addr));
|
||||||
let end_frame = Frame::containing_address(PhysicalAddress::new(end_addr));
|
let end_frame = Frame::containing_address(PhysicalAddress::new(end_addr));
|
||||||
for frame in Frame::range_inclusive(start_frame, end_frame) {
|
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);
|
active_table.identity_map(frame, entry::PRESENT | entry::NO_EXECUTE, allocator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Search for RSDP
|
// Search for RSDP
|
||||||
if let Some(rsdp) = RSDP::search(start_addr, end_addr) {
|
if let Some(rsdp) = RSDP::search(start_addr, end_addr) {
|
||||||
println!("{:?}", rsdp);
|
println!("{:?}", rsdp);
|
||||||
|
|
||||||
let rsdt_frame = Frame::containing_address(PhysicalAddress::new(rsdp.rsdt_address as usize));
|
let mut get_sdt = |sdt_address: usize| -> &'static SDT {
|
||||||
active_table.identity_map(rsdt_frame, entry::PRESENT | entry::NO_EXECUTE, allocator);
|
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() {
|
for &c in sdt.signature.iter() {
|
||||||
print!("{}", c as char);
|
print!("{}", c as char);
|
||||||
}
|
}
|
||||||
|
println!(":");
|
||||||
println!("{:?}", sdt);
|
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
|
None
|
||||||
}
|
}
|
||||||
|
@ -56,19 +90,29 @@ pub struct RSDP {
|
||||||
revision: u8,
|
revision: u8,
|
||||||
rsdt_address: u32,
|
rsdt_address: u32,
|
||||||
length: u32,
|
length: u32,
|
||||||
xsdt_address: u32,
|
xsdt_address: u64,
|
||||||
extended_checksum: u8,
|
extended_checksum: u8,
|
||||||
reserved: [u8; 3]
|
reserved: [u8; 3]
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RSDP {
|
impl RSDP {
|
||||||
|
/// Search for the RSDP
|
||||||
pub fn search(start_addr: usize, end_addr: usize) -> Option<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>() {
|
for i in 0 .. (end_addr + 1 - start_addr)/16 {
|
||||||
let mut rsdp = unsafe { &*(start_addr as *const RSDP).offset(i as isize) };
|
let mut rsdp = unsafe { &*((start_addr + i * 16) as *const RSDP) };
|
||||||
if &rsdp.signature == b"RSD PTR " {
|
if &rsdp.signature == b"RSD PTR " {
|
||||||
return Some(*rsdp);
|
return Some(*rsdp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
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)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
#[repr(packed)]
|
#[repr(packed)]
|
||||||
pub struct SDTHeader {
|
pub struct SDT {
|
||||||
pub signature: [u8; 4],
|
pub signature: [u8; 4],
|
||||||
pub length: u32,
|
pub length: u32,
|
||||||
pub revision: u8,
|
pub revision: u8,
|
||||||
|
@ -9,5 +11,23 @@ pub struct SDTHeader {
|
||||||
pub oem_table_id: [u8; 8],
|
pub oem_table_id: [u8; 8],
|
||||||
pub oem_revision: u32,
|
pub oem_revision: u32,
|
||||||
pub creator_id: 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