Implemented table API in full

This commit is contained in:
Connor Wood
2017-07-23 13:42:30 +01:00
parent 4288182106
commit c79eb0eeab
10 changed files with 125 additions and 22 deletions

View File

@@ -36,8 +36,12 @@ pub enum AmlError {
}
pub fn parse_aml_table(sdt: &Sdt) -> Result<Vec<String>, AmlError> {
parse_aml_with_scope(sdt, String::from_str("\\").unwrap())
}
pub fn parse_aml_with_scope(sdt: &Sdt, scope: String) -> Result<Vec<String>, AmlError> {
let data = sdt.data();
let mut ctx = AmlExecutionContext::new(String::from_str("\\").unwrap());
let mut ctx = AmlExecutionContext::new(scope);
parse_term_list(data, &mut ctx)?;

View File

@@ -113,6 +113,13 @@ impl AmlValue {
_ => Err(AmlError::AmlValueError)
}
}
pub fn get_as_ddb_handle(&self) -> Result<Vec<String>, AmlError> {
match *self {
AmlValue::DDBHandle(ref v) => Ok(v.clone()),
_ => Err(AmlError::AmlValueError)
}
}
pub fn get_as_string(&self) -> Result<String, AmlError> {
match *self {

View File

@@ -363,12 +363,19 @@ fn parse_def_unload(data: &[u8],
})
}
// TODO: remove from namespace all values added when `object` was loaded
// TODO: globally synchronous (how?)
parser_opcode_extended!(data, 0x2A);
let object = parse_super_name(&data[2..], ctx)?;
let delta = ctx.get(object.val).get_as_ddb_handle()?;
let mut namespace = ctx.prelock();
if let Some(ref mut ns) = *namespace {
for o in delta {
ns.remove(&o);
}
}
Ok(AmlParseType {
val: AmlValue::None,
len: 2 + object.len

View File

@@ -2,7 +2,7 @@ use alloc::boxed::Box;
use collections::string::String;
use collections::vec::Vec;
use super::AmlError;
use super::{AmlError, parse_aml_with_scope};
use super::parser::{AmlParseType, ParseResult, AmlExecutionContext, ExecutionState};
use super::namespace::{AmlValue, ObjectReference};
use super::pkglength::parse_pkg_length;
@@ -11,6 +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;
#[derive(Debug, Clone)]
pub enum MatchOpcode {
@@ -1263,8 +1264,6 @@ fn parse_def_load_table(data: &[u8],
})
}
// TODO: Compute the result
// TODO: Store the result, if appropriate
// TODO: Clean up
parser_opcode_extended!(data, 0x1F);
@@ -1275,8 +1274,34 @@ 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 {
let sig_str = unsafe {
*(signature.val.get_as_string()?.as_bytes().as_ptr() as *const [u8; 4])
};
let oem_str = unsafe {
*(oem_id.val.get_as_string()?.as_bytes().as_ptr() as *const [u8; 6])
};
let oem_table_str = unsafe {
*(oem_table_id.val.get_as_string()?.as_bytes().as_ptr() as *const [u8; 8])
};
let sdt = rxsdt.find(sig_str, oem_str, oem_table_str);
if let Some(sdt) = sdt {
let hdl = parse_aml_with_scope(sdt, root_path.val.get_as_string()?)?;
ctx.modify(parameter_path.val, parameter_data.val);
return Ok(AmlParseType {
val: AmlValue::DDBHandle(hdl),
len: 2 + signature.len + oem_id.len + oem_table_id.len + root_path.len + parameter_path.len + parameter_data.len
});
}
}
Ok(AmlParseType {
val: AmlValue::Uninitialized,
val: AmlValue::IntegerConstant(0),
len: 2 + signature.len + oem_id.len + oem_table_id.len + root_path.len + parameter_path.len + parameter_data.len
})
}

View File

