diff --git a/src/acpi/aml/dataobj.rs b/src/acpi/aml/dataobj.rs index 042b9d5..885396a 100644 --- a/src/acpi/aml/dataobj.rs +++ b/src/acpi/aml/dataobj.rs @@ -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 { + fn execute(&self, namespace: &mut BTreeMap, scope: String) -> Option { 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 { + fn execute(&self, namespace: &mut BTreeMap, scope: String) -> Option { 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 { + fn execute(&self, namespace: &mut BTreeMap, scope: String) -> Option { match *self { ComputationalData::Byte(b) => Some(AmlValue::IntegerConstant(b as u64)), ComputationalData::Word(w) => Some(AmlValue::IntegerConstant(w as u64)), diff --git a/src/acpi/aml/mod.rs b/src/acpi/aml/mod.rs index bc0cee9..a50ec4c 100644 --- a/src/acpi/aml/mod.rs +++ b/src/acpi/aml/mod.rs @@ -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; + fn execute(&self, namespace: &mut BTreeMap, scope: String) -> Option; } // TODO: make private @@ -42,7 +42,7 @@ pub enum AmlError { AmlParseError(&'static str) } -pub fn parse_aml_table(sdt: &'static Sdt) -> Result { +pub fn parse_aml_table(sdt: &'static Sdt) -> Result, 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 { // 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); diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index aeb2637..8a9f978 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -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 { + fn execute(&self, namespace: &mut BTreeMap, scope: String) -> Option { 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 + }); }, _ => () } diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index 3e12e55..fc801fc 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -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), - Namespace(Vec), - 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), + Device(BTreeMap), 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, + len: Box + }, Package(Vec), String(String), PowerResource, - Processor, + Processor { + proc_id: u8, + p_blk: Option, + obj_list: BTreeMap + }, RawDataBuffer, - ThermalZone + ThermalZone(BTreeMap) } 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 { - let scope_string = String::from_str(scope_str).unwrap(); - self.find(scope_string) - } - - pub fn find(&self, scope_string: String) -> Option { - 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; } diff --git a/src/acpi/aml/namespacemodifier.rs b/src/acpi/aml/namespacemodifier.rs index d6a003f..c1e2395 100644 --- a/src/acpi/aml/namespacemodifier.rs +++ b/src/acpi/aml/namespacemodifier.rs @@ -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 { + fn execute(&self, namespace: &mut BTreeMap, scope: String) -> Option { 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))); }, _ => () } diff --git a/src/acpi/aml/termlist.rs b/src/acpi/aml/termlist.rs index b998784..72d876d 100644 --- a/src/acpi/aml/termlist.rs +++ b/src/acpi/aml/termlist.rs @@ -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 { - fn execute(&self, namespace: &mut AmlNamespace, scope: String) -> Option { + fn execute(&self, namespace: &mut BTreeMap, scope: String) -> Option { for term in self { term.execute(namespace, scope.clone()); } @@ -48,7 +49,7 @@ impl AmlExecutable for Vec { } impl AmlExecutable for Object { - fn execute(&self, namespace: &mut AmlNamespace, scope: String) -> Option { + fn execute(&self, namespace: &mut BTreeMap, scope: String) -> Option { 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 { - fn execute(&self, namespace: &mut AmlNamespace, scope: String) -> Option { + fn execute(&self, namespace: &mut BTreeMap, scope: String) -> Option { for term in self { term.execute(namespace, scope.clone()); } @@ -67,7 +68,7 @@ impl AmlExecutable for Vec { } impl AmlExecutable for TermArg { - fn execute(&self, namespace: &mut AmlNamespace, scope: String) -> Option { + fn execute(&self, namespace: &mut BTreeMap, scope: String) -> Option { 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 { + fn execute(&self, namespace: &mut BTreeMap, scope: String) -> Option { match *self { TermObj::NamespaceModifier(ref res) => res.execute(namespace, scope.clone()), TermObj::NamedObj(ref res) => res.execute(namespace, scope.clone()), diff --git a/src/acpi/aml/type1opcode.rs b/src/acpi/aml/type1opcode.rs index 103e542..d476a24 100644 --- a/src/acpi/aml/type1opcode.rs +++ b/src/acpi/aml/type1opcode.rs @@ -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 { + fn execute(&self, namespace: &mut BTreeMap, scope: String) -> Option { None } } diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index 744dbef..0313d82 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -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 { + fn execute(&self, namespace: &mut BTreeMap, scope: String) -> Option { None } } @@ -273,7 +274,7 @@ pub enum PackageElement { } impl AmlExecutable for DefPackage { - fn execute(&self, namespace: &mut AmlNamespace, scope: String) -> Option { + fn execute(&self, namespace: &mut BTreeMap, scope: String) -> Option { match *self { DefPackage::Package { ref num_elements, ref elements } => { let mut values: Vec = vec!(); diff --git a/src/acpi/mod.rs b/src/acpi/mod.rs index f279116..9b07703 100644 --- a/src/acpi/mod.rs +++ b/src/acpi/mod.rs @@ -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, - pub namespace: Option, + pub namespace: Option>, pub hpet: Option } diff --git a/src/stop.rs b/src/stop.rs index 7a9ac75..4f152bf 100644 --- a/src/stop.rs +++ b/src/stop.rs @@ -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");