Moved Processor to namespace, and refactored namespace layout to use BTreeMap

This commit is contained in:
Connor Wood
2017-06-21 20:02:05 +01:00
parent 73562b3f56
commit b4ddaeadbb
10 changed files with 96 additions and 225 deletions

View File

@@ -1,7 +1,8 @@
use collections::vec::Vec;
use collections::string::String;
use collections::btree_map::BTreeMap;
use super::{AmlInternalError, AmlExecutable, AmlValue, AmlNamespace, get_namespace_string};
use super::{AmlInternalError, AmlExecutable, AmlValue, get_namespace_string};
use super::type2opcode::{parse_def_buffer, parse_def_package, parse_def_var_package,
DefBuffer, DefPackage, DefVarPackage};
@@ -43,7 +44,7 @@ pub enum ComputationalData {
}
impl AmlExecutable for DataRefObj {
fn execute(&self, namespace: &mut AmlNamespace, scope: String) -> Option<AmlValue> {
fn execute(&self, namespace: &mut BTreeMap<String, AmlValue>, scope: String) -> Option<AmlValue> {
match *self {
DataRefObj::DataObj(ref cd) => cd.execute(namespace, scope),
_ => Some(AmlValue::Integer)
@@ -52,7 +53,7 @@ impl AmlExecutable for DataRefObj {
}
impl AmlExecutable for DataObj {
fn execute(&self, namespace: &mut AmlNamespace, scope: String) -> Option<AmlValue> {
fn execute(&self, namespace: &mut BTreeMap<String, AmlValue>, scope: String) -> Option<AmlValue> {
match *self {
DataObj::ComputationalData(ref cd) => cd.execute(namespace, scope),
DataObj::DefPackage(ref pkg) => pkg.execute(namespace, scope),
@@ -62,7 +63,7 @@ impl AmlExecutable for DataObj {
}
impl AmlExecutable for ComputationalData {
fn execute(&self, namespace: &mut AmlNamespace, scope: String) -> Option<AmlValue> {
fn execute(&self, namespace: &mut BTreeMap<String, AmlValue>, scope: String) -> Option<AmlValue> {
match *self {
ComputationalData::Byte(b) => Some(AmlValue::IntegerConstant(b as u64)),
ComputationalData::Word(w) => Some(AmlValue::IntegerConstant(w as u64)),

View File

@@ -4,6 +4,7 @@
use alloc::boxed::Box;
use collections::string::String;
use collections::vec::Vec;
use collections::btree_map::BTreeMap;
use core::fmt::Debug;
use core::str::FromStr;
@@ -23,12 +24,11 @@ mod type1opcode;
mod type2opcode;
use self::termlist::{parse_term_list, TermObj};
pub use self::namespace::{get_namespace_string, AmlNamespace, AmlValue};
use self::namespace::AmlNamespaceContents;
pub use self::namespace::{get_namespace_string, AmlValue};
// TODO: This should be able to take parameters, and may also return multiple values
pub trait AmlExecutable {
fn execute(&self, namespace: &mut AmlNamespace, scope: String) -> Option<AmlValue>;
fn execute(&self, namespace: &mut BTreeMap<String, AmlValue>, scope: String) -> Option<AmlValue>;
}
// TODO: make private
@@ -42,7 +42,7 @@ pub enum AmlError {
AmlParseError(&'static str)
}
pub fn parse_aml_table(sdt: &'static Sdt) -> Result<AmlNamespace, AmlError> {
pub fn parse_aml_table(sdt: &'static Sdt) -> Result<BTreeMap<String, AmlValue>, AmlError> {
let data = sdt.data();
let term_list = match parse_term_list(data) {
@@ -56,7 +56,7 @@ pub fn parse_aml_table(sdt: &'static Sdt) -> Result<AmlNamespace, AmlError> {
// Unwrap is fine here. I mean come on, if this goes wrong you've got bigger problems than AML
// not loading...
let mut global_namespace = AmlNamespace::new_namespace(&global_namespace_specifier);
let mut global_namespace = BTreeMap::new();
term_list.execute(&mut global_namespace, global_namespace_specifier.clone());
println!("{:#?}", global_namespace);

View File

@@ -1,8 +1,11 @@
use alloc::boxed::Box;
use collections::string::String;
use collections::vec::Vec;
use core::str::FromStr;
use super::{AmlInternalError, AmlExecutable, AmlValue, AmlNamespace, AmlNamespaceContents, get_namespace_string};
use collections::btree_map::BTreeMap;
use super::{AmlInternalError, AmlExecutable, AmlValue, get_namespace_string};
use super::namestring::{parse_name_string, parse_name_seg};
use super::termlist::{parse_term_arg, parse_term_list, parse_object_list, TermArg, TermObj, Object};
use super::pkglength::parse_pkg_length;
@@ -115,7 +118,7 @@ pub struct Method {
}
impl AmlExecutable for NamedObj {
fn execute(&self, namespace: &mut AmlNamespace, scope: String) -> Option<AmlValue> {
fn execute(&self, namespace: &mut BTreeMap<String, AmlValue>, scope: String) -> Option<AmlValue> {
match *self {
NamedObj::DefOpRegion { ref name, ref region, ref offset, ref len } => {
let local_scope_string = get_namespace_string(scope.clone(), name.clone());
@@ -130,10 +133,10 @@ impl AmlExecutable for NamedObj {
_ => return None
};
namespace.push_to(local_scope_string, AmlNamespaceContents::OpRegion {
namespace.insert(local_scope_string, AmlValue::OperationRegion {
region: *region,
offset: resolved_offset,
len: resolved_len
offset: Box::new(resolved_offset),
len: Box::new(resolved_len)
});
},
NamedObj::DefField { ref name, ref flags, ref field_list } => {
@@ -145,7 +148,7 @@ impl AmlExecutable for NamedObj {
FieldElement::NamedField { name: ref field_name, length } => {
let local_scope_string = get_namespace_string(scope.clone(),
field_name.clone());
namespace.push_to(local_scope_string, AmlNamespaceContents::Field {
namespace.insert(local_scope_string, AmlValue::FieldUnit {
op_region: name.clone(),
flags: flags.clone(),
offset: offset.clone(),
@@ -160,16 +163,35 @@ impl AmlExecutable for NamedObj {
},
NamedObj::DefMethod { ref name, ref method } => {
let local_scope_string = get_namespace_string(scope.clone(), name.clone());
namespace.push_to(local_scope_string, AmlNamespaceContents::Value(
AmlValue::Method(method.clone())));
namespace.insert(local_scope_string, AmlValue::Method(method.clone()));
},
NamedObj::DefDevice { ref name, ref obj_list } => {
let local_scope_string = get_namespace_string(scope, name.clone());
obj_list.execute(namespace, local_scope_string);
let mut local_namespace = BTreeMap::new();
obj_list.execute(&mut local_namespace, String::new());
namespace.insert(local_scope_string, AmlValue::Device(local_namespace));
},
NamedObj::DefThermalZone { ref name, ref obj_list } => {
let local_scope_string = get_namespace_string(scope, name.clone());
obj_list.execute(namespace, local_scope_string);
let mut local_namespace = BTreeMap::new();
obj_list.execute(&mut local_namespace, String::new());
namespace.insert(local_scope_string, AmlValue::ThermalZone(local_namespace));
},
NamedObj::DefProcessor { ref name, proc_id, p_blk_addr, p_blk_len, ref obj_list } => {
let local_scope_string = get_namespace_string(scope, name.clone());
let mut local_namespace = BTreeMap::new();
obj_list.execute(&mut local_namespace, String::new());
namespace.insert(local_scope_string, AmlValue::Processor {
proc_id: proc_id,
p_blk: if p_blk_len > 0 { Some(p_blk_addr) } else { None },
obj_list: local_namespace
});
},
_ => ()
}

View File

@@ -1,36 +1,13 @@
use alloc::boxed::Box;
use collections::string::String;
use collections::vec::Vec;
use collections::btree_map::BTreeMap;
use core::str::FromStr;
use super::namedobj::{ RegionSpace, FieldFlags, Method };
use super::termlist::Object;
#[derive(Debug, Clone)]
pub struct AmlNamespace {
name: String,
contents: AmlNamespaceContents
}
#[derive(Debug, Clone)]
pub enum AmlNamespaceContents {
Value(AmlValue),
SubNamespace(Box<AmlNamespace>),
Namespace(Vec<AmlNamespaceContents>),
Alias(String),
OpRegion {
region: RegionSpace,
offset: AmlValue,
len: AmlValue
},
Field {
op_region: String,
flags: FieldFlags,
offset: usize,
length: usize
}
}
use super::namestring::SuperName;
#[derive(Debug, Clone)]
pub enum AmlValue {
@@ -39,21 +16,34 @@ pub enum AmlValue {
BufferField,
DDBHandle,
DebugObject,
Device(Vec<Object>),
Device(BTreeMap<String, AmlValue>),
Event,
FieldUnit,
FieldUnit {
op_region: String,
flags: FieldFlags,
offset: usize,
length: usize
},
Integer,
IntegerConstant(u64),
Method(Method),
Mutex,
ObjectReference,
OperationRegion,
ObjectReference(SuperName),
OperationRegion {
region: RegionSpace,
offset: Box<AmlValue>,
len: Box<AmlValue>
},
Package(Vec<AmlValue>),
String(String),
PowerResource,
Processor,
Processor {
proc_id: u8,
p_blk: Option<u32>,
obj_list: BTreeMap<String, AmlValue>
},
RawDataBuffer,
ThermalZone
ThermalZone(BTreeMap<String, AmlValue>)
}
impl AmlValue {
@@ -72,161 +62,15 @@ impl AmlValue {
}
}
impl AmlNamespace {
pub fn new_namespace(name: &String) -> AmlNamespace {
AmlNamespace {
name: name.clone(),
contents: AmlNamespaceContents::Namespace(vec!())
}
}
pub fn find_str(&self, scope_str: &str) -> Option<AmlValue> {
let scope_string = String::from_str(scope_str).unwrap();
self.find(scope_string)
}
pub fn find(&self, scope_string: String) -> Option<AmlValue> {
if scope_string.len() == 0 {
match self.contents {
AmlNamespaceContents::Value(ref v) => return Some(v.clone()),
_ => return None
}
}
let mut scope_string = scope_string.clone();
if scope_string.starts_with("\\") {
if self.name != "\\" {
return None;
}
scope_string.remove(0);
}
if scope_string.starts_with(".") {
scope_string.remove(0);
}
if scope_string.len() == 0 {
match self.contents {
AmlNamespaceContents::Value(ref v) => return Some(v.clone()),
_ => return None
}
}
let (current, nextset) = match scope_string.find(".") {
Some(s) => {
let (x, mut y) = scope_string.split_at(s);
y = &y[1..];
(String::from_str(x).unwrap(), String::from_str(y).unwrap())
},
None => if scope_string.len() <= 4 {
(scope_string, String::from_str("").unwrap())
} else {
return None;
}
};
match self.contents {
AmlNamespaceContents::Namespace(ref namespace) => {
// TODO: Remove this while loop here, there has to be a more elegant way
let mut current_index = 0;
while current_index < namespace.len() {
match namespace[current_index] {
AmlNamespaceContents::SubNamespace(ref ns) => if ns.name == current {
return ns.find(nextset);
},
_ => ()
}
current_index += 1;
}
},
_ => ()
}
None
}
pub fn push(&mut self, val: AmlNamespaceContents) {
match self.contents {
AmlNamespaceContents::Namespace(ref mut v) => v.push(val),
_ => () // TODO: Error this
}
}
pub fn push_to(&mut self, scope_string: String, contents: AmlNamespaceContents) {
if scope_string.len() == 0 {
return;
}
let mut scope_string = scope_string.clone();
if scope_string.starts_with("\\") {
if self.name != "\\" {
return;
// TODO: Error this
}
scope_string.remove(0);
}
if scope_string.starts_with(".") {
scope_string.remove(0);
}
if scope_string.len() == 0 {
return;
}
let (current, nextset) = match scope_string.find(".") {
Some(s) => {
let (x, mut y) = scope_string.split_at(s);
y = &y[1..];
(String::from_str(x).unwrap(), String::from_str(y).unwrap())
},
None => if scope_string.len() <= 4 {
(scope_string, String::from_str("").unwrap())
} else {
return;
}
};
match self.contents {
AmlNamespaceContents::Namespace(ref mut namespace) => {
// TODO: Remove this while loop here, there has to be a more elegant way
let mut current_index = 0;
while current_index < namespace.len() {
match namespace[current_index] {
AmlNamespaceContents::SubNamespace(ref mut ns) => if ns.name == current {
ns.push_to(nextset, contents);
return;
},
_ => ()
}
current_index += 1;
}
let mut next = AmlNamespace {
name: current,
contents: contents
};
namespace.push(AmlNamespaceContents::SubNamespace(Box::new(next)));
}
_ => () // TODO: Error this
}
}
pub fn push_subordinate_namespace(&mut self, scope_string: String) {
self.push_to(scope_string, AmlNamespaceContents::Namespace(vec!()));
}
}
pub fn get_namespace_string(current: String, modifier: String) -> String {
if current.len() == 0 {
return modifier;
}
if modifier.len() == 0 {
return current;
}
if modifier.starts_with("\\") {
return modifier;
}

View File

@@ -1,10 +1,11 @@
use alloc::boxed::Box;
use collections::string::String;
use collections::vec::Vec;
use collections::btree_map::BTreeMap;
use super::{AmlInternalError, AmlExecutable, AmlValue, AmlNamespace, AmlNamespaceContents, get_namespace_string};
use super::{AmlInternalError, AmlExecutable, AmlValue, get_namespace_string};
use super::pkglength::parse_pkg_length;
use super::namestring::parse_name_string;
use super::namestring::{parse_name_string, SuperName};
use super::termlist::{parse_term_list, TermObj};
use super::dataobj::{parse_data_ref_obj, DataRefObj};
@@ -26,12 +27,10 @@ pub enum NamespaceModifier {
}
impl AmlExecutable for NamespaceModifier {
fn execute(&self, namespace: &mut AmlNamespace, scope: String) -> Option<AmlValue> {
fn execute(&self, namespace: &mut BTreeMap<String, AmlValue>, scope: String) -> Option<AmlValue> {
match *self {
NamespaceModifier::Scope { name: ref name, terms: ref terms } => {
let local_scope_string = get_namespace_string(scope, name.clone());
namespace.push_subordinate_namespace(local_scope_string.clone());
terms.execute(namespace, local_scope_string);
},
NamespaceModifier::Name { ref name, ref data_ref_obj } => {
@@ -41,13 +40,13 @@ impl AmlExecutable for NamespaceModifier {
None => return None
};
namespace.push_to(local_scope_string, AmlNamespaceContents::Value(dro));
namespace.insert(local_scope_string, dro);
},
NamespaceModifier::Alias { ref source_name, ref alias_name } => {
let local_scope_string = get_namespace_string(scope.clone(), source_name.clone());
let local_alias_string = get_namespace_string(scope.clone(), alias_name.clone());
namespace.push_to(local_scope_string, AmlNamespaceContents::Alias(local_alias_string));
namespace.insert(local_scope_string, AmlValue::ObjectReference(SuperName::NameString(local_alias_string)));
},
_ => ()
}

View File

@@ -1,8 +1,9 @@
use alloc::boxed::Box;
use collections::string::String;
use collections::vec::Vec;
use collections::btree_map::BTreeMap;
use super::{AmlInternalError, AmlExecutable, AmlValue, AmlNamespace, get_namespace_string};
use super::{AmlInternalError, AmlExecutable, AmlValue, get_namespace_string};
use super::namespacemodifier::{parse_namespace_modifier, NamespaceModifier};
use super::namedobj::{parse_named_obj, NamedObj};
use super::dataobj::{parse_data_obj, parse_arg_obj, parse_local_obj, DataObj, ArgObj, LocalObj};
@@ -38,7 +39,7 @@ pub struct MethodInvocation {
}
impl AmlExecutable for Vec<Object> {
fn execute(&self, namespace: &mut AmlNamespace, scope: String) -> Option<AmlValue> {
fn execute(&self, namespace: &mut BTreeMap<String, AmlValue>, scope: String) -> Option<AmlValue> {
for term in self {
term.execute(namespace, scope.clone());
}
@@ -48,7 +49,7 @@ impl AmlExecutable for Vec<Object> {
}
impl AmlExecutable for Object {
fn execute(&self, namespace: &mut AmlNamespace, scope: String) -> Option<AmlValue> {
fn execute(&self, namespace: &mut BTreeMap<String, AmlValue>, scope: String) -> Option<AmlValue> {
match *self {
Object::NamespaceModifier(ref d) => d.execute(namespace, scope),
Object::NamedObj(ref d) => d.execute(namespace, scope)
@@ -57,7 +58,7 @@ impl AmlExecutable for Object {
}
impl AmlExecutable for Vec<TermObj> {
fn execute(&self, namespace: &mut AmlNamespace, scope: String) -> Option<AmlValue> {
fn execute(&self, namespace: &mut BTreeMap<String, AmlValue>, scope: String) -> Option<AmlValue> {
for term in self {
term.execute(namespace, scope.clone());
}
@@ -67,7 +68,7 @@ impl AmlExecutable for Vec<TermObj> {
}
impl AmlExecutable for TermArg {
fn execute(&self, namespace: &mut AmlNamespace, scope: String) -> Option<AmlValue> {
fn execute(&self, namespace: &mut BTreeMap<String, AmlValue>, scope: String) -> Option<AmlValue> {
match *self {
TermArg::LocalObj(ref l) => Some(AmlValue::Integer),
TermArg::DataObj(ref d) => d.execute(namespace, scope),
@@ -78,7 +79,7 @@ impl AmlExecutable for TermArg {
}
impl AmlExecutable for TermObj {
fn execute(&self, namespace: &mut AmlNamespace, scope: String) -> Option<AmlValue> {
fn execute(&self, namespace: &mut BTreeMap<String, AmlValue>, scope: String) -> Option<AmlValue> {
match *self {
TermObj::NamespaceModifier(ref res) => res.execute(namespace, scope.clone()),
TermObj::NamedObj(ref res) => res.execute(namespace, scope.clone()),

View File

@@ -1,8 +1,9 @@
use alloc::boxed::Box;
use collections::string::String;
use collections::vec::Vec;
use collections::btree_map::BTreeMap;
use super::{AmlInternalError, AmlExecutable, AmlValue, AmlNamespace};
use super::{AmlInternalError, AmlExecutable, AmlValue};
use super::pkglength::parse_pkg_length;
use super::termlist::{parse_term_arg, parse_term_list, TermObj, TermArg};
use super::namestring::{parse_name_string, parse_super_name, SuperName};
@@ -45,7 +46,7 @@ pub enum Type1OpCode {
}
impl AmlExecutable for Type1OpCode {
fn execute(&self, namespace: &mut AmlNamespace, scope: String) -> Option<AmlValue> {
fn execute(&self, namespace: &mut BTreeMap<String, AmlValue>, scope: String) -> Option<AmlValue> {
None
}
}

View File

@@ -1,8 +1,9 @@
use alloc::boxed::Box;
use collections::string::String;
use collections::vec::Vec;
use collections::btree_map::BTreeMap;
use super::{AmlInternalError, AmlExecutable, AmlValue, AmlNamespace};
use super::{AmlInternalError, AmlExecutable, AmlValue};
use super::pkglength::parse_pkg_length;
use super::termlist::{parse_term_arg, parse_method_invocation, TermArg, MethodInvocation};
use super::namestring::{parse_super_name, parse_target, parse_name_string, parse_simple_name,
@@ -201,7 +202,7 @@ pub enum Type2OpCode {
}
impl AmlExecutable for Type2OpCode {
fn execute(&self, namespace: &mut AmlNamespace, scope: String) -> Option<AmlValue> {
fn execute(&self, namespace: &mut BTreeMap<String, AmlValue>, scope: String) -> Option<AmlValue> {
None
}
}
@@ -273,7 +274,7 @@ pub enum PackageElement {
}
impl AmlExecutable for DefPackage {
fn execute(&self, namespace: &mut AmlNamespace, scope: String) -> Option<AmlValue> {
fn execute(&self, namespace: &mut BTreeMap<String, AmlValue>, scope: String) -> Option<AmlValue> {
match *self {
DefPackage::Package { ref num_elements, ref elements } => {
let mut values: Vec<AmlValue> = vec!();

View File

@@ -3,6 +3,8 @@
use core::intrinsics::{atomic_load, atomic_store};
use core::sync::atomic::Ordering;
use collections::btree_map::BTreeMap;
use collections::string::String;
use spin::Mutex;
@@ -20,7 +22,7 @@ use self::sdt::Sdt;
use self::xsdt::Xsdt;
use self::hpet::Hpet;
use self::aml::{is_aml_table, parse_aml_table, AmlNamespace, AmlError};
use self::aml::{is_aml_table, parse_aml_table, AmlError, AmlValue};
pub mod hpet;
mod dmar;
@@ -273,7 +275,7 @@ pub unsafe fn init(active_table: &mut ActivePageTable) {
pub struct Acpi {
pub fadt: Option<Fadt>,
pub namespace: Option<AmlNamespace>,
pub namespace: Option<BTreeMap<String, AmlValue>>,
pub hpet: Option<Hpet>
}

View File

@@ -12,7 +12,7 @@ pub unsafe extern fn kstop() -> ! {
let port = fadt.pm1a_control_block as u16;
let mut val = 1 << 13;
if let Some(ref namespace) = acpi.namespace {
if let Some(s) = namespace.find_str("\\_S5") {
if let Some(s) = namespace.get("\\_S5") {
if let Some(p) = s.get_as_package() {
let slp_typa = p[0].get_as_integer().expect("SLP_TYPa is not an integer");
let slp_typb = p[1].get_as_integer().expect("SLP_TYPb is not an integer");