@@ -5,6 +5,7 @@ use core::intrinsics::{atomic_load, atomic_store};
use core::sync::atomic::Ordering;
use collections::btree_map::BTreeMap;
use collections::string::String;
use alloc::boxed::Box;
use syscall::io::{Io, Pio};
@@ -25,6 +26,7 @@ use self::rsdt::Rsdt;
use self::sdt::Sdt;
use self::xsdt::Xsdt;
use self::hpet::Hpet;
use self::rxsdt::Rxsdt;
use self::aml::{is_aml_table, parse_aml_table, AmlError, AmlValue};
@@ -36,6 +38,7 @@ mod rsdt;
mod sdt;
mod xsdt;
mod aml;
mod rxsdt;
const TRAMPOLINE: usize = 0x7E00;
const AP_STARTUP: usize = TRAMPOLINE + 512;
@@ -261,18 +264,32 @@ pub unsafe fn init(active_table: &mut ActivePageTable) {
print!("{}", c as char);
}
println!(":");
if let Some(rsdt) = Rsdt::new(rxsdt) {
for sdt_address in rsdt.iter() {
let sdt = get_sdt(sdt_address, active_table);
parse_sdt(sdt, active_table);
}
let rxsdt: Box<Rxsdt + Send + Sync> = if let Some(rsdt) = Rsdt::new(rxsdt) {
Box::new(rsdt)
} else if let Some(xsdt) = Xsdt::new(rxsdt) {
for sdt_address in xsdt.iter() {
let sdt = get_sdt(sdt_address, active_table);
parse_sdt(sdt, active_table);
}
Box::new(xsdt)
} else {
println!("UNKNOWN RSDT OR XSDT SIGNATURE");
return;
};
{
let mut rxsdt_ptr = ACPI_TABLE.rxsdt.write();
*rxsdt_ptr = Some(rxsdt);
}
{
let rxsdt_ptr = ACPI_TABLE.rxsdt.read();
if let Some(ref rxsdt) = *rxsdt_ptr {
rxsdt.map_all(active_table);
for sdt_address in rxsdt.iter() {
let sdt = unsafe { &*(sdt_address as *const Sdt) };
parse_sdt(sdt, active_table);
}
}
}
} else {
println!("NO RSDP FOUND");
@@ -321,6 +338,7 @@ pub fn set_global_s_state(state: u8) {
}
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>>,
@@ -328,6 +346,7 @@ 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),

View File

@@ -1,6 +1,8 @@
use core::mem;
use alloc::boxed::Box;
use super::sdt::Sdt;
use super::rxsdt::Rxsdt;
#[derive(Debug)]
pub struct Rsdt(&'static Sdt);
@@ -13,12 +15,14 @@ impl Rsdt {
None
}
}
}
pub fn iter(&self) -> RsdtIter {
RsdtIter {
impl Rxsdt for Rsdt {
fn iter(&self) -> Box<Iterator<Item = usize>> {
Box::new(RsdtIter {
sdt: self.0,
i: 0
}
})
}
}

28
src/acpi/rxsdt.rs Normal file
View File

@@ -0,0 +1,28 @@
use alloc::boxed::Box;
use paging::ActivePageTable;
use super::sdt::Sdt;
use super::get_sdt;
pub trait Rxsdt {
fn iter(&self) -> Box<Iterator<Item = usize>>;
fn map_all(&self, active_table: &mut ActivePageTable) {
for sdt in self.iter() {
get_sdt(sdt, active_table);
}
}
fn find(&self, signature: [u8; 4], oem_id: [u8; 6], oem_table_id: [u8; 8]) -> Option<&'static Sdt> {
for sdt in self.iter() {
let sdt = unsafe { &*(sdt as *const Sdt) };
if sdt.match_pattern(signature, oem_id, oem_table_id) {
return Some(sdt);
}
}
return None;
}
}

View File

@@ -35,4 +35,8 @@ impl Sdt {
pub fn data(&self) -> &[u8] {
unsafe { slice::from_raw_parts(self.data_address() as *const u8, self.data_len()) }
}
pub fn match_pattern(&self, signature: [u8; 4], oem_id: [u8; 6], oem_table_id: [u8; 8]) -> bool{
self.signature == signature && self.oem_id == oem_id && self.oem_table_id == oem_table_id
}
}

View File

@@ -1,6 +1,8 @@
use core::mem;
use alloc::boxed::Box;
use super::sdt::Sdt;
use super::rxsdt::Rxsdt;
#[derive(Debug)]
pub struct Xsdt(&'static Sdt);
@@ -13,12 +15,14 @@ impl Xsdt {
None
}
}
}
pub fn iter(&self) -> XsdtIter {
XsdtIter {
impl Rxsdt for Xsdt {
fn iter(&self) -> Box<Iterator<Item = usize>> {
Box::new(XsdtIter {
sdt: self.0,
i: 0
}
})
}
}

View File

@@ -19,6 +19,7 @@
#![feature(never_type)]
#![feature(thread_local)]
#![feature(unique)]
#![feature(conservative_impl_trait)]
#![no_std]
extern crate alloc_kernel as allocator;