From 190686a85348ec43c0a5c1f9626a032e7afa0d1b Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Mon, 19 Jun 2017 13:33:20 +0100 Subject: [PATCH 001/113] Moved Alias to the namespace --- src/acpi/aml/mod.rs | 18 +++--------------- src/acpi/aml/namespace.rs | 15 +++++++++++++++ src/acpi/aml/namespacemodifier.rs | 6 ++++++ src/start.rs | 3 +++ 4 files changed, 27 insertions(+), 15 deletions(-) diff --git a/src/acpi/aml/mod.rs b/src/acpi/aml/mod.rs index 296317d..bc0cee9 100644 --- a/src/acpi/aml/mod.rs +++ b/src/acpi/aml/mod.rs @@ -23,7 +23,7 @@ mod type1opcode; mod type2opcode; use self::termlist::{parse_term_list, TermObj}; -pub use self::namespace::{AmlNamespace, AmlValue}; +pub use self::namespace::{get_namespace_string, AmlNamespace, AmlValue}; use self::namespace::AmlNamespaceContents; // TODO: This should be able to take parameters, and may also return multiple values @@ -42,20 +42,6 @@ pub enum AmlError { AmlParseError(&'static str) } -pub fn get_namespace_string(current: String, modifier: String) -> String { - if modifier.starts_with("\\") { - return modifier; - } - - if modifier.starts_with("^") { - // TODO - } - - let mut namespace = current.clone(); - namespace.push('.'); - namespace + &modifier -} - pub fn parse_aml_table(sdt: &'static Sdt) -> Result { let data = sdt.data(); @@ -73,6 +59,8 @@ pub fn parse_aml_table(sdt: &'static Sdt) -> Result { let mut global_namespace = AmlNamespace::new_namespace(&global_namespace_specifier); term_list.execute(&mut global_namespace, global_namespace_specifier.clone()); + println!("{:#?}", global_namespace); + Ok(global_namespace) } diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index dc3c1c8..9f7343e 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -17,6 +17,7 @@ pub enum AmlNamespaceContents { Value(AmlValue), SubNamespace(Box), Namespace(Vec), + Alias(String), OpRegion { region: RegionSpace, offset: AmlValue, @@ -223,3 +224,17 @@ impl AmlNamespace { self.push_to(scope_string, AmlNamespaceContents::Namespace(vec!())); } } + +pub fn get_namespace_string(current: String, modifier: String) -> String { + if modifier.starts_with("\\") { + return modifier; + } + + if modifier.starts_with("^") { + // TODO + } + + let mut namespace = current.clone(); + namespace.push('.'); + namespace + &modifier +} diff --git a/src/acpi/aml/namespacemodifier.rs b/src/acpi/aml/namespacemodifier.rs index 217347a..d6a003f 100644 --- a/src/acpi/aml/namespacemodifier.rs +++ b/src/acpi/aml/namespacemodifier.rs @@ -43,6 +43,12 @@ impl AmlExecutable for NamespaceModifier { namespace.push_to(local_scope_string, AmlNamespaceContents::Value(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)); + }, _ => () } diff --git a/src/start.rs b/src/start.rs index bf9deda..55e5cbe 100644 --- a/src/start.rs +++ b/src/start.rs @@ -15,6 +15,8 @@ use memory; use paging::{self, entry, Page, VirtualAddress}; use paging::mapper::MapperFlushAll; +use stop; + /// Test of zero values in BSS. static BSS_TEST_ZERO: usize = 0; /// Test of non-zero values in data. @@ -157,6 +159,7 @@ pub unsafe extern fn kstart_ap(cpu_id: usize, bsp_table: usize, stack_start: usi } pub unsafe fn usermode(ip: usize, sp: usize) -> ! { + stop::kstop(); // Go to usermode asm!("mov ds, ax mov es, ax From 3ed94405aa93b0c3df9be0093f6e41da1154a03c Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Mon, 19 Jun 2017 13:49:37 +0100 Subject: [PATCH 002/113] Moved DefDevice and DefThermalZone to namespace --- src/acpi/aml/namedobj.rs | 8 ++++++++ src/acpi/aml/namespace.rs | 3 ++- src/acpi/aml/termlist.rs | 19 +++++++++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index 26cca7b..aeb2637 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -163,6 +163,14 @@ impl AmlExecutable for NamedObj { namespace.push_to(local_scope_string, AmlNamespaceContents::Value( 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); + }, + NamedObj::DefThermalZone { ref name, ref obj_list } => { + let local_scope_string = get_namespace_string(scope, name.clone()); + obj_list.execute(namespace, local_scope_string); + }, _ => () } diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index 9f7343e..f869cea 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -5,6 +5,7 @@ use collections::vec::Vec; use core::str::FromStr; use super::namedobj::{ RegionSpace, FieldFlags, Method }; +use super::termlist::Object; #[derive(Debug, Clone)] pub struct AmlNamespace { @@ -38,7 +39,7 @@ pub enum AmlValue { BufferField, DDBHandle, DebugObject, - Device, + Device(Vec), Event, FieldUnit, Integer, diff --git a/src/acpi/aml/termlist.rs b/src/acpi/aml/termlist.rs index b236584..b998784 100644 --- a/src/acpi/aml/termlist.rs +++ b/src/acpi/aml/termlist.rs @@ -37,6 +37,25 @@ pub struct MethodInvocation { } +impl AmlExecutable for Vec { + fn execute(&self, namespace: &mut AmlNamespace, scope: String) -> Option { + for term in self { + term.execute(namespace, scope.clone()); + } + + None + } +} + +impl AmlExecutable for Object { + fn execute(&self, namespace: &mut AmlNamespace, scope: String) -> Option { + match *self { + Object::NamespaceModifier(ref d) => d.execute(namespace, scope), + Object::NamedObj(ref d) => d.execute(namespace, scope) + } + } +} + impl AmlExecutable for Vec { fn execute(&self, namespace: &mut AmlNamespace, scope: String) -> Option { for term in self { From 7095219316eb800c7779f7a463c442dc67af936c Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Mon, 19 Jun 2017 14:12:26 +0100 Subject: [PATCH 003/113] Moved ComputationalData::String into namespace --- src/acpi/aml/dataobj.rs | 1 + src/acpi/aml/namespace.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/acpi/aml/dataobj.rs b/src/acpi/aml/dataobj.rs index 4400c8d..042b9d5 100644 --- a/src/acpi/aml/dataobj.rs +++ b/src/acpi/aml/dataobj.rs @@ -71,6 +71,7 @@ impl AmlExecutable for ComputationalData { ComputationalData::Zero => Some(AmlValue::IntegerConstant(0)), ComputationalData::One => Some(AmlValue::IntegerConstant(1)), ComputationalData::Ones => Some(AmlValue::IntegerConstant(0xFFFFFFFFFFFFFFFF)), + ComputationalData::String(ref s) => Some(AmlValue::String(s.clone())), _ => Some(AmlValue::Integer) } } diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index f869cea..3e12e55 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -49,7 +49,7 @@ pub enum AmlValue { ObjectReference, OperationRegion, Package(Vec), - String, + String(String), PowerResource, Processor, RawDataBuffer, From 636d94fd20273c375187262d42ba19e2c6775d0a Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Wed, 21 Jun 2017 20:02:05 +0100 Subject: [PATCH 004/113] Moved Processor to namespace, and refactored namespace layout to use BTreeMap --- src/acpi/aml/dataobj.rs | 9 +- src/acpi/aml/mod.rs | 10 +- src/acpi/aml/namedobj.rs | 42 ++++-- src/acpi/aml/namespace.rs | 214 ++++-------------------------- src/acpi/aml/namespacemodifier.rs | 13 +- src/acpi/aml/termlist.rs | 13 +- src/acpi/aml/type1opcode.rs | 5 +- src/acpi/aml/type2opcode.rs | 7 +- src/acpi/mod.rs | 6 +- src/stop.rs | 2 +- 10 files changed, 96 insertions(+), 225 deletions(-) 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 54a55e5..e1f617f 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; @@ -19,7 +21,7 @@ use self::rsdt::Rsdt; use self::sdt::Sdt; use self::xsdt::Xsdt; -use self::aml::{is_aml_table, parse_aml_table, AmlNamespace, AmlError}; +use self::aml::{is_aml_table, parse_aml_table, AmlError, AmlValue}; mod dmar; mod fadt; @@ -268,7 +270,7 @@ pub unsafe fn init(active_table: &mut ActivePageTable) { pub struct Acpi { pub fadt: Option, - pub namespace: Option, + pub namespace: Option>, } pub static ACPI_TABLE: Mutex = Mutex::new(Acpi { fadt: None, namespace: None }); 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"); From fceba822ebe8e3f008eee7255a89780bc5758df9 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Wed, 21 Jun 2017 20:13:44 +0100 Subject: [PATCH 005/113] Moved PowerResource into namespace --- src/acpi/aml/namedobj.rs | 12 ++++++++++++ src/acpi/aml/namespace.rs | 6 +++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index 8a9f978..8589d6f 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -193,6 +193,18 @@ impl AmlExecutable for NamedObj { obj_list: local_namespace }); }, + NamedObj::DefPowerRes { ref name, system_level, resource_order, 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::PowerResource { + system_level, + resource_order, + obj_list: local_namespace + }); + }, _ => () } diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index fc801fc..5d725da 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -36,7 +36,11 @@ pub enum AmlValue { }, Package(Vec), String(String), - PowerResource, + PowerResource { + system_level: u8, + resource_order: u16, + obj_list: BTreeMap + }, Processor { proc_id: u8, p_blk: Option, From 19ccb3612b3e0884162a6d8a627076ea43a313dd Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Wed, 21 Jun 2017 20:27:46 +0100 Subject: [PATCH 006/113] Moved Mutex to namespace --- src/acpi/aml/namedobj.rs | 4 ++++ src/acpi/aml/namespace.rs | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index 8589d6f..4fdd8f6 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -205,6 +205,10 @@ impl AmlExecutable for NamedObj { obj_list: local_namespace }); }, + NamedObj::DefMutex { ref name, sync_level } => { + let local_scope_string = get_namespace_string(scope, name.clone()); + namespace.insert(local_scope_string, AmlValue::Mutex(sync_level)); + }, _ => () } diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index 5d725da..ab49846 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -27,7 +27,7 @@ pub enum AmlValue { Integer, IntegerConstant(u64), Method(Method), - Mutex, + Mutex(u8), ObjectReference(SuperName), OperationRegion { region: RegionSpace, From 312aff03c458be8725ce92b493bddbed5a063b8b Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Wed, 21 Jun 2017 20:50:08 +0100 Subject: [PATCH 007/113] Moved Event to namespace --- src/acpi/aml/.#namedobj.rs | 1 + src/acpi/aml/namedobj.rs | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 120000 src/acpi/aml/.#namedobj.rs diff --git a/src/acpi/aml/.#namedobj.rs b/src/acpi/aml/.#namedobj.rs new file mode 120000 index 0000000..66a0d21 --- /dev/null +++ b/src/acpi/aml/.#namedobj.rs @@ -0,0 +1 @@ +venos@Maponos.11470:1498034251 \ No newline at end of file diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index 4fdd8f6..24b6256 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -209,7 +209,11 @@ impl AmlExecutable for NamedObj { let local_scope_string = get_namespace_string(scope, name.clone()); namespace.insert(local_scope_string, AmlValue::Mutex(sync_level)); }, - _ => () + NamedObj::DefEvent { ref name } => { + let local_scope_string = get_namespace_string(scope, name.clone()); + namespace.insert(local_scope_string, AmlValue::Event); + }, +// _ => () } None From 2e64cea81f7037e6c8647f35673a62e40f1a234e Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Wed, 21 Jun 2017 20:54:29 +0100 Subject: [PATCH 008/113] Removed temporary files --- src/acpi/aml/.#namedobj.rs | 1 - src/acpi/aml/namedobj.rs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) delete mode 120000 src/acpi/aml/.#namedobj.rs diff --git a/src/acpi/aml/.#namedobj.rs b/src/acpi/aml/.#namedobj.rs deleted file mode 120000 index 66a0d21..0000000 --- a/src/acpi/aml/.#namedobj.rs +++ /dev/null @@ -1 +0,0 @@ -venos@Maponos.11470:1498034251 \ No newline at end of file diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index 24b6256..87c5bc7 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -213,7 +213,7 @@ impl AmlExecutable for NamedObj { let local_scope_string = get_namespace_string(scope, name.clone()); namespace.insert(local_scope_string, AmlValue::Event); }, -// _ => () + _ => () } None From 12e7d1ad4db4c8a23e0f71fbd046dbe723e0b511 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Thu, 22 Jun 2017 12:02:17 +0100 Subject: [PATCH 009/113] Moved BankField to the namespace --- src/acpi/aml/namedobj.rs | 29 +++++++++++++++++++++++++++++ src/acpi/aml/namespace.rs | 1 + 2 files changed, 30 insertions(+) diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index 87c5bc7..203d20a 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -120,6 +120,34 @@ pub struct Method { impl AmlExecutable for NamedObj { fn execute(&self, namespace: &mut BTreeMap, scope: String) -> Option { match *self { + NamedObj::DefBankField { ref region_name, ref bank_name, ref bank_value, ref flags, ref field_list } => { + let mut offset: usize = 0; + let bank_val = if let Some(b) = bank_value.execute(namespace, scope.clone()) { + Box::new(b) + } else { + return None; + }; + + for f in field_list { + match *f { + FieldElement::ReservedField { length } => offset += length, + FieldElement::NamedField { name: ref field_name, length } => { + let local_scope_string = get_namespace_string(scope.clone(), + field_name.clone()); + namespace.insert(local_scope_string, AmlValue::FieldUnit { + op_region: region_name.clone(), + bank_selector: Some((bank_name.clone(), bank_val.clone())), + flags: flags.clone(), + offset: offset.clone(), + length: length.clone() + }); + + offset += length; + }, + _ => () + } + } + }, NamedObj::DefOpRegion { ref name, ref region, ref offset, ref len } => { let local_scope_string = get_namespace_string(scope.clone(), name.clone()); @@ -150,6 +178,7 @@ impl AmlExecutable for NamedObj { field_name.clone()); namespace.insert(local_scope_string, AmlValue::FieldUnit { op_region: name.clone(), + bank_selector: None, flags: flags.clone(), offset: offset.clone(), length: length.clone() diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index ab49846..0e99aaf 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -20,6 +20,7 @@ pub enum AmlValue { Event, FieldUnit { op_region: String, + bank_selector: Option<(String, Box)>, flags: FieldFlags, offset: usize, length: usize From cef562c83213e0f3c0e6c3b02e79be4610b4c442 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Thu, 22 Jun 2017 12:16:30 +0100 Subject: [PATCH 010/113] Moved BufferFields into namespace --- src/acpi/aml/namedobj.rs | 90 +++++++++++++++++++++++++++++++++++++++ src/acpi/aml/namespace.rs | 6 ++- 2 files changed, 95 insertions(+), 1 deletion(-) diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index 203d20a..1123535 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -148,6 +148,96 @@ impl AmlExecutable for NamedObj { } } }, + NamedObj::DefCreateBitField { ref name, ref source_buf, ref bit_index } => { + let local_scope_string = get_namespace_string(scope.clone(), name.clone()); + + let resolved_source_buf = match source_buf.execute(namespace, scope.clone()) { + Some(r) => Box::new(r), + _ => return None + }; + let resolved_index = match bit_index.execute(namespace, scope.clone()) { + Some(r) => Box::new(r), + _ => return None + }; + + namespace.insert(local_scope_string, AmlValue::BufferField { + source_buf: resolved_source_buf, + index: resolved_index, + length: 1 + }); + }, + NamedObj::DefCreateByteField { ref name, ref source_buf, ref byte_index } => { + let local_scope_string = get_namespace_string(scope.clone(), name.clone()); + + let resolved_source_buf = match source_buf.execute(namespace, scope.clone()) { + Some(r) => Box::new(r), + _ => return None + }; + let resolved_index = match byte_index.execute(namespace, scope.clone()) { + Some(r) => Box::new(r), + _ => return None + }; + + namespace.insert(local_scope_string, AmlValue::BufferField { + source_buf: resolved_source_buf, + index: resolved_index, + length: 8 + }); + }, + NamedObj::DefCreateWordField { ref name, ref source_buf, ref byte_index } => { + let local_scope_string = get_namespace_string(scope.clone(), name.clone()); + + let resolved_source_buf = match source_buf.execute(namespace, scope.clone()) { + Some(r) => Box::new(r), + _ => return None + }; + let resolved_index = match byte_index.execute(namespace, scope.clone()) { + Some(r) => Box::new(r), + _ => return None + }; + + namespace.insert(local_scope_string, AmlValue::BufferField { + source_buf: resolved_source_buf, + index: resolved_index, + length: 16 + }); + }, + NamedObj::DefCreateDWordField { ref name, ref source_buf, ref byte_index } => { + let local_scope_string = get_namespace_string(scope.clone(), name.clone()); + + let resolved_source_buf = match source_buf.execute(namespace, scope.clone()) { + Some(r) => Box::new(r), + _ => return None + }; + let resolved_index = match byte_index.execute(namespace, scope.clone()) { + Some(r) => Box::new(r), + _ => return None + }; + + namespace.insert(local_scope_string, AmlValue::BufferField { + source_buf: resolved_source_buf, + index: resolved_index, + length: 32 + }); + }, + NamedObj::DefCreateQWordField { ref name, ref source_buf, ref byte_index } => { + let local_scope_string = get_namespace_string(scope.clone(), name.clone()); + + let resolved_source_buf = match source_buf.execute(namespace, scope.clone()) { + Some(r) => Box::new(r), + _ => return None + }; + let resolved_index = match byte_index.execute(namespace, scope.clone()) { + Some(r) => Box::new(r), + _ => return None + }; + + namespace.insert(local_scope_string, AmlValue::BufferField { + source_buf: resolved_source_buf, + index: resolved_index, + length: 64 + }); + }, NamedObj::DefOpRegion { ref name, ref region, ref offset, ref len } => { let local_scope_string = get_namespace_string(scope.clone(), name.clone()); diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index 0e99aaf..f95a25a 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -13,7 +13,11 @@ use super::namestring::SuperName; pub enum AmlValue { Uninitialized, Buffer, - BufferField, + BufferField { + source_buf: Box, + index: Box, + length: usize + }, DDBHandle, DebugObject, Device(BTreeMap), From 94e391c9b6802b13887d4feff14ddfdfd646b667 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Thu, 22 Jun 2017 12:23:14 +0100 Subject: [PATCH 011/113] Moved arbitrary length buffer field into namespace --- src/acpi/aml/namedobj.rs | 32 +++++++++++++++++++++++++++----- src/acpi/aml/namespace.rs | 2 +- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index 1123535..dc206a1 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -163,7 +163,7 @@ impl AmlExecutable for NamedObj { namespace.insert(local_scope_string, AmlValue::BufferField { source_buf: resolved_source_buf, index: resolved_index, - length: 1 + length: Box::new(AmlValue::IntegerConstant(1)) }); }, NamedObj::DefCreateByteField { ref name, ref source_buf, ref byte_index } => { @@ -181,7 +181,7 @@ impl AmlExecutable for NamedObj { namespace.insert(local_scope_string, AmlValue::BufferField { source_buf: resolved_source_buf, index: resolved_index, - length: 8 + length: Box::new(AmlValue::IntegerConstant(8)) }); }, NamedObj::DefCreateWordField { ref name, ref source_buf, ref byte_index } => { @@ -199,7 +199,7 @@ impl AmlExecutable for NamedObj { namespace.insert(local_scope_string, AmlValue::BufferField { source_buf: resolved_source_buf, index: resolved_index, - length: 16 + length: Box::new(AmlValue::IntegerConstant(16)) }); }, NamedObj::DefCreateDWordField { ref name, ref source_buf, ref byte_index } => { @@ -217,7 +217,7 @@ impl AmlExecutable for NamedObj { namespace.insert(local_scope_string, AmlValue::BufferField { source_buf: resolved_source_buf, index: resolved_index, - length: 32 + length: Box::new(AmlValue::IntegerConstant(32)) }); }, NamedObj::DefCreateQWordField { ref name, ref source_buf, ref byte_index } => { @@ -235,7 +235,29 @@ impl AmlExecutable for NamedObj { namespace.insert(local_scope_string, AmlValue::BufferField { source_buf: resolved_source_buf, index: resolved_index, - length: 64 + length: Box::new(AmlValue::IntegerConstant(64)) + }); + }, + NamedObj::DefCreateField { ref name, ref source_buf, ref bit_index, ref num_bits } => { + let local_scope_string = get_namespace_string(scope.clone(), name.clone()); + + let resolved_source_buf = match source_buf.execute(namespace, scope.clone()) { + Some(r) => Box::new(r), + _ => return None + }; + let resolved_index = match bit_index.execute(namespace, scope.clone()) { + Some(r) => Box::new(r), + _ => return None + }; + let resolved_length = match num_bits.execute(namespace, scope.clone()) { + Some(r) => Box::new(r), + _ => return None + }; + + namespace.insert(local_scope_string, AmlValue::BufferField { + source_buf: resolved_source_buf, + index: resolved_index, + length: resolved_length }); }, NamedObj::DefOpRegion { ref name, ref region, ref offset, ref len } => { diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index f95a25a..f52206f 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -16,7 +16,7 @@ pub enum AmlValue { BufferField { source_buf: Box, index: Box, - length: usize + length: Box }, DDBHandle, DebugObject, From 443c1ac1f8c42432246fc891a14009a6a9c9fb0a Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Thu, 22 Jun 2017 12:45:58 +0100 Subject: [PATCH 012/113] Moved indexfield to namespace --- src/acpi/aml/namedobj.rs | 35 +++++++++++++++++++++++++++++++---- src/acpi/aml/namespace.rs | 16 ++++++++++++++-- 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index dc206a1..0a21504 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -6,6 +6,7 @@ use core::str::FromStr; use collections::btree_map::BTreeMap; use super::{AmlInternalError, AmlExecutable, AmlValue, get_namespace_string}; +use super::namespace::FieldSelector; 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; @@ -135,8 +136,35 @@ impl AmlExecutable for NamedObj { let local_scope_string = get_namespace_string(scope.clone(), field_name.clone()); namespace.insert(local_scope_string, AmlValue::FieldUnit { - op_region: region_name.clone(), - bank_selector: Some((bank_name.clone(), bank_val.clone())), + selector: FieldSelector::Bank { + region: region_name.clone(), + bank_selector: bank_val.clone() + }, + flags: flags.clone(), + offset: offset.clone(), + length: length.clone() + }); + + offset += length; + }, + _ => () + } + } + }, + NamedObj::DefIndexField { ref idx_name, ref data_name, ref flags, ref field_list } => { + let mut offset: usize = 0; + + for f in field_list { + match *f { + FieldElement::ReservedField { length } => offset += length, + FieldElement::NamedField { name: ref field_name, length } => { + let local_scope_string = get_namespace_string(scope.clone(), + field_name.clone()); + namespace.insert(local_scope_string, AmlValue::FieldUnit { + selector: FieldSelector::Index { + index_selector: idx_name.clone(), + data_selector: data_name.clone() + }, flags: flags.clone(), offset: offset.clone(), length: length.clone() @@ -289,8 +317,7 @@ impl AmlExecutable for NamedObj { let local_scope_string = get_namespace_string(scope.clone(), field_name.clone()); namespace.insert(local_scope_string, AmlValue::FieldUnit { - op_region: name.clone(), - bank_selector: None, + selector: FieldSelector::Region(name.clone()), flags: flags.clone(), offset: offset.clone(), length: length.clone() diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index f52206f..7d16ec0 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -9,6 +9,19 @@ use super::namedobj::{ RegionSpace, FieldFlags, Method }; use super::termlist::Object; use super::namestring::SuperName; +#[derive(Debug, Clone)] +pub enum FieldSelector { + Region(String), + Bank { + region: String, + bank_selector: Box + }, + Index { + index_selector: String, + data_selector: String + } +} + #[derive(Debug, Clone)] pub enum AmlValue { Uninitialized, @@ -23,8 +36,7 @@ pub enum AmlValue { Device(BTreeMap), Event, FieldUnit { - op_region: String, - bank_selector: Option<(String, Box)>, + selector: FieldSelector, flags: FieldFlags, offset: usize, length: usize From 0a67ad4b235e57fa5d20cb6104c07111c57fc295 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Thu, 22 Jun 2017 13:34:05 +0100 Subject: [PATCH 013/113] Moved DataRegion into namespace - more infrastructure required --- src/acpi/aml/namedobj.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index 0a21504..7b40db4 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -288,6 +288,15 @@ impl AmlExecutable for NamedObj { length: resolved_length }); }, + NamedObj::DefDataRegion { ref name, ref signature, ref oem_id, ref oem_table_id } => { + let local_scope_string = get_namespace_string(scope.clone(), name.clone()); + + namespace.insert(local_scope_string, AmlValue::OperationRegion { + region: RegionSpace::SystemMemory, + offset: Box::new(AmlValue::IntegerConstant(0)), + len: Box::new(AmlValue::IntegerConstant(0)) + }); + }, NamedObj::DefOpRegion { ref name, ref region, ref offset, ref len } => { let local_scope_string = get_namespace_string(scope.clone(), name.clone()); From c8eca653b8a894e0f8baa15958edd3d0a30183c6 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Thu, 22 Jun 2017 15:09:04 +0100 Subject: [PATCH 014/113] Moved ConnectFieldNameString into namespace --- src/acpi/aml/namedobj.rs | 14 +++++++++++++- src/acpi/aml/namespace.rs | 1 + 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index 7b40db4..40de06f 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -7,7 +7,7 @@ use collections::btree_map::BTreeMap; use super::{AmlInternalError, AmlExecutable, AmlValue, get_namespace_string}; use super::namespace::FieldSelector; -use super::namestring::{parse_name_string, parse_name_seg}; +use super::namestring::{parse_name_string, parse_name_seg, SuperName}; use super::termlist::{parse_term_arg, parse_term_list, parse_object_list, TermArg, TermObj, Object}; use super::pkglength::parse_pkg_length; use super::type2opcode::{parse_def_buffer, DefBuffer}; @@ -123,6 +123,7 @@ impl AmlExecutable for NamedObj { match *self { NamedObj::DefBankField { ref region_name, ref bank_name, ref bank_value, ref flags, ref field_list } => { let mut offset: usize = 0; + let mut connection = AmlValue::Uninitialized; let bank_val = if let Some(b) = bank_value.execute(namespace, scope.clone()) { Box::new(b) } else { @@ -132,6 +133,8 @@ impl AmlExecutable for NamedObj { for f in field_list { match *f { FieldElement::ReservedField { length } => offset += length, + FieldElement::ConnectFieldNameString(ref name) => connection = + AmlValue::ObjectReference(SuperName::NameString(name.clone())), FieldElement::NamedField { name: ref field_name, length } => { let local_scope_string = get_namespace_string(scope.clone(), field_name.clone()); @@ -140,6 +143,7 @@ impl AmlExecutable for NamedObj { region: region_name.clone(), bank_selector: bank_val.clone() }, + connection: Box::new(connection.clone()), flags: flags.clone(), offset: offset.clone(), length: length.clone() @@ -153,10 +157,13 @@ impl AmlExecutable for NamedObj { }, NamedObj::DefIndexField { ref idx_name, ref data_name, ref flags, ref field_list } => { let mut offset: usize = 0; + let mut connection = AmlValue::Uninitialized; for f in field_list { match *f { FieldElement::ReservedField { length } => offset += length, + FieldElement::ConnectFieldNameString(ref name) => connection = + AmlValue::ObjectReference(SuperName::NameString(name.clone())), FieldElement::NamedField { name: ref field_name, length } => { let local_scope_string = get_namespace_string(scope.clone(), field_name.clone()); @@ -165,6 +172,7 @@ impl AmlExecutable for NamedObj { index_selector: idx_name.clone(), data_selector: data_name.clone() }, + connection: Box::new(connection.clone()), flags: flags.clone(), offset: offset.clone(), length: length.clone() @@ -318,15 +326,19 @@ impl AmlExecutable for NamedObj { }, NamedObj::DefField { ref name, ref flags, ref field_list } => { let mut offset: usize = 0; + let mut connection = AmlValue::Uninitialized; for f in field_list { match *f { FieldElement::ReservedField { length } => offset += length, + FieldElement::ConnectFieldNameString(ref name) => connection = + AmlValue::ObjectReference(SuperName::NameString(name.clone())), FieldElement::NamedField { name: ref field_name, length } => { let local_scope_string = get_namespace_string(scope.clone(), field_name.clone()); namespace.insert(local_scope_string, AmlValue::FieldUnit { selector: FieldSelector::Region(name.clone()), + connection: Box::new(connection.clone()), flags: flags.clone(), offset: offset.clone(), length: length.clone() diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index 7d16ec0..375057e 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -37,6 +37,7 @@ pub enum AmlValue { Event, FieldUnit { selector: FieldSelector, + connection: Box, flags: FieldFlags, offset: usize, length: usize From fb0e5137e883cc2918ef5140eb973b8f18bbbe92 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Thu, 22 Jun 2017 15:22:19 +0100 Subject: [PATCH 015/113] Moved ConnectFieldBufferData to the namespace --- src/acpi/aml/namedobj.rs | 18 ++++++++++++++++++ src/acpi/aml/namespace.rs | 5 ++++- src/acpi/aml/type2opcode.rs | 19 +++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index 40de06f..664b767 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -135,6 +135,12 @@ impl AmlExecutable for NamedObj { FieldElement::ReservedField { length } => offset += length, FieldElement::ConnectFieldNameString(ref name) => connection = AmlValue::ObjectReference(SuperName::NameString(name.clone())), + FieldElement::ConnectFieldBufferData(ref buf) => { + connection = match buf.execute(namespace, scope.clone()) { + Some(c) => c, + None => return None + }; + }, FieldElement::NamedField { name: ref field_name, length } => { let local_scope_string = get_namespace_string(scope.clone(), field_name.clone()); @@ -164,6 +170,12 @@ impl AmlExecutable for NamedObj { FieldElement::ReservedField { length } => offset += length, FieldElement::ConnectFieldNameString(ref name) => connection = AmlValue::ObjectReference(SuperName::NameString(name.clone())), + FieldElement::ConnectFieldBufferData(ref buf) => { + connection = match buf.execute(namespace, scope.clone()) { + Some(c) => c, + None => return None + }; + }, FieldElement::NamedField { name: ref field_name, length } => { let local_scope_string = get_namespace_string(scope.clone(), field_name.clone()); @@ -333,6 +345,12 @@ impl AmlExecutable for NamedObj { FieldElement::ReservedField { length } => offset += length, FieldElement::ConnectFieldNameString(ref name) => connection = AmlValue::ObjectReference(SuperName::NameString(name.clone())), + FieldElement::ConnectFieldBufferData(ref buf) => { + connection = match buf.execute(namespace, scope.clone()) { + Some(c) => c, + None => return None + }; + }, FieldElement::NamedField { name: ref field_name, length } => { let local_scope_string = get_namespace_string(scope.clone(), field_name.clone()); diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index 375057e..a492aab 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -25,7 +25,10 @@ pub enum FieldSelector { #[derive(Debug, Clone)] pub enum AmlValue { Uninitialized, - Buffer, + Buffer { + length: Box, + byte_list: Vec + }, BufferField { source_buf: Box, index: Box, diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index 0313d82..e96bdbc 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -207,6 +207,25 @@ impl AmlExecutable for Type2OpCode { } } +impl AmlExecutable for DefBuffer { + fn execute(&self, namespace: &mut BTreeMap, scope: String) -> Option { + match *self { + DefBuffer::Buffer { ref buffer_size, ref byte_list } => { + let length = match buffer_size.execute(namespace, scope.clone()) { + Some(l) => Box::new(l), + _ => return None + }; + + Some(AmlValue::Buffer { + length: length, + byte_list: byte_list.clone() + }) + }, + _ => None + } + } +} + #[derive(Debug, Clone)] pub enum DefObjectType { SuperName(SuperName), From c83cefee089dd414686332b39c591055bb31b0d6 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Thu, 22 Jun 2017 15:43:00 +0100 Subject: [PATCH 016/113] Moved AccessType into namespace --- src/acpi/aml/namedobj.rs | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index 664b767..66af6d6 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -124,6 +124,7 @@ impl AmlExecutable for NamedObj { NamedObj::DefBankField { ref region_name, ref bank_name, ref bank_value, ref flags, ref field_list } => { let mut offset: usize = 0; let mut connection = AmlValue::Uninitialized; + let mut flags = flags.clone(); let bank_val = if let Some(b) = bank_value.execute(namespace, scope.clone()) { Box::new(b) } else { @@ -141,6 +142,12 @@ impl AmlExecutable for NamedObj { None => return None }; }, + FieldElement::AccessField { ref access_type, ref access_attrib } => { + match *access_type { + AccessType::BufferAcc(_) => flags.access_type = AccessType::BufferAcc(access_attrib.clone()), + ref a => flags.access_type = a.clone() + } + }, FieldElement::NamedField { name: ref field_name, length } => { let local_scope_string = get_namespace_string(scope.clone(), field_name.clone()); @@ -157,13 +164,13 @@ impl AmlExecutable for NamedObj { offset += length; }, - _ => () } } }, NamedObj::DefIndexField { ref idx_name, ref data_name, ref flags, ref field_list } => { let mut offset: usize = 0; let mut connection = AmlValue::Uninitialized; + let mut flags = flags.clone(); for f in field_list { match *f { @@ -176,6 +183,12 @@ impl AmlExecutable for NamedObj { None => return None }; }, + FieldElement::AccessField { ref access_type, ref access_attrib } => { + match *access_type { + AccessType::BufferAcc(_) => flags.access_type = AccessType::BufferAcc(access_attrib.clone()), + ref a => flags.access_type = a.clone() + } + }, FieldElement::NamedField { name: ref field_name, length } => { let local_scope_string = get_namespace_string(scope.clone(), field_name.clone()); @@ -191,8 +204,7 @@ impl AmlExecutable for NamedObj { }); offset += length; - }, - _ => () + } } } }, @@ -339,6 +351,7 @@ impl AmlExecutable for NamedObj { NamedObj::DefField { ref name, ref flags, ref field_list } => { let mut offset: usize = 0; let mut connection = AmlValue::Uninitialized; + let mut flags = flags.clone(); for f in field_list { match *f { @@ -351,6 +364,12 @@ impl AmlExecutable for NamedObj { None => return None }; }, + FieldElement::AccessField { ref access_type, ref access_attrib } => { + match *access_type { + AccessType::BufferAcc(_) => flags.access_type = AccessType::BufferAcc(access_attrib.clone()), + ref a => flags.access_type = a.clone() + } + }, FieldElement::NamedField { name: ref field_name, length } => { let local_scope_string = get_namespace_string(scope.clone(), field_name.clone()); @@ -363,8 +382,7 @@ impl AmlExecutable for NamedObj { }); offset += length; - }, - _ => () + } } } }, @@ -456,7 +474,7 @@ pub enum AccessType { WordAcc, DWordAcc, QWordAcc, - BufferAcc + BufferAcc(AccessAttrib) } #[derive(Debug, Clone)] @@ -559,7 +577,7 @@ fn parse_def_bank_field(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalErr 2 => AccessType::WordAcc, 3 => AccessType::DWordAcc, 4 => AccessType::QWordAcc, - 5 => AccessType::BufferAcc, + 5 => AccessType::BufferAcc(AccessAttrib::AttribByte), _ => return Err(AmlInternalError::AmlParseError("BankField - invalid access type")) }, lock_rule: (flags_raw & 0x10) == 0x10, @@ -738,7 +756,7 @@ fn parse_def_field(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> { 2 => AccessType::WordAcc, 3 => AccessType::DWordAcc, 4 => AccessType::QWordAcc, - 5 => AccessType::BufferAcc, + 5 => AccessType::BufferAcc(AccessAttrib::AttribByte), _ => return Err(AmlInternalError::AmlParseError("Field - Invalid access type")) }, lock_rule: (flags_raw & 0x10) == 0x10, @@ -788,7 +806,7 @@ fn parse_def_index_field(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalEr 2 => AccessType::WordAcc, 3 => AccessType::DWordAcc, 4 => AccessType::QWordAcc, - 5 => AccessType::BufferAcc, + 5 => AccessType::BufferAcc(AccessAttrib::AttribByte), _ => return Err(AmlInternalError::AmlParseError("IndexField - Invalid access type")) }, lock_rule: (flags_raw & 0x10) == 0x10, @@ -870,7 +888,7 @@ fn parse_access_field(data: &[u8]) -> Result<(FieldElement, usize), AmlInternalE 2 => AccessType::WordAcc, 3 => AccessType::DWordAcc, 4 => AccessType::QWordAcc, - 5 => AccessType::BufferAcc, + 5 => AccessType::BufferAcc(AccessAttrib::AttribByte), _ => return Err(AmlInternalError::AmlParseError("AccessField - Invalid access type")) }; From be1a75e4725323dc7a32612a648574b49eaee575 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Thu, 22 Jun 2017 16:25:19 +0100 Subject: [PATCH 017/113] Finalized ACPIType --- src/acpi/aml/dataobj.rs | 6 +++--- src/acpi/aml/namespace.rs | 7 ++++--- src/acpi/aml/termlist.rs | 6 +++--- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/acpi/aml/dataobj.rs b/src/acpi/aml/dataobj.rs index 885396a..27f81f8 100644 --- a/src/acpi/aml/dataobj.rs +++ b/src/acpi/aml/dataobj.rs @@ -47,7 +47,7 @@ impl AmlExecutable for DataRefObj { fn execute(&self, namespace: &mut BTreeMap, scope: String) -> Option { match *self { DataRefObj::DataObj(ref cd) => cd.execute(namespace, scope), - _ => Some(AmlValue::Integer) + _ => Some(AmlValue::Uninitialized) } } } @@ -57,7 +57,7 @@ impl AmlExecutable for DataObj { match *self { DataObj::ComputationalData(ref cd) => cd.execute(namespace, scope), DataObj::DefPackage(ref pkg) => pkg.execute(namespace, scope), - _ => Some(AmlValue::Integer) + _ => Some(AmlValue::Uninitialized) } } } @@ -73,7 +73,7 @@ impl AmlExecutable for ComputationalData { ComputationalData::One => Some(AmlValue::IntegerConstant(1)), ComputationalData::Ones => Some(AmlValue::IntegerConstant(0xFFFFFFFFFFFFFFFF)), ComputationalData::String(ref s) => Some(AmlValue::String(s.clone())), - _ => Some(AmlValue::Integer) + _ => Some(AmlValue::Uninitialized) } } } diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index a492aab..be49f7b 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -8,6 +8,7 @@ use core::str::FromStr; use super::namedobj::{ RegionSpace, FieldFlags, Method }; use super::termlist::Object; use super::namestring::SuperName; +use super::type2opcode::Type2OpCode; #[derive(Debug, Clone)] pub enum FieldSelector { @@ -34,7 +35,7 @@ pub enum AmlValue { index: Box, length: Box }, - DDBHandle, + DDBHandle(u32), // Index into the XSDT DebugObject, Device(BTreeMap), Event, @@ -45,7 +46,7 @@ pub enum AmlValue { offset: usize, length: usize }, - Integer, + Integer(Type2OpCode), IntegerConstant(u64), Method(Method), Mutex(u8), @@ -67,7 +68,7 @@ pub enum AmlValue { p_blk: Option, obj_list: BTreeMap }, - RawDataBuffer, + RawDataBuffer(Vec), ThermalZone(BTreeMap) } diff --git a/src/acpi/aml/termlist.rs b/src/acpi/aml/termlist.rs index 72d876d..c7d0c5f 100644 --- a/src/acpi/aml/termlist.rs +++ b/src/acpi/aml/termlist.rs @@ -70,10 +70,10 @@ impl AmlExecutable for Vec { impl AmlExecutable for TermArg { fn execute(&self, namespace: &mut BTreeMap, scope: String) -> Option { match *self { - TermArg::LocalObj(ref l) => Some(AmlValue::Integer), + TermArg::LocalObj(ref l) => Some(AmlValue::Uninitialized), TermArg::DataObj(ref d) => d.execute(namespace, scope), - TermArg::ArgObj(ref a) => Some(AmlValue::Integer), - TermArg::Type2Opcode(ref o) => Some(AmlValue::Integer) + TermArg::ArgObj(ref a) => Some(AmlValue::Uninitialized), + TermArg::Type2Opcode(ref o) => Some(AmlValue::Uninitialized) } } } From 9fb15e7e9255f786b3c135d24642946fc6f0b559 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Thu, 22 Jun 2017 19:12:40 +0100 Subject: [PATCH 018/113] Namespaces can now be concatenated, handling of SSDTs is now performed --- src/acpi/aml/mod.rs | 4 +--- src/acpi/mod.rs | 13 ++++++++++--- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/acpi/aml/mod.rs b/src/acpi/aml/mod.rs index a50ec4c..7ad0473 100644 --- a/src/acpi/aml/mod.rs +++ b/src/acpi/aml/mod.rs @@ -59,13 +59,11 @@ pub fn parse_aml_table(sdt: &'static Sdt) -> Result, let mut global_namespace = BTreeMap::new(); term_list.execute(&mut global_namespace, global_namespace_specifier.clone()); - println!("{:#?}", global_namespace); - Ok(global_namespace) } pub fn is_aml_table(sdt: &'static Sdt) -> bool { - if &sdt.signature == b"DSDT" {//|| &sdt.signature == b"SSDT" { + if &sdt.signature == b"DSDT" || &sdt.signature == b"SSDT" { true } else { false diff --git a/src/acpi/mod.rs b/src/acpi/mod.rs index e1f617f..ead12f5 100644 --- a/src/acpi/mod.rs +++ b/src/acpi/mod.rs @@ -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 spin::Mutex; @@ -198,14 +199,20 @@ fn parse_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) { } } } else if is_aml_table(sdt) { - ACPI_TABLE.lock().namespace = match parse_aml_table(sdt) { + match parse_aml_table(sdt) { Ok(res) => { println!(": Parsed"); - Some(res) + let ref mut namespace = ACPI_TABLE.lock().namespace; + + if let Some(ref mut ns) = *namespace { + let mut res = res.clone(); + ns.append(&mut res); + } else { + *namespace = Some(res); + } }, Err(AmlError::AmlParseError(e)) => { println!(": {}", e); - None } }; } else { From f72f97ef36566a7b6a0f52cf1b0d65b9c8ec923a Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Fri, 23 Jun 2017 14:02:40 +0100 Subject: [PATCH 019/113] Rolled parsing and execution steps into one for namespace modifiers --- src/acpi/aml/mod.rs | 10 +-- src/acpi/aml/namespacemodifier.rs | 119 +++++++++++------------------- src/acpi/aml/parser.rs | 16 ++++ src/acpi/aml/parsermacros.rs | 21 ++++-- src/acpi/aml/termlist.rs | 27 ++++--- 5 files changed, 95 insertions(+), 98 deletions(-) create mode 100644 src/acpi/aml/parser.rs diff --git a/src/acpi/aml/mod.rs b/src/acpi/aml/mod.rs index 7ad0473..a6d5a35 100644 --- a/src/acpi/aml/mod.rs +++ b/src/acpi/aml/mod.rs @@ -22,22 +22,16 @@ mod namedobj; mod dataobj; mod type1opcode; mod type2opcode; +mod parser; +use self::parser::{ParseResult, AmlInternalError}; use self::termlist::{parse_term_list, TermObj}; 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 BTreeMap, scope: String) -> Option; } -// TODO: make private -pub enum AmlInternalError { - AmlParseError(&'static str), - AmlInvalidOpCode, - AmlDeferredLoad -} - pub enum AmlError { AmlParseError(&'static str) } diff --git a/src/acpi/aml/namespacemodifier.rs b/src/acpi/aml/namespacemodifier.rs index c1e2395..8e7e2cc 100644 --- a/src/acpi/aml/namespacemodifier.rs +++ b/src/acpi/aml/namespacemodifier.rs @@ -9,55 +9,11 @@ use super::namestring::{parse_name_string, SuperName}; use super::termlist::{parse_term_list, TermObj}; use super::dataobj::{parse_data_ref_obj, DataRefObj}; -#[derive(Debug, Clone)] -pub enum NamespaceModifier { - Name { - name: String, - data_ref_obj: DataRefObj - }, - Scope { - name: String, - terms: Vec - }, - Alias { - source_name: String, - alias_name: String - }, - DeferredLoad(Vec) -} - -impl AmlExecutable for NamespaceModifier { - 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()); - terms.execute(namespace, local_scope_string); - }, - NamespaceModifier::Name { ref name, ref data_ref_obj } => { - let local_scope_string = get_namespace_string(scope.clone(), name.clone()); - let dro = match data_ref_obj.execute(namespace, scope) { - Some(s) => s, - None => return None - }; - - 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.insert(local_scope_string, AmlValue::ObjectReference(SuperName::NameString(local_alias_string))); - }, - _ => () - } - - None - } -} - -pub fn parse_namespace_modifier(data: &[u8]) -> Result<(NamespaceModifier, usize), AmlInternalError> { +pub fn parse_namespace_modifier(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_selector! { - data, + data, namespace, scope, parse_alias_op, parse_scope_op, parse_name_op @@ -66,42 +22,57 @@ pub fn parse_namespace_modifier(data: &[u8]) -> Result<(NamespaceModifier, usize Err(AmlInternalError::AmlInvalidOpCode) } -fn parse_alias_op(data: &[u8]) -> Result<(NamespaceModifier, usize), AmlInternalError> { +fn parse_alias_op(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode!(data, 0x06); - let (source_name, source_name_len) = parse_name_string(&data[1..])?; - let (alias_name, alias_name_len) = parse_name_string(&data[1 + source_name_len..])?; + let source_name = parse_name_string(&data[1..], namespace, scope)?; + let alias_name = parse_name_string(&data[1 + source_name_len..], namespace, scope)?; + + let local_scope_string = get_namespace_string(scope.clone(), parser_verify_value!(source_name)); + let local_alias_string = get_namespace_string(scope.clone(), parser_verify_value!(alias_name)); - Ok((NamespaceModifier::Alias {source_name, alias_name}, 1 + source_name_len + alias_name_len)) + namespace.insert(local_scope_string, AmlValue::ObjectReference( + SuperName::NameString(local_alias_string))); + + Ok(AmlParseType { + val: None, + len: 1 + source_name.len + alias_name.len + }) } -fn parse_name_op(data: &[u8]) -> Result<(NamespaceModifier, usize), AmlInternalError> { +fn parse_name_op(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode!(data, 0x08); + + let name = parse_name_string(&data[1..], namespace, scope)?; + let data_ref_obj = parse_data_ref_obj(&data[1 + name_len..], namespace, scope)?; + + let local_scope_string = get_namespace_string(scope.clone(), parser_verify_value!(name)); - let (name, name_len) = parse_name_string(&data[1..])?; - let (data_ref_obj, data_ref_obj_len) = parse_data_ref_obj(&data[1 + name_len..])?; - - Ok((NamespaceModifier::Name {name, data_ref_obj}, 1 + name_len + data_ref_obj_len)) + namespace.insert(local_scope_string, parser_verify_value!(data_ref_obj)); + + Ok(AmlParseType { + val: None, + len: 1 + name_len + data_ref_obj_len + }) } -fn parse_scope_op(data: &[u8]) -> Result<(NamespaceModifier, usize), AmlInternalError> { +fn parse_scope_op(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode!(data, 0x10); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; - let (name, name_len) = match parse_name_string(&data[1 + pkg_length_len..]) { - Ok(p) => p, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((NamespaceModifier::DeferredLoad(data[0 .. 1 + pkg_length].to_vec()), - 1 + pkg_length)), - Err(e) => return Err(e) - }; - let terms = match parse_term_list(&data[1 + pkg_length_len + name_len..]) { - Ok(p) => p, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((NamespaceModifier::DeferredLoad(data[0 .. 1 + pkg_length].to_vec()), - 1 + pkg_length)), - Err(e) => return Err(e) - }; - - Ok((NamespaceModifier::Scope {name, terms}, pkg_length + 1)) + let name = parse_name_string(&data[1 + pkg_length_len..], namespace, scope)?; + + let local_scope_string = get_namespace_string(scope, parser_verify_value!(name)); + parse_term_list(&data[1 + pkg_length_len + name_len..], namespace, local_scope_string)?; + + Ok(AmlParseType { + val: None, + len: 1 + pkg_length + }) } diff --git a/src/acpi/aml/parser.rs b/src/acpi/aml/parser.rs new file mode 100644 index 0000000..321f013 --- /dev/null +++ b/src/acpi/aml/parser.rs @@ -0,0 +1,16 @@ +use super::AmlValue; + +pub type ParseResult = Result; + +pub struct AmlParseType { + val: Option, + len: usize +} + +// TODO: make private +pub enum AmlInternalError { + AmlParseError(&'static str), + AmlInvalidOpCode, + AmlValueError, + AmlDeferredLoad +} diff --git a/src/acpi/aml/parsermacros.rs b/src/acpi/aml/parsermacros.rs index 50e3aed..7c9e101 100644 --- a/src/acpi/aml/parsermacros.rs +++ b/src/acpi/aml/parsermacros.rs @@ -1,15 +1,15 @@ #[macro_export] macro_rules! parser_selector { - {$data:expr, $func:expr} => { - match $func($data) { + {$data:expr, $namespace:expr, $scope:expr, $func:expr} => { + match $func($data, $namespace, $scope) { Ok(res) => return Ok(res), Err(AmlInternalError::AmlInvalidOpCode) => (), Err(e) => return Err(e) } }; - {$data:expr, $func:expr, $($funcs:expr),+} => { - parser_selector! {$data, $func}; - parser_selector! {$data, $($funcs),*}; + {$data:expr, $namespace:expr, $scope:expr, $func:expr, $($funcs:expr),+} => { + parser_selector! {$data, $namespace, $scope, $func}; + parser_selector! {$data, $namespace, $scope, $($funcs),*}; }; } @@ -47,3 +47,14 @@ macro_rules! parser_opcode_extended { } }; } + +#[macro_export] +macro_rules! parser_verify_value { + ($val:expr) => { + match $val.val { + Some(s) => s, + None => return Err(AmlInternalError::AmlValueError) + } + }; +} + diff --git a/src/acpi/aml/termlist.rs b/src/acpi/aml/termlist.rs index c7d0c5f..5e5482e 100644 --- a/src/acpi/aml/termlist.rs +++ b/src/acpi/aml/termlist.rs @@ -89,17 +89,20 @@ impl AmlExecutable for TermObj { } } -pub fn parse_term_list(data: &[u8]) -> Result, AmlInternalError> { - let mut terms: Vec = vec!(); +pub fn parse_term_list(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { let mut current_offset: usize = 0; while current_offset < data.len() { - let (res, len) = parse_term_obj(&data[current_offset..])?; - terms.push(res); + let (res, len) = parse_term_obj(&data[current_offset..], namespace, scope)?; current_offset += len; } - Ok(terms) + Ok(AmlParseType { + val: None, + len: data.len() + }) } pub fn parse_term_arg(data: &[u8]) -> Result<(TermArg, usize), AmlInternalError> { @@ -142,13 +145,15 @@ pub fn parse_method_invocation(data: &[u8]) -> Result<(MethodInvocation, usize), Err(AmlInternalError::AmlDeferredLoad) } -fn parse_term_obj(data: &[u8]) -> Result<(TermObj, usize), AmlInternalError> { +fn parse_term_obj(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_selector! { - data, - parser_wrap!(TermObj::NamespaceModifier, parser_wrap!(Box::new, parse_namespace_modifier)), - parser_wrap!(TermObj::NamedObj, parser_wrap!(Box::new, parse_named_obj)), - parser_wrap!(TermObj::Type1Opcode, parser_wrap!(Box::new, parse_type1_opcode)), - parser_wrap!(TermObj::Type2Opcode, parser_wrap!(Box::new, parse_type2_opcode)) + data, namespace, scope, + parse_namespace_modifier, + parse_named_obj, + parse_type1_opcode, + parse_type2_opcode }; Err(AmlInternalError::AmlInvalidOpCode) From 590610f4a5d7576c248ff5aaa1bd31f5b3d27b34 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Sun, 2 Jul 2017 13:07:43 +0100 Subject: [PATCH 020/113] Refactored parser to execute in the parse step for efficiency and simplicity --- src/acpi/aml/dataobj.rs | 205 +++-- src/acpi/aml/mod.rs | 30 +- src/acpi/aml/namedobj.rs | 1175 ++++++++++---------------- src/acpi/aml/namespace.rs | 46 +- src/acpi/aml/namespacemodifier.rs | 46 +- src/acpi/aml/namestring.rs | 106 +-- src/acpi/aml/parser.rs | 20 +- src/acpi/aml/parsermacros.rs | 31 +- src/acpi/aml/pkglength.rs | 6 +- src/acpi/aml/termlist.rs | 153 +--- src/acpi/aml/type1opcode.rs | 404 ++++----- src/acpi/aml/type2opcode.rs | 1308 +++++++++++++++-------------- src/acpi/mod.rs | 8 +- src/stop.rs | 2 +- 14 files changed, 1622 insertions(+), 1918 deletions(-) diff --git a/src/acpi/aml/dataobj.rs b/src/acpi/aml/dataobj.rs index 27f81f8..77f7d2f 100644 --- a/src/acpi/aml/dataobj.rs +++ b/src/acpi/aml/dataobj.rs @@ -2,132 +2,99 @@ use collections::vec::Vec; use collections::string::String; use collections::btree_map::BTreeMap; -use super::{AmlInternalError, AmlExecutable, AmlValue, get_namespace_string}; +use super::AmlError; +use super::parser::{AmlParseType, ParseResult}; +use super::namespace::{AmlValue, ObjectReference}; -use super::type2opcode::{parse_def_buffer, parse_def_package, parse_def_var_package, - DefBuffer, DefPackage, DefVarPackage}; -use super::termlist::{parse_term_arg, TermArg}; -use super::namestring::{parse_super_name, SuperName}; +use super::type2opcode::{parse_def_buffer, parse_def_package, parse_def_var_package}; +use super::termlist::parse_term_arg; +use super::namestring::parse_super_name; -#[derive(Debug, Clone)] -pub enum DataObj { - ComputationalData(ComputationalData), - DefPackage(DefPackage), - DefVarPackage(DefVarPackage) -} - -#[derive(Debug, Clone)] -pub enum DataRefObj { - DataObj(DataObj), - ObjectReference(TermArg), - DDBHandle(SuperName) -} - -#[derive(Debug, Clone)] -pub struct ArgObj(u8); -#[derive(Debug, Clone)] -pub struct LocalObj(u8); -// Not actually doing anything to contain data, but does give us type guarantees, which is useful - -#[derive(Debug, Clone)] -pub enum ComputationalData { - Byte(u8), - Word(u16), - DWord(u32), - QWord(u64), - String(String), - Zero, - One, - Ones, - DefBuffer(DefBuffer), - RevisionOp -} - -impl AmlExecutable for DataRefObj { - fn execute(&self, namespace: &mut BTreeMap, scope: String) -> Option { - match *self { - DataRefObj::DataObj(ref cd) => cd.execute(namespace, scope), - _ => Some(AmlValue::Uninitialized) - } - } -} - -impl AmlExecutable for DataObj { - 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), - _ => Some(AmlValue::Uninitialized) - } - } -} - -impl AmlExecutable for ComputationalData { - 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)), - ComputationalData::DWord(d) => Some(AmlValue::IntegerConstant(d as u64)), - ComputationalData::QWord(q) => Some(AmlValue::IntegerConstant(q as u64)), - ComputationalData::Zero => Some(AmlValue::IntegerConstant(0)), - ComputationalData::One => Some(AmlValue::IntegerConstant(1)), - ComputationalData::Ones => Some(AmlValue::IntegerConstant(0xFFFFFFFFFFFFFFFF)), - ComputationalData::String(ref s) => Some(AmlValue::String(s.clone())), - _ => Some(AmlValue::Uninitialized) - } - } -} - -pub fn parse_data_obj(data: &[u8]) -> Result<(DataObj, usize), AmlInternalError> { +pub fn parse_data_obj(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_selector! { - data, - parser_wrap!(DataObj::ComputationalData, parse_computational_data), - parser_wrap!(DataObj::DefPackage, parse_def_package), - parser_wrap!(DataObj::DefVarPackage, parse_def_var_package) + data, namespace, scope.clone(), + parse_computational_data, + parse_def_package, + parse_def_var_package }; - Err(AmlInternalError::AmlInvalidOpCode) + Err(AmlError::AmlInvalidOpCode) } -pub fn parse_data_ref_obj(data: &[u8]) -> Result<(DataRefObj, usize), AmlInternalError> { +pub fn parse_data_ref_obj(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_selector! { - data, - parser_wrap!(DataRefObj::DataObj, parse_data_obj), - parser_wrap!(DataRefObj::ObjectReference, parse_term_arg), - parser_wrap!(DataRefObj::DDBHandle, parse_super_name) + data, namespace, scope.clone(), + parse_data_obj, + parse_term_arg }; - Err(AmlInternalError::AmlInvalidOpCode) -} - -pub fn parse_arg_obj(data: &[u8]) -> Result<(ArgObj, usize), AmlInternalError> { - match data[0] { - 0x68 ... 0x6E => Ok((ArgObj(data[0] - 0x68), 1 as usize)), - _ => Err(AmlInternalError::AmlInvalidOpCode) + match parse_super_name(data, namespace, scope.clone()) { + Ok(res) => match res.val { + AmlValue::String(s) => Ok(AmlParseType { + val: AmlValue::ObjectReference(ObjectReference::NamedObj(s)), + len: res.len + }), + _ => Ok(res) + }, + Err(e) => Err(e) } } -pub fn parse_local_obj(data: &[u8]) -> Result<(LocalObj, usize), AmlInternalError> { +pub fn parse_arg_obj(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { match data[0] { - 0x60 ... 0x67 => Ok((LocalObj(data[0] - 0x60), 1 as usize)), - _ => Err(AmlInternalError::AmlInvalidOpCode) + 0x68 ... 0x6E => Ok(AmlParseType { + val: AmlValue::ObjectReference(ObjectReference::ArgObj(data[0] - 0x68)), + len: 1 as usize + }), + _ => Err(AmlError::AmlInvalidOpCode) } } -fn parse_computational_data(data: &[u8]) -> Result<(ComputationalData, usize), AmlInternalError> { +pub fn parse_local_obj(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { match data[0] { - 0x0A => Ok((ComputationalData::Byte(data[1]), 2 as usize)), + 0x68 ... 0x6E => Ok(AmlParseType { + val: AmlValue::ObjectReference(ObjectReference::LocalObj(data[0] - 0x60)), + len: 1 as usize + }), + _ => Err(AmlError::AmlInvalidOpCode) + } +} + +fn parse_computational_data(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + match data[0] { + 0x0A => Ok(AmlParseType { + val: AmlValue::Integer(data[1] as u64), + len: 2 as usize + }), 0x0B => { let res = (data[1] as u16) + ((data[2] as u16) << 8); - Ok((ComputationalData::Word(res), 3 as usize)) + + Ok(AmlParseType { + val: AmlValue::Integer(res as u64), + len: 3 as usize + }) }, 0x0C => { let res = (data[1] as u32) + ((data[2] as u32) << 8) + ((data[3] as u32) << 16) + ((data[4] as u32) << 24); - Ok((ComputationalData::DWord(res), 5 as usize)) + + Ok(AmlParseType { + val: AmlValue::Integer(res as u64), + len: 5 as usize + }) }, 0x0D => { let mut cur_ptr: usize = 1; @@ -139,8 +106,11 @@ fn parse_computational_data(data: &[u8]) -> Result<(ComputationalData, usize), A } match String::from_utf8(cur_string) { - Ok(s) => Ok((ComputationalData::String(s.clone()), s.clone().len() + 2)), - Err(_) => Err(AmlInternalError::AmlParseError("String data - invalid string")) + Ok(s) => Ok(AmlParseType { + val: AmlValue::String(s.clone()), + len: s.clone().len() + 2 + }), + Err(_) => Err(AmlError::AmlParseError("String data - invalid string")) } }, 0x0E => { @@ -152,19 +122,32 @@ fn parse_computational_data(data: &[u8]) -> Result<(ComputationalData, usize), A ((data[6] as u64) << 40) + ((data[7] as u64) << 48) + ((data[8] as u64) << 56); - Ok((ComputationalData::QWord(res), 9 as usize)) + + Ok(AmlParseType { + val: AmlValue::Integer(res as u64), + len: 9 as usize + }) }, - 0x00 => Ok((ComputationalData::Zero, 1 as usize)), - 0x01 => Ok((ComputationalData::One, 1 as usize)), + 0x00 => Ok(AmlParseType { + val: AmlValue::IntegerConstant(0 as u64), + len: 9 as usize + }), + 0x01 => Ok(AmlParseType { + val: AmlValue::IntegerConstant(1 as u64), + len: 9 as usize + }), 0x5B => if data[1] == 0x30 { - Ok((ComputationalData::RevisionOp, 2 as usize)) + Ok(AmlParseType { + val: AmlValue::IntegerConstant(20170630 as u64), + len: 2 as usize + }) } else { - Err(AmlInternalError::AmlInvalidOpCode) + Err(AmlError::AmlInvalidOpCode) }, - 0xFF => Ok((ComputationalData::Ones, 1 as usize)), - _ => match parse_def_buffer(data) { - Ok((res, size)) => Ok((ComputationalData::DefBuffer(res), size)), - Err(e) => Err(e) - } + 0xFF => Ok(AmlParseType { + val: AmlValue::IntegerConstant(0xFFFFFFFFFFFFFFFF), + len: 9 as usize + }), + _ => parse_def_buffer(data, namespace, scope.clone()) } } diff --git a/src/acpi/aml/mod.rs b/src/acpi/aml/mod.rs index a6d5a35..a113c0b 100644 --- a/src/acpi/aml/mod.rs +++ b/src/acpi/aml/mod.rs @@ -24,34 +24,26 @@ mod type1opcode; mod type2opcode; mod parser; -use self::parser::{ParseResult, AmlInternalError}; -use self::termlist::{parse_term_list, TermObj}; -pub use self::namespace::{get_namespace_string, AmlValue}; - -pub trait AmlExecutable { - fn execute(&self, namespace: &mut BTreeMap, scope: String) -> Option; -} +use self::parser::ParseResult; +use self::termlist::parse_term_list; +pub use self::namespace::AmlValue; +#[derive(Debug)] pub enum AmlError { - AmlParseError(&'static str) + AmlParseError(&'static str), + AmlInvalidOpCode, + AmlValueError, + AmlDeferredLoad, + AmlFatalError(u8, u16, AmlValue) } pub fn parse_aml_table(sdt: &'static Sdt) -> Result, AmlError> { let data = sdt.data(); - let term_list = match parse_term_list(data) { - Ok(res) => res, - Err(AmlInternalError::AmlParseError(s)) => return Err(AmlError::AmlParseError(s)), - Err(AmlInternalError::AmlInvalidOpCode) => return Err(AmlError::AmlParseError("Unable to match opcode")), - Err(AmlInternalError::AmlDeferredLoad) => return Err(AmlError::AmlParseError("Deferred load reached top level")) - }; - let global_namespace_specifier = String::from_str("\\").unwrap(); - // 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 = BTreeMap::new(); - term_list.execute(&mut global_namespace, global_namespace_specifier.clone()); + + let term_list = parse_term_list(data, &mut global_namespace, global_namespace_specifier.clone())?; Ok(global_namespace) } diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index 66af6d6..c521893 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -5,444 +5,20 @@ use core::str::FromStr; use collections::btree_map::BTreeMap; -use super::{AmlInternalError, AmlExecutable, AmlValue, get_namespace_string}; -use super::namespace::FieldSelector; -use super::namestring::{parse_name_string, parse_name_seg, SuperName}; -use super::termlist::{parse_term_arg, parse_term_list, parse_object_list, TermArg, TermObj, Object}; +use super::AmlError; +use super::parser::{AmlParseType, ParseResult, AmlParseTypeGeneric}; +use super::namespace::{AmlValue, ObjectReference, FieldSelector, get_namespace_string}; +use super::namestring::{parse_name_string, parse_name_seg}; +use super::termlist::{parse_term_arg, parse_term_list, parse_object_list}; use super::pkglength::parse_pkg_length; -use super::type2opcode::{parse_def_buffer, DefBuffer}; - -#[derive(Debug, Clone)] -pub enum NamedObj { - DefBankField { - region_name: String, - bank_name: String, - bank_value: TermArg, - flags: FieldFlags, - field_list: Vec - }, - DefCreateBitField { - name: String, - source_buf: TermArg, - bit_index: TermArg - }, - DefCreateByteField { - name: String, - source_buf: TermArg, - byte_index: TermArg - }, - DefCreateWordField { - name: String, - source_buf: TermArg, - byte_index: TermArg - }, - DefCreateDWordField { - name: String, - source_buf: TermArg, - byte_index: TermArg - }, - DefCreateQWordField { - name: String, - source_buf: TermArg, - byte_index: TermArg - }, - DefCreateField { - name: String, - source_buf: TermArg, - bit_index: TermArg, - num_bits: TermArg - }, - DefDataRegion { - name: String, - signature: TermArg, - oem_id: TermArg, - oem_table_id: TermArg - }, - DefDevice { - name: String, - obj_list: Vec - }, - DefEvent { - name: String - }, - DefOpRegion { - name: String, - region: RegionSpace, - offset: TermArg, - len: TermArg - }, - DefField { - name: String, - flags: FieldFlags, - field_list: Vec - }, - DefIndexField { - idx_name: String, - data_name: String, - flags: FieldFlags, - field_list: Vec - }, - DefMethod { - name: String, - method: Method - }, - DefMutex { - name: String, - sync_level: u8 - }, - DefPowerRes { - name: String, - system_level: u8, - resource_order: u16, - obj_list: Vec - }, - DefProcessor { - name: String, - proc_id: u8, - p_blk_addr: u32, - p_blk_len: u8, - obj_list: Vec - }, - DefThermalZone { - name: String, - obj_list: Vec - }, - DeferredLoad(Vec) -} +use super::type2opcode::parse_def_buffer; #[derive(Debug, Clone)] pub struct Method { arg_count: u8, serialized: bool, sync_level: u8, - term_list: Vec -} - -impl AmlExecutable for NamedObj { - fn execute(&self, namespace: &mut BTreeMap, scope: String) -> Option { - match *self { - NamedObj::DefBankField { ref region_name, ref bank_name, ref bank_value, ref flags, ref field_list } => { - let mut offset: usize = 0; - let mut connection = AmlValue::Uninitialized; - let mut flags = flags.clone(); - let bank_val = if let Some(b) = bank_value.execute(namespace, scope.clone()) { - Box::new(b) - } else { - return None; - }; - - for f in field_list { - match *f { - FieldElement::ReservedField { length } => offset += length, - FieldElement::ConnectFieldNameString(ref name) => connection = - AmlValue::ObjectReference(SuperName::NameString(name.clone())), - FieldElement::ConnectFieldBufferData(ref buf) => { - connection = match buf.execute(namespace, scope.clone()) { - Some(c) => c, - None => return None - }; - }, - FieldElement::AccessField { ref access_type, ref access_attrib } => { - match *access_type { - AccessType::BufferAcc(_) => flags.access_type = AccessType::BufferAcc(access_attrib.clone()), - ref a => flags.access_type = a.clone() - } - }, - FieldElement::NamedField { name: ref field_name, length } => { - let local_scope_string = get_namespace_string(scope.clone(), - field_name.clone()); - namespace.insert(local_scope_string, AmlValue::FieldUnit { - selector: FieldSelector::Bank { - region: region_name.clone(), - bank_selector: bank_val.clone() - }, - connection: Box::new(connection.clone()), - flags: flags.clone(), - offset: offset.clone(), - length: length.clone() - }); - - offset += length; - }, - } - } - }, - NamedObj::DefIndexField { ref idx_name, ref data_name, ref flags, ref field_list } => { - let mut offset: usize = 0; - let mut connection = AmlValue::Uninitialized; - let mut flags = flags.clone(); - - for f in field_list { - match *f { - FieldElement::ReservedField { length } => offset += length, - FieldElement::ConnectFieldNameString(ref name) => connection = - AmlValue::ObjectReference(SuperName::NameString(name.clone())), - FieldElement::ConnectFieldBufferData(ref buf) => { - connection = match buf.execute(namespace, scope.clone()) { - Some(c) => c, - None => return None - }; - }, - FieldElement::AccessField { ref access_type, ref access_attrib } => { - match *access_type { - AccessType::BufferAcc(_) => flags.access_type = AccessType::BufferAcc(access_attrib.clone()), - ref a => flags.access_type = a.clone() - } - }, - FieldElement::NamedField { name: ref field_name, length } => { - let local_scope_string = get_namespace_string(scope.clone(), - field_name.clone()); - namespace.insert(local_scope_string, AmlValue::FieldUnit { - selector: FieldSelector::Index { - index_selector: idx_name.clone(), - data_selector: data_name.clone() - }, - connection: Box::new(connection.clone()), - flags: flags.clone(), - offset: offset.clone(), - length: length.clone() - }); - - offset += length; - } - } - } - }, - NamedObj::DefCreateBitField { ref name, ref source_buf, ref bit_index } => { - let local_scope_string = get_namespace_string(scope.clone(), name.clone()); - - let resolved_source_buf = match source_buf.execute(namespace, scope.clone()) { - Some(r) => Box::new(r), - _ => return None - }; - let resolved_index = match bit_index.execute(namespace, scope.clone()) { - Some(r) => Box::new(r), - _ => return None - }; - - namespace.insert(local_scope_string, AmlValue::BufferField { - source_buf: resolved_source_buf, - index: resolved_index, - length: Box::new(AmlValue::IntegerConstant(1)) - }); - }, - NamedObj::DefCreateByteField { ref name, ref source_buf, ref byte_index } => { - let local_scope_string = get_namespace_string(scope.clone(), name.clone()); - - let resolved_source_buf = match source_buf.execute(namespace, scope.clone()) { - Some(r) => Box::new(r), - _ => return None - }; - let resolved_index = match byte_index.execute(namespace, scope.clone()) { - Some(r) => Box::new(r), - _ => return None - }; - - namespace.insert(local_scope_string, AmlValue::BufferField { - source_buf: resolved_source_buf, - index: resolved_index, - length: Box::new(AmlValue::IntegerConstant(8)) - }); - }, - NamedObj::DefCreateWordField { ref name, ref source_buf, ref byte_index } => { - let local_scope_string = get_namespace_string(scope.clone(), name.clone()); - - let resolved_source_buf = match source_buf.execute(namespace, scope.clone()) { - Some(r) => Box::new(r), - _ => return None - }; - let resolved_index = match byte_index.execute(namespace, scope.clone()) { - Some(r) => Box::new(r), - _ => return None - }; - - namespace.insert(local_scope_string, AmlValue::BufferField { - source_buf: resolved_source_buf, - index: resolved_index, - length: Box::new(AmlValue::IntegerConstant(16)) - }); - }, - NamedObj::DefCreateDWordField { ref name, ref source_buf, ref byte_index } => { - let local_scope_string = get_namespace_string(scope.clone(), name.clone()); - - let resolved_source_buf = match source_buf.execute(namespace, scope.clone()) { - Some(r) => Box::new(r), - _ => return None - }; - let resolved_index = match byte_index.execute(namespace, scope.clone()) { - Some(r) => Box::new(r), - _ => return None - }; - - namespace.insert(local_scope_string, AmlValue::BufferField { - source_buf: resolved_source_buf, - index: resolved_index, - length: Box::new(AmlValue::IntegerConstant(32)) - }); - }, - NamedObj::DefCreateQWordField { ref name, ref source_buf, ref byte_index } => { - let local_scope_string = get_namespace_string(scope.clone(), name.clone()); - - let resolved_source_buf = match source_buf.execute(namespace, scope.clone()) { - Some(r) => Box::new(r), - _ => return None - }; - let resolved_index = match byte_index.execute(namespace, scope.clone()) { - Some(r) => Box::new(r), - _ => return None - }; - - namespace.insert(local_scope_string, AmlValue::BufferField { - source_buf: resolved_source_buf, - index: resolved_index, - length: Box::new(AmlValue::IntegerConstant(64)) - }); - }, - NamedObj::DefCreateField { ref name, ref source_buf, ref bit_index, ref num_bits } => { - let local_scope_string = get_namespace_string(scope.clone(), name.clone()); - - let resolved_source_buf = match source_buf.execute(namespace, scope.clone()) { - Some(r) => Box::new(r), - _ => return None - }; - let resolved_index = match bit_index.execute(namespace, scope.clone()) { - Some(r) => Box::new(r), - _ => return None - }; - let resolved_length = match num_bits.execute(namespace, scope.clone()) { - Some(r) => Box::new(r), - _ => return None - }; - - namespace.insert(local_scope_string, AmlValue::BufferField { - source_buf: resolved_source_buf, - index: resolved_index, - length: resolved_length - }); - }, - NamedObj::DefDataRegion { ref name, ref signature, ref oem_id, ref oem_table_id } => { - let local_scope_string = get_namespace_string(scope.clone(), name.clone()); - - namespace.insert(local_scope_string, AmlValue::OperationRegion { - region: RegionSpace::SystemMemory, - offset: Box::new(AmlValue::IntegerConstant(0)), - len: Box::new(AmlValue::IntegerConstant(0)) - }); - }, - NamedObj::DefOpRegion { ref name, ref region, ref offset, ref len } => { - let local_scope_string = get_namespace_string(scope.clone(), name.clone()); - - let resolved_offset = match offset.execute(namespace, scope.clone()) { - Some(r) => r, - _ => return None - }; - - let resolved_len = match len.execute(namespace, scope.clone()) { - Some(r) => r, - _ => return None - }; - - namespace.insert(local_scope_string, AmlValue::OperationRegion { - region: *region, - offset: Box::new(resolved_offset), - len: Box::new(resolved_len) - }); - }, - NamedObj::DefField { ref name, ref flags, ref field_list } => { - let mut offset: usize = 0; - let mut connection = AmlValue::Uninitialized; - let mut flags = flags.clone(); - - for f in field_list { - match *f { - FieldElement::ReservedField { length } => offset += length, - FieldElement::ConnectFieldNameString(ref name) => connection = - AmlValue::ObjectReference(SuperName::NameString(name.clone())), - FieldElement::ConnectFieldBufferData(ref buf) => { - connection = match buf.execute(namespace, scope.clone()) { - Some(c) => c, - None => return None - }; - }, - FieldElement::AccessField { ref access_type, ref access_attrib } => { - match *access_type { - AccessType::BufferAcc(_) => flags.access_type = AccessType::BufferAcc(access_attrib.clone()), - ref a => flags.access_type = a.clone() - } - }, - FieldElement::NamedField { name: ref field_name, length } => { - let local_scope_string = get_namespace_string(scope.clone(), - field_name.clone()); - namespace.insert(local_scope_string, AmlValue::FieldUnit { - selector: FieldSelector::Region(name.clone()), - connection: Box::new(connection.clone()), - flags: flags.clone(), - offset: offset.clone(), - length: length.clone() - }); - - offset += length; - } - } - } - }, - NamedObj::DefMethod { ref name, ref method } => { - let local_scope_string = get_namespace_string(scope.clone(), name.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()); - - 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()); - - 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 - }); - }, - NamedObj::DefPowerRes { ref name, system_level, resource_order, 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::PowerResource { - system_level, - resource_order, - obj_list: local_namespace - }); - }, - NamedObj::DefMutex { ref name, sync_level } => { - let local_scope_string = get_namespace_string(scope, name.clone()); - namespace.insert(local_scope_string, AmlValue::Mutex(sync_level)); - }, - NamedObj::DefEvent { ref name } => { - let local_scope_string = get_namespace_string(scope, name.clone()); - namespace.insert(local_scope_string, AmlValue::Event); - }, - _ => () - } - - None - } + term_list: Vec } #[derive(Debug, Copy, Clone)] @@ -485,20 +61,15 @@ pub enum UpdateRule { } #[derive(Debug, Clone)] -pub enum FieldElement { - NamedField { - name: String, - length: usize - }, - ReservedField { - length: usize - }, - AccessField { - access_type: AccessType, - access_attrib: AccessAttrib - }, - ConnectFieldNameString(String), - ConnectFieldBufferData(DefBuffer), +pub struct NamedField { + name: String, + length: usize +} + +#[derive(Debug, Clone)] +pub struct AccessField { + access_type: AccessType, + access_attrib: AccessAttrib } #[derive(Debug, Clone)] @@ -515,9 +86,11 @@ pub enum AccessAttrib { AttribBlockProcessCall } -pub fn parse_named_obj(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> { +pub fn parse_named_obj(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_selector! { - data, + data, namespace, scope.clone(), parse_def_bank_field, parse_def_create_bit_field, parse_def_create_byte_field, @@ -538,39 +111,26 @@ pub fn parse_named_obj(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalErro parse_def_thermal_zone }; - Err(AmlInternalError::AmlInvalidOpCode) + Err(AmlError::AmlInvalidOpCode) } -fn parse_def_bank_field(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> { +fn parse_def_bank_field(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Why isn't bank name used? parser_opcode_extended!(data, 0x87); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[2..])?; - let (region_name, region_name_len) = match parse_name_string( - &data[2 + pkg_length_len .. 2 + pkg_length]) { - Ok(res) => res, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_length].to_vec()), 2 + pkg_length)), - Err(e) => return Err(e) - }; + let data = &data[2 + pkg_length_len .. 2 + pkg_length]; + + let region_name = parse_name_string(data, namespace, scope.clone())?; + let bank_name = parse_name_string(&data[2 + pkg_length_len + region_name.len .. 2 + pkg_length], namespace, scope.clone())?; - let (bank_name, bank_name_len) = match parse_name_string( - &data[2 + pkg_length_len + region_name_len .. 2 + pkg_length]) { - Ok(res) => res, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_length].to_vec()), 2 + pkg_length)), - Err(e) => return Err(e) - }; + let bank_value = parse_term_arg( + &data[2 + pkg_length_len + region_name.len .. 2 + pkg_length], namespace, scope.clone())?; - let (bank_value, bank_value_len) = match parse_term_arg( - &data[2 + pkg_length_len + region_name_len .. 2 + pkg_length]) { - Ok(res) => res, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_length].to_vec()), 2 + pkg_length)), - Err(e) => return Err(e) - }; - - let flags_raw = data[2 + pkg_length_len + region_name_len + bank_name_len + bank_value_len]; - let flags = FieldFlags { + let flags_raw = data[2 + pkg_length_len + region_name.len + bank_name.len + bank_value.len]; + let mut flags = FieldFlags { access_type: match flags_raw & 0x0F { 0 => AccessType::AnyAcc, 1 => AccessType::ByteAcc, @@ -578,145 +138,239 @@ fn parse_def_bank_field(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalErr 3 => AccessType::DWordAcc, 4 => AccessType::QWordAcc, 5 => AccessType::BufferAcc(AccessAttrib::AttribByte), - _ => return Err(AmlInternalError::AmlParseError("BankField - invalid access type")) + _ => return Err(AmlError::AmlParseError("BankField - invalid access type")) }, lock_rule: (flags_raw & 0x10) == 0x10, update_rule: match (flags_raw & 0x60) >> 5 { 0 => UpdateRule::Preserve, 1 => UpdateRule::WriteAsOnes, 2 => UpdateRule::WriteAsZeros, - _ => return Err(AmlInternalError::AmlParseError("BankField - invalid update rule")) + _ => return Err(AmlError::AmlParseError("BankField - invalid update rule")) } }; - let field_list = match parse_field_list( - &data[3 + pkg_length_len + region_name_len + bank_name_len + bank_value_len .. - 2 + pkg_length]) { - Ok(p) => p, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_length].to_vec()), 2 + pkg_length)), - Err(e) => return Err(e) + let selector = FieldSelector::Bank { + region: region_name.val.get_as_string()?, + bank_selector: Box::new(bank_value.val) }; - Ok((NamedObj::DefBankField {region_name, bank_name, bank_value, flags, field_list}, - 2 + pkg_length)) + let field_list = parse_field_list( + &data[3 + pkg_length_len + region_name.len + bank_name.len + bank_value.len .. + 2 + pkg_length], namespace, scope, selector, &mut flags)?; + + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + pkg_length + }) } -fn parse_def_create_bit_field(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> { +fn parse_def_create_bit_field(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode!(data, 0x8D); - let (source_buf, source_buf_len) = parse_term_arg(&data[1..])?; - let (bit_index, bit_index_len) = parse_term_arg(&data[1 + source_buf_len..])?; - let (name, name_len) = parse_name_string(&data[1 + source_buf_len + bit_index_len..])?; + let source_buf = parse_term_arg(&data[2..], namespace, scope.clone())?; + let bit_index = parse_term_arg(&data[2 + source_buf.len..], namespace, scope.clone())?; + let name = parse_name_string(&data[1 + source_buf.len + bit_index.len..], namespace, scope.clone())?; + + let local_scope_string = get_namespace_string(scope.clone(), name.val); + + namespace.insert(local_scope_string, AmlValue::BufferField { + source_buf: Box::new(source_buf.val), + index: Box::new(bit_index.val), + length: Box::new(AmlValue::IntegerConstant(1)) + }); - Ok((NamedObj::DefCreateBitField {name, source_buf, bit_index}, - 1 + source_buf_len + bit_index_len + name_len)) + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + name.len + source_buf.len + bit_index.len + }) } -fn parse_def_create_byte_field(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> { +fn parse_def_create_byte_field(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode!(data, 0x8C); - let (source_buf, source_buf_len) = parse_term_arg(&data[1..])?; - let (byte_index, byte_index_len) = parse_term_arg(&data[1 + source_buf_len..])?; - let (name, name_len) = parse_name_string(&data[1 + source_buf_len + byte_index_len..])?; + let source_buf = parse_term_arg(&data[2..], namespace, scope.clone())?; + let bit_index = parse_term_arg(&data[2 + source_buf.len..], namespace, scope.clone())?; + let name = parse_name_string(&data[1 + source_buf.len + bit_index.len..], namespace, scope.clone())?; + + let local_scope_string = get_namespace_string(scope.clone(), name.val); + + namespace.insert(local_scope_string, AmlValue::BufferField { + source_buf: Box::new(source_buf.val), + index: Box::new(bit_index.val), + length: Box::new(AmlValue::IntegerConstant(8)) + }); - Ok((NamedObj::DefCreateByteField {name, source_buf, byte_index}, - 1 + source_buf_len + byte_index_len + name_len)) + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + name.len + source_buf.len + bit_index.len + }) } -fn parse_def_create_word_field(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> { +fn parse_def_create_word_field(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode!(data, 0x8B); - let (source_buf, source_buf_len) = parse_term_arg(&data[1..])?; - let (byte_index, byte_index_len) = parse_term_arg(&data[1 + source_buf_len..])?; - let (name, name_len) = parse_name_string(&data[1 + source_buf_len + byte_index_len..])?; + let source_buf = parse_term_arg(&data[2..], namespace, scope.clone())?; + let bit_index = parse_term_arg(&data[2 + source_buf.len..], namespace, scope.clone())?; + let name = parse_name_string(&data[1 + source_buf.len + bit_index.len..], namespace, scope.clone())?; + + let local_scope_string = get_namespace_string(scope.clone(), name.val); + + namespace.insert(local_scope_string, AmlValue::BufferField { + source_buf: Box::new(source_buf.val), + index: Box::new(bit_index.val), + length: Box::new(AmlValue::IntegerConstant(16)) + }); - Ok((NamedObj::DefCreateWordField {name, source_buf, byte_index}, - 1 + source_buf_len + byte_index_len + name_len)) + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + name.len + source_buf.len + bit_index.len + }) } -fn parse_def_create_dword_field(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> { +fn parse_def_create_dword_field(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode!(data, 0x8A); - let (source_buf, source_buf_len) = parse_term_arg(&data[1..])?; - let (byte_index, byte_index_len) = parse_term_arg(&data[1 + source_buf_len..])?; - let (name, name_len) = parse_name_string(&data[1 + source_buf_len + byte_index_len..])?; + let source_buf = parse_term_arg(&data[2..], namespace, scope.clone())?; + let bit_index = parse_term_arg(&data[2 + source_buf.len..], namespace, scope.clone())?; + let name = parse_name_string(&data[1 + source_buf.len + bit_index.len..], namespace, scope.clone())?; + + let local_scope_string = get_namespace_string(scope.clone(), name.val); + + namespace.insert(local_scope_string, AmlValue::BufferField { + source_buf: Box::new(source_buf.val), + index: Box::new(bit_index.val), + length: Box::new(AmlValue::IntegerConstant(32)) + }); - Ok((NamedObj::DefCreateDWordField {name, source_buf, byte_index}, - 1 + source_buf_len + byte_index_len + name_len)) + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + name.len + source_buf.len + bit_index.len + }) } -fn parse_def_create_qword_field(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> { +fn parse_def_create_qword_field(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode!(data, 0x8F); - let (source_buf, source_buf_len) = parse_term_arg(&data[1..])?; - let (byte_index, byte_index_len) = parse_term_arg(&data[1 + source_buf_len..])?; - let (name, name_len) = parse_name_string(&data[1 + source_buf_len + byte_index_len..])?; + let source_buf = parse_term_arg(&data[2..], namespace, scope.clone())?; + let bit_index = parse_term_arg(&data[2 + source_buf.len..], namespace, scope.clone())?; + let name = parse_name_string(&data[1 + source_buf.len + bit_index.len..], namespace, scope.clone())?; + + let local_scope_string = get_namespace_string(scope.clone(), name.val); + + namespace.insert(local_scope_string, AmlValue::BufferField { + source_buf: Box::new(source_buf.val), + index: Box::new(bit_index.val), + length: Box::new(AmlValue::IntegerConstant(64)) + }); - Ok((NamedObj::DefCreateQWordField {name, source_buf, byte_index}, - 1 + source_buf_len + byte_index_len + name_len)) + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + name.len + source_buf.len + bit_index.len + }) } -fn parse_def_create_field(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> { +fn parse_def_create_field(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode_extended!(data, 0x13); - let (source_buf, source_buf_len) = parse_term_arg(&data[2..])?; - let (bit_index, bit_index_len) = parse_term_arg(&data[2 + source_buf_len..])?; - let (num_bits, num_bits_len) = parse_term_arg(&data[2 + source_buf_len + bit_index_len..])?; - let (name, name_len) = parse_name_string( - &data[2 + source_buf_len + bit_index_len + num_bits_len..])?; - - Ok((NamedObj::DefCreateField {name, source_buf, bit_index, num_bits}, - 2 + source_buf_len + bit_index_len + num_bits_len + name_len)) + let source_buf = parse_term_arg(&data[2..], namespace, scope.clone())?; + let bit_index = parse_term_arg(&data[2 + source_buf.len..], namespace, scope.clone())?; + let num_bits = parse_term_arg(&data[2 + source_buf.len + bit_index.len..], namespace, scope.clone())?; + let name = parse_name_string(&data[2 + source_buf.len + bit_index.len + num_bits.len..], namespace, scope.clone())?; + + let local_scope_string = get_namespace_string(scope.clone(), name.val); + + namespace.insert(local_scope_string, AmlValue::BufferField { + source_buf: Box::new(source_buf.val), + index: Box::new(bit_index.val), + length: Box::new(num_bits.val) + }); + + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + name.len + source_buf.len + bit_index.len + num_bits.len + }) } -fn parse_def_data_region(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> { +fn parse_def_data_region(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Find the actual offset and length, once table mapping is implemented parser_opcode_extended!(data, 0x88); - let (name, name_len) = parse_name_string(&data[2..])?; - let (signature, signature_len) = parse_term_arg(&data[2 + name_len..])?; - let (oem_id, oem_id_len) = parse_term_arg(&data[2 + name_len + signature_len..])?; - let (oem_table_id, oem_table_id_len) = parse_term_arg( - &data[2 + name_len + signature_len + oem_id_len..])?; + let name = parse_name_string(&data[2..], namespace, scope.clone())?; + let signature = parse_term_arg(&data[2 + name.len..], namespace, scope.clone())?; + let oem_id = parse_term_arg(&data[2 + name.len + signature.len..], namespace, scope.clone())?; + let oem_table_id = parse_term_arg(&data[2 + name.len + signature.len + oem_id.len..], namespace, scope.clone())?; + + let local_scope_string = get_namespace_string(scope.clone(), name.val); - Ok((NamedObj::DefDataRegion {name, signature, oem_id, oem_table_id}, - 2 + name_len + signature_len + oem_id_len + oem_table_id_len)) + namespace.insert(local_scope_string, AmlValue::OperationRegion { + region: RegionSpace::SystemMemory, + offset: Box::new(AmlValue::IntegerConstant(0)), + len: Box::new(AmlValue::IntegerConstant(0)) + }); + + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + name.len + signature.len + oem_id.len + oem_table_id.len + }) } -fn parse_def_event(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> { +fn parse_def_event(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode_extended!(data, 0x02); - let (name, name_len) = parse_name_string(&data[2..])?; + let name = parse_name_string(&data[2..], namespace, scope.clone())?; + + let local_scope_string = get_namespace_string(scope, name.val); + namespace.insert(local_scope_string, AmlValue::Event); - Ok((NamedObj::DefEvent {name}, 2 + name_len)) + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + name.len + }) } -fn parse_def_device(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> { +fn parse_def_device(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode_extended!(data, 0x82); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[2..])?; - let (name, name_len) = match parse_name_string(&data[2 + pkg_length_len .. 2 + pkg_length]) { - Ok(p) => p, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_length].to_vec()), 2 + pkg_length)), - Err(e) => return Err(e) - }; + let name = parse_name_string(&data[2 + pkg_length_len .. 2 + pkg_length], namespace, scope.clone())?; + + let mut local_namespace = BTreeMap::new(); + let obj_list = parse_object_list(&data[2 + pkg_length_len + name.len .. 2 + pkg_length], &mut local_namespace, String::new())?; - let obj_list = match parse_object_list(&data[2 + pkg_length_len + name_len .. 2 + pkg_length]) { - Ok(p) => p, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_length].to_vec()), 2 + pkg_length)), - Err(e) => return Err(e) - }; + let local_scope_string = get_namespace_string(scope, name.val); + namespace.insert(local_scope_string, AmlValue::Device(local_namespace)); - Ok((NamedObj::DefDevice {name, obj_list}, 2 + pkg_length_len)) + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + pkg_length + }) } -fn parse_def_op_region(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> { +fn parse_def_op_region(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode_extended!(data, 0x80); - let (name, name_len) = parse_name_string(&data[2..])?; - let region = match data[2 + name_len] { + let name = parse_name_string(&data[2..], namespace, scope.clone())?; + let region = match data[2 + name.len] { 0x00 => RegionSpace::SystemMemory, 0x01 => RegionSpace::SystemIO, 0x02 => RegionSpace::PCIConfig, @@ -727,29 +381,36 @@ fn parse_def_op_region(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalErro 0x07 => RegionSpace::IPMI, 0x08 => RegionSpace::GeneralPurposeIO, 0x09 => RegionSpace::GenericSerialBus, - 0x80 ... 0xFF => RegionSpace::UserDefined(data[2 + name_len]), - _ => return Err(AmlInternalError::AmlParseError("OpRegion - invalid region")) + 0x80 ... 0xFF => RegionSpace::UserDefined(data[2 + name.len]), + _ => return Err(AmlError::AmlParseError("OpRegion - invalid region")) }; - let (offset, offset_len) = parse_term_arg(&data[3 + name_len..])?; - let (len, len_len) = parse_term_arg(&data[3 + name_len + offset_len..])?; + let offset = parse_term_arg(&data[3 + name.len..], namespace, scope.clone())?; + let len = parse_term_arg(&data[3 + name.len + offset.len..], namespace, scope.clone())?; - Ok((NamedObj::DefOpRegion {name, region, offset, len}, 3 + name_len + offset_len + len_len)) + let local_scope_string = get_namespace_string(scope.clone(), name.val); + namespace.insert(local_scope_string, AmlValue::OperationRegion { + region: region, + offset: Box::new(offset.val), + len: Box::new(len.val) + }); + + Ok(AmlParseType { + val: AmlValue::None, + len: 3 + name.len + offset.len + len.len + }) } -fn parse_def_field(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> { +fn parse_def_field(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode_extended!(data, 0x81); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[2..])?; - let (name, name_len) = match parse_name_string(&data[2 + pkg_length_len .. 2 + pkg_length]) { - Ok(p) => p, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_length].to_vec()), 2 + pkg_length)), - Err(e) => return Err(e) - }; + let name = parse_name_string(&data[2 + pkg_length_len .. 2 + pkg_length], namespace, scope.clone())?; - let flags_raw = data[2 + pkg_length_len + name_len]; - let flags = FieldFlags { + let flags_raw = data[2 + pkg_length_len + name.len]; + let mut flags = FieldFlags { access_type: match flags_raw & 0x0F { 0 => AccessType::AnyAcc, 1 => AccessType::ByteAcc, @@ -757,49 +418,38 @@ fn parse_def_field(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> { 3 => AccessType::DWordAcc, 4 => AccessType::QWordAcc, 5 => AccessType::BufferAcc(AccessAttrib::AttribByte), - _ => return Err(AmlInternalError::AmlParseError("Field - Invalid access type")) + _ => return Err(AmlError::AmlParseError("Field - Invalid access type")) }, lock_rule: (flags_raw & 0x10) == 0x10, update_rule: match (flags_raw & 0x60) >> 5 { 0 => UpdateRule::Preserve, 1 => UpdateRule::WriteAsOnes, 2 => UpdateRule::WriteAsZeros, - _ => return Err(AmlInternalError::AmlParseError("Field - Invalid update rule")) + _ => return Err(AmlError::AmlParseError("Field - Invalid update rule")) } }; - let field_list = match parse_field_list(&data[3 + pkg_length_len + name_len .. 2 + pkg_length]) { - Ok(p) => p, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_length].to_vec()), 2 + pkg_length)), - Err(e) => return Err(e) - }; + let selector = FieldSelector::Region(name.val.get_as_string()?); - Ok((NamedObj::DefField {name, flags, field_list}, 2 + pkg_length)) + let field_list = parse_field_list(&data[3 + pkg_length_len + name.len .. 2 + pkg_length], namespace, scope, selector, &mut flags)?; + + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + pkg_length + }) } -fn parse_def_index_field(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> { +fn parse_def_index_field(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode_extended!(data, 0x86); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[2..])?; - let (idx_name, idx_name_len) = match parse_name_string( - &data[2 + pkg_length_len .. 2 + pkg_length]) { - Ok(p) => p, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_length].to_vec()), 2 + pkg_length)), - Err(e) => return Err(e) - }; + let idx_name = parse_name_string( &data[2 + pkg_length_len .. 2 + pkg_length], namespace, scope.clone())?; + let data_name = parse_name_string(&data[2 + pkg_length_len + idx_name.len .. 2 + pkg_length], namespace, scope.clone())?; - let (data_name, data_name_len) = match parse_name_string( - &data[2 + pkg_length_len + idx_name_len .. 2 + pkg_length]) { - Ok(p) => p, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_length].to_vec()), 2 + pkg_length)), - Err(e) => return Err(e) - }; - - let flags_raw = data[2 + pkg_length_len + idx_name_len + data_name_len]; - let flags = FieldFlags { + let flags_raw = data[2 + pkg_length_len + idx_name.len + data_name.len]; + let mut flags = FieldFlags { access_type: match flags_raw & 0x0F { 0 => AccessType::AnyAcc, 1 => AccessType::ByteAcc, @@ -807,78 +457,129 @@ fn parse_def_index_field(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalEr 3 => AccessType::DWordAcc, 4 => AccessType::QWordAcc, 5 => AccessType::BufferAcc(AccessAttrib::AttribByte), - _ => return Err(AmlInternalError::AmlParseError("IndexField - Invalid access type")) + _ => return Err(AmlError::AmlParseError("IndexField - Invalid access type")) }, lock_rule: (flags_raw & 0x10) == 0x10, update_rule: match (flags_raw & 0x60) >> 5 { 0 => UpdateRule::Preserve, 1 => UpdateRule::WriteAsOnes, 2 => UpdateRule::WriteAsZeros, - _ => return Err(AmlInternalError::AmlParseError("IndexField - Invalid update rule")) + _ => return Err(AmlError::AmlParseError("IndexField - Invalid update rule")) } }; - let field_list = match parse_field_list( - &data[3 + pkg_length_len + idx_name_len + data_name_len .. 2 + pkg_length]) { - Ok(p) => p, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_length].to_vec()), 2 + pkg_length)), - Err(e) => return Err(e) + let selector = FieldSelector::Index { + index_selector: idx_name.val.get_as_string()?, + data_selector: data_name.val.get_as_string()? }; - Ok((NamedObj::DefIndexField {idx_name, data_name, flags, field_list}, 2 + pkg_length)) + let field_list = parse_field_list( + &data[3 + pkg_length_len + idx_name.len + data_name.len .. 2 + pkg_length], namespace, scope, selector, &mut flags)?; + + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + pkg_length + }) } -fn parse_field_list(data: &[u8]) -> Result, AmlInternalError> { - let mut terms: Vec = vec!(); +fn parse_field_list(data: &[u8], + namespace: &mut BTreeMap, + scope: String, + selector: FieldSelector, + flags: &mut FieldFlags) -> ParseResult { let mut current_offset: usize = 0; + let mut connection = AmlValue::Uninitialized; while current_offset < data.len() { - let (res, len) = match parse_field_element(&data[current_offset..]) { - Ok(r) => r, - Err(AmlInternalError::AmlInvalidOpCode) => - return Err(AmlInternalError::AmlParseError("FieldList - no valid field")), + match parse_field_element(&data[current_offset..], namespace, scope.clone(), selector.clone(), + &mut connection, flags, &mut current_offset) { + Ok(_) => (), + Err(AmlError::AmlInvalidOpCode) => + return Err(AmlError::AmlParseError("FieldList - no valid field")), Err(e) => return Err(e) - }; - - terms.push(res); - current_offset += len; + } } - Ok(terms) + Ok(AmlParseType { + val: AmlValue::None, + len: data.len() + }) } -fn parse_field_element(data: &[u8]) -> Result<(FieldElement, usize), AmlInternalError> { - parser_selector! { - data, - parse_named_field, - parse_reserved_field, - parse_access_field, - parse_connect_field +fn parse_field_element(data: &[u8], + namespace: &mut BTreeMap, + scope: String, + selector: FieldSelector, + connection: &mut AmlValue, + flags: &mut FieldFlags, + offset: &mut usize) -> ParseResult { + let length = if let Ok(field) = parse_named_field(data, namespace, scope.clone()) { + let local_scope_string = get_namespace_string(scope.clone(), AmlValue::String(field.val.name.clone())); + + namespace.insert(local_scope_string, AmlValue::FieldUnit { + selector: selector.clone(), + connection: Box::new(connection.clone()), + flags: flags.clone(), + offset: offset.clone(), + length: field.val.length + }); + + field.len + } else if let Ok(field) = parse_reserved_field(data, namespace, scope.clone()) { + *offset += field.val; + field.len + } else if let Ok(field) = parse_access_field(data, namespace, scope.clone()) { + match field.val.access_type { + AccessType::BufferAcc(_) => + flags.access_type = AccessType::BufferAcc(field.val.access_attrib.clone()), + ref a => flags.access_type = a.clone() + } + + field.len + } else if let Ok(field) = parse_connect_field(data, namespace, scope.clone()) { + *connection = field.val.clone(); + field.len + } else { + return Err(AmlError::AmlInvalidOpCode); }; - - Err(AmlInternalError::AmlInvalidOpCode) + + Ok(AmlParseType { + val: AmlValue::None, + len: length + }) } -fn parse_named_field(data: &[u8]) -> Result<(FieldElement, usize), AmlInternalError> { +fn parse_named_field(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> Result, AmlError> { let (name_seg, name_seg_len) = parse_name_seg(&data[0..4])?; let name = match String::from_utf8(name_seg) { Ok(s) => s, - Err(_) => return Err(AmlInternalError::AmlParseError("NamedField - invalid name")) + Err(_) => return Err(AmlError::AmlParseError("NamedField - invalid name")) }; let (length, length_len) = parse_pkg_length(&data[4..])?; - Ok((FieldElement::NamedField {name, length}, 4 + length_len)) + Ok(AmlParseTypeGeneric { + val: NamedField { name, length }, + len: 4 + length_len + }) } -fn parse_reserved_field(data: &[u8]) -> Result<(FieldElement, usize), AmlInternalError> { +fn parse_reserved_field(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> Result, AmlError> { parser_opcode!(data, 0x00); let (length, length_len) = parse_pkg_length(&data[1..])?; - Ok((FieldElement::ReservedField {length}, 1 + length_len)) + Ok(AmlParseTypeGeneric { + val: length, + len: 1 + length_len + }) } -fn parse_access_field(data: &[u8]) -> Result<(FieldElement, usize), AmlInternalError> { +fn parse_access_field(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> Result, AmlError> { parser_opcode!(data, 0x01, 0x03); let flags_raw = data[1]; @@ -889,7 +590,7 @@ fn parse_access_field(data: &[u8]) -> Result<(FieldElement, usize), AmlInternalE 3 => AccessType::DWordAcc, 4 => AccessType::QWordAcc, 5 => AccessType::BufferAcc(AccessAttrib::AttribByte), - _ => return Err(AmlInternalError::AmlParseError("AccessField - Invalid access type")) + _ => return Err(AmlError::AmlParseError("AccessField - Invalid access type")) }; let access_attrib = match (flags_raw & 0xC0) >> 6 { @@ -904,155 +605,169 @@ fn parse_access_field(data: &[u8]) -> Result<(FieldElement, usize), AmlInternalE 0x0D => AccessAttrib::AttribBlockProcessCall, 0x0E => AccessAttrib::AttribRawBytes(data[3]), 0x0F => AccessAttrib::AttribRawProcessBytes(data[3]), - _ => return Err(AmlInternalError::AmlParseError("AccessField - Invalid access attrib")) + _ => return Err(AmlError::AmlParseError("AccessField - Invalid access attrib")) }, 1 => AccessAttrib::AttribBytes(data[2]), 2 => AccessAttrib::AttribRawBytes(data[2]), 3 => AccessAttrib::AttribRawProcessBytes(data[2]), - _ => return Err(AmlInternalError::AmlParseError("AccessField - Invalid access attrib")) + _ => return Err(AmlError::AmlParseError("AccessField - Invalid access attrib")) // This should never happen but the compiler bitches if I don't cover this }; - return Ok((FieldElement::AccessField {access_type, access_attrib}, if data[0] == 0x01 { - 3 as usize - } else { - 4 as usize - })) + Ok(AmlParseTypeGeneric { + val: AccessField { access_type, access_attrib }, + len: if data[0] == 0x01 { + 3 as usize + } else { + 4 as usize + } + }) } -fn parse_connect_field(data: &[u8]) -> Result<(FieldElement, usize), AmlInternalError> { +fn parse_connect_field(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode!(data, 0x02); - match parse_def_buffer(&data[1..]) { - Ok((buf, buf_len)) => return Ok((FieldElement::ConnectFieldBufferData(buf), buf_len + 1)), - Err(AmlInternalError::AmlInvalidOpCode) => (), - Err(e) => return Err(e) - } - - match parse_name_string(&data[1..]) { - Ok((name, name_len)) => Ok((FieldElement::ConnectFieldNameString(name), name_len + 1)), - Err(AmlInternalError::AmlInvalidOpCode) => Err(AmlInternalError::AmlParseError("ConnectField - unable to match field")), - Err(e) => Err(e) + if let Ok(e) = parse_def_buffer(&data[1..], namespace, scope.clone()) { + Ok(AmlParseType { + val: e.val, + len: e.len + 1 + }) + } else { + let name = parse_name_string(&data[1..], namespace, scope.clone())?; + Ok(AmlParseType { + val: AmlValue::ObjectReference(ObjectReference::NamedObj(name.val.get_as_string()?)), + len: name.len + 1 + }) } } -fn parse_def_method(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> { +fn parse_def_method(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode!(data, 0x14); let (pkg_len, pkg_len_len) = parse_pkg_length(&data[1..])?; - let (name, name_len) = match parse_name_string(&data[1 + pkg_len_len..]) { - Ok(p) => p, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((NamedObj::DeferredLoad(data[0 .. 1 + pkg_len].to_vec()), 1 + pkg_len)), - Err(e) => return Err(e) - }; - let flags = data[1 + pkg_len_len + name_len]; + let name = parse_name_string(&data[1 + pkg_len_len..], namespace, scope.clone())?; + let flags = data[1 + pkg_len_len + name.len]; let arg_count = flags & 0x07; let serialized = (flags & 0x08) == 0x08; let sync_level = flags & 0xF0 >> 4; - let term_list = match parse_term_list(&data[2 + pkg_len_len + name_len .. 1 + pkg_len]) { - Ok(p) => p, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((NamedObj::DeferredLoad(data[0 .. 1 + pkg_len].to_vec()), 1 + pkg_len)), - Err(e) => return Err(e) - }; + let term_list = &data[2 + pkg_len_len + name.len .. 1 + pkg_len]; + + let local_scope_string = get_namespace_string(scope.clone(), name.val); + namespace.insert(local_scope_string, AmlValue::Method(Method { + arg_count, + serialized, + sync_level, + term_list: term_list.to_vec() + })); - Ok((NamedObj::DefMethod { - name: name, - method: Method { - arg_count, - serialized, - sync_level, - term_list - } - }, pkg_len + 1)) + Ok(AmlParseType { + val: AmlValue::None, + len: 1 + pkg_len + }) } -fn parse_def_mutex(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> { +fn parse_def_mutex(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode_extended!(data, 0x01); - let (name, name_len) = match parse_name_string(&data[2 ..]) { - Ok(p) => p, - Err(e) => return Err(e), - }; - let flags = data[2 + name_len]; + let name = parse_name_string(&data[2 ..], namespace, scope.clone())?; + let flags = data[2 + name.len]; let sync_level = flags & 0x0F; + + let local_scope_string = get_namespace_string(scope, name.val); + namespace.insert(local_scope_string, AmlValue::Mutex(sync_level)); - Ok((NamedObj::DefMutex {name, sync_level}, name_len + 3)) + Ok(AmlParseType { + val: AmlValue::None, + len: 3 + name.len + }) } -fn parse_def_power_res(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> { +fn parse_def_power_res(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode_extended!(data, 0x84); let (pkg_len, pkg_len_len) = parse_pkg_length(&data[2..])?; - let (name, name_len) = match parse_name_string(&data[2 + pkg_len_len..]) { - Ok(p) => p, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_len].to_vec()), 2 + pkg_len)), - Err(e) => return Err(e) - }; + let name = parse_name_string(&data[2 + pkg_len_len..], namespace, scope.clone())?; + + let local_scope_string = get_namespace_string(scope, name.val); + let mut local_namespace = BTreeMap::new(); - let system_level = data[2 + pkg_len_len + name_len]; - let resource_order: u16 = (data[3 + pkg_len_len + name_len] as u16) + - ((data[4 + pkg_len_len + name_len] as u16) << 8); + let system_level = data[2 + pkg_len_len + name.len]; + let resource_order: u16 = (data[3 + pkg_len_len + name.len] as u16) + + ((data[4 + pkg_len_len + name.len] as u16) << 8); - let obj_list = match parse_object_list(&data[5 + pkg_len_len + name_len .. 2 + pkg_len]) { - Ok(p) => p, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_len].to_vec()), 2 + pkg_len)), - Err(e) => return Err(e) - }; + parse_object_list(&data[5 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_namespace, String::new())?; + + namespace.insert(local_scope_string, AmlValue::PowerResource { + system_level, + resource_order, + obj_list: local_namespace + }); - Ok((NamedObj::DefPowerRes {name, system_level, resource_order, obj_list}, 2 + pkg_len)) + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + pkg_len + }) } -fn parse_def_processor(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> { +fn parse_def_processor(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode_extended!(data, 0x83); let (pkg_len, pkg_len_len) = parse_pkg_length(&data[2..])?; - let (name, name_len) = match parse_name_string(&data[2 + pkg_len_len..]) { - Ok(p) => p, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_len].to_vec()), 2 + pkg_len)), - Err(e) => return Err(e) - }; + let name = parse_name_string(&data[2 + pkg_len_len..], namespace, scope.clone())?; + + let local_scope_string = get_namespace_string(scope, name.val); + let mut local_namespace = BTreeMap::new(); + + let proc_id = data[2 + pkg_len_len + name.len]; + let p_blk_addr: u32 = (data[3 + pkg_len_len + name.len] as u32) + + ((data[4 + pkg_len_len + name.len] as u32) << 8) + + ((data[5 + pkg_len_len + name.len] as u32) << 16) + + ((data[6 + pkg_len_len + name.len] as u32) << 24); + let p_blk_len = data[7 + pkg_len_len + name.len]; - let proc_id = data[2 + pkg_len_len + name_len]; - let p_blk_addr: u32 = (data[3 + pkg_len_len + name_len] as u32) + - ((data[4 + pkg_len_len + name_len] as u32) << 8) + - ((data[5 + pkg_len_len + name_len] as u32) << 16) + - ((data[6 + pkg_len_len + name_len] as u32) << 24); - let p_blk_len = data[7 + pkg_len_len + name_len]; + parse_object_list(&data[8 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_namespace, String::new())?; - let obj_list = match parse_object_list(&data[8 + pkg_len_len + name_len .. 2 + pkg_len]) { - Ok(p) => p, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_len].to_vec()), 2 + pkg_len)), - Err(e) => return Err(e) - }; + 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 + }); - Ok((NamedObj::DefProcessor {name, proc_id, p_blk_addr, p_blk_len, obj_list}, 2 + pkg_len)) + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + pkg_len + }) } -fn parse_def_thermal_zone(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> { - parser_opcode_extended!(data, 0x85); - +fn parse_def_thermal_zone(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + parser_opcode_extended!(data, 0x85); + let (pkg_len, pkg_len_len) = parse_pkg_length(&data[2..])?; - let (name, name_len) = match parse_name_string(&data[2 + pkg_len_len..]) { - Ok(p) => p, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_len].to_vec()), 2 + pkg_len)), - Err(e) => return Err(e) - }; + let name = parse_name_string(&data[2 + pkg_len_len .. 2 + pkg_len], namespace, scope.clone())?; + + let local_scope_string = get_namespace_string(scope, name.val); + let mut local_namespace = BTreeMap::new(); + + parse_object_list(&data[2 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_namespace, String::new())?; + + namespace.insert(local_scope_string, AmlValue::ThermalZone(local_namespace)); - let obj_list = match parse_object_list(&data[2 + pkg_len_len + name_len .. 2 + pkg_len]) { - Ok(p) => p, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_len].to_vec()), 2 + pkg_len)), - Err(e) => return Err(e) - }; - - Ok((NamedObj::DefThermalZone {name, obj_list}, 2 + pkg_len)) + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + pkg_len + }) } diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index be49f7b..d2ac417 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -6,9 +6,7 @@ use collections::btree_map::BTreeMap; use core::str::FromStr; use super::namedobj::{ RegionSpace, FieldFlags, Method }; -use super::termlist::Object; -use super::namestring::SuperName; -use super::type2opcode::Type2OpCode; +use super::AmlError; #[derive(Debug, Clone)] pub enum FieldSelector { @@ -23,8 +21,17 @@ pub enum FieldSelector { } } +#[derive(Debug, Clone)] +pub enum ObjectReference { + ArgObj(u8), + LocalObj(u8), + NamedObj(String), + Object(Box) +} + #[derive(Debug, Clone)] pub enum AmlValue { + None, Uninitialized, Buffer { length: Box, @@ -46,11 +53,11 @@ pub enum AmlValue { offset: usize, length: usize }, - Integer(Type2OpCode), + Integer(u64), IntegerConstant(u64), Method(Method), Mutex(u8), - ObjectReference(SuperName), + ObjectReference(ObjectReference), OperationRegion { region: RegionSpace, offset: Box, @@ -73,22 +80,37 @@ pub enum AmlValue { } impl AmlValue { - pub fn get_as_package(&self) -> Option> { + // TODO: These should be able to throw errors rather than returning options + pub fn get_as_string(&self) -> Result { match *self { - AmlValue::Package(ref p) => Some(p.clone()), - _ => None + AmlValue::String(ref s) => Ok(s.clone()), + _ => Err(AmlError::AmlValueError) + } + } + + pub fn get_as_package(&self) -> Result, AmlError> { + match *self { + AmlValue::Package(ref p) => Ok(p.clone()), + _ => Err(AmlError::AmlValueError) } } - pub fn get_as_integer(&self) -> Option { + pub fn get_as_integer(&self) -> Result { match *self { - AmlValue::IntegerConstant(ref i) => Some(i.clone()), - _ => None + AmlValue::IntegerConstant(ref i) => Ok(i.clone()), + _ => Err(AmlError::AmlValueError) } } } -pub fn get_namespace_string(current: String, modifier: String) -> String { +pub fn get_namespace_string(current: String, modifier_v: AmlValue) -> String { + // TODO: Type error if modifier not string + let modifier = if let Ok(s) = modifier_v.get_as_string() { + s + } else { + return current; + }; + if current.len() == 0 { return modifier; } diff --git a/src/acpi/aml/namespacemodifier.rs b/src/acpi/aml/namespacemodifier.rs index 8e7e2cc..b04d405 100644 --- a/src/acpi/aml/namespacemodifier.rs +++ b/src/acpi/aml/namespacemodifier.rs @@ -3,23 +3,25 @@ use collections::string::String; use collections::vec::Vec; use collections::btree_map::BTreeMap; -use super::{AmlInternalError, AmlExecutable, AmlValue, get_namespace_string}; +use super::AmlError; +use super::parser::{AmlParseType, ParseResult, AmlParseTypeGeneric}; +use super::namespace::{AmlValue, ObjectReference, FieldSelector, get_namespace_string}; use super::pkglength::parse_pkg_length; -use super::namestring::{parse_name_string, SuperName}; -use super::termlist::{parse_term_list, TermObj}; -use super::dataobj::{parse_data_ref_obj, DataRefObj}; +use super::namestring::parse_name_string; +use super::termlist::parse_term_list; +use super::dataobj::parse_data_ref_obj; pub fn parse_namespace_modifier(data: &[u8], namespace: &mut BTreeMap, scope: String) -> ParseResult { parser_selector! { - data, namespace, scope, + data, namespace, scope.clone(), parse_alias_op, parse_scope_op, parse_name_op }; - Err(AmlInternalError::AmlInvalidOpCode) + Err(AmlError::AmlInvalidOpCode) } fn parse_alias_op(data: &[u8], @@ -27,17 +29,17 @@ fn parse_alias_op(data: &[u8], scope: String) -> ParseResult { parser_opcode!(data, 0x06); - let source_name = parse_name_string(&data[1..], namespace, scope)?; - let alias_name = parse_name_string(&data[1 + source_name_len..], namespace, scope)?; + let source_name = parse_name_string(&data[1..], namespace, scope.clone())?; + let alias_name = parse_name_string(&data[1 + source_name.len..], namespace, scope.clone())?; - let local_scope_string = get_namespace_string(scope.clone(), parser_verify_value!(source_name)); - let local_alias_string = get_namespace_string(scope.clone(), parser_verify_value!(alias_name)); + let local_scope_string = get_namespace_string(scope.clone(), source_name.val); + let local_alias_string = get_namespace_string(scope.clone(), alias_name.val); namespace.insert(local_scope_string, AmlValue::ObjectReference( - SuperName::NameString(local_alias_string))); + ObjectReference::NamedObj(local_alias_string))); Ok(AmlParseType { - val: None, + val: AmlValue::None, len: 1 + source_name.len + alias_name.len }) } @@ -47,16 +49,16 @@ fn parse_name_op(data: &[u8], scope: String) -> ParseResult { parser_opcode!(data, 0x08); - let name = parse_name_string(&data[1..], namespace, scope)?; - let data_ref_obj = parse_data_ref_obj(&data[1 + name_len..], namespace, scope)?; + let name = parse_name_string(&data[1..], namespace, scope.clone())?; + let data_ref_obj = parse_data_ref_obj(&data[1 + name.len..], namespace, scope.clone())?; - let local_scope_string = get_namespace_string(scope.clone(), parser_verify_value!(name)); + let local_scope_string = get_namespace_string(scope.clone(), name.val); - namespace.insert(local_scope_string, parser_verify_value!(data_ref_obj)); + namespace.insert(local_scope_string, data_ref_obj.val); Ok(AmlParseType { - val: None, - len: 1 + name_len + data_ref_obj_len + val: AmlValue::None, + len: 1 + name.len + data_ref_obj.len }) } @@ -66,13 +68,13 @@ fn parse_scope_op(data: &[u8], parser_opcode!(data, 0x10); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; - let name = parse_name_string(&data[1 + pkg_length_len..], namespace, scope)?; + let name = parse_name_string(&data[1 + pkg_length_len..], namespace, scope.clone())?; - let local_scope_string = get_namespace_string(scope, parser_verify_value!(name)); - parse_term_list(&data[1 + pkg_length_len + name_len..], namespace, local_scope_string)?; + let local_scope_string = get_namespace_string(scope, name.val); + parse_term_list(&data[1 + pkg_length_len + name.len..], namespace, local_scope_string)?; Ok(AmlParseType { - val: None, + val: AmlValue::None, len: 1 + pkg_length }) } diff --git a/src/acpi/aml/namestring.rs b/src/acpi/aml/namestring.rs index 8015a8c..ccbdcce 100644 --- a/src/acpi/aml/namestring.rs +++ b/src/acpi/aml/namestring.rs @@ -1,27 +1,16 @@ use collections::vec::Vec; use collections::string::String; +use collections::btree_map::BTreeMap; -use super::AmlInternalError; +use super::AmlError; +use super::parser::{AmlParseType, ParseResult, AmlParseTypeGeneric}; +use super::namespace::{AmlValue, ObjectReference, FieldSelector, get_namespace_string}; +use super::dataobj::{parse_arg_obj, parse_local_obj}; +use super::type2opcode::parse_type6_opcode; -use super::dataobj::{parse_arg_obj, parse_local_obj, ArgObj, LocalObj}; -use super::type2opcode::{parse_type6_opcode, Type6OpCode}; - -#[derive(Debug, Clone)] -pub enum SuperName { - NameString(String), - ArgObj(ArgObj), - LocalObj(LocalObj), - DebugObj, - Type6OpCode(Type6OpCode) -} - -#[derive(Debug, Clone)] -pub enum Target { - SuperName(SuperName), - Null -} - -pub fn parse_name_string(data: &[u8]) -> Result<(String, usize), AmlInternalError> { +pub fn parse_name_string(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { let mut characters: Vec = vec!(); let mut starting_index: usize = 0; @@ -36,7 +25,7 @@ pub fn parse_name_string(data: &[u8]) -> Result<(String, usize), AmlInternalErro } let sel = |data| { - parser_selector! { + parser_selector_simple! { data, parse_dual_name_path, parse_multi_name_path, @@ -44,7 +33,7 @@ pub fn parse_name_string(data: &[u8]) -> Result<(String, usize), AmlInternalErro parse_name_seg }; - Err(AmlInternalError::AmlInvalidOpCode) + Err(AmlError::AmlInvalidOpCode) }; let (mut chr, len) = sel(&data[starting_index..])?; characters.append(&mut chr); @@ -52,35 +41,38 @@ pub fn parse_name_string(data: &[u8]) -> Result<(String, usize), AmlInternalErro let name_string = String::from_utf8(characters); match name_string { - Ok(s) => Ok((s.clone(), len + starting_index)), - Err(_) => Err(AmlInternalError::AmlParseError("Namestring - Name is invalid")) + Ok(s) => Ok(AmlParseType { + val: AmlValue::String(s.clone()), + len: len + starting_index + }), + Err(_) => Err(AmlError::AmlParseError("Namestring - Name is invalid")) } } -fn parse_null_name(data: &[u8]) -> Result<(Vec, usize), AmlInternalError> { +fn parse_null_name(data: &[u8]) -> Result<(Vec, usize), AmlError> { parser_opcode!(data, 0x00); Ok((vec!(), 1 as usize)) } -pub fn parse_name_seg(data: &[u8]) -> Result<(Vec, usize), AmlInternalError> { +pub fn parse_name_seg(data: &[u8]) -> Result<(Vec, usize), AmlError> { match data[0] { 0x41 ... 0x5A | 0x5F => (), - _ => return Err(AmlInternalError::AmlInvalidOpCode) + _ => return Err(AmlError::AmlInvalidOpCode) } match data[1] { 0x30 ... 0x39 | 0x41 ... 0x5A | 0x5F => (), - _ => return Err(AmlInternalError::AmlInvalidOpCode) + _ => return Err(AmlError::AmlInvalidOpCode) } match data[2] { 0x30 ... 0x39 | 0x41 ... 0x5A | 0x5F => (), - _ => return Err(AmlInternalError::AmlInvalidOpCode) + _ => return Err(AmlError::AmlInvalidOpCode) } match data[3] { 0x30 ... 0x39 | 0x41 ... 0x5A | 0x5F => (), - _ => return Err(AmlInternalError::AmlInvalidOpCode) + _ => return Err(AmlError::AmlInvalidOpCode) } let mut name_seg = vec!(data[0], data[1], data[2], data[3]); @@ -91,7 +83,7 @@ pub fn parse_name_seg(data: &[u8]) -> Result<(Vec, usize), AmlInternalError> Ok((name_seg, 4 as usize)) } -fn parse_dual_name_path(data: &[u8]) -> Result<(Vec, usize), AmlInternalError> { +fn parse_dual_name_path(data: &[u8]) -> Result<(Vec, usize), AmlError> { parser_opcode!(data, 0x2E); let mut characters: Vec = vec!(); @@ -118,12 +110,12 @@ fn parse_dual_name_path(data: &[u8]) -> Result<(Vec, usize), AmlInternalErro Ok((characters, dual_len)) } -fn parse_multi_name_path(data: &[u8]) -> Result<(Vec, usize), AmlInternalError> { +fn parse_multi_name_path(data: &[u8]) -> Result<(Vec, usize), AmlError> { parser_opcode!(data, 0x2F); let seg_count = data[1]; if seg_count == 0x00 { - return Err(AmlInternalError::AmlParseError("MultiName Path - can't have zero name segments")); + return Err(AmlError::AmlParseError("MultiName Path - can't have zero name segments")); } let mut current_seg = 0; @@ -149,40 +141,52 @@ fn parse_multi_name_path(data: &[u8]) -> Result<(Vec, usize), AmlInternalErr Ok((characters, multi_len)) } -pub fn parse_super_name(data: &[u8]) -> Result<(SuperName, usize), AmlInternalError> { +pub fn parse_super_name(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_selector! { - data, + data, namespace, scope.clone(), parse_simple_name, - parser_wrap!(SuperName::Type6OpCode, parse_type6_opcode), + parse_type6_opcode, parse_debug_obj }; - Err(AmlInternalError::AmlInvalidOpCode) + Err(AmlError::AmlInvalidOpCode) } -fn parse_debug_obj(data: &[u8]) -> Result<(SuperName, usize), AmlInternalError> { +fn parse_debug_obj(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode_extended!(data, 0x31); - Ok((SuperName::DebugObj, 2 as usize)) + + Ok(AmlParseType { + val: AmlValue::DebugObject, + len: 2 as usize + }) } -pub fn parse_simple_name(data: &[u8]) -> Result<(SuperName, usize), AmlInternalError> { +pub fn parse_simple_name(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_selector! { - data, - parser_wrap!(SuperName::NameString, parse_name_string), - parser_wrap!(SuperName::ArgObj, parse_arg_obj), - parser_wrap!(SuperName::LocalObj, parse_local_obj) + data, namespace, scope.clone(), + parse_name_string, + parse_arg_obj, + parse_local_obj }; - Err(AmlInternalError::AmlInvalidOpCode) + Err(AmlError::AmlInvalidOpCode) } -pub fn parse_target(data: &[u8]) -> Result<(Target, usize), AmlInternalError> { +pub fn parse_target(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { if data[0] == 0x00 { - Ok((Target::Null, 1 as usize)) + Ok(AmlParseType { + val: AmlValue::None, + len: 1 as usize + }) } else { - match parse_super_name(data) { - Ok((name, name_len)) => Ok((Target::SuperName(name), name_len)), - Err(e) => Err(e) - } + parse_super_name(data, namespace, scope.clone()) } } diff --git a/src/acpi/aml/parser.rs b/src/acpi/aml/parser.rs index 321f013..080a1ae 100644 --- a/src/acpi/aml/parser.rs +++ b/src/acpi/aml/parser.rs @@ -1,16 +1,10 @@ -use super::AmlValue; +use super::namespace::AmlValue; +use super::AmlError; -pub type ParseResult = Result; +pub type ParseResult = Result; +pub type AmlParseType = AmlParseTypeGeneric; -pub struct AmlParseType { - val: Option, - len: usize -} - -// TODO: make private -pub enum AmlInternalError { - AmlParseError(&'static str), - AmlInvalidOpCode, - AmlValueError, - AmlDeferredLoad +pub struct AmlParseTypeGeneric { + pub val: T, + pub len: usize } diff --git a/src/acpi/aml/parsermacros.rs b/src/acpi/aml/parsermacros.rs index 7c9e101..6b9555a 100644 --- a/src/acpi/aml/parsermacros.rs +++ b/src/acpi/aml/parsermacros.rs @@ -3,7 +3,7 @@ macro_rules! parser_selector { {$data:expr, $namespace:expr, $scope:expr, $func:expr} => { match $func($data, $namespace, $scope) { Ok(res) => return Ok(res), - Err(AmlInternalError::AmlInvalidOpCode) => (), + Err(AmlError::AmlInvalidOpCode) => (), Err(e) => return Err(e) } }; @@ -13,12 +13,29 @@ macro_rules! parser_selector { }; } +macro_rules! parser_selector_simple { + {$data:expr, $func:expr} => { + match $func($data) { + Ok(res) => return Ok(res), + Err(AmlError::AmlInvalidOpCode) => (), + Err(e) => return Err(e) + } + }; + {$data:expr, $func:expr, $($funcs:expr),+} => { + parser_selector_simple! {$data, $func}; + parser_selector_simple! {$data, $($funcs),*}; + }; +} + #[macro_export] macro_rules! parser_wrap { ($wrap:expr, $func:expr) => { - |data| { + |data, namespace, scope| { match $func(data) { - Ok((res, size)) => Ok(($wrap(res), size)), + Ok(res) => Ok(AmlParseTypeGeneric { + val: $wrap(res.val), + len: res.len + }), Err(e) => Err(e) } } @@ -29,12 +46,12 @@ macro_rules! parser_wrap { macro_rules! parser_opcode { ($data:expr, $opcode:expr) => { if $data[0] != $opcode { - return Err(AmlInternalError::AmlInvalidOpCode); + return Err(AmlError::AmlInvalidOpCode); } }; ($data:expr, $opcode:expr, $alternate_opcode:expr) => { if $data[0] != $opcode && $data[0] != $alternate_opcode { - return Err(AmlInternalError::AmlInvalidOpCode); + return Err(AmlError::AmlInvalidOpCode); } }; } @@ -43,7 +60,7 @@ macro_rules! parser_opcode { macro_rules! parser_opcode_extended { ($data:expr, $opcode:expr) => { if $data[0] != 0x5B || $data[1] != $opcode { - return Err(AmlInternalError::AmlInvalidOpCode); + return Err(AmlError::AmlInvalidOpCode); } }; } @@ -53,7 +70,7 @@ macro_rules! parser_verify_value { ($val:expr) => { match $val.val { Some(s) => s, - None => return Err(AmlInternalError::AmlValueError) + None => return Err(AmlError::AmlValueError) } }; } diff --git a/src/acpi/aml/pkglength.rs b/src/acpi/aml/pkglength.rs index 7c4ace8..b93939f 100644 --- a/src/acpi/aml/pkglength.rs +++ b/src/acpi/aml/pkglength.rs @@ -1,6 +1,6 @@ -use super::AmlInternalError; +use super::AmlError; -pub fn parse_pkg_length(data: &[u8]) -> Result<(usize, usize), AmlInternalError> { +pub fn parse_pkg_length(data: &[u8]) -> Result<(usize, usize), AmlError> { let lead_byte = data[0]; let count_bytes: usize = (lead_byte >> 6) as usize; @@ -10,7 +10,7 @@ pub fn parse_pkg_length(data: &[u8]) -> Result<(usize, usize), AmlInternalError> let upper_two = (lead_byte >> 4) & 0x03; if upper_two != 0 { - return Err(AmlInternalError::AmlParseError("Invalid package length")); + return Err(AmlError::AmlParseError("Invalid package length")); } let mut current_byte = 0; diff --git a/src/acpi/aml/termlist.rs b/src/acpi/aml/termlist.rs index 5e5482e..bc2a747 100644 --- a/src/acpi/aml/termlist.rs +++ b/src/acpi/aml/termlist.rs @@ -3,158 +3,91 @@ use collections::string::String; use collections::vec::Vec; use collections::btree_map::BTreeMap; -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}; -use super::type1opcode::{parse_type1_opcode, Type1OpCode}; -use super::type2opcode::{parse_type2_opcode, Type2OpCode}; +use super::AmlError; +use super::parser::{AmlParseType, ParseResult, AmlParseTypeGeneric}; +use super::namespace::{AmlValue, ObjectReference, FieldSelector, get_namespace_string}; +use super::namespacemodifier::parse_namespace_modifier; +use super::namedobj::parse_named_obj; +use super::dataobj::{parse_data_obj, parse_arg_obj, parse_local_obj}; +use super::type1opcode::parse_type1_opcode; +use super::type2opcode::parse_type2_opcode; use super::namestring::parse_name_string; -#[derive(Debug, Clone)] -pub enum TermArg { - LocalObj(Box), - DataObj(Box), - ArgObj(Box), - Type2Opcode(Box) -} - -#[derive(Debug, Clone)] -pub enum TermObj { - NamespaceModifier(Box), - NamedObj(Box), - Type1Opcode(Box), - Type2Opcode(Box) -} - -#[derive(Debug, Clone)] -pub enum Object { - NamespaceModifier(Box), - NamedObj(Box) -} - -#[derive(Debug, Clone)] -pub struct MethodInvocation { - -} - -impl AmlExecutable for Vec { - fn execute(&self, namespace: &mut BTreeMap, scope: String) -> Option { - for term in self { - term.execute(namespace, scope.clone()); - } - - None - } -} - -impl AmlExecutable for Object { - 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) - } - } -} - -impl AmlExecutable for Vec { - fn execute(&self, namespace: &mut BTreeMap, scope: String) -> Option { - for term in self { - term.execute(namespace, scope.clone()); - } - - None - } -} - -impl AmlExecutable for TermArg { - fn execute(&self, namespace: &mut BTreeMap, scope: String) -> Option { - match *self { - TermArg::LocalObj(ref l) => Some(AmlValue::Uninitialized), - TermArg::DataObj(ref d) => d.execute(namespace, scope), - TermArg::ArgObj(ref a) => Some(AmlValue::Uninitialized), - TermArg::Type2Opcode(ref o) => Some(AmlValue::Uninitialized) - } - } -} - -impl AmlExecutable for TermObj { - 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()), - TermObj::Type1Opcode(ref res) => res.execute(namespace, scope.clone()), - TermObj::Type2Opcode(ref res) => res.execute(namespace, scope.clone()) - } - } -} - pub fn parse_term_list(data: &[u8], namespace: &mut BTreeMap, scope: String) -> ParseResult { let mut current_offset: usize = 0; while current_offset < data.len() { - let (res, len) = parse_term_obj(&data[current_offset..], namespace, scope)?; - current_offset += len; + let res = parse_term_obj(&data[current_offset..], namespace, scope.clone())?; + current_offset += res.len; } Ok(AmlParseType { - val: None, + val: AmlValue::None, len: data.len() }) } -pub fn parse_term_arg(data: &[u8]) -> Result<(TermArg, usize), AmlInternalError> { +pub fn parse_term_arg(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_selector! { - data, - parser_wrap!(TermArg::LocalObj, parser_wrap!(Box::new, parse_local_obj)), - parser_wrap!(TermArg::DataObj, parser_wrap!(Box::new, parse_data_obj)), - parser_wrap!(TermArg::ArgObj, parser_wrap!(Box::new, parse_arg_obj)), - parser_wrap!(TermArg::Type2Opcode, parser_wrap!(Box::new, parse_type2_opcode)) + data, namespace, scope.clone(), + parse_local_obj, + parse_data_obj, + parse_arg_obj, + parse_type2_opcode }; - Err(AmlInternalError::AmlInvalidOpCode) + Err(AmlError::AmlInvalidOpCode) } -pub fn parse_object_list(data: &[u8]) -> Result, AmlInternalError> { - let mut terms: Vec = vec!(); +pub fn parse_object_list(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { let mut current_offset: usize = 0; while current_offset < data.len() { - let (res, len) = parse_object(&data[current_offset..])?; - terms.push(res); - current_offset += len; + let res = parse_object(&data[current_offset..], namespace, scope.clone())?; + current_offset += res.len; } - Ok(terms) + Ok(AmlParseType { + val: AmlValue::None, + len: data.len() + }) } -fn parse_object(data: &[u8]) -> Result<(Object, usize), AmlInternalError> { +fn parse_object(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_selector! { - data, - parser_wrap!(Object::NamespaceModifier, parser_wrap!(Box::new, parse_namespace_modifier)), - parser_wrap!(Object::NamedObj, parser_wrap!(Box::new, parse_named_obj)) + data, namespace, scope.clone(), + parse_namespace_modifier, + parse_named_obj }; - Err(AmlInternalError::AmlInvalidOpCode) + Err(AmlError::AmlInvalidOpCode) } -pub fn parse_method_invocation(data: &[u8]) -> Result<(MethodInvocation, usize), AmlInternalError> { - let (name, name_len) = parse_name_string(data)?; - Err(AmlInternalError::AmlDeferredLoad) +pub fn parse_method_invocation(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + let name = parse_name_string(data, namespace, scope)?; + Err(AmlError::AmlDeferredLoad) } fn parse_term_obj(data: &[u8], namespace: &mut BTreeMap, scope: String) -> ParseResult { parser_selector! { - data, namespace, scope, + data, namespace, scope.clone(), parse_namespace_modifier, parse_named_obj, parse_type1_opcode, parse_type2_opcode }; - Err(AmlInternalError::AmlInvalidOpCode) + Err(AmlError::AmlInvalidOpCode) } diff --git a/src/acpi/aml/type1opcode.rs b/src/acpi/aml/type1opcode.rs index d476a24..b32acf8 100644 --- a/src/acpi/aml/type1opcode.rs +++ b/src/acpi/aml/type1opcode.rs @@ -3,76 +3,22 @@ use collections::string::String; use collections::vec::Vec; use collections::btree_map::BTreeMap; -use super::{AmlInternalError, AmlExecutable, AmlValue}; +use super::AmlError; +use super::parser::{AmlParseType, ParseResult}; +use super::namespace::{AmlValue, ObjectReference}; 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}; - -#[derive(Debug, Clone)] -pub enum Type1OpCode { - DefBreak, - DefBreakPoint, - DefContinue, - DefFatal { - fatal_type: u8, - fatal_code: u16, - fatal_arg: TermArg - }, - DefNoop, - DefIfElse { - if_block: IfBlock, - else_block: IfBlock - }, - DefLoad { - name: String, - ddb_handle_object: SuperName - }, - DefNotify { - object: SuperName, - value: TermArg - }, - DefRelease(SuperName), - DefReset(SuperName), - DefSignal(SuperName), - DefSleep(TermArg), - DefStall(TermArg), - DefUnload(SuperName), - DefWhile { - predicate: TermArg, - block: Vec - }, - DefReturn(TermArg), - DeferredLoad(Vec) -} - -impl AmlExecutable for Type1OpCode { - fn execute(&self, namespace: &mut BTreeMap, scope: String) -> Option { - None - } -} - -#[derive(Debug, Clone)] -pub enum IfBlock { - If { - predicate: TermArg, - if_block: Vec - }, - Else(Vec), - NoBlock, - DeferredLoad(Vec) -} - -pub fn parse_type1_opcode(data: &[u8]) -> Result<(Type1OpCode, usize), AmlInternalError> { - match data[0] { - 0xA5 => return Ok((Type1OpCode::DefBreak, 1 as usize)), - 0xCC => return Ok((Type1OpCode::DefBreakPoint, 1 as usize)), - 0x9F => return Ok((Type1OpCode::DefContinue, 1 as usize)), - 0xA3 => return Ok((Type1OpCode::DefNoop, 1 as usize)), - _ => () - } +use super::termlist::{parse_term_arg, parse_term_list}; +use super::namestring::{parse_name_string, parse_super_name}; +pub fn parse_type1_opcode(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_selector! { - data, + data, namespace, scope.clone(), + parse_def_break, + parse_def_breakpoint, + parse_def_continue, + parse_def_noop, parse_def_fatal, parse_def_if_else, parse_def_load, @@ -87,174 +33,248 @@ pub fn parse_type1_opcode(data: &[u8]) -> Result<(Type1OpCode, usize), AmlIntern parse_def_while }; - Err(AmlInternalError::AmlInvalidOpCode) + Err(AmlError::AmlInvalidOpCode) } -fn parse_def_fatal(data: &[u8]) -> Result<(Type1OpCode, usize), AmlInternalError> { - if data[0] != 0x5B || data[1] != 0x32 { - return Err(AmlInternalError::AmlInvalidOpCode); - } +fn parse_def_break(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Implement + parser_opcode!(data, 0xA5); + + Ok(AmlParseType { + val: AmlValue::None, + len: 1 as usize + }) +} + +fn parse_def_breakpoint(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Implement + parser_opcode!(data, 0xCC); + + Ok(AmlParseType { + val: AmlValue::None, + len: 1 as usize + }) +} + +fn parse_def_continue(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Implement + parser_opcode!(data, 0x9F); + + Ok(AmlParseType { + val: AmlValue::None, + len: 1 as usize + }) +} + +fn parse_def_noop(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + parser_opcode!(data, 0xA3); + + Ok(AmlParseType { + val: AmlValue::None, + len: 1 as usize + }) +} + +fn parse_def_fatal(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + parser_opcode_extended!(data, 0x32); let fatal_type = data[2]; - let fatal_code: u16 = (data[3] as u16) + - ((data[4] as u16) << 8); - let (fatal_arg, fatal_arg_len) = parse_term_arg(&data[5..])?; + let fatal_code: u16 = (data[3] as u16) + ((data[4] as u16) << 8); + let fatal_arg = parse_term_arg(&data[5..], namespace, scope.clone())?; - Ok((Type1OpCode::DefFatal {fatal_type, fatal_code, fatal_arg}, fatal_arg_len + 5)) + Err(AmlError::AmlFatalError(fatal_type, fatal_code, fatal_arg.val)) } -fn parse_def_load(data: &[u8]) -> Result<(Type1OpCode, usize), AmlInternalError> { - if data[0] != 0x5B || data[1] != 0x20 { - return Err(AmlInternalError::AmlInvalidOpCode); - } +fn parse_def_load(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Load in the table pointed to by `name` + // TODO: Set DDB_Handle to the handle returned by loading in the table + // TODO: Run the AML parser on the table, in a secondary namespace + parser_opcode_extended!(data, 0x20); - let (name, name_len) = parse_name_string(&data[2..])?; - let (ddb_handle_object, ddb_handle_object_len) = parse_super_name(&data[2 + name_len..])?; - - Ok((Type1OpCode::DefLoad {name, ddb_handle_object}, 2 + name_len + ddb_handle_object_len)) + let name = parse_name_string(&data[2..], namespace, scope.clone())?; + let ddb_handle_object = parse_super_name(&data[2 + name.len..], namespace, scope.clone())?; + + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + name.len + ddb_handle_object.len + }) } -fn parse_def_notify(data: &[u8]) -> Result<(Type1OpCode, usize), AmlInternalError> { - if data[0] != 0x86 { - return Err(AmlInternalError::AmlInvalidOpCode); - } +fn parse_def_notify(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: This requires significantly more infrastructure from the OS itself, see 5.6.6 + parser_opcode!(data, 0x86); - let (object, object_len) = parse_super_name(&data[1..])?; - let (value, value_len) = parse_term_arg(&data[1 + object_len..])?; + let object = parse_super_name(&data[1..], namespace, scope.clone())?; + let value = parse_term_arg(&data[1 + object.len..], namespace, scope.clone())?; - Ok((Type1OpCode::DefNotify {object, value}, 1 + object_len + value_len)) + Ok(AmlParseType { + val: AmlValue::None, + len: 1 + object.len + value.len + }) } -fn parse_def_release(data: &[u8]) -> Result<(Type1OpCode, usize), AmlInternalError> { - if data[0] != 0x5B || data[1] != 0x27 { - return Err(AmlInternalError::AmlInvalidOpCode); - } +fn parse_def_release(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Check ownership of the mutex pointed to + // TODO: FATAL if not owned + // TODO: Release if it is + parser_opcode_extended!(data, 0x27); - let (object, object_len) = parse_super_name(&data[2..])?; + let object = parse_super_name(&data[2..], namespace, scope.clone())?; - Ok((Type1OpCode::DefRelease(object), 2 + object_len)) + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + object.len + }) } -fn parse_def_reset(data: &[u8]) -> Result<(Type1OpCode, usize), AmlInternalError> { - if data[0] != 0x5B || data[1] != 0x26 { - return Err(AmlInternalError::AmlInvalidOpCode); - } +fn parse_def_reset(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: object (of type Event) is a semaphore. Reset the resource count to 0 + parser_opcode_extended!(data, 0x26); - let (object, object_len) = parse_super_name(&data[2..])?; + let object = parse_super_name(&data[2..], namespace, scope.clone())?; - Ok((Type1OpCode::DefReset(object), 2 + object_len)) + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + object.len + }) } -fn parse_def_signal(data: &[u8]) -> Result<(Type1OpCode, usize), AmlInternalError> { - if data[0] != 0x5B || data[1] != 0x24 { - return Err(AmlInternalError::AmlInvalidOpCode); - } +fn parse_def_signal(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Increment the resource count of the semaphore + parser_opcode_extended!(data, 0x24); - let (object, object_len) = parse_super_name(&data[2..])?; + let object = parse_super_name(&data[2..], namespace, scope.clone())?; - Ok((Type1OpCode::DefSignal(object), 2 + object_len)) + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + object.len + }) } -fn parse_def_sleep(data: &[u8]) -> Result<(Type1OpCode, usize), AmlInternalError> { - if data[0] != 0x5B || data[1] != 0x22 { - return Err(AmlInternalError::AmlInvalidOpCode); - } +fn parse_def_sleep(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Sleep the processor for the specified number of milliseconds (minimum) + parser_opcode_extended!(data, 0x22); - let (time, time_len) = parse_term_arg(&data[2..])?; + let time = parse_term_arg(&data[2..], namespace, scope.clone())?; - Ok((Type1OpCode::DefSleep(time), 2 + time_len)) + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + time.len + }) } -fn parse_def_stall(data: &[u8]) -> Result<(Type1OpCode, usize), AmlInternalError> { - if data[0] != 0x5B || data[1] != 0x21 { - return Err(AmlInternalError::AmlInvalidOpCode); - } +fn parse_def_stall(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Sleep the processor for the specified number of microseconds (minimum) + parser_opcode_extended!(data, 0x21); - let (time, time_len) = parse_term_arg(&data[2..])?; + let time = parse_term_arg(&data[2..], namespace, scope.clone())?; - Ok((Type1OpCode::DefStall(time), 2 + time_len)) + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + time.len + }) } -fn parse_def_unload(data: &[u8]) -> Result<(Type1OpCode, usize), AmlInternalError> { - if data[0] != 0x5B || data[1] != 0x2A { - return Err(AmlInternalError::AmlInvalidOpCode); - } +fn parse_def_unload(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: remove from namespace all values added when `object` was loaded + // TODO: globally synchronous (how?) + parser_opcode_extended!(data, 0x2A); - let (object, object_len) = parse_super_name(&data[2..])?; + let object = parse_super_name(&data[2..], namespace, scope.clone())?; - Ok((Type1OpCode::DefUnload(object), 2 + object_len)) + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + object.len + }) } -fn parse_def_if_else(data: &[u8]) -> Result<(Type1OpCode, usize), AmlInternalError> { - if data[0] != 0xA0 { - return Err(AmlInternalError::AmlInvalidOpCode); +fn parse_def_if_else(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + parser_opcode!(data, 0xA0); + + let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; + let if_condition = parse_term_arg(&data[1 + pkg_length_len .. 1 + pkg_length], namespace, scope.clone())?; + + let (else_length, else_length_len) = if data.len() > 1 + pkg_length && data[1 + pkg_length] == 0xA1 { + parse_pkg_length(&data[2 + pkg_length..])? + } else { + (0 as usize, 0 as usize) + }; + + if if_condition.val.get_as_integer()? > 0 { + parse_term_list(&data[1 + pkg_length_len + if_condition.len .. 1 + pkg_length], + namespace, scope.clone())?; + } else if else_length > 0 { + parse_term_list(&data[2 + pkg_length + else_length_len .. 2 + pkg_length + else_length], + namespace, scope.clone())?; } + Ok(AmlParseType { + val: AmlValue::None, + len: 1 + pkg_length + if else_length > 0 { 1 + else_length } else { 0 } + }) +} + +fn parse_def_while(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + parser_opcode!(data, 0xA2); + let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; - let if_block = match parse_term_arg(&data[1 + pkg_length_len..]) { - Ok((predicate, predicate_len)) => { - match parse_term_list(&data[1 + pkg_length_len + predicate_len .. 1 + pkg_length]) { - Ok(if_block) => IfBlock::If {predicate, if_block}, - Err(AmlInternalError::AmlDeferredLoad) => - IfBlock::DeferredLoad(data[0 .. 1 + pkg_length].to_vec()), - Err(e) => return Err(e) - } - }, - Err(AmlInternalError::AmlDeferredLoad) => - IfBlock::DeferredLoad(data[0 .. 1 + pkg_length].to_vec()), - Err(e) => return Err(e) - }; - - let (else_block, else_block_len) = parse_def_else(&data[1 + pkg_length..])?; - - return Ok((Type1OpCode::DefIfElse {if_block, else_block}, - pkg_length + else_block_len + 1)); + loop { + let predicate = parse_term_arg(&data[1 + pkg_length_len..], namespace, scope.clone())?; + if predicate.val.get_as_integer()? == 0 { + break; + } + + parse_term_list(&data[1 + pkg_length_len + predicate.len .. 1 + pkg_length], namespace, scope.clone())?; + } + + Ok(AmlParseType { + val: AmlValue::None, + len: 1 + pkg_length + }) } -fn parse_def_else(data: &[u8]) -> Result<(IfBlock, usize), AmlInternalError> { - if data.len() == 0 || data[0] != 0xA1 { - // We might be at the very end of a buffer, in which case there isn't an else - return Ok((IfBlock::NoBlock, 0)); - } +fn parse_def_return(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Return to the calling context + // TODO: We need contexts for that + parser_opcode!(data, 0xA4); - let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; - match parse_term_list(&data[1 + pkg_length_len .. 1 + pkg_length]) { - Ok(term_list) => Ok((IfBlock::Else(term_list), 1 + pkg_length)), - Err(AmlInternalError::AmlDeferredLoad) => - Ok((IfBlock::DeferredLoad(data[0 .. 1 + pkg_length].to_vec()), 1 + pkg_length)), - Err(e) => return Err(e) - } -} - -fn parse_def_while(data: &[u8]) -> Result<(Type1OpCode, usize), AmlInternalError> { - if data[0] != 0xA2 { - return Err(AmlInternalError::AmlInvalidOpCode); - } - - let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; - let (predicate, predicate_len) = match parse_term_arg(&data[1 + pkg_length_len..]) { - Ok(p) => p, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((Type1OpCode::DeferredLoad(data[0 .. 1 + pkg_length].to_vec()), 1 + pkg_length)), - Err(e) => return Err(e) - }; - let block = match parse_term_list(&data[1 + pkg_length_len + predicate_len .. 1 + pkg_length]) { - Ok(p) => p, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((Type1OpCode::DeferredLoad(data[0 .. 1 + pkg_length].to_vec()), 1 + pkg_length)), - Err(e) => return Err(e) - }; - - Ok((Type1OpCode::DefWhile {predicate, block}, pkg_length + 1)) -} - -fn parse_def_return(data: &[u8]) -> Result<(Type1OpCode, usize), AmlInternalError> { - if data[0] != 0xA4 { - return Err(AmlInternalError::AmlInvalidOpCode); - } - - let (arg_object, arg_object_len) = parse_term_arg(&data[1..])?; - - Ok((Type1OpCode::DefReturn(arg_object), 1 + arg_object_len)) + let arg_object = parse_term_arg(&data[1..], namespace, scope.clone())?; + + Ok(AmlParseType { + val: AmlValue::None, + len: 1 + arg_object.len + }) } diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index e96bdbc..eef85e1 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -3,236 +3,13 @@ use collections::string::String; use collections::vec::Vec; use collections::btree_map::BTreeMap; -use super::{AmlInternalError, AmlExecutable, AmlValue}; +use super::AmlError; +use super::parser::{AmlParseType, ParseResult}; +use super::namespace::{AmlValue, ObjectReference}; 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, - SuperName, Target}; -use super::dataobj::{parse_data_ref_obj, DataRefObj}; - -#[derive(Debug, Clone)] -pub enum Type2OpCode { - DefAcquire { - object: SuperName, - timeout: u16 - }, - DefBuffer(DefBuffer), - DefPackage(DefPackage), - DefVarPackage(DefVarPackage), - DefDerefOf(TermArg), - DefRefOf(SuperName), - DefIncrement(SuperName), - DefIndex(DefIndex), - DefDecrement(SuperName), - DefFindSetLeftBit { - operand: TermArg, - target: Target - }, - DefFindSetRightBit { - operand: TermArg, - target: Target - }, - DefFromBCD { - operand: TermArg, - target: Target - }, - DefDivide { - dividend: TermArg, - divisor: TermArg, - remainder: Target, - quotient: Target - }, - DefCondRefOf { - operand: SuperName, - target: Target - }, - DefCopyObject { - source: TermArg, - destination: SuperName - }, - DefLAnd { - lhs: TermArg, - rhs: TermArg - }, - DefLEqual { - lhs: TermArg, - rhs: TermArg - }, - DefLGreater { - lhs: TermArg, - rhs: TermArg - }, - DefLLess { - lhs: TermArg, - rhs: TermArg - }, - DefLNot(TermArg), - DefLOr { - lhs: TermArg, - rhs: TermArg - }, - DefSizeOf(SuperName), - DefStore { - operand: TermArg, - target: SuperName - }, - DefSubtract { - minuend: TermArg, - subtrahend: TermArg, - target: Target - }, - DefToBuffer { - operand: TermArg, - target: Target - }, - DefToHexString { - operand: TermArg, - target: Target - }, - DefToBCD { - operand: TermArg, - target: Target - }, - DefToDecimalString { - operand: TermArg, - target: Target - }, - DefToInteger { - operand: TermArg, - target: Target - }, - DefToString { - operand: TermArg, - length: TermArg, - target: Target - }, - DefConcat { - lhs: TermArg, - rhs: TermArg, - target: Target - }, - DefConcatRes { - lhs: TermArg, - rhs: TermArg, - target: Target - }, - DefShiftLeft { - lhs: TermArg, - rhs: TermArg, - target: Target - }, - DefShiftRight { - lhs: TermArg, - rhs: TermArg, - target: Target - }, - DefAdd { - lhs: TermArg, - rhs: TermArg, - target: Target - }, - DefMultiply { - lhs: TermArg, - rhs: TermArg, - target: Target - }, - DefMod { - dividend: TermArg, - divisor: TermArg, - target: Target - }, - DefAnd { - lhs: TermArg, - rhs: TermArg, - target: Target - }, - DefNAnd { - lhs: TermArg, - rhs: TermArg, - target: Target - }, - DefOr { - lhs: TermArg, - rhs: TermArg, - target: Target - }, - DefXor { - lhs: TermArg, - rhs: TermArg, - target: Target - }, - DefNOr { - lhs: TermArg, - rhs: TermArg, - target: Target - }, - DefNot { - operand: TermArg, - target: Target - }, - DefLoadTable { - signature: TermArg, - oem_id: TermArg, - oem_table_id: TermArg, - root_path: TermArg, - parameter_path: TermArg, - parameter_data: TermArg - }, - DefMatch { - search_pkg: TermArg, - first_operation: MatchOpcode, - first_operand: TermArg, - second_operation: MatchOpcode, - second_operand: TermArg, - start_index: TermArg - }, - DefMid { - source: TermArg, - index: TermArg, - length: TermArg, - target: Target - }, - DefWait { - event_object: SuperName, - operand: TermArg - }, - DefObjectType(DefObjectType), - DefTimer, - MethodInvocation(MethodInvocation) -} - -impl AmlExecutable for Type2OpCode { - fn execute(&self, namespace: &mut BTreeMap, scope: String) -> Option { - None - } -} - -impl AmlExecutable for DefBuffer { - fn execute(&self, namespace: &mut BTreeMap, scope: String) -> Option { - match *self { - DefBuffer::Buffer { ref buffer_size, ref byte_list } => { - let length = match buffer_size.execute(namespace, scope.clone()) { - Some(l) => Box::new(l), - _ => return None - }; - - Some(AmlValue::Buffer { - length: length, - byte_list: byte_list.clone() - }) - }, - _ => None - } - } -} - -#[derive(Debug, Clone)] -pub enum DefObjectType { - SuperName(SuperName), - DefIndex(DefIndex), - DefRefOf(SuperName), - DefDerefOf(TermArg) -} +use super::termlist::{parse_term_arg, parse_method_invocation}; +use super::namestring::{parse_super_name, parse_target, parse_name_string, parse_simple_name}; +use super::dataobj::parse_data_ref_obj; #[derive(Debug, Clone)] pub enum MatchOpcode { @@ -244,84 +21,11 @@ pub enum MatchOpcode { MGT } -#[derive(Debug, Clone)] -pub enum Type6OpCode { - DefDerefOf(TermArg), - DefRefOf(Box), - DefIndex(DefIndex), - MethodInvocation(MethodInvocation) -} - -#[derive(Debug, Clone)] -pub struct DefIndex { - obj: TermArg, - idx: TermArg, - target: Box -} - -#[derive(Debug, Clone)] -pub enum DefBuffer { - Buffer { - buffer_size: TermArg, - byte_list: Vec - }, - DeferredLoad(Vec) -} - -#[derive(Debug, Clone)] -pub enum DefPackage { - Package { - num_elements: u8, - elements: Vec - }, - DeferredLoad(Vec) -} - -#[derive(Debug, Clone)] -pub enum DefVarPackage { - Package { - num_elements: TermArg, - elements: Vec - }, - DeferredLoad(Vec) -} - -#[derive(Debug, Clone)] -pub enum PackageElement { - DataRefObj(DataRefObj), - NameString(String) -} - -impl AmlExecutable for DefPackage { - fn execute(&self, namespace: &mut BTreeMap, scope: String) -> Option { - match *self { - DefPackage::Package { ref num_elements, ref elements } => { - let mut values: Vec = vec!(); - - for element in elements { - match *element { - PackageElement::DataRefObj(ref d) => { - let elem = match d.execute(namespace, scope.clone()) { - Some(e) => e, - None => continue - }; - - values.push(elem); - }, - _ => return None - } - } - - Some(AmlValue::Package(values)) - }, - _ => None - } - } -} - -pub fn parse_type2_opcode(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +pub fn parse_type2_opcode(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_selector! { - data, + data, namespace, scope.clone(), parse_def_increment, parse_def_acquire, parse_def_wait, @@ -364,589 +68,905 @@ pub fn parse_type2_opcode(data: &[u8]) -> Result<(Type2OpCode, usize), AmlIntern parse_def_nor, parse_def_not, parse_def_timer, - parser_wrap!(Type2OpCode::DefBuffer, parse_def_buffer), - parser_wrap!(Type2OpCode::DefPackage, parse_def_package), - parser_wrap!(Type2OpCode::DefVarPackage, parse_def_var_package), - parser_wrap!(Type2OpCode::DefObjectType, parse_def_object_type), - parser_wrap!(Type2OpCode::DefDerefOf, parse_def_deref_of), - parser_wrap!(Type2OpCode::DefRefOf, parse_def_ref_of), - parser_wrap!(Type2OpCode::DefIndex, parse_def_index), - parser_wrap!(Type2OpCode::MethodInvocation, parse_method_invocation) + parse_def_buffer, + parse_def_package, + parse_def_var_package, + parse_def_object_type, + parse_def_deref_of, + parse_def_ref_of, + parse_def_index, + parse_method_invocation }; - Err(AmlInternalError::AmlInvalidOpCode) + Err(AmlError::AmlInvalidOpCode) } -pub fn parse_type6_opcode(data: &[u8]) -> Result<(Type6OpCode, usize), AmlInternalError> { +pub fn parse_type6_opcode(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_selector! { - data, - parser_wrap!(Type6OpCode::DefDerefOf, parse_def_deref_of), - parser_wrap!(Type6OpCode::DefRefOf, parser_wrap!(Box::new, parse_def_ref_of)), - parser_wrap!(Type6OpCode::DefIndex, parse_def_index), - parser_wrap!(Type6OpCode::MethodInvocation, parse_method_invocation) + data, namespace, scope.clone(), + parse_def_deref_of, + parse_def_ref_of, + parse_def_index, + parse_method_invocation }; - Err(AmlInternalError::AmlInvalidOpCode) + Err(AmlError::AmlInvalidOpCode) } -pub fn parse_def_object_type(data: &[u8]) -> Result<(DefObjectType, usize), AmlInternalError> { +pub fn parse_def_object_type(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode!(data, 0x8E); parser_selector! { - data, - parser_wrap!(DefObjectType::SuperName, parse_super_name), - parser_wrap!(DefObjectType::DefRefOf, parse_def_ref_of), - parser_wrap!(DefObjectType::DefDerefOf, parse_def_deref_of), - parser_wrap!(DefObjectType::DefIndex, parse_def_index) + data, namespace, scope.clone(), + parse_super_name, + parse_def_ref_of, + parse_def_deref_of, + parse_def_index } - Err(AmlInternalError::AmlInvalidOpCode) + Err(AmlError::AmlInvalidOpCode) } -pub fn parse_def_package(data: &[u8]) -> Result<(DefPackage, usize), AmlInternalError> { +pub fn parse_def_package(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Handle deferred loads in here + // TODO: Truncate/extend array if necessary parser_opcode!(data, 0x12); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; let num_elements = data[1 + pkg_length_len]; - - let elements = match parse_package_elements_list(&data[2 + pkg_length_len .. 1 + pkg_length]) { - Ok(e) => e, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((DefPackage::DeferredLoad(data[0 .. 1 + pkg_length].to_vec()), 1 + pkg_length)), - Err(e) => return Err(e) - }; - - Ok((DefPackage::Package {num_elements, elements}, 1 + pkg_length)) + let elements = parse_package_elements_list(&data[2 + pkg_length_len .. 1 + pkg_length], + namespace, scope.clone())?; + + Ok(AmlParseType { + val: elements.val, + len: 1 + pkg_length + }) } -pub fn parse_def_var_package(data: &[u8]) -> Result<(DefVarPackage, usize), AmlInternalError> { +pub fn parse_def_var_package(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Handle deferred loads in here + // TODO: Truncate/extend array if necessary parser_opcode!(data, 0x13); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; - let (num_elements, num_elements_len) = parse_term_arg(&data[1 + pkg_length_len ..])?; - - let elements = match parse_package_elements_list(&data[1 + pkg_length_len + num_elements_len .. - 1 + pkg_length]) { - Ok(e) => e, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((DefVarPackage::DeferredLoad(data[0 .. 1 + pkg_length].to_vec()), - 1 + pkg_length)), - Err(e) => return Err(e) - }; - - Ok((DefVarPackage::Package {num_elements, elements}, 1 + pkg_length)) + let num_elements = parse_term_arg(&data[1 + pkg_length_len .. 1 + pkg_length], namespace, scope.clone())?; + let elements = parse_package_elements_list(&data[1 + pkg_length_len + num_elements.len .. + 1 + pkg_length], namespace, scope.clone())?; + + Ok(AmlParseType { + val: elements.val, + len: 1 + pkg_length + }) } -fn parse_package_elements_list(data: &[u8]) -> Result, AmlInternalError> { +fn parse_package_elements_list(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { let mut current_offset: usize = 0; - let mut elements: Vec = vec!(); + let mut elements: Vec = vec!(); while current_offset < data.len() { - match parse_data_ref_obj(&data[current_offset ..]) { - Ok((data_ref_obj, data_ref_obj_len)) => { - elements.push(PackageElement::DataRefObj(data_ref_obj)); - current_offset += data_ref_obj_len; - }, - Err(AmlInternalError::AmlInvalidOpCode) => - match parse_name_string(&data[current_offset ..]) { - Ok((name_string, name_string_len)) => { - elements.push(PackageElement::NameString(name_string)); - current_offset += name_string_len; - }, - Err(e) => return Err(e) - }, - Err(e) => return Err(e) - } + let dro = if let Ok(e) = parse_data_ref_obj(&data[current_offset..], namespace, scope.clone()) { + e + } else { + parse_name_string(&data[current_offset..], namespace, scope.clone())? + }; + + elements.push(dro.val); + current_offset += dro.len; } - Ok(elements) + Ok(AmlParseType { + val: AmlValue::Package(elements), + len: data.len() + }) } -pub fn parse_def_buffer(data: &[u8]) -> Result<(DefBuffer, usize), AmlInternalError> { +pub fn parse_def_buffer(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Perform computation parser_opcode!(data, 0x11); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; - let (buffer_size, buffer_size_len) = match parse_term_arg(&data[1 + pkg_length_len..]) { - Ok(s) => s, - Err(AmlInternalError::AmlDeferredLoad) => return Ok((DefBuffer::DeferredLoad( - data[0 .. 1 + pkg_length].to_vec() - ), 1 + pkg_length)), - Err(e) => return Err(e), - }; - let byte_list = data[1 + pkg_length_len + buffer_size_len .. 1 + pkg_length].to_vec(); + let buffer_size = parse_term_arg(&data[1 + pkg_length_len..], namespace, scope.clone())?; + let byte_list = data[1 + pkg_length_len + buffer_size.len .. 1 + pkg_length].to_vec(); - Ok((DefBuffer::Buffer {buffer_size, byte_list}, pkg_length + 1)) + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 1 + pkg_length + }) } -fn parse_def_ref_of(data: &[u8]) -> Result<(SuperName, usize), AmlInternalError> { +fn parse_def_ref_of(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Perform computation parser_opcode!(data, 0x71); - let (obj_reference, obj_reference_len) = parse_super_name(&data[1..])?; - Ok((obj_reference, obj_reference_len + 1)) + let obj = parse_super_name(&data[1..], namespace, scope.clone())?; + + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 1 + obj.len + }) } -fn parse_def_deref_of(data: &[u8]) -> Result<(TermArg, usize), AmlInternalError> { +fn parse_def_deref_of(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Perform computation parser_opcode!(data, 0x83); - let (obj_reference, obj_reference_len) = parse_term_arg(&data[1..])?; - Ok((obj_reference, obj_reference_len + 1)) + let obj = parse_term_arg(&data[1..], namespace, scope.clone())?; + + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 1 + obj.len + }) } -fn parse_def_acquire(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_acquire(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Store the result + // TODO: Perform computation parser_opcode_extended!(data, 0x23); - let (object, object_len) = parse_super_name(&data[2..])?; - let timeout = (data[2 + object_len] as u16) + - ((data[3 + object_len] as u16) << 8); - - Ok((Type2OpCode::DefAcquire {object, timeout}, object_len + 4)) + let obj = parse_super_name(&data[1..], namespace, scope.clone())?; + let timeout = (data[2 + obj.len] as u16) + ((data[3 + obj.len] as u16) << 8); + + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 4 + obj.len + }) } -fn parse_def_increment(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_increment(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Store the result + // TODO: Perform computation parser_opcode!(data, 0x75); - let (obj, obj_len) = parse_super_name(&data[1..])?; - Ok((Type2OpCode::DefIncrement(obj), obj_len + 1)) + let obj = parse_super_name(&data[1..], namespace, scope.clone())?; + + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 1 + obj.len + }) } -fn parse_def_index(data: &[u8]) -> Result<(DefIndex, usize), AmlInternalError> { +fn parse_def_index(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Store the result, if appropriate + // TODO: Perform computation parser_opcode!(data, 0x88); - let (obj, obj_len) = parse_term_arg(&data[1..])?; - let (idx, idx_len) = parse_term_arg(&data[1 + obj_len..])?; - let (target, target_len) = parse_target(&data[1 + obj_len + idx_len..])?; - - Ok((DefIndex {obj, idx, target: Box::new(target)}, 1 + obj_len + idx_len + target_len)) + let obj = parse_term_arg(&data[1..], namespace, scope.clone())?; + let idx = parse_term_arg(&data[1 + obj.len..], namespace, scope.clone())?; + let target = parse_target(&data[1 + obj.len + idx.len..], namespace, scope.clone())?; + + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 1 + obj.len + idx.len + target.len + }) } -fn parse_def_land(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_land(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode!(data, 0x90); - let (lhs, lhs_len) = parse_term_arg(&data[1..])?; - let (rhs, rhs_len) = parse_term_arg(&data[1 + lhs_len..])?; + let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; + let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefLAnd {lhs, rhs}, 1 + lhs_len + rhs_len)) + let result = if lhs.val.get_as_integer()? > 0 && rhs.val.get_as_integer()? > 0 { 1 } else { 0 }; + + Ok(AmlParseType { + val: AmlValue::IntegerConstant(result), + len: 1 + lhs.len + rhs.len + }) } -fn parse_def_lequal(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_lequal(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode!(data, 0x93); - let (lhs, lhs_len) = parse_term_arg(&data[1..])?; - let (rhs, rhs_len) = parse_term_arg(&data[1 + lhs_len..])?; + let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; + let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefLEqual {lhs, rhs}, 1 + lhs_len + rhs_len)) + let result = if lhs.val.get_as_integer()? == rhs.val.get_as_integer()? { 1 } else { 0 }; + + Ok(AmlParseType { + val: AmlValue::IntegerConstant(result), + len: 1 + lhs.len + rhs.len + }) } -fn parse_def_lgreater(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_lgreater(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode!(data, 0x94); - let (lhs, lhs_len) = parse_term_arg(&data[1..])?; - let (rhs, rhs_len) = parse_term_arg(&data[1 + lhs_len..])?; + let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; + let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefLGreater {lhs, rhs}, 1 + lhs_len + rhs_len)) + let result = if lhs.val.get_as_integer()? > rhs.val.get_as_integer()? { 1 } else { 0 }; + + Ok(AmlParseType { + val: AmlValue::IntegerConstant(result), + len: 1 + lhs.len + rhs.len + }) } -fn parse_def_lless(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_lless(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode!(data, 0x95); - let (lhs, lhs_len) = parse_term_arg(&data[1..])?; - let (rhs, rhs_len) = parse_term_arg(&data[1 + lhs_len..])?; + let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; + let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefLLess {lhs, rhs}, 1 + lhs_len + rhs_len)) + let result = if lhs.val.get_as_integer()? < rhs.val.get_as_integer()? { 1 } else { 0 }; + + Ok(AmlParseType { + val: AmlValue::IntegerConstant(result), + len: 1 + lhs.len + rhs.len + }) } -fn parse_def_lnot(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_lnot(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode!(data, 0x92); - let (operand, operand_len) = parse_term_arg(&data[1..])?; - - Ok((Type2OpCode::DefLNot(operand), 1 + operand_len)) + let operand = parse_term_arg(&data[1..], namespace, scope.clone())?; + let result = if operand.val.get_as_integer()? == 0 { 1 } else { 0 }; + + Ok(AmlParseType { + val: AmlValue::IntegerConstant(result), + len: 1 + operand.len + }) } -fn parse_def_lor(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_lor(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode!(data, 0x91); - let (lhs, lhs_len) = parse_term_arg(&data[1..])?; - let (rhs, rhs_len) = parse_term_arg(&data[1 + lhs_len..])?; + let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; + let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefLOr {lhs, rhs}, 1 + lhs_len + rhs_len)) + let result = if lhs.val.get_as_integer()? > 0 || rhs.val.get_as_integer()? > 0 { 1 } else { 0 }; + + Ok(AmlParseType { + val: AmlValue::IntegerConstant(result), + len: 1 + lhs.len + rhs.len + }) } -fn parse_def_to_hex_string(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_to_hex_string(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Compute the result + // TODO: Store the result, if appropriate parser_opcode!(data, 0x98); - let (operand, operand_len) = parse_term_arg(&data[1..])?; - let (target, target_len) = parse_target(&data[1 + operand_len..])?; + let operand = parse_term_arg(&data[2..], namespace, scope.clone())?; + let target = parse_target(&data[2 + operand.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefToHexString {operand, target}, 1 + operand_len + target_len)) + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 1 + operand.len + target.len + }) } -fn parse_def_to_buffer(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_to_buffer(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Compute the result + // TODO: Store the result, if appropriate parser_opcode!(data, 0x96); - let (operand, operand_len) = parse_term_arg(&data[1..])?; - let (target, target_len) = parse_target(&data[1 + operand_len..])?; + let operand = parse_term_arg(&data[2..], namespace, scope.clone())?; + let target = parse_target(&data[2 + operand.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefToBuffer {operand, target}, 1 + operand_len + target_len)) + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 1 + operand.len + target.len + }) } -fn parse_def_to_bcd(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_to_bcd(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Compute the result + // TODO: Store the result, if appropriate parser_opcode_extended!(data, 0x29); - let (operand, operand_len) = parse_term_arg(&data[2..])?; - let (target, target_len) = parse_target(&data[2 + operand_len..])?; + let operand = parse_term_arg(&data[2..], namespace, scope.clone())?; + let target = parse_target(&data[2 + operand.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefToBCD {operand, target}, 2 + operand_len + target_len)) + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 1 + operand.len + target.len + }) } -fn parse_def_to_decimal_string(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_to_decimal_string(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Compute the result + // TODO: Store the result, if appropriate parser_opcode!(data, 0x97); - let (operand, operand_len) = parse_term_arg(&data[1..])?; - let (target, target_len) = parse_target(&data[1 + operand_len..])?; + let operand = parse_term_arg(&data[2..], namespace, scope.clone())?; + let target = parse_target(&data[2 + operand.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefToDecimalString {operand, target}, 1 + operand_len + target_len)) + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 1 + operand.len + target.len + }) } -fn parse_def_to_integer(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_to_integer(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Compute the result + // TODO: Store the result, if appropriate parser_opcode!(data, 0x99); - let (operand, operand_len) = parse_term_arg(&data[1..])?; - let (target, target_len) = parse_target(&data[1 + operand_len..])?; + let operand = parse_term_arg(&data[2..], namespace, scope.clone())?; + let target = parse_target(&data[2 + operand.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefToInteger {operand, target}, 1 + operand_len + target_len)) + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 1 + operand.len + target.len + }) } -fn parse_def_to_string(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_to_string(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Compute the result + // TODO: Store the result, if appropriate parser_opcode!(data, 0x9C); - let (operand, operand_len) = parse_term_arg(&data[1..])?; - let (length, length_len) = parse_term_arg(&data[1 + operand_len..])?; - let (target, target_len) = parse_target(&data[1 + operand_len + length_len..])?; + let operand = parse_term_arg(&data[1..], namespace, scope.clone())?; + let length = parse_term_arg(&data[1 + operand.len..], namespace, scope.clone())?; + let target = parse_target(&data[1 + operand.len + length.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefToString {operand, length, target}, 1 + operand_len + length_len + target_len)) + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 1 + operand.len + length.len + target.len + }) } -fn parse_def_subtract(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_subtract(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Store the result, if appropriate parser_opcode!(data, 0x74); - let (minuend, minuend_len) = parse_term_arg(&data[1..])?; - let (subtrahend, subtrahend_len) = parse_term_arg(&data[1 + minuend_len..])?; - let (target, target_len) = parse_target(&data[1 + minuend_len + subtrahend_len..])?; + let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; + let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefSubtract {minuend, subtrahend, target}, 1 + minuend_len + subtrahend_len + target_len)) + let result = lhs.val.get_as_integer()? - rhs.val.get_as_integer()?; + + Ok(AmlParseType { + val: AmlValue::IntegerConstant(result), + len: 1 + lhs.len + rhs.len + target.len + }) } -fn parse_def_size_of(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_size_of(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Perform the computation parser_opcode!(data, 0x87); - let (name, name_len) = parse_super_name(&data[1..])?; - Ok((Type2OpCode::DefSizeOf(name), name_len + 1)) + let name = parse_super_name(&data[1..], namespace, scope.clone())?; + + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 1 + name.len + }) } -fn parse_def_store(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_store(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Perform the store parser_opcode!(data, 0x70); - let (operand, operand_len) = parse_term_arg(&data[1..])?; - let (target, target_len) = parse_super_name(&data[1 + operand_len..])?; - - Ok((Type2OpCode::DefStore {operand, target}, operand_len + target_len + 1)) + let operand = parse_term_arg(&data[1..], namespace, scope.clone())?; + let target = parse_super_name(&data[1 + operand.len..], namespace, scope.clone())?; + + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 1 + operand.len + target.len + }) } -fn parse_def_or(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_or(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Store the result, if appropriate parser_opcode!(data, 0x7D); - let (lhs, lhs_len) = parse_term_arg(&data[1..])?; - let (rhs, rhs_len) = parse_term_arg(&data[1 + lhs_len..])?; - let (target, target_len) = parse_target(&data[1 + lhs_len + rhs_len..])?; - - Ok((Type2OpCode::DefOr {lhs, rhs, target}, 1 + lhs_len + rhs_len + target_len)) + let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; + let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; + + let result = lhs.val.get_as_integer()? | rhs.val.get_as_integer()?; + + Ok(AmlParseType { + val: AmlValue::IntegerConstant(result), + len: 1 + lhs.len + rhs.len + target.len + }) } -fn parse_def_shift_left(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_shift_left(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Store the result, if appropriate parser_opcode!(data, 0x79); - let (lhs, lhs_len) = parse_term_arg(&data[1..])?; - let (rhs, rhs_len) = parse_term_arg(&data[1 + lhs_len..])?; - let (target, target_len) = parse_target(&data[1 + lhs_len + rhs_len..])?; - - Ok((Type2OpCode::DefShiftLeft {lhs, rhs, target}, 1 + lhs_len + rhs_len + target_len)) + let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; + let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; + + let result = lhs.val.get_as_integer()? >> rhs.val.get_as_integer()?; + + Ok(AmlParseType { + val: AmlValue::IntegerConstant(result), + len: 1 + lhs.len + rhs.len + target.len + }) } -fn parse_def_shift_right(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_shift_right(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Store the result, if appropriate parser_opcode!(data, 0x7A); - let (lhs, lhs_len) = parse_term_arg(&data[1..])?; - let (rhs, rhs_len) = parse_term_arg(&data[1 + lhs_len..])?; - let (target, target_len) = parse_target(&data[1 + lhs_len + rhs_len..])?; - - Ok((Type2OpCode::DefShiftRight {lhs, rhs, target}, 1 + lhs_len + rhs_len + target_len)) + let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; + let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; + + let result = lhs.val.get_as_integer()? << rhs.val.get_as_integer()?; + + Ok(AmlParseType { + val: AmlValue::IntegerConstant(result), + len: 1 + lhs.len + rhs.len + target.len + }) } -fn parse_def_add(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_add(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Store the result, if appropriate parser_opcode!(data, 0x72); - let (lhs, lhs_len) = parse_term_arg(&data[1..])?; - let (rhs, rhs_len) = parse_term_arg(&data[1 + lhs_len..])?; - let (target, target_len) = parse_target(&data[1 + lhs_len + rhs_len..])?; - - Ok((Type2OpCode::DefAdd {lhs, rhs, target}, 1 + lhs_len + rhs_len + target_len)) + let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; + let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; + + let result = lhs.val.get_as_integer()? + rhs.val.get_as_integer()?; + + Ok(AmlParseType { + val: AmlValue::IntegerConstant(result), + len: 1 + lhs.len + rhs.len + target.len + }) } -fn parse_def_and(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_and(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Store the result, if appropriate parser_opcode!(data, 0x7B); - let (lhs, lhs_len) = parse_term_arg(&data[1..])?; - let (rhs, rhs_len) = parse_term_arg(&data[1 + lhs_len..])?; - let (target, target_len) = parse_target(&data[1 + lhs_len + rhs_len..])?; - - Ok((Type2OpCode::DefAnd {lhs, rhs, target}, 1 + lhs_len + rhs_len + target_len)) + let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; + let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; + + let result = lhs.val.get_as_integer()? & rhs.val.get_as_integer()?; + + Ok(AmlParseType { + val: AmlValue::IntegerConstant(result), + len: 1 + lhs.len + rhs.len + target.len + }) } -fn parse_def_xor(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_xor(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Store the result, if appropriate parser_opcode!(data, 0x7F); - let (lhs, lhs_len) = parse_term_arg(&data[1..])?; - let (rhs, rhs_len) = parse_term_arg(&data[1 + lhs_len..])?; - let (target, target_len) = parse_target(&data[1 + lhs_len + rhs_len..])?; - - Ok((Type2OpCode::DefXor {lhs, rhs, target}, 1 + lhs_len + rhs_len + target_len)) + let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; + let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; + + let result = lhs.val.get_as_integer()? ^ rhs.val.get_as_integer()?; + + Ok(AmlParseType { + val: AmlValue::IntegerConstant(result), + len: 1 + lhs.len + rhs.len + target.len + }) } -fn parse_def_concat_res(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_concat_res(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Compute the result + // TODO: Store the result, if appropriate parser_opcode!(data, 0x84); - let (lhs, lhs_len) = parse_term_arg(&data[1..])?; - let (rhs, rhs_len) = parse_term_arg(&data[1 + lhs_len..])?; - let (target, target_len) = parse_target(&data[1 + lhs_len + rhs_len..])?; - - Ok((Type2OpCode::DefConcatRes {lhs, rhs, target}, 1 + lhs_len + rhs_len + target_len)) + let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; + let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; + + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 1 + lhs.len + rhs.len + target.len + }) } -fn parse_def_wait(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_wait(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Compute the result parser_opcode_extended!(data, 0x25); - let (event_object, event_object_len) = parse_super_name(&data[2..])?; - let (operand, operand_len) = parse_term_arg(&data[2 + event_object_len..])?; + let event_object = parse_super_name(&data[2..], namespace, scope.clone())?; + let operand = parse_term_arg(&data[2 + event_object.len..], namespace, scope.clone())?; - - Ok((Type2OpCode::DefWait {event_object, operand}, 2 + event_object_len + operand_len)) + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 2 + event_object.len + operand.len + }) } -fn parse_def_cond_ref_of(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_cond_ref_of(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Compute the result + // TODO: Store the result parser_opcode_extended!(data, 0x12); - let (operand, operand_len) = parse_super_name(&data[2..])?; - let (target, target_len) = parse_target(&data[2 + operand_len..])?; + let operand = parse_super_name(&data[2..], namespace, scope.clone())?; + let target = parse_target(&data[2 + operand.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefCondRefOf {operand, target}, 2 + operand_len + target_len)) + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 2 + operand.len + target.len + }) } -fn parse_def_copy_object(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_copy_object(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Compute the result + // TODO: Store the result parser_opcode!(data, 0x9D); - let (source, source_len) = parse_term_arg(&data[1..])?; - let (destination, destination_len) = parse_simple_name(&data[1 + source_len..])?; + let source = parse_term_arg(&data[1..], namespace, scope.clone())?; + let destination = parse_simple_name(&data[1 + source.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefCopyObject {source, destination}, 1 + source_len + destination_len)) + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 1 + source.len + destination.len + }) } -fn parse_def_concat(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_concat(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Compute the result + // TODO: Store the result parser_opcode!(data, 0x73); - let (lhs, lhs_len) = parse_term_arg(&data[1..])?; - let (rhs, rhs_len) = parse_term_arg(&data[1 + lhs_len..])?; - let (target, target_len) = parse_target(&data[1 + lhs_len + rhs_len..])?; + let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; + let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefConcat {lhs, rhs, target}, 1 + lhs_len + rhs_len + target_len)) + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 1 + lhs.len + rhs.len + target.len + }) } -fn parse_def_decrement(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_decrement(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Compute the result + // TODO: Store the result parser_opcode!(data, 0x76); - let (target, target_len) = parse_super_name(&data[1..])?; + let target = parse_super_name(&data[1..], namespace, scope.clone())?; - Ok((Type2OpCode::DefDecrement(target), 1 + target_len)) + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 1 + target.len + }) } -fn parse_def_divide(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_divide(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Compute the result + // TODO: Store the result, if appropriate parser_opcode!(data, 0x78); - let (dividend, dividend_len) = parse_term_arg(&data[1..])?; - let (divisor, divisor_len) = parse_term_arg(&data[1 + dividend_len..])?; - let (remainder, remainder_len) = parse_target(&data[1 + dividend_len + divisor_len..])?; - let (quotient, quotient_len) = parse_target(&data[1 + dividend_len + divisor_len + remainder_len..])?; - - Ok((Type2OpCode::DefDivide {dividend, divisor, remainder, quotient}, - 1 + dividend_len + divisor_len + remainder_len + quotient_len)) + let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; + let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; + let target_remainder = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; + let target_quotient = parse_target(&data[1 + lhs.len + rhs.len + target_remainder.len..], namespace, scope.clone())?; + + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 1 + lhs.len + rhs.len + target_remainder.len + target_quotient.len + }) } -fn parse_def_find_set_left_bit(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_find_set_left_bit(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Compute the result + // TODO: Store the result, if appropriate parser_opcode!(data, 0x81); - let (operand, operand_len) = parse_term_arg(&data[1..])?; - let (target, target_len) = parse_target(&data[1 + operand_len..])?; + let operand = parse_term_arg(&data[2..], namespace, scope.clone())?; + let target = parse_target(&data[2 + operand.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefFindSetLeftBit {operand, target}, 1 + operand_len + target_len)) + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 1 + operand.len + target.len + }) } -fn parse_def_find_set_right_bit(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { - if data[0] != 0x82 { - return Err(AmlInternalError::AmlInvalidOpCode); - } +fn parse_def_find_set_right_bit(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Compute the result + // TODO: Store the result, if appropriate + parser_opcode!(data, 0x82); - let (operand, operand_len) = parse_term_arg(&data[1..])?; - let (target, target_len) = parse_target(&data[1 + operand_len..])?; + let operand = parse_term_arg(&data[2..], namespace, scope.clone())?; + let target = parse_target(&data[2 + operand.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefFindSetRightBit {operand, target}, 1 + operand_len + target_len)) + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 1 + operand.len + target.len + }) } -fn parse_def_load_table(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { - if data[0] != 0x5B || data[1] != 0x1F { - return Err(AmlInternalError::AmlInvalidOpCode); - } +fn parse_def_load_table(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Compute the result + // TODO: Store the result, if appropriate + // TODO: Clean up + parser_opcode_extended!(data, 0x1F); - let (signature, signature_len) = parse_term_arg(&data[2..])?; - let (oem_id, oem_id_len) = parse_term_arg(&data[2 + signature_len..])?; - let (oem_table_id, oem_table_id_len) = parse_term_arg(&data[2 + signature_len + oem_id_len..])?; - let (root_path, root_path_len) = - parse_term_arg(&data[2 + signature_len + oem_id_len + oem_table_id_len..])?; - let (parameter_path, parameter_path_len) = - parse_term_arg(&data[2 + signature_len + oem_id_len + oem_table_id_len + root_path_len..])?; - let (parameter_data, parameter_data_len) = - parse_term_arg(&data[2 + signature_len + oem_id_len + oem_table_id_len + root_path_len + - parameter_path_len..])?; + let signature = parse_term_arg(&data[2..], namespace, scope.clone())?; + let oem_id = parse_term_arg(&data[2 + signature.len..], namespace, scope.clone())?; + let oem_table_id = parse_term_arg(&data[2 + signature.len + oem_id.len..], namespace, scope.clone())?; + let root_path = parse_term_arg(&data[2 + signature.len + oem_id.len + oem_table_id.len..], namespace, scope.clone())?; + let parameter_path = parse_term_arg(&data[2 + signature.len + oem_id.len + oem_table_id.len + root_path.len..], namespace, scope.clone())?; + let parameter_data = parse_term_arg(&data[2 + signature.len + oem_id.len + oem_table_id.len + root_path.len + parameter_path.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefLoadTable {signature, oem_id, oem_table_id, root_path, - parameter_path, parameter_data}, - 2 + signature_len + oem_id_len + oem_table_id_len + root_path_len + - parameter_path_len + parameter_data_len)) + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 2 + signature.len + oem_id.len + oem_table_id.len + root_path.len + parameter_path.len + parameter_data.len + }) } -fn parse_def_match(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { - if data[0] != 0x89 { - return Err(AmlInternalError::AmlInvalidOpCode); - } - - let (search_pkg, search_pkg_len) = parse_term_arg(&data[1..])?; - let first_operation = match data[1 + search_pkg_len] { +fn parse_def_match(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Compute the result + // TODO: Store the result, if appropriate + // TODO: Clean up match blocks + parser_opcode!(data, 0x28); + + let search_pkg = parse_term_arg(&data[1..], namespace, scope.clone())?; + + let first_operation = match data[1 + search_pkg.len] { 0 => MatchOpcode::MTR, 1 => MatchOpcode::MEQ, 2 => MatchOpcode::MLE, 3 => MatchOpcode::MLT, 4 => MatchOpcode::MGE, 5 => MatchOpcode::MGT, - _ => return Err(AmlInternalError::AmlParseError("DefMatch - Invalid Opcode")) + _ => return Err(AmlError::AmlParseError("DefMatch - Invalid Opcode")) }; - let (first_operand, first_operand_len) = parse_term_arg(&data[2 + search_pkg_len..])?; + let first_operand = parse_term_arg(&data[2 + search_pkg.len..], namespace, scope.clone())?; - let second_operation = match data[2 + search_pkg_len + first_operand_len] { + let second_operation = match data[2 + search_pkg.len + first_operand.len] { 0 => MatchOpcode::MTR, 1 => MatchOpcode::MEQ, 2 => MatchOpcode::MLE, 3 => MatchOpcode::MLT, 4 => MatchOpcode::MGE, 5 => MatchOpcode::MGT, - _ => return Err(AmlInternalError::AmlParseError("DefMatch - Invalid Opcode")) + _ => return Err(AmlError::AmlParseError("DefMatch - Invalid Opcode")) }; - let (second_operand, second_operand_len) = - parse_term_arg(&data[3 + search_pkg_len + first_operand_len..])?; + let second_operand = parse_term_arg(&data[3 + search_pkg.len + first_operand.len..], namespace, scope.clone())?; + + let start_index = parse_term_arg(&data[3 + search_pkg.len + first_operand.len + second_operand.len..], namespace, scope.clone())?; - let (start_index, start_index_len) = - parse_term_arg(&data[3 + search_pkg_len + first_operand_len + second_operand_len..])?; - - Ok((Type2OpCode::DefMatch {search_pkg, first_operation, first_operand, - second_operation, second_operand, start_index}, - 3 + search_pkg_len + first_operand_len + second_operand_len + start_index_len)) + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 3 + search_pkg.len + first_operand.len + second_operand.len + start_index.len + }) } -fn parse_def_from_bcd(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { - if data[0] != 0x5B || data[1] != 0x28 { - return Err(AmlInternalError::AmlInvalidOpCode); - } +fn parse_def_from_bcd(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Store the result, if appropriate + // TODO: Clean up match block + parser_opcode_extended!(data, 0x28); - let (operand, operand_len) = parse_term_arg(&data[2..])?; - let (target, target_len) = parse_target(&data[2 + operand_len..])?; + let operand = parse_term_arg(&data[2..], namespace, scope.clone())?; + let target = parse_target(&data[2 + operand.len..], namespace, scope.clone())?; + + let result = match target.val.get_as_integer() { + Ok(i) => { + let mut i = i; + let mut ires = 0; - Ok((Type2OpCode::DefFromBCD {operand, target}, 2 + operand_len + target_len)) + while i != 0 { + if i & 0x0F > 10 { + return Err(AmlError::AmlValueError); + } + + ires *= 10; + ires += i & 0x0F; + i >>= 4; + } + + ires + }, + Err(e) => return Err(e) + }; + + Ok(AmlParseType { + val: AmlValue::IntegerConstant(result), + len: 2 + operand.len + target.len + }) } -fn parse_def_mid(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { - if data[0] != 0x9E { - return Err(AmlInternalError::AmlInvalidOpCode); - } +fn parse_def_mid(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Compute the result + // TODO: Store the result, if appropriate + parser_opcode!(data, 0x9E); - let (source, source_len) = parse_term_arg(&data[1..])?; - let (index, index_len) = parse_term_arg(&data[1 + source_len..])?; - let (length, length_len) = parse_term_arg(&data[1 + source_len + index_len..])?; - let (target, target_len) = parse_target(&data[1 + source_len + index_len + length_len..])?; + let source = parse_term_arg(&data[1..], namespace, scope.clone())?; + let index = parse_term_arg(&data[1 + source.len..], namespace, scope.clone())?; + let length = parse_term_arg(&data[1 + source.len + index.len..], namespace, scope.clone())?; + let target = parse_target(&data[1 + source.len + index.len + length.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefMid {source, index, length, target}, - 1 + source_len + index_len + length_len + target_len)) + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 1 + source.len + index.len + length.len + target.len + }) } -fn parse_def_mod(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { - if data[0] != 0x85 { - return Err(AmlInternalError::AmlInvalidOpCode); - } +fn parse_def_mod(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Store the result, if appropriate + // TODO: Fatal exception on rhs == 0 + parser_opcode!(data, 0x85); - let (dividend, dividend_len) = parse_term_arg(&data[1..])?; - let (divisor, divisor_len) = parse_term_arg(&data[1 + dividend_len..])?; - let (target, target_len) = parse_target(&data[1 + dividend_len + divisor_len..])?; + let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; + let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefMod {dividend, divisor, target}, 1 + dividend_len + divisor_len + target_len)) + let result = lhs.val.get_as_integer()? % rhs.val.get_as_integer()?; + + Ok(AmlParseType { + val: AmlValue::IntegerConstant(result), + len: 1 + lhs.len + rhs.len + target.len + }) } -fn parse_def_multiply(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { - if data[0] != 0x77 { - return Err(AmlInternalError::AmlInvalidOpCode); - } +fn parse_def_multiply(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Store the result, if appropriate + // TODO: Handle overflow + parser_opcode!(data, 0x77); - let (lhs, lhs_len) = parse_term_arg(&data[1..])?; - let (rhs, rhs_len) = parse_term_arg(&data[1 + lhs_len..])?; - let (target, target_len) = parse_target(&data[1 + lhs_len + rhs_len..])?; + let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; + let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefMultiply {lhs, rhs, target}, 1 + lhs_len + rhs_len + target_len)) + let result = lhs.val.get_as_integer()? * rhs.val.get_as_integer()?; + + Ok(AmlParseType { + val: AmlValue::IntegerConstant(result), + len: 1 + lhs.len + rhs.len + target.len + }) } -fn parse_def_nand(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { - if data[0] != 0x7C { - return Err(AmlInternalError::AmlInvalidOpCode); - } +fn parse_def_nand(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Store the result, if appropriate + parser_opcode!(data, 0x7C); - let (lhs, lhs_len) = parse_term_arg(&data[1..])?; - let (rhs, rhs_len) = parse_term_arg(&data[1 + lhs_len..])?; - let (target, target_len) = parse_target(&data[1 + lhs_len + rhs_len..])?; + let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; + let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefNAnd {lhs, rhs, target}, 1 + lhs_len + rhs_len + target_len)) + let result = !(lhs.val.get_as_integer()? & rhs.val.get_as_integer()?); + + Ok(AmlParseType { + val: AmlValue::IntegerConstant(result), + len: 1 + lhs.len + rhs.len + target.len + }) } -fn parse_def_nor(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { - if data[0] != 0x7E { - return Err(AmlInternalError::AmlInvalidOpCode); - } +fn parse_def_nor(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Store the result, if appropriate + parser_opcode!(data, 0x7E); - let (lhs, lhs_len) = parse_term_arg(&data[1..])?; - let (rhs, rhs_len) = parse_term_arg(&data[1 + lhs_len..])?; - let (target, target_len) = parse_target(&data[1 + lhs_len + rhs_len..])?; + let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; + let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefNOr {lhs, rhs, target}, 1 + lhs_len + rhs_len + target_len)) + let result = !(lhs.val.get_as_integer()? | rhs.val.get_as_integer()?); + + Ok(AmlParseType { + val: AmlValue::IntegerConstant(result), + len: 1 + lhs.len + rhs.len + target.len + }) } -fn parse_def_not(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { - if data[0] != 0x80 { - return Err(AmlInternalError::AmlInvalidOpCode); - } +fn parse_def_not(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Store the result, if appropriate + parser_opcode!(data, 0x80); - let (operand, operand_len) = parse_term_arg(&data[1..])?; - let (target, target_len) = parse_target(&data[1 + operand_len..])?; + let operand = parse_term_arg(&data[1..], namespace, scope.clone())?; + let target = parse_target(&data[1 + operand.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefNot {operand, target}, 1 + operand_len + target_len)) + let result = !operand.val.get_as_integer()?; + + Ok(AmlParseType { + val: AmlValue::IntegerConstant(result), + len: 1 + operand.len + target.len + }) } -fn parse_def_timer(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { - if data[0] != 0x5B || data[1] != 0x33 { - return Err(AmlInternalError::AmlInvalidOpCode) - } - - Ok((Type2OpCode::DefTimer, 2 as usize)) +fn parse_def_timer(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Read from the hardware timer, and split into 100ns intervals + parser_opcode_extended!(data, 0x33); + + Ok(AmlParseType { + val: AmlValue::IntegerConstant(0), + len: 2 as usize + }) } diff --git a/src/acpi/mod.rs b/src/acpi/mod.rs index ead12f5..51b4e96 100644 --- a/src/acpi/mod.rs +++ b/src/acpi/mod.rs @@ -211,9 +211,11 @@ fn parse_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) { *namespace = Some(res); } }, - Err(AmlError::AmlParseError(e)) => { - println!(": {}", e); - } + Err(AmlError::AmlParseError(e)) => println!(": {}", e), + Err(AmlError::AmlInvalidOpCode) => println!(": Invalid opcode"), + Err(AmlError::AmlValueError) => println!(": Type constraints or value bounds not met"), + Err(AmlError::AmlDeferredLoad) => println!(": Deferred load reached top level"), + Err(AmlError::AmlFatalError(_, _, _)) => println!(": Fatal error occurred") }; } else { println!(": Unknown"); diff --git a/src/stop.rs b/src/stop.rs index 4f152bf..6dec9a1 100644 --- a/src/stop.rs +++ b/src/stop.rs @@ -13,7 +13,7 @@ pub unsafe extern fn kstop() -> ! { let mut val = 1 << 13; if let Some(ref namespace) = acpi.namespace { if let Some(s) = namespace.get("\\_S5") { - if let Some(p) = s.get_as_package() { + if let Ok(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"); From 50ac9d3abed461f9265d5c5aa59d8793ff3583ca Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Mon, 3 Jul 2017 10:31:01 +0100 Subject: [PATCH 021/113] Added a context manager --- src/acpi/aml/dataobj.rs | 27 +-- src/acpi/aml/mod.rs | 15 +- src/acpi/aml/namedobj.rs | 294 +++++++++++----------- src/acpi/aml/namespace.rs | 1 + src/acpi/aml/namespacemodifier.rs | 44 ++-- src/acpi/aml/namestring.rs | 23 +- src/acpi/aml/parser.rs | 8 + src/acpi/aml/parsermacros.rs | 10 +- src/acpi/aml/termlist.rs | 35 ++- src/acpi/aml/type1opcode.rs | 91 +++---- src/acpi/aml/type2opcode.rs | 389 +++++++++++++----------------- 11 files changed, 425 insertions(+), 512 deletions(-) diff --git a/src/acpi/aml/dataobj.rs b/src/acpi/aml/dataobj.rs index 77f7d2f..4025f7f 100644 --- a/src/acpi/aml/dataobj.rs +++ b/src/acpi/aml/dataobj.rs @@ -3,18 +3,17 @@ use collections::string::String; use collections::btree_map::BTreeMap; use super::AmlError; -use super::parser::{AmlParseType, ParseResult}; -use super::namespace::{AmlValue, ObjectReference}; +use super::parser::{ AmlParseType, ParseResult, AmlExecutionContext }; +use super::namespace::{ AmlValue, ObjectReference }; use super::type2opcode::{parse_def_buffer, parse_def_package, parse_def_var_package}; use super::termlist::parse_term_arg; use super::namestring::parse_super_name; pub fn parse_data_obj(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_selector! { - data, namespace, scope.clone(), + data, ctx, parse_computational_data, parse_def_package, parse_def_var_package @@ -24,15 +23,14 @@ pub fn parse_data_obj(data: &[u8], } pub fn parse_data_ref_obj(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_selector! { - data, namespace, scope.clone(), + data, ctx, parse_data_obj, parse_term_arg }; - match parse_super_name(data, namespace, scope.clone()) { + match parse_super_name(data, ctx) { Ok(res) => match res.val { AmlValue::String(s) => Ok(AmlParseType { val: AmlValue::ObjectReference(ObjectReference::NamedObj(s)), @@ -45,8 +43,7 @@ pub fn parse_data_ref_obj(data: &[u8], } pub fn parse_arg_obj(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { match data[0] { 0x68 ... 0x6E => Ok(AmlParseType { val: AmlValue::ObjectReference(ObjectReference::ArgObj(data[0] - 0x68)), @@ -57,8 +54,7 @@ pub fn parse_arg_obj(data: &[u8], } pub fn parse_local_obj(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { match data[0] { 0x68 ... 0x6E => Ok(AmlParseType { val: AmlValue::ObjectReference(ObjectReference::LocalObj(data[0] - 0x60)), @@ -69,8 +65,7 @@ pub fn parse_local_obj(data: &[u8], } fn parse_computational_data(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { match data[0] { 0x0A => Ok(AmlParseType { val: AmlValue::Integer(data[1] as u64), @@ -148,6 +143,6 @@ fn parse_computational_data(data: &[u8], val: AmlValue::IntegerConstant(0xFFFFFFFFFFFFFFFF), len: 9 as usize }), - _ => parse_def_buffer(data, namespace, scope.clone()) + _ => parse_def_buffer(data, ctx) } } diff --git a/src/acpi/aml/mod.rs b/src/acpi/aml/mod.rs index a113c0b..d20ce4c 100644 --- a/src/acpi/aml/mod.rs +++ b/src/acpi/aml/mod.rs @@ -24,7 +24,7 @@ mod type1opcode; mod type2opcode; mod parser; -use self::parser::ParseResult; +use self::parser::{ ParseResult, AmlExecutionContext }; use self::termlist::parse_term_list; pub use self::namespace::AmlValue; @@ -39,13 +39,14 @@ pub enum AmlError { pub fn parse_aml_table(sdt: &'static Sdt) -> Result, AmlError> { let data = sdt.data(); + let mut ctx = AmlExecutionContext { + namespace: &mut BTreeMap::new(), + scope: String::from_str("\\").unwrap() + }; + + let term_list = parse_term_list(data, &mut ctx)?; - let global_namespace_specifier = String::from_str("\\").unwrap(); - let mut global_namespace = BTreeMap::new(); - - let term_list = parse_term_list(data, &mut global_namespace, global_namespace_specifier.clone())?; - - Ok(global_namespace) + Ok(ctx.namespace.clone()) } pub fn is_aml_table(sdt: &'static Sdt) -> bool { diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index c521893..3c4605b 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -6,8 +6,8 @@ use core::str::FromStr; use collections::btree_map::BTreeMap; use super::AmlError; -use super::parser::{AmlParseType, ParseResult, AmlParseTypeGeneric}; -use super::namespace::{AmlValue, ObjectReference, FieldSelector, get_namespace_string}; +use super::parser::{ AmlParseType, ParseResult, AmlParseTypeGeneric, AmlExecutionContext }; +use super::namespace::{ AmlValue, ObjectReference, FieldSelector, get_namespace_string }; use super::namestring::{parse_name_string, parse_name_seg}; use super::termlist::{parse_term_arg, parse_term_list, parse_object_list}; use super::pkglength::parse_pkg_length; @@ -87,10 +87,9 @@ pub enum AccessAttrib { } pub fn parse_named_obj(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_selector! { - data, namespace, scope.clone(), + data, ctx, parse_def_bank_field, parse_def_create_bit_field, parse_def_create_byte_field, @@ -115,19 +114,17 @@ pub fn parse_named_obj(data: &[u8], } fn parse_def_bank_field(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Why isn't bank name used? parser_opcode_extended!(data, 0x87); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[2..])?; let data = &data[2 + pkg_length_len .. 2 + pkg_length]; - let region_name = parse_name_string(data, namespace, scope.clone())?; - let bank_name = parse_name_string(&data[2 + pkg_length_len + region_name.len .. 2 + pkg_length], namespace, scope.clone())?; + let region_name = parse_name_string(data, ctx)?; + let bank_name = parse_name_string(&data[2 + pkg_length_len + region_name.len .. 2 + pkg_length], ctx)?; - let bank_value = parse_term_arg( - &data[2 + pkg_length_len + region_name.len .. 2 + pkg_length], namespace, scope.clone())?; + let bank_value = parse_term_arg(&data[2 + pkg_length_len + region_name.len .. 2 + pkg_length], ctx)?; let flags_raw = data[2 + pkg_length_len + region_name.len + bank_name.len + bank_value.len]; let mut flags = FieldFlags { @@ -156,7 +153,7 @@ fn parse_def_bank_field(data: &[u8], let field_list = parse_field_list( &data[3 + pkg_length_len + region_name.len + bank_name.len + bank_value.len .. - 2 + pkg_length], namespace, scope, selector, &mut flags)?; + 2 + pkg_length], ctx, selector, &mut flags)?; Ok(AmlParseType { val: AmlValue::None, @@ -165,17 +162,16 @@ fn parse_def_bank_field(data: &[u8], } fn parse_def_create_bit_field(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode!(data, 0x8D); - let source_buf = parse_term_arg(&data[2..], namespace, scope.clone())?; - let bit_index = parse_term_arg(&data[2 + source_buf.len..], namespace, scope.clone())?; - let name = parse_name_string(&data[1 + source_buf.len + bit_index.len..], namespace, scope.clone())?; + let source_buf = parse_term_arg(&data[2..], ctx)?; + let bit_index = parse_term_arg(&data[2 + source_buf.len..], ctx)?; + let name = parse_name_string(&data[1 + source_buf.len + bit_index.len..], ctx)?; - let local_scope_string = get_namespace_string(scope.clone(), name.val); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); - namespace.insert(local_scope_string, AmlValue::BufferField { + ctx.namespace.insert(local_scope_string, AmlValue::BufferField { source_buf: Box::new(source_buf.val), index: Box::new(bit_index.val), length: Box::new(AmlValue::IntegerConstant(1)) @@ -188,17 +184,16 @@ fn parse_def_create_bit_field(data: &[u8], } fn parse_def_create_byte_field(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode!(data, 0x8C); - let source_buf = parse_term_arg(&data[2..], namespace, scope.clone())?; - let bit_index = parse_term_arg(&data[2 + source_buf.len..], namespace, scope.clone())?; - let name = parse_name_string(&data[1 + source_buf.len + bit_index.len..], namespace, scope.clone())?; + let source_buf = parse_term_arg(&data[2..], ctx)?; + let bit_index = parse_term_arg(&data[2 + source_buf.len..], ctx)?; + let name = parse_name_string(&data[1 + source_buf.len + bit_index.len..], ctx)?; - let local_scope_string = get_namespace_string(scope.clone(), name.val); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); - namespace.insert(local_scope_string, AmlValue::BufferField { + ctx.namespace.insert(local_scope_string, AmlValue::BufferField { source_buf: Box::new(source_buf.val), index: Box::new(bit_index.val), length: Box::new(AmlValue::IntegerConstant(8)) @@ -211,17 +206,16 @@ fn parse_def_create_byte_field(data: &[u8], } fn parse_def_create_word_field(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode!(data, 0x8B); - let source_buf = parse_term_arg(&data[2..], namespace, scope.clone())?; - let bit_index = parse_term_arg(&data[2 + source_buf.len..], namespace, scope.clone())?; - let name = parse_name_string(&data[1 + source_buf.len + bit_index.len..], namespace, scope.clone())?; + let source_buf = parse_term_arg(&data[2..], ctx)?; + let bit_index = parse_term_arg(&data[2 + source_buf.len..], ctx)?; + let name = parse_name_string(&data[1 + source_buf.len + bit_index.len..], ctx)?; - let local_scope_string = get_namespace_string(scope.clone(), name.val); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); - namespace.insert(local_scope_string, AmlValue::BufferField { + ctx.namespace.insert(local_scope_string, AmlValue::BufferField { source_buf: Box::new(source_buf.val), index: Box::new(bit_index.val), length: Box::new(AmlValue::IntegerConstant(16)) @@ -234,17 +228,16 @@ fn parse_def_create_word_field(data: &[u8], } fn parse_def_create_dword_field(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode!(data, 0x8A); - let source_buf = parse_term_arg(&data[2..], namespace, scope.clone())?; - let bit_index = parse_term_arg(&data[2 + source_buf.len..], namespace, scope.clone())?; - let name = parse_name_string(&data[1 + source_buf.len + bit_index.len..], namespace, scope.clone())?; + let source_buf = parse_term_arg(&data[2..], ctx)?; + let bit_index = parse_term_arg(&data[2 + source_buf.len..], ctx)?; + let name = parse_name_string(&data[1 + source_buf.len + bit_index.len..], ctx)?; - let local_scope_string = get_namespace_string(scope.clone(), name.val); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); - namespace.insert(local_scope_string, AmlValue::BufferField { + ctx.namespace.insert(local_scope_string, AmlValue::BufferField { source_buf: Box::new(source_buf.val), index: Box::new(bit_index.val), length: Box::new(AmlValue::IntegerConstant(32)) @@ -257,17 +250,16 @@ fn parse_def_create_dword_field(data: &[u8], } fn parse_def_create_qword_field(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode!(data, 0x8F); - let source_buf = parse_term_arg(&data[2..], namespace, scope.clone())?; - let bit_index = parse_term_arg(&data[2 + source_buf.len..], namespace, scope.clone())?; - let name = parse_name_string(&data[1 + source_buf.len + bit_index.len..], namespace, scope.clone())?; + let source_buf = parse_term_arg(&data[2..], ctx)?; + let bit_index = parse_term_arg(&data[2 + source_buf.len..], ctx)?; + let name = parse_name_string(&data[1 + source_buf.len + bit_index.len..], ctx)?; - let local_scope_string = get_namespace_string(scope.clone(), name.val); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); - namespace.insert(local_scope_string, AmlValue::BufferField { + ctx.namespace.insert(local_scope_string, AmlValue::BufferField { source_buf: Box::new(source_buf.val), index: Box::new(bit_index.val), length: Box::new(AmlValue::IntegerConstant(64)) @@ -280,18 +272,17 @@ fn parse_def_create_qword_field(data: &[u8], } fn parse_def_create_field(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode_extended!(data, 0x13); - let source_buf = parse_term_arg(&data[2..], namespace, scope.clone())?; - let bit_index = parse_term_arg(&data[2 + source_buf.len..], namespace, scope.clone())?; - let num_bits = parse_term_arg(&data[2 + source_buf.len + bit_index.len..], namespace, scope.clone())?; - let name = parse_name_string(&data[2 + source_buf.len + bit_index.len + num_bits.len..], namespace, scope.clone())?; + let source_buf = parse_term_arg(&data[2..], ctx)?; + let bit_index = parse_term_arg(&data[2 + source_buf.len..], ctx)?; + let num_bits = parse_term_arg(&data[2 + source_buf.len + bit_index.len..], ctx)?; + let name = parse_name_string(&data[2 + source_buf.len + bit_index.len + num_bits.len..], ctx)?; - let local_scope_string = get_namespace_string(scope.clone(), name.val); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); - namespace.insert(local_scope_string, AmlValue::BufferField { + ctx.namespace.insert(local_scope_string, AmlValue::BufferField { source_buf: Box::new(source_buf.val), index: Box::new(bit_index.val), length: Box::new(num_bits.val) @@ -304,19 +295,18 @@ fn parse_def_create_field(data: &[u8], } fn parse_def_data_region(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Find the actual offset and length, once table mapping is implemented parser_opcode_extended!(data, 0x88); - let name = parse_name_string(&data[2..], namespace, scope.clone())?; - let signature = parse_term_arg(&data[2 + name.len..], namespace, scope.clone())?; - let oem_id = parse_term_arg(&data[2 + name.len + signature.len..], namespace, scope.clone())?; - let oem_table_id = parse_term_arg(&data[2 + name.len + signature.len + oem_id.len..], namespace, scope.clone())?; - - let local_scope_string = get_namespace_string(scope.clone(), name.val); + let name = parse_name_string(&data[2..], ctx)?; + let signature = parse_term_arg(&data[2 + name.len..], ctx)?; + let oem_id = parse_term_arg(&data[2 + name.len + signature.len..], ctx)?; + let oem_table_id = parse_term_arg(&data[2 + name.len + signature.len + oem_id.len..], ctx)?; - namespace.insert(local_scope_string, AmlValue::OperationRegion { + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); + + ctx.namespace.insert(local_scope_string, AmlValue::OperationRegion { region: RegionSpace::SystemMemory, offset: Box::new(AmlValue::IntegerConstant(0)), len: Box::new(AmlValue::IntegerConstant(0)) @@ -329,14 +319,13 @@ fn parse_def_data_region(data: &[u8], } fn parse_def_event(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode_extended!(data, 0x02); - let name = parse_name_string(&data[2..], namespace, scope.clone())?; + let name = parse_name_string(&data[2..], ctx)?; - let local_scope_string = get_namespace_string(scope, name.val); - namespace.insert(local_scope_string, AmlValue::Event); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); + ctx.namespace.insert(local_scope_string, AmlValue::Event); Ok(AmlParseType { val: AmlValue::None, @@ -345,18 +334,23 @@ fn parse_def_event(data: &[u8], } fn parse_def_device(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { + // TODO: How to handle local context deferreds + // TODO: How to also handle local context reference to calling context parser_opcode_extended!(data, 0x82); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[2..])?; - let name = parse_name_string(&data[2 + pkg_length_len .. 2 + pkg_length], namespace, scope.clone())?; - - let mut local_namespace = BTreeMap::new(); - let obj_list = parse_object_list(&data[2 + pkg_length_len + name.len .. 2 + pkg_length], &mut local_namespace, String::new())?; + let name = parse_name_string(&data[2 + pkg_length_len .. 2 + pkg_length], ctx)?; - let local_scope_string = get_namespace_string(scope, name.val); - namespace.insert(local_scope_string, AmlValue::Device(local_namespace)); + let mut local_ctx = AmlExecutionContext { + namespace: &mut BTreeMap::new(), + scope: String::new() + }; + + let obj_list = parse_object_list(&data[2 + pkg_length_len + name.len .. 2 + pkg_length], &mut local_ctx)?; + + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); + ctx.namespace.insert(local_scope_string, AmlValue::Device(local_ctx.namespace.clone())); Ok(AmlParseType { val: AmlValue::None, @@ -365,11 +359,10 @@ fn parse_def_device(data: &[u8], } fn parse_def_op_region(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode_extended!(data, 0x80); - let name = parse_name_string(&data[2..], namespace, scope.clone())?; + let name = parse_name_string(&data[2..], ctx)?; let region = match data[2 + name.len] { 0x00 => RegionSpace::SystemMemory, 0x01 => RegionSpace::SystemIO, @@ -385,11 +378,11 @@ fn parse_def_op_region(data: &[u8], _ => return Err(AmlError::AmlParseError("OpRegion - invalid region")) }; - let offset = parse_term_arg(&data[3 + name.len..], namespace, scope.clone())?; - let len = parse_term_arg(&data[3 + name.len + offset.len..], namespace, scope.clone())?; + let offset = parse_term_arg(&data[3 + name.len..], ctx)?; + let len = parse_term_arg(&data[3 + name.len + offset.len..], ctx)?; - let local_scope_string = get_namespace_string(scope.clone(), name.val); - namespace.insert(local_scope_string, AmlValue::OperationRegion { + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); + ctx.namespace.insert(local_scope_string, AmlValue::OperationRegion { region: region, offset: Box::new(offset.val), len: Box::new(len.val) @@ -402,12 +395,11 @@ fn parse_def_op_region(data: &[u8], } fn parse_def_field(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode_extended!(data, 0x81); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[2..])?; - let name = parse_name_string(&data[2 + pkg_length_len .. 2 + pkg_length], namespace, scope.clone())?; + let name = parse_name_string(&data[2 + pkg_length_len .. 2 + pkg_length], ctx)?; let flags_raw = data[2 + pkg_length_len + name.len]; let mut flags = FieldFlags { @@ -431,7 +423,7 @@ fn parse_def_field(data: &[u8], let selector = FieldSelector::Region(name.val.get_as_string()?); - let field_list = parse_field_list(&data[3 + pkg_length_len + name.len .. 2 + pkg_length], namespace, scope, selector, &mut flags)?; + let field_list = parse_field_list(&data[3 + pkg_length_len + name.len .. 2 + pkg_length], ctx, selector, &mut flags)?; Ok(AmlParseType { val: AmlValue::None, @@ -440,13 +432,12 @@ fn parse_def_field(data: &[u8], } fn parse_def_index_field(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode_extended!(data, 0x86); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[2..])?; - let idx_name = parse_name_string( &data[2 + pkg_length_len .. 2 + pkg_length], namespace, scope.clone())?; - let data_name = parse_name_string(&data[2 + pkg_length_len + idx_name.len .. 2 + pkg_length], namespace, scope.clone())?; + let idx_name = parse_name_string(&data[2 + pkg_length_len .. 2 + pkg_length], ctx)?; + let data_name = parse_name_string(&data[2 + pkg_length_len + idx_name.len .. 2 + pkg_length], ctx)?; let flags_raw = data[2 + pkg_length_len + idx_name.len + data_name.len]; let mut flags = FieldFlags { @@ -474,7 +465,7 @@ fn parse_def_index_field(data: &[u8], }; let field_list = parse_field_list( - &data[3 + pkg_length_len + idx_name.len + data_name.len .. 2 + pkg_length], namespace, scope, selector, &mut flags)?; + &data[3 + pkg_length_len + idx_name.len + data_name.len .. 2 + pkg_length], ctx, selector, &mut flags)?; Ok(AmlParseType { val: AmlValue::None, @@ -483,21 +474,14 @@ fn parse_def_index_field(data: &[u8], } fn parse_field_list(data: &[u8], - namespace: &mut BTreeMap, - scope: String, + ctx: &mut AmlExecutionContext, selector: FieldSelector, flags: &mut FieldFlags) -> ParseResult { let mut current_offset: usize = 0; let mut connection = AmlValue::Uninitialized; while current_offset < data.len() { - match parse_field_element(&data[current_offset..], namespace, scope.clone(), selector.clone(), - &mut connection, flags, &mut current_offset) { - Ok(_) => (), - Err(AmlError::AmlInvalidOpCode) => - return Err(AmlError::AmlParseError("FieldList - no valid field")), - Err(e) => return Err(e) - } + parse_field_element(&data[current_offset..], ctx, selector.clone(), &mut connection, flags, &mut current_offset)?; } Ok(AmlParseType { @@ -507,16 +491,15 @@ fn parse_field_list(data: &[u8], } fn parse_field_element(data: &[u8], - namespace: &mut BTreeMap, - scope: String, + ctx: &mut AmlExecutionContext, selector: FieldSelector, connection: &mut AmlValue, flags: &mut FieldFlags, offset: &mut usize) -> ParseResult { - let length = if let Ok(field) = parse_named_field(data, namespace, scope.clone()) { - let local_scope_string = get_namespace_string(scope.clone(), AmlValue::String(field.val.name.clone())); + let length = if let Ok(field) = parse_named_field(data, ctx) { + let local_scope_string = get_namespace_string(ctx.scope.clone(), AmlValue::String(field.val.name.clone())); - namespace.insert(local_scope_string, AmlValue::FieldUnit { + ctx.namespace.insert(local_scope_string, AmlValue::FieldUnit { selector: selector.clone(), connection: Box::new(connection.clone()), flags: flags.clone(), @@ -525,10 +508,10 @@ fn parse_field_element(data: &[u8], }); field.len - } else if let Ok(field) = parse_reserved_field(data, namespace, scope.clone()) { + } else if let Ok(field) = parse_reserved_field(data, ctx) { *offset += field.val; field.len - } else if let Ok(field) = parse_access_field(data, namespace, scope.clone()) { + } else if let Ok(field) = parse_access_field(data, ctx) { match field.val.access_type { AccessType::BufferAcc(_) => flags.access_type = AccessType::BufferAcc(field.val.access_attrib.clone()), @@ -536,7 +519,7 @@ fn parse_field_element(data: &[u8], } field.len - } else if let Ok(field) = parse_connect_field(data, namespace, scope.clone()) { + } else if let Ok(field) = parse_connect_field(data, ctx) { *connection = field.val.clone(); field.len } else { @@ -550,8 +533,7 @@ fn parse_field_element(data: &[u8], } fn parse_named_field(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> Result, AmlError> { + ctx: &mut AmlExecutionContext) -> Result, AmlError> { let (name_seg, name_seg_len) = parse_name_seg(&data[0..4])?; let name = match String::from_utf8(name_seg) { Ok(s) => s, @@ -566,8 +548,7 @@ fn parse_named_field(data: &[u8], } fn parse_reserved_field(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> Result, AmlError> { + ctx: &mut AmlExecutionContext) -> Result, AmlError> { parser_opcode!(data, 0x00); let (length, length_len) = parse_pkg_length(&data[1..])?; @@ -578,8 +559,7 @@ fn parse_reserved_field(data: &[u8], } fn parse_access_field(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> Result, AmlError> { + ctx: &mut AmlExecutionContext) -> Result, AmlError> { parser_opcode!(data, 0x01, 0x03); let flags_raw = data[1]; @@ -625,17 +605,16 @@ fn parse_access_field(data: &[u8], } fn parse_connect_field(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode!(data, 0x02); - if let Ok(e) = parse_def_buffer(&data[1..], namespace, scope.clone()) { + if let Ok(e) = parse_def_buffer(&data[1..], ctx) { Ok(AmlParseType { val: e.val, len: e.len + 1 }) } else { - let name = parse_name_string(&data[1..], namespace, scope.clone())?; + let name = parse_name_string(&data[1..], ctx)?; Ok(AmlParseType { val: AmlValue::ObjectReference(ObjectReference::NamedObj(name.val.get_as_string()?)), len: name.len + 1 @@ -644,12 +623,11 @@ fn parse_connect_field(data: &[u8], } fn parse_def_method(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode!(data, 0x14); let (pkg_len, pkg_len_len) = parse_pkg_length(&data[1..])?; - let name = parse_name_string(&data[1 + pkg_len_len..], namespace, scope.clone())?; + let name = parse_name_string(&data[1 + pkg_len_len..], ctx)?; let flags = data[1 + pkg_len_len + name.len]; let arg_count = flags & 0x07; @@ -658,8 +636,8 @@ fn parse_def_method(data: &[u8], let term_list = &data[2 + pkg_len_len + name.len .. 1 + pkg_len]; - let local_scope_string = get_namespace_string(scope.clone(), name.val); - namespace.insert(local_scope_string, AmlValue::Method(Method { + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); + ctx.namespace.insert(local_scope_string, AmlValue::Method(Method { arg_count, serialized, sync_level, @@ -673,16 +651,15 @@ fn parse_def_method(data: &[u8], } fn parse_def_mutex(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode_extended!(data, 0x01); - let name = parse_name_string(&data[2 ..], namespace, scope.clone())?; + let name = parse_name_string(&data[2 ..], ctx)?; let flags = data[2 + name.len]; let sync_level = flags & 0x0F; - let local_scope_string = get_namespace_string(scope, name.val); - namespace.insert(local_scope_string, AmlValue::Mutex(sync_level)); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); + ctx.namespace.insert(local_scope_string, AmlValue::Mutex(sync_level)); Ok(AmlParseType { val: AmlValue::None, @@ -691,26 +668,31 @@ fn parse_def_mutex(data: &[u8], } fn parse_def_power_res(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { + // TODO: How to handle local context deferreds + // TODO: How to also handle local context reference to calling context parser_opcode_extended!(data, 0x84); let (pkg_len, pkg_len_len) = parse_pkg_length(&data[2..])?; - let name = parse_name_string(&data[2 + pkg_len_len..], namespace, scope.clone())?; + let name = parse_name_string(&data[2 + pkg_len_len..], ctx)?; - let local_scope_string = get_namespace_string(scope, name.val); - let mut local_namespace = BTreeMap::new(); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); let system_level = data[2 + pkg_len_len + name.len]; let resource_order: u16 = (data[3 + pkg_len_len + name.len] as u16) + ((data[4 + pkg_len_len + name.len] as u16) << 8); - parse_object_list(&data[5 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_namespace, String::new())?; + let mut local_ctx = AmlExecutionContext { + namespace: &mut BTreeMap::new(), + scope: String::new() + }; + + parse_object_list(&data[5 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_ctx)?; - namespace.insert(local_scope_string, AmlValue::PowerResource { + ctx.namespace.insert(local_scope_string, AmlValue::PowerResource { system_level, resource_order, - obj_list: local_namespace + obj_list: local_ctx.namespace.clone() }); Ok(AmlParseType { @@ -720,15 +702,13 @@ fn parse_def_power_res(data: &[u8], } fn parse_def_processor(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode_extended!(data, 0x83); let (pkg_len, pkg_len_len) = parse_pkg_length(&data[2..])?; - let name = parse_name_string(&data[2 + pkg_len_len..], namespace, scope.clone())?; + let name = parse_name_string(&data[2 + pkg_len_len..], ctx)?; - let local_scope_string = get_namespace_string(scope, name.val); - let mut local_namespace = BTreeMap::new(); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); let proc_id = data[2 + pkg_len_len + name.len]; let p_blk_addr: u32 = (data[3 + pkg_len_len + name.len] as u32) + @@ -737,12 +717,17 @@ fn parse_def_processor(data: &[u8], ((data[6 + pkg_len_len + name.len] as u32) << 24); let p_blk_len = data[7 + pkg_len_len + name.len]; - parse_object_list(&data[8 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_namespace, String::new())?; + let mut local_ctx = AmlExecutionContext { + namespace: &mut BTreeMap::new(), + scope: String::new() + }; - namespace.insert(local_scope_string, AmlValue::Processor { + parse_object_list(&data[8 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_ctx)?; + + ctx.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 + obj_list: local_ctx.namespace.clone() }); Ok(AmlParseType { @@ -752,19 +737,22 @@ fn parse_def_processor(data: &[u8], } fn parse_def_thermal_zone(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode_extended!(data, 0x85); let (pkg_len, pkg_len_len) = parse_pkg_length(&data[2..])?; - let name = parse_name_string(&data[2 + pkg_len_len .. 2 + pkg_len], namespace, scope.clone())?; + let name = parse_name_string(&data[2 + pkg_len_len .. 2 + pkg_len], ctx)?; - let local_scope_string = get_namespace_string(scope, name.val); - let mut local_namespace = BTreeMap::new(); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); + + let mut local_ctx = AmlExecutionContext { + namespace: &mut BTreeMap::new(), + scope: String::new() + }; - parse_object_list(&data[2 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_namespace, String::new())?; + parse_object_list(&data[2 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_ctx)?; - namespace.insert(local_scope_string, AmlValue::ThermalZone(local_namespace)); + ctx.namespace.insert(local_scope_string, AmlValue::ThermalZone(local_ctx.namespace.clone())); Ok(AmlParseType { val: AmlValue::None, diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index d2ac417..54cef02 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -6,6 +6,7 @@ use collections::btree_map::BTreeMap; use core::str::FromStr; use super::namedobj::{ RegionSpace, FieldFlags, Method }; +use super::parser::AmlExecutionContext; use super::AmlError; #[derive(Debug, Clone)] diff --git a/src/acpi/aml/namespacemodifier.rs b/src/acpi/aml/namespacemodifier.rs index b04d405..35cd1a3 100644 --- a/src/acpi/aml/namespacemodifier.rs +++ b/src/acpi/aml/namespacemodifier.rs @@ -4,7 +4,7 @@ use collections::vec::Vec; use collections::btree_map::BTreeMap; use super::AmlError; -use super::parser::{AmlParseType, ParseResult, AmlParseTypeGeneric}; +use super::parser::{AmlParseType, ParseResult, AmlParseTypeGeneric, AmlExecutionContext}; use super::namespace::{AmlValue, ObjectReference, FieldSelector, get_namespace_string}; use super::pkglength::parse_pkg_length; use super::namestring::parse_name_string; @@ -12,10 +12,9 @@ use super::termlist::parse_term_list; use super::dataobj::parse_data_ref_obj; pub fn parse_namespace_modifier(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_selector! { - data, namespace, scope.clone(), + data, ctx, parse_alias_op, parse_scope_op, parse_name_op @@ -25,17 +24,16 @@ pub fn parse_namespace_modifier(data: &[u8], } fn parse_alias_op(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode!(data, 0x06); - let source_name = parse_name_string(&data[1..], namespace, scope.clone())?; - let alias_name = parse_name_string(&data[1 + source_name.len..], namespace, scope.clone())?; + let source_name = parse_name_string(&data[1..], ctx)?; + let alias_name = parse_name_string(&data[1 + source_name.len..], ctx)?; - let local_scope_string = get_namespace_string(scope.clone(), source_name.val); - let local_alias_string = get_namespace_string(scope.clone(), alias_name.val); + let local_scope_string = get_namespace_string(ctx.scope.clone(), source_name.val); + let local_alias_string = get_namespace_string(ctx.scope.clone(), alias_name.val); - namespace.insert(local_scope_string, AmlValue::ObjectReference( + ctx.namespace.insert(local_scope_string, AmlValue::ObjectReference( ObjectReference::NamedObj(local_alias_string))); Ok(AmlParseType { @@ -45,16 +43,15 @@ fn parse_alias_op(data: &[u8], } fn parse_name_op(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode!(data, 0x08); - let name = parse_name_string(&data[1..], namespace, scope.clone())?; - let data_ref_obj = parse_data_ref_obj(&data[1 + name.len..], namespace, scope.clone())?; + let name = parse_name_string(&data[1..], ctx)?; + let data_ref_obj = parse_data_ref_obj(&data[1 + name.len..], ctx)?; - let local_scope_string = get_namespace_string(scope.clone(), name.val); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); - namespace.insert(local_scope_string, data_ref_obj.val); + ctx.namespace.insert(local_scope_string, data_ref_obj.val); Ok(AmlParseType { val: AmlValue::None, @@ -63,15 +60,18 @@ fn parse_name_op(data: &[u8], } fn parse_scope_op(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode!(data, 0x10); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; - let name = parse_name_string(&data[1 + pkg_length_len..], namespace, scope.clone())?; + let name = parse_name_string(&data[1 + pkg_length_len..], ctx)?; - let local_scope_string = get_namespace_string(scope, name.val); - parse_term_list(&data[1 + pkg_length_len + name.len..], namespace, local_scope_string)?; + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); + let containing_scope_string = ctx.scope.clone(); + + ctx.scope = local_scope_string; + parse_term_list(&data[1 + pkg_length_len + name.len..], ctx)?; + ctx.scope = containing_scope_string; Ok(AmlParseType { val: AmlValue::None, diff --git a/src/acpi/aml/namestring.rs b/src/acpi/aml/namestring.rs index ccbdcce..e63a9b0 100644 --- a/src/acpi/aml/namestring.rs +++ b/src/acpi/aml/namestring.rs @@ -3,14 +3,13 @@ use collections::string::String; use collections::btree_map::BTreeMap; use super::AmlError; -use super::parser::{AmlParseType, ParseResult, AmlParseTypeGeneric}; +use super::parser::{AmlParseType, ParseResult, AmlParseTypeGeneric, AmlExecutionContext}; use super::namespace::{AmlValue, ObjectReference, FieldSelector, get_namespace_string}; use super::dataobj::{parse_arg_obj, parse_local_obj}; use super::type2opcode::parse_type6_opcode; pub fn parse_name_string(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { let mut characters: Vec = vec!(); let mut starting_index: usize = 0; @@ -142,10 +141,9 @@ fn parse_multi_name_path(data: &[u8]) -> Result<(Vec, usize), AmlError> { } pub fn parse_super_name(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_selector! { - data, namespace, scope.clone(), + data, ctx, parse_simple_name, parse_type6_opcode, parse_debug_obj @@ -155,8 +153,7 @@ pub fn parse_super_name(data: &[u8], } fn parse_debug_obj(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode_extended!(data, 0x31); Ok(AmlParseType { @@ -166,10 +163,9 @@ fn parse_debug_obj(data: &[u8], } pub fn parse_simple_name(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_selector! { - data, namespace, scope.clone(), + data, ctx, parse_name_string, parse_arg_obj, parse_local_obj @@ -179,14 +175,13 @@ pub fn parse_simple_name(data: &[u8], } pub fn parse_target(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { if data[0] == 0x00 { Ok(AmlParseType { val: AmlValue::None, len: 1 as usize }) } else { - parse_super_name(data, namespace, scope.clone()) + parse_super_name(data, ctx) } } diff --git a/src/acpi/aml/parser.rs b/src/acpi/aml/parser.rs index 080a1ae..b316319 100644 --- a/src/acpi/aml/parser.rs +++ b/src/acpi/aml/parser.rs @@ -1,3 +1,6 @@ +use collections::string::String; +use collections::btree_map::BTreeMap; + use super::namespace::AmlValue; use super::AmlError; @@ -8,3 +11,8 @@ pub struct AmlParseTypeGeneric { pub val: T, pub len: usize } + +pub struct AmlExecutionContext<'a> { + pub namespace: &'a mut BTreeMap, + pub scope: String +} diff --git a/src/acpi/aml/parsermacros.rs b/src/acpi/aml/parsermacros.rs index 6b9555a..3f8cf61 100644 --- a/src/acpi/aml/parsermacros.rs +++ b/src/acpi/aml/parsermacros.rs @@ -1,15 +1,15 @@ #[macro_export] macro_rules! parser_selector { - {$data:expr, $namespace:expr, $scope:expr, $func:expr} => { - match $func($data, $namespace, $scope) { + {$data:expr, $ctx:expr, $func:expr} => { + match $func($data, $ctx) { Ok(res) => return Ok(res), Err(AmlError::AmlInvalidOpCode) => (), Err(e) => return Err(e) } }; - {$data:expr, $namespace:expr, $scope:expr, $func:expr, $($funcs:expr),+} => { - parser_selector! {$data, $namespace, $scope, $func}; - parser_selector! {$data, $namespace, $scope, $($funcs),*}; + {$data:expr, $ctx:expr, $func:expr, $($funcs:expr),+} => { + parser_selector! {$data, $ctx, $func}; + parser_selector! {$data, $ctx, $($funcs),*}; }; } diff --git a/src/acpi/aml/termlist.rs b/src/acpi/aml/termlist.rs index bc2a747..bbce0e4 100644 --- a/src/acpi/aml/termlist.rs +++ b/src/acpi/aml/termlist.rs @@ -4,7 +4,7 @@ use collections::vec::Vec; use collections::btree_map::BTreeMap; use super::AmlError; -use super::parser::{AmlParseType, ParseResult, AmlParseTypeGeneric}; +use super::parser::{ AmlParseType, ParseResult, AmlParseTypeGeneric, AmlExecutionContext }; use super::namespace::{AmlValue, ObjectReference, FieldSelector, get_namespace_string}; use super::namespacemodifier::parse_namespace_modifier; use super::namedobj::parse_named_obj; @@ -14,12 +14,11 @@ use super::type2opcode::parse_type2_opcode; use super::namestring::parse_name_string; pub fn parse_term_list(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { let mut current_offset: usize = 0; while current_offset < data.len() { - let res = parse_term_obj(&data[current_offset..], namespace, scope.clone())?; + let res = parse_term_obj(&data[current_offset..], ctx)?; current_offset += res.len; } @@ -30,10 +29,9 @@ pub fn parse_term_list(data: &[u8], } pub fn parse_term_arg(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_selector! { - data, namespace, scope.clone(), + data, ctx, parse_local_obj, parse_data_obj, parse_arg_obj, @@ -44,12 +42,11 @@ pub fn parse_term_arg(data: &[u8], } pub fn parse_object_list(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { let mut current_offset: usize = 0; while current_offset < data.len() { - let res = parse_object(&data[current_offset..], namespace, scope.clone())?; + let res = parse_object(&data[current_offset..], ctx)?; current_offset += res.len; } @@ -60,10 +57,9 @@ pub fn parse_object_list(data: &[u8], } fn parse_object(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_selector! { - data, namespace, scope.clone(), + data, ctx, parse_namespace_modifier, parse_named_obj }; @@ -72,17 +68,18 @@ fn parse_object(data: &[u8], } pub fn parse_method_invocation(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { - let name = parse_name_string(data, namespace, scope)?; + ctx: &mut AmlExecutionContext) -> ParseResult { + // TODO: Check if method exists in namespace + // TODO: If so, parse appropriate number of parameters + // TODO: If not, add deferred load to ctx + let name = parse_name_string(data, ctx)?; Err(AmlError::AmlDeferredLoad) } fn parse_term_obj(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_selector! { - data, namespace, scope.clone(), + data, ctx, parse_namespace_modifier, parse_named_obj, parse_type1_opcode, diff --git a/src/acpi/aml/type1opcode.rs b/src/acpi/aml/type1opcode.rs index b32acf8..7bc9546 100644 --- a/src/acpi/aml/type1opcode.rs +++ b/src/acpi/aml/type1opcode.rs @@ -4,17 +4,16 @@ use collections::vec::Vec; use collections::btree_map::BTreeMap; use super::AmlError; -use super::parser::{AmlParseType, ParseResult}; +use super::parser::{AmlParseType, ParseResult, AmlExecutionContext}; use super::namespace::{AmlValue, ObjectReference}; use super::pkglength::parse_pkg_length; use super::termlist::{parse_term_arg, parse_term_list}; use super::namestring::{parse_name_string, parse_super_name}; pub fn parse_type1_opcode(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_selector! { - data, namespace, scope.clone(), + data, ctx, parse_def_break, parse_def_breakpoint, parse_def_continue, @@ -37,8 +36,7 @@ pub fn parse_type1_opcode(data: &[u8], } fn parse_def_break(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Implement parser_opcode!(data, 0xA5); @@ -49,8 +47,7 @@ fn parse_def_break(data: &[u8], } fn parse_def_breakpoint(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Implement parser_opcode!(data, 0xCC); @@ -61,8 +58,7 @@ fn parse_def_breakpoint(data: &[u8], } fn parse_def_continue(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Implement parser_opcode!(data, 0x9F); @@ -73,8 +69,7 @@ fn parse_def_continue(data: &[u8], } fn parse_def_noop(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode!(data, 0xA3); Ok(AmlParseType { @@ -84,27 +79,25 @@ fn parse_def_noop(data: &[u8], } fn parse_def_fatal(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode_extended!(data, 0x32); let fatal_type = data[2]; let fatal_code: u16 = (data[3] as u16) + ((data[4] as u16) << 8); - let fatal_arg = parse_term_arg(&data[5..], namespace, scope.clone())?; + let fatal_arg = parse_term_arg(&data[5..], ctx)?; Err(AmlError::AmlFatalError(fatal_type, fatal_code, fatal_arg.val)) } fn parse_def_load(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Load in the table pointed to by `name` // TODO: Set DDB_Handle to the handle returned by loading in the table // TODO: Run the AML parser on the table, in a secondary namespace parser_opcode_extended!(data, 0x20); - let name = parse_name_string(&data[2..], namespace, scope.clone())?; - let ddb_handle_object = parse_super_name(&data[2 + name.len..], namespace, scope.clone())?; + let name = parse_name_string(&data[2..], ctx)?; + let ddb_handle_object = parse_super_name(&data[2 + name.len..], ctx)?; Ok(AmlParseType { val: AmlValue::None, @@ -113,13 +106,12 @@ fn parse_def_load(data: &[u8], } fn parse_def_notify(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: This requires significantly more infrastructure from the OS itself, see 5.6.6 parser_opcode!(data, 0x86); - let object = parse_super_name(&data[1..], namespace, scope.clone())?; - let value = parse_term_arg(&data[1 + object.len..], namespace, scope.clone())?; + let object = parse_super_name(&data[1..], ctx)?; + let value = parse_term_arg(&data[1 + object.len..], ctx)?; Ok(AmlParseType { val: AmlValue::None, @@ -128,14 +120,13 @@ fn parse_def_notify(data: &[u8], } fn parse_def_release(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Check ownership of the mutex pointed to // TODO: FATAL if not owned // TODO: Release if it is parser_opcode_extended!(data, 0x27); - let object = parse_super_name(&data[2..], namespace, scope.clone())?; + let object = parse_super_name(&data[2..], ctx)?; Ok(AmlParseType { val: AmlValue::None, @@ -144,12 +135,11 @@ fn parse_def_release(data: &[u8], } fn parse_def_reset(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: object (of type Event) is a semaphore. Reset the resource count to 0 parser_opcode_extended!(data, 0x26); - let object = parse_super_name(&data[2..], namespace, scope.clone())?; + let object = parse_super_name(&data[2..], ctx)?; Ok(AmlParseType { val: AmlValue::None, @@ -158,12 +148,11 @@ fn parse_def_reset(data: &[u8], } fn parse_def_signal(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Increment the resource count of the semaphore parser_opcode_extended!(data, 0x24); - let object = parse_super_name(&data[2..], namespace, scope.clone())?; + let object = parse_super_name(&data[2..], ctx)?; Ok(AmlParseType { val: AmlValue::None, @@ -172,12 +161,11 @@ fn parse_def_signal(data: &[u8], } fn parse_def_sleep(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Sleep the processor for the specified number of milliseconds (minimum) parser_opcode_extended!(data, 0x22); - let time = parse_term_arg(&data[2..], namespace, scope.clone())?; + let time = parse_term_arg(&data[2..], ctx)?; Ok(AmlParseType { val: AmlValue::None, @@ -186,12 +174,11 @@ fn parse_def_sleep(data: &[u8], } fn parse_def_stall(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Sleep the processor for the specified number of microseconds (minimum) parser_opcode_extended!(data, 0x21); - let time = parse_term_arg(&data[2..], namespace, scope.clone())?; + let time = parse_term_arg(&data[2..], ctx)?; Ok(AmlParseType { val: AmlValue::None, @@ -200,13 +187,12 @@ fn parse_def_stall(data: &[u8], } fn parse_def_unload(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // 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..], namespace, scope.clone())?; + let object = parse_super_name(&data[2..], ctx)?; Ok(AmlParseType { val: AmlValue::None, @@ -215,12 +201,11 @@ fn parse_def_unload(data: &[u8], } fn parse_def_if_else(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode!(data, 0xA0); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; - let if_condition = parse_term_arg(&data[1 + pkg_length_len .. 1 + pkg_length], namespace, scope.clone())?; + let if_condition = parse_term_arg(&data[1 + pkg_length_len .. 1 + pkg_length], ctx)?; let (else_length, else_length_len) = if data.len() > 1 + pkg_length && data[1 + pkg_length] == 0xA1 { parse_pkg_length(&data[2 + pkg_length..])? @@ -229,11 +214,9 @@ fn parse_def_if_else(data: &[u8], }; if if_condition.val.get_as_integer()? > 0 { - parse_term_list(&data[1 + pkg_length_len + if_condition.len .. 1 + pkg_length], - namespace, scope.clone())?; + parse_term_list(&data[1 + pkg_length_len + if_condition.len .. 1 + pkg_length], ctx)?; } else if else_length > 0 { - parse_term_list(&data[2 + pkg_length + else_length_len .. 2 + pkg_length + else_length], - namespace, scope.clone())?; + parse_term_list(&data[2 + pkg_length + else_length_len .. 2 + pkg_length + else_length], ctx)?; } Ok(AmlParseType { @@ -243,19 +226,18 @@ fn parse_def_if_else(data: &[u8], } fn parse_def_while(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode!(data, 0xA2); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; loop { - let predicate = parse_term_arg(&data[1 + pkg_length_len..], namespace, scope.clone())?; + let predicate = parse_term_arg(&data[1 + pkg_length_len..], ctx)?; if predicate.val.get_as_integer()? == 0 { break; } - parse_term_list(&data[1 + pkg_length_len + predicate.len .. 1 + pkg_length], namespace, scope.clone())?; + parse_term_list(&data[1 + pkg_length_len + predicate.len .. 1 + pkg_length], ctx)?; } Ok(AmlParseType { @@ -265,13 +247,12 @@ fn parse_def_while(data: &[u8], } fn parse_def_return(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Return to the calling context // TODO: We need contexts for that parser_opcode!(data, 0xA4); - let arg_object = parse_term_arg(&data[1..], namespace, scope.clone())?; + let arg_object = parse_term_arg(&data[1..], ctx)?; Ok(AmlParseType { val: AmlValue::None, diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index eef85e1..0685251 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -4,7 +4,7 @@ use collections::vec::Vec; use collections::btree_map::BTreeMap; use super::AmlError; -use super::parser::{AmlParseType, ParseResult}; +use super::parser::{AmlParseType, ParseResult, AmlExecutionContext}; use super::namespace::{AmlValue, ObjectReference}; use super::pkglength::parse_pkg_length; use super::termlist::{parse_term_arg, parse_method_invocation}; @@ -22,10 +22,9 @@ pub enum MatchOpcode { } pub fn parse_type2_opcode(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_selector! { - data, namespace, scope.clone(), + data, ctx, parse_def_increment, parse_def_acquire, parse_def_wait, @@ -82,10 +81,9 @@ pub fn parse_type2_opcode(data: &[u8], } pub fn parse_type6_opcode(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_selector! { - data, namespace, scope.clone(), + data, ctx, parse_def_deref_of, parse_def_ref_of, parse_def_index, @@ -96,11 +94,10 @@ pub fn parse_type6_opcode(data: &[u8], } pub fn parse_def_object_type(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode!(data, 0x8E); parser_selector! { - data, namespace, scope.clone(), + data, ctx, parse_super_name, parse_def_ref_of, parse_def_deref_of, @@ -111,16 +108,14 @@ pub fn parse_def_object_type(data: &[u8], } pub fn parse_def_package(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Handle deferred loads in here // TODO: Truncate/extend array if necessary parser_opcode!(data, 0x12); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; let num_elements = data[1 + pkg_length_len]; - let elements = parse_package_elements_list(&data[2 + pkg_length_len .. 1 + pkg_length], - namespace, scope.clone())?; + let elements = parse_package_elements_list(&data[2 + pkg_length_len .. 1 + pkg_length], ctx)?; Ok(AmlParseType { val: elements.val, @@ -129,16 +124,15 @@ pub fn parse_def_package(data: &[u8], } pub fn parse_def_var_package(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Handle deferred loads in here // TODO: Truncate/extend array if necessary parser_opcode!(data, 0x13); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; - let num_elements = parse_term_arg(&data[1 + pkg_length_len .. 1 + pkg_length], namespace, scope.clone())?; + let num_elements = parse_term_arg(&data[1 + pkg_length_len .. 1 + pkg_length], ctx)?; let elements = parse_package_elements_list(&data[1 + pkg_length_len + num_elements.len .. - 1 + pkg_length], namespace, scope.clone())?; + 1 + pkg_length], ctx)?; Ok(AmlParseType { val: elements.val, @@ -147,16 +141,15 @@ pub fn parse_def_var_package(data: &[u8], } fn parse_package_elements_list(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { let mut current_offset: usize = 0; let mut elements: Vec = vec!(); while current_offset < data.len() { - let dro = if let Ok(e) = parse_data_ref_obj(&data[current_offset..], namespace, scope.clone()) { + let dro = if let Ok(e) = parse_data_ref_obj(&data[current_offset..], ctx) { e } else { - parse_name_string(&data[current_offset..], namespace, scope.clone())? + parse_name_string(&data[current_offset..], ctx)? }; elements.push(dro.val); @@ -170,13 +163,12 @@ fn parse_package_elements_list(data: &[u8], } pub fn parse_def_buffer(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Perform computation parser_opcode!(data, 0x11); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; - let buffer_size = parse_term_arg(&data[1 + pkg_length_len..], namespace, scope.clone())?; + let buffer_size = parse_term_arg(&data[1 + pkg_length_len..], ctx)?; let byte_list = data[1 + pkg_length_len + buffer_size.len .. 1 + pkg_length].to_vec(); Ok(AmlParseType { @@ -186,12 +178,11 @@ pub fn parse_def_buffer(data: &[u8], } fn parse_def_ref_of(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Perform computation parser_opcode!(data, 0x71); - let obj = parse_super_name(&data[1..], namespace, scope.clone())?; + let obj = parse_super_name(&data[1..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -200,12 +191,11 @@ fn parse_def_ref_of(data: &[u8], } fn parse_def_deref_of(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Perform computation parser_opcode!(data, 0x83); - let obj = parse_term_arg(&data[1..], namespace, scope.clone())?; + let obj = parse_term_arg(&data[1..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -214,13 +204,12 @@ fn parse_def_deref_of(data: &[u8], } fn parse_def_acquire(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Store the result // TODO: Perform computation parser_opcode_extended!(data, 0x23); - let obj = parse_super_name(&data[1..], namespace, scope.clone())?; + let obj = parse_super_name(&data[1..], ctx)?; let timeout = (data[2 + obj.len] as u16) + ((data[3 + obj.len] as u16) << 8); Ok(AmlParseType { @@ -230,13 +219,12 @@ fn parse_def_acquire(data: &[u8], } fn parse_def_increment(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Store the result // TODO: Perform computation parser_opcode!(data, 0x75); - let obj = parse_super_name(&data[1..], namespace, scope.clone())?; + let obj = parse_super_name(&data[1..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -245,15 +233,14 @@ fn parse_def_increment(data: &[u8], } fn parse_def_index(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Store the result, if appropriate // TODO: Perform computation parser_opcode!(data, 0x88); - let obj = parse_term_arg(&data[1..], namespace, scope.clone())?; - let idx = parse_term_arg(&data[1 + obj.len..], namespace, scope.clone())?; - let target = parse_target(&data[1 + obj.len + idx.len..], namespace, scope.clone())?; + let obj = parse_term_arg(&data[1..], ctx)?; + let idx = parse_term_arg(&data[1 + obj.len..], ctx)?; + let target = parse_target(&data[1 + obj.len + idx.len..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -262,12 +249,11 @@ fn parse_def_index(data: &[u8], } fn parse_def_land(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode!(data, 0x90); - let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; - let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; + let lhs = parse_term_arg(&data[1..], ctx)?; + let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; let result = if lhs.val.get_as_integer()? > 0 && rhs.val.get_as_integer()? > 0 { 1 } else { 0 }; @@ -278,12 +264,11 @@ fn parse_def_land(data: &[u8], } fn parse_def_lequal(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode!(data, 0x93); - let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; - let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; + let lhs = parse_term_arg(&data[1..], ctx)?; + let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; let result = if lhs.val.get_as_integer()? == rhs.val.get_as_integer()? { 1 } else { 0 }; @@ -294,12 +279,11 @@ fn parse_def_lequal(data: &[u8], } fn parse_def_lgreater(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode!(data, 0x94); - let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; - let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; + let lhs = parse_term_arg(&data[1..], ctx)?; + let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; let result = if lhs.val.get_as_integer()? > rhs.val.get_as_integer()? { 1 } else { 0 }; @@ -310,12 +294,11 @@ fn parse_def_lgreater(data: &[u8], } fn parse_def_lless(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode!(data, 0x95); - let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; - let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; + let lhs = parse_term_arg(&data[1..], ctx)?; + let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; let result = if lhs.val.get_as_integer()? < rhs.val.get_as_integer()? { 1 } else { 0 }; @@ -326,11 +309,10 @@ fn parse_def_lless(data: &[u8], } fn parse_def_lnot(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode!(data, 0x92); - let operand = parse_term_arg(&data[1..], namespace, scope.clone())?; + let operand = parse_term_arg(&data[1..], ctx)?; let result = if operand.val.get_as_integer()? == 0 { 1 } else { 0 }; Ok(AmlParseType { @@ -340,12 +322,11 @@ fn parse_def_lnot(data: &[u8], } fn parse_def_lor(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode!(data, 0x91); - let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; - let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; + let lhs = parse_term_arg(&data[1..], ctx)?; + let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; let result = if lhs.val.get_as_integer()? > 0 || rhs.val.get_as_integer()? > 0 { 1 } else { 0 }; @@ -356,14 +337,13 @@ fn parse_def_lor(data: &[u8], } fn parse_def_to_hex_string(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Compute the result // TODO: Store the result, if appropriate parser_opcode!(data, 0x98); - let operand = parse_term_arg(&data[2..], namespace, scope.clone())?; - let target = parse_target(&data[2 + operand.len..], namespace, scope.clone())?; + let operand = parse_term_arg(&data[2..], ctx)?; + let target = parse_target(&data[2 + operand.len..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -372,14 +352,13 @@ fn parse_def_to_hex_string(data: &[u8], } fn parse_def_to_buffer(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Compute the result // TODO: Store the result, if appropriate parser_opcode!(data, 0x96); - let operand = parse_term_arg(&data[2..], namespace, scope.clone())?; - let target = parse_target(&data[2 + operand.len..], namespace, scope.clone())?; + let operand = parse_term_arg(&data[2..], ctx)?; + let target = parse_target(&data[2 + operand.len..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -388,14 +367,13 @@ fn parse_def_to_buffer(data: &[u8], } fn parse_def_to_bcd(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Compute the result // TODO: Store the result, if appropriate parser_opcode_extended!(data, 0x29); - let operand = parse_term_arg(&data[2..], namespace, scope.clone())?; - let target = parse_target(&data[2 + operand.len..], namespace, scope.clone())?; + let operand = parse_term_arg(&data[2..], ctx)?; + let target = parse_target(&data[2 + operand.len..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -404,14 +382,13 @@ fn parse_def_to_bcd(data: &[u8], } fn parse_def_to_decimal_string(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Compute the result // TODO: Store the result, if appropriate parser_opcode!(data, 0x97); - let operand = parse_term_arg(&data[2..], namespace, scope.clone())?; - let target = parse_target(&data[2 + operand.len..], namespace, scope.clone())?; + let operand = parse_term_arg(&data[2..], ctx)?; + let target = parse_target(&data[2 + operand.len..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -420,14 +397,13 @@ fn parse_def_to_decimal_string(data: &[u8], } fn parse_def_to_integer(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Compute the result // TODO: Store the result, if appropriate parser_opcode!(data, 0x99); - let operand = parse_term_arg(&data[2..], namespace, scope.clone())?; - let target = parse_target(&data[2 + operand.len..], namespace, scope.clone())?; + let operand = parse_term_arg(&data[2..], ctx)?; + let target = parse_target(&data[2 + operand.len..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -436,15 +412,14 @@ fn parse_def_to_integer(data: &[u8], } fn parse_def_to_string(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Compute the result // TODO: Store the result, if appropriate parser_opcode!(data, 0x9C); - let operand = parse_term_arg(&data[1..], namespace, scope.clone())?; - let length = parse_term_arg(&data[1 + operand.len..], namespace, scope.clone())?; - let target = parse_target(&data[1 + operand.len + length.len..], namespace, scope.clone())?; + let operand = parse_term_arg(&data[1..], ctx)?; + let length = parse_term_arg(&data[1 + operand.len..], ctx)?; + let target = parse_target(&data[1 + operand.len + length.len..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -453,14 +428,13 @@ fn parse_def_to_string(data: &[u8], } fn parse_def_subtract(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Store the result, if appropriate parser_opcode!(data, 0x74); - let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; - let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; - let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; + let lhs = parse_term_arg(&data[1..], ctx)?; + let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; let result = lhs.val.get_as_integer()? - rhs.val.get_as_integer()?; @@ -471,12 +445,11 @@ fn parse_def_subtract(data: &[u8], } fn parse_def_size_of(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Perform the computation parser_opcode!(data, 0x87); - let name = parse_super_name(&data[1..], namespace, scope.clone())?; + let name = parse_super_name(&data[1..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -485,13 +458,12 @@ fn parse_def_size_of(data: &[u8], } fn parse_def_store(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Perform the store parser_opcode!(data, 0x70); - let operand = parse_term_arg(&data[1..], namespace, scope.clone())?; - let target = parse_super_name(&data[1 + operand.len..], namespace, scope.clone())?; + let operand = parse_term_arg(&data[1..], ctx)?; + let target = parse_super_name(&data[1 + operand.len..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -500,14 +472,13 @@ fn parse_def_store(data: &[u8], } fn parse_def_or(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Store the result, if appropriate parser_opcode!(data, 0x7D); - let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; - let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; - let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; + let lhs = parse_term_arg(&data[1..], ctx)?; + let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; let result = lhs.val.get_as_integer()? | rhs.val.get_as_integer()?; @@ -518,14 +489,13 @@ fn parse_def_or(data: &[u8], } fn parse_def_shift_left(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Store the result, if appropriate parser_opcode!(data, 0x79); - let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; - let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; - let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; + let lhs = parse_term_arg(&data[1..], ctx)?; + let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; let result = lhs.val.get_as_integer()? >> rhs.val.get_as_integer()?; @@ -536,14 +506,13 @@ fn parse_def_shift_left(data: &[u8], } fn parse_def_shift_right(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Store the result, if appropriate parser_opcode!(data, 0x7A); - let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; - let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; - let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; + let lhs = parse_term_arg(&data[1..], ctx)?; + let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; let result = lhs.val.get_as_integer()? << rhs.val.get_as_integer()?; @@ -554,14 +523,13 @@ fn parse_def_shift_right(data: &[u8], } fn parse_def_add(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Store the result, if appropriate parser_opcode!(data, 0x72); - let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; - let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; - let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; + let lhs = parse_term_arg(&data[1..], ctx)?; + let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; let result = lhs.val.get_as_integer()? + rhs.val.get_as_integer()?; @@ -572,14 +540,13 @@ fn parse_def_add(data: &[u8], } fn parse_def_and(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Store the result, if appropriate parser_opcode!(data, 0x7B); - let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; - let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; - let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; + let lhs = parse_term_arg(&data[1..], ctx)?; + let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; let result = lhs.val.get_as_integer()? & rhs.val.get_as_integer()?; @@ -590,14 +557,13 @@ fn parse_def_and(data: &[u8], } fn parse_def_xor(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Store the result, if appropriate parser_opcode!(data, 0x7F); - let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; - let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; - let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; + let lhs = parse_term_arg(&data[1..], ctx)?; + let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; let result = lhs.val.get_as_integer()? ^ rhs.val.get_as_integer()?; @@ -608,15 +574,14 @@ fn parse_def_xor(data: &[u8], } fn parse_def_concat_res(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Compute the result // TODO: Store the result, if appropriate parser_opcode!(data, 0x84); - let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; - let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; - let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; + let lhs = parse_term_arg(&data[1..], ctx)?; + let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -625,13 +590,12 @@ fn parse_def_concat_res(data: &[u8], } fn parse_def_wait(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Compute the result parser_opcode_extended!(data, 0x25); - let event_object = parse_super_name(&data[2..], namespace, scope.clone())?; - let operand = parse_term_arg(&data[2 + event_object.len..], namespace, scope.clone())?; + let event_object = parse_super_name(&data[2..], ctx)?; + let operand = parse_term_arg(&data[2 + event_object.len..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -640,14 +604,13 @@ fn parse_def_wait(data: &[u8], } fn parse_def_cond_ref_of(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Compute the result // TODO: Store the result parser_opcode_extended!(data, 0x12); - let operand = parse_super_name(&data[2..], namespace, scope.clone())?; - let target = parse_target(&data[2 + operand.len..], namespace, scope.clone())?; + let operand = parse_super_name(&data[2..], ctx)?; + let target = parse_target(&data[2 + operand.len..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -656,14 +619,13 @@ fn parse_def_cond_ref_of(data: &[u8], } fn parse_def_copy_object(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Compute the result // TODO: Store the result parser_opcode!(data, 0x9D); - let source = parse_term_arg(&data[1..], namespace, scope.clone())?; - let destination = parse_simple_name(&data[1 + source.len..], namespace, scope.clone())?; + let source = parse_term_arg(&data[1..], ctx)?; + let destination = parse_simple_name(&data[1 + source.len..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -672,15 +634,14 @@ fn parse_def_copy_object(data: &[u8], } fn parse_def_concat(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Compute the result // TODO: Store the result parser_opcode!(data, 0x73); - let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; - let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; - let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; + let lhs = parse_term_arg(&data[1..], ctx)?; + let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -689,13 +650,12 @@ fn parse_def_concat(data: &[u8], } fn parse_def_decrement(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Compute the result // TODO: Store the result parser_opcode!(data, 0x76); - let target = parse_super_name(&data[1..], namespace, scope.clone())?; + let target = parse_super_name(&data[1..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -704,16 +664,15 @@ fn parse_def_decrement(data: &[u8], } fn parse_def_divide(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Compute the result // TODO: Store the result, if appropriate parser_opcode!(data, 0x78); - let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; - let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; - let target_remainder = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; - let target_quotient = parse_target(&data[1 + lhs.len + rhs.len + target_remainder.len..], namespace, scope.clone())?; + let lhs = parse_term_arg(&data[1..], ctx)?; + let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; + let target_remainder = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; + let target_quotient = parse_target(&data[1 + lhs.len + rhs.len + target_remainder.len..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -722,14 +681,13 @@ fn parse_def_divide(data: &[u8], } fn parse_def_find_set_left_bit(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Compute the result // TODO: Store the result, if appropriate parser_opcode!(data, 0x81); - let operand = parse_term_arg(&data[2..], namespace, scope.clone())?; - let target = parse_target(&data[2 + operand.len..], namespace, scope.clone())?; + let operand = parse_term_arg(&data[2..], ctx)?; + let target = parse_target(&data[2 + operand.len..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -738,14 +696,13 @@ fn parse_def_find_set_left_bit(data: &[u8], } fn parse_def_find_set_right_bit(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Compute the result // TODO: Store the result, if appropriate parser_opcode!(data, 0x82); - let operand = parse_term_arg(&data[2..], namespace, scope.clone())?; - let target = parse_target(&data[2 + operand.len..], namespace, scope.clone())?; + let operand = parse_term_arg(&data[2..], ctx)?; + let target = parse_target(&data[2 + operand.len..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -754,19 +711,18 @@ fn parse_def_find_set_right_bit(data: &[u8], } fn parse_def_load_table(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Compute the result // TODO: Store the result, if appropriate // TODO: Clean up parser_opcode_extended!(data, 0x1F); - let signature = parse_term_arg(&data[2..], namespace, scope.clone())?; - let oem_id = parse_term_arg(&data[2 + signature.len..], namespace, scope.clone())?; - let oem_table_id = parse_term_arg(&data[2 + signature.len + oem_id.len..], namespace, scope.clone())?; - let root_path = parse_term_arg(&data[2 + signature.len + oem_id.len + oem_table_id.len..], namespace, scope.clone())?; - let parameter_path = parse_term_arg(&data[2 + signature.len + oem_id.len + oem_table_id.len + root_path.len..], namespace, scope.clone())?; - let parameter_data = parse_term_arg(&data[2 + signature.len + oem_id.len + oem_table_id.len + root_path.len + parameter_path.len..], namespace, scope.clone())?; + let signature = parse_term_arg(&data[2..], ctx)?; + let oem_id = parse_term_arg(&data[2 + signature.len..], ctx)?; + let oem_table_id = parse_term_arg(&data[2 + signature.len + oem_id.len..], ctx)?; + let root_path = parse_term_arg(&data[2 + signature.len + oem_id.len + oem_table_id.len..], ctx)?; + 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)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -775,14 +731,13 @@ fn parse_def_load_table(data: &[u8], } fn parse_def_match(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Compute the result // TODO: Store the result, if appropriate // TODO: Clean up match blocks parser_opcode!(data, 0x28); - let search_pkg = parse_term_arg(&data[1..], namespace, scope.clone())?; + let search_pkg = parse_term_arg(&data[1..], ctx)?; let first_operation = match data[1 + search_pkg.len] { 0 => MatchOpcode::MTR, @@ -793,7 +748,7 @@ fn parse_def_match(data: &[u8], 5 => MatchOpcode::MGT, _ => return Err(AmlError::AmlParseError("DefMatch - Invalid Opcode")) }; - let first_operand = parse_term_arg(&data[2 + search_pkg.len..], namespace, scope.clone())?; + let first_operand = parse_term_arg(&data[2 + search_pkg.len..], ctx)?; let second_operation = match data[2 + search_pkg.len + first_operand.len] { 0 => MatchOpcode::MTR, @@ -804,9 +759,9 @@ fn parse_def_match(data: &[u8], 5 => MatchOpcode::MGT, _ => return Err(AmlError::AmlParseError("DefMatch - Invalid Opcode")) }; - let second_operand = parse_term_arg(&data[3 + search_pkg.len + first_operand.len..], namespace, scope.clone())?; + let second_operand = parse_term_arg(&data[3 + search_pkg.len + first_operand.len..], ctx)?; - let start_index = parse_term_arg(&data[3 + search_pkg.len + first_operand.len + second_operand.len..], namespace, scope.clone())?; + let start_index = parse_term_arg(&data[3 + search_pkg.len + first_operand.len + second_operand.len..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -815,14 +770,13 @@ fn parse_def_match(data: &[u8], } fn parse_def_from_bcd(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Store the result, if appropriate // TODO: Clean up match block parser_opcode_extended!(data, 0x28); - let operand = parse_term_arg(&data[2..], namespace, scope.clone())?; - let target = parse_target(&data[2 + operand.len..], namespace, scope.clone())?; + let operand = parse_term_arg(&data[2..], ctx)?; + let target = parse_target(&data[2 + operand.len..], ctx)?; let result = match target.val.get_as_integer() { Ok(i) => { @@ -851,16 +805,15 @@ fn parse_def_from_bcd(data: &[u8], } fn parse_def_mid(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Compute the result // TODO: Store the result, if appropriate parser_opcode!(data, 0x9E); - let source = parse_term_arg(&data[1..], namespace, scope.clone())?; - let index = parse_term_arg(&data[1 + source.len..], namespace, scope.clone())?; - let length = parse_term_arg(&data[1 + source.len + index.len..], namespace, scope.clone())?; - let target = parse_target(&data[1 + source.len + index.len + length.len..], namespace, scope.clone())?; + let source = parse_term_arg(&data[1..], ctx)?; + let index = parse_term_arg(&data[1 + source.len..], ctx)?; + let length = parse_term_arg(&data[1 + source.len + index.len..], ctx)?; + let target = parse_target(&data[1 + source.len + index.len + length.len..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -869,15 +822,14 @@ fn parse_def_mid(data: &[u8], } fn parse_def_mod(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Store the result, if appropriate // TODO: Fatal exception on rhs == 0 parser_opcode!(data, 0x85); - let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; - let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; - let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; + let lhs = parse_term_arg(&data[1..], ctx)?; + let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; let result = lhs.val.get_as_integer()? % rhs.val.get_as_integer()?; @@ -888,15 +840,14 @@ fn parse_def_mod(data: &[u8], } fn parse_def_multiply(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Store the result, if appropriate // TODO: Handle overflow parser_opcode!(data, 0x77); - let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; - let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; - let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; + let lhs = parse_term_arg(&data[1..], ctx)?; + let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; let result = lhs.val.get_as_integer()? * rhs.val.get_as_integer()?; @@ -907,14 +858,13 @@ fn parse_def_multiply(data: &[u8], } fn parse_def_nand(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Store the result, if appropriate parser_opcode!(data, 0x7C); - let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; - let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; - let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; + let lhs = parse_term_arg(&data[1..], ctx)?; + let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; let result = !(lhs.val.get_as_integer()? & rhs.val.get_as_integer()?); @@ -925,14 +875,13 @@ fn parse_def_nand(data: &[u8], } fn parse_def_nor(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Store the result, if appropriate parser_opcode!(data, 0x7E); - let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; - let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; - let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; + let lhs = parse_term_arg(&data[1..], ctx)?; + let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; let result = !(lhs.val.get_as_integer()? | rhs.val.get_as_integer()?); @@ -943,13 +892,12 @@ fn parse_def_nor(data: &[u8], } fn parse_def_not(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Store the result, if appropriate parser_opcode!(data, 0x80); - let operand = parse_term_arg(&data[1..], namespace, scope.clone())?; - let target = parse_target(&data[1 + operand.len..], namespace, scope.clone())?; + let operand = parse_term_arg(&data[1..], ctx)?; + let target = parse_target(&data[1 + operand.len..], ctx)?; let result = !operand.val.get_as_integer()?; @@ -960,8 +908,7 @@ fn parse_def_not(data: &[u8], } fn parse_def_timer(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Read from the hardware timer, and split into 100ns intervals parser_opcode_extended!(data, 0x33); From def456a8e54a1b704a19988e8b14c41f8ccc9841 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Mon, 3 Jul 2017 11:11:07 +0100 Subject: [PATCH 022/113] Added object modification --- src/acpi/aml/mod.rs | 5 +- src/acpi/aml/namedobj.rs | 24 ++------- src/acpi/aml/parser.rs | 49 +++++++++++++++-- src/acpi/aml/type2opcode.rs | 101 +++++++++++++++++++++--------------- 4 files changed, 108 insertions(+), 71 deletions(-) diff --git a/src/acpi/aml/mod.rs b/src/acpi/aml/mod.rs index d20ce4c..fa2e070 100644 --- a/src/acpi/aml/mod.rs +++ b/src/acpi/aml/mod.rs @@ -39,10 +39,7 @@ pub enum AmlError { pub fn parse_aml_table(sdt: &'static Sdt) -> Result, AmlError> { let data = sdt.data(); - let mut ctx = AmlExecutionContext { - namespace: &mut BTreeMap::new(), - scope: String::from_str("\\").unwrap() - }; + let mut ctx = AmlExecutionContext::new(String::from_str("\\").unwrap()); let term_list = parse_term_list(data, &mut ctx)?; diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index 3c4605b..06ad1cf 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -342,11 +342,7 @@ fn parse_def_device(data: &[u8], let (pkg_length, pkg_length_len) = parse_pkg_length(&data[2..])?; let name = parse_name_string(&data[2 + pkg_length_len .. 2 + pkg_length], ctx)?; - let mut local_ctx = AmlExecutionContext { - namespace: &mut BTreeMap::new(), - scope: String::new() - }; - + let mut local_ctx = AmlExecutionContext::new(String::new()); let obj_list = parse_object_list(&data[2 + pkg_length_len + name.len .. 2 + pkg_length], &mut local_ctx)?; let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); @@ -682,11 +678,7 @@ fn parse_def_power_res(data: &[u8], let resource_order: u16 = (data[3 + pkg_len_len + name.len] as u16) + ((data[4 + pkg_len_len + name.len] as u16) << 8); - let mut local_ctx = AmlExecutionContext { - namespace: &mut BTreeMap::new(), - scope: String::new() - }; - + let mut local_ctx = AmlExecutionContext::new(String::new()); parse_object_list(&data[5 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_ctx)?; ctx.namespace.insert(local_scope_string, AmlValue::PowerResource { @@ -717,11 +709,7 @@ fn parse_def_processor(data: &[u8], ((data[6 + pkg_len_len + name.len] as u32) << 24); let p_blk_len = data[7 + pkg_len_len + name.len]; - let mut local_ctx = AmlExecutionContext { - namespace: &mut BTreeMap::new(), - scope: String::new() - }; - + let mut local_ctx = AmlExecutionContext::new(String::new()); parse_object_list(&data[8 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_ctx)?; ctx.namespace.insert(local_scope_string, AmlValue::Processor { @@ -745,11 +733,7 @@ fn parse_def_thermal_zone(data: &[u8], let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); - let mut local_ctx = AmlExecutionContext { - namespace: &mut BTreeMap::new(), - scope: String::new() - }; - + let mut local_ctx = AmlExecutionContext::new(String::new()); parse_object_list(&data[2 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_ctx)?; ctx.namespace.insert(local_scope_string, AmlValue::ThermalZone(local_ctx.namespace.clone())); diff --git a/src/acpi/aml/parser.rs b/src/acpi/aml/parser.rs index b316319..d918292 100644 --- a/src/acpi/aml/parser.rs +++ b/src/acpi/aml/parser.rs @@ -1,7 +1,7 @@ use collections::string::String; use collections::btree_map::BTreeMap; -use super::namespace::AmlValue; +use super::namespace::{ AmlValue, ObjectReference }; use super::AmlError; pub type ParseResult = Result; @@ -12,7 +12,48 @@ pub struct AmlParseTypeGeneric { pub len: usize } -pub struct AmlExecutionContext<'a> { - pub namespace: &'a mut BTreeMap, - pub scope: String +pub struct AmlExecutionContext { + pub namespace: BTreeMap, + pub scope: String, + pub local_vars: [AmlValue; 8], + pub arg_vars: [AmlValue; 8] +} + +impl AmlExecutionContext { + pub fn new(scope: String) -> AmlExecutionContext { + AmlExecutionContext { + namespace: BTreeMap::new(), + scope: scope, + local_vars: [AmlValue::Uninitialized, + AmlValue::Uninitialized, + AmlValue::Uninitialized, + AmlValue::Uninitialized, + AmlValue::Uninitialized, + AmlValue::Uninitialized, + AmlValue::Uninitialized, + AmlValue::Uninitialized], + arg_vars: [AmlValue::Uninitialized, + AmlValue::Uninitialized, + AmlValue::Uninitialized, + AmlValue::Uninitialized, + AmlValue::Uninitialized, + AmlValue::Uninitialized, + AmlValue::Uninitialized, + AmlValue::Uninitialized] + } + } + + pub fn modify(&mut self, name: AmlValue, value: AmlValue) { + // TODO: throw errors + // TODO: return DRO + match name { + AmlValue::None => (), + AmlValue::ObjectReference(r) => match r { + ObjectReference::ArgObj(i) => (), + ObjectReference::LocalObj(i) => self.local_vars[i as usize] = value, + _ => () + }, + _ => () + } + } } diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index 0685251..475b942 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -429,17 +429,18 @@ fn parse_def_to_string(data: &[u8], fn parse_def_subtract(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Store the result, if appropriate parser_opcode!(data, 0x74); let lhs = parse_term_arg(&data[1..], ctx)?; let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; - let result = lhs.val.get_as_integer()? - rhs.val.get_as_integer()?; + let result = AmlValue::Integer(lhs.val.get_as_integer()? - rhs.val.get_as_integer()?); + + ctx.modify(target.val, result.clone()); Ok(AmlParseType { - val: AmlValue::IntegerConstant(result), + val: result, len: 1 + lhs.len + rhs.len + target.len }) } @@ -459,11 +460,13 @@ fn parse_def_size_of(data: &[u8], fn parse_def_store(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Perform the store + // TODO: Return the DRO parser_opcode!(data, 0x70); let operand = parse_term_arg(&data[1..], ctx)?; let target = parse_super_name(&data[1 + operand.len..], ctx)?; + + ctx.modify(target.val, operand.val); Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -473,102 +476,108 @@ fn parse_def_store(data: &[u8], fn parse_def_or(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Store the result, if appropriate parser_opcode!(data, 0x7D); let lhs = parse_term_arg(&data[1..], ctx)?; let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; - let result = lhs.val.get_as_integer()? | rhs.val.get_as_integer()?; + let result = AmlValue::Integer(lhs.val.get_as_integer()? | rhs.val.get_as_integer()?); + + ctx.modify(target.val, result.clone()); Ok(AmlParseType { - val: AmlValue::IntegerConstant(result), + val: result, len: 1 + lhs.len + rhs.len + target.len }) } fn parse_def_shift_left(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Store the result, if appropriate parser_opcode!(data, 0x79); let lhs = parse_term_arg(&data[1..], ctx)?; let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; - let result = lhs.val.get_as_integer()? >> rhs.val.get_as_integer()?; + let result = AmlValue::Integer(lhs.val.get_as_integer()? >> rhs.val.get_as_integer()?); + + ctx.modify(target.val, result.clone()); Ok(AmlParseType { - val: AmlValue::IntegerConstant(result), + val: result, len: 1 + lhs.len + rhs.len + target.len }) } fn parse_def_shift_right(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Store the result, if appropriate parser_opcode!(data, 0x7A); let lhs = parse_term_arg(&data[1..], ctx)?; let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; - - let result = lhs.val.get_as_integer()? << rhs.val.get_as_integer()?; - + + let result = AmlValue::Integer(lhs.val.get_as_integer()? << rhs.val.get_as_integer()?); + + ctx.modify(target.val, result.clone()); + Ok(AmlParseType { - val: AmlValue::IntegerConstant(result), + val: result, len: 1 + lhs.len + rhs.len + target.len }) } fn parse_def_add(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Store the result, if appropriate parser_opcode!(data, 0x72); let lhs = parse_term_arg(&data[1..], ctx)?; let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; - let result = lhs.val.get_as_integer()? + rhs.val.get_as_integer()?; + let result = AmlValue::Integer(lhs.val.get_as_integer()? + rhs.val.get_as_integer()?); + + ctx.modify(target.val, result.clone()); Ok(AmlParseType { - val: AmlValue::IntegerConstant(result), + val: result, len: 1 + lhs.len + rhs.len + target.len }) } fn parse_def_and(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Store the result, if appropriate parser_opcode!(data, 0x7B); let lhs = parse_term_arg(&data[1..], ctx)?; let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; - let result = lhs.val.get_as_integer()? & rhs.val.get_as_integer()?; + let result = AmlValue::Integer(lhs.val.get_as_integer()? & rhs.val.get_as_integer()?); + + ctx.modify(target.val, result.clone()); Ok(AmlParseType { - val: AmlValue::IntegerConstant(result), + val: result, len: 1 + lhs.len + rhs.len + target.len }) } fn parse_def_xor(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Store the result, if appropriate parser_opcode!(data, 0x7F); let lhs = parse_term_arg(&data[1..], ctx)?; let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; - let result = lhs.val.get_as_integer()? ^ rhs.val.get_as_integer()?; + let result = AmlValue::Integer(lhs.val.get_as_integer()? ^ rhs.val.get_as_integer()?); + + ctx.modify(target.val, result.clone()); Ok(AmlParseType { - val: AmlValue::IntegerConstant(result), + val: result, len: 1 + lhs.len + rhs.len + target.len }) } @@ -771,14 +780,13 @@ fn parse_def_match(data: &[u8], fn parse_def_from_bcd(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Store the result, if appropriate // TODO: Clean up match block parser_opcode_extended!(data, 0x28); let operand = parse_term_arg(&data[2..], ctx)?; let target = parse_target(&data[2 + operand.len..], ctx)?; - let result = match target.val.get_as_integer() { + let result = AmlValue::Integer(match target.val.get_as_integer() { Ok(i) => { let mut i = i; let mut ires = 0; @@ -796,10 +804,12 @@ fn parse_def_from_bcd(data: &[u8], ires }, Err(e) => return Err(e) - }; + }); + + ctx.modify(target.val, result.clone()); Ok(AmlParseType { - val: AmlValue::IntegerConstant(result), + val: result, len: 2 + operand.len + target.len }) } @@ -823,7 +833,6 @@ fn parse_def_mid(data: &[u8], fn parse_def_mod(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Store the result, if appropriate // TODO: Fatal exception on rhs == 0 parser_opcode!(data, 0x85); @@ -831,17 +840,18 @@ fn parse_def_mod(data: &[u8], let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; - let result = lhs.val.get_as_integer()? % rhs.val.get_as_integer()?; + let result = AmlValue::Integer(lhs.val.get_as_integer()? % rhs.val.get_as_integer()?); + + ctx.modify(target.val, result.clone()); Ok(AmlParseType { - val: AmlValue::IntegerConstant(result), + val: result, len: 1 + lhs.len + rhs.len + target.len }) } fn parse_def_multiply(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Store the result, if appropriate // TODO: Handle overflow parser_opcode!(data, 0x77); @@ -849,60 +859,65 @@ fn parse_def_multiply(data: &[u8], let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; - let result = lhs.val.get_as_integer()? * rhs.val.get_as_integer()?; + let result = AmlValue::Integer(lhs.val.get_as_integer()? * rhs.val.get_as_integer()?); + + ctx.modify(target.val, result.clone()); Ok(AmlParseType { - val: AmlValue::IntegerConstant(result), + val: result, len: 1 + lhs.len + rhs.len + target.len }) } fn parse_def_nand(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Store the result, if appropriate parser_opcode!(data, 0x7C); let lhs = parse_term_arg(&data[1..], ctx)?; let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; - let result = !(lhs.val.get_as_integer()? & rhs.val.get_as_integer()?); + let result = AmlValue::Integer(!(lhs.val.get_as_integer()? & rhs.val.get_as_integer()?)); + + ctx.modify(target.val, result.clone()); Ok(AmlParseType { - val: AmlValue::IntegerConstant(result), + val: result, len: 1 + lhs.len + rhs.len + target.len }) } fn parse_def_nor(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Store the result, if appropriate parser_opcode!(data, 0x7E); let lhs = parse_term_arg(&data[1..], ctx)?; let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; - let result = !(lhs.val.get_as_integer()? | rhs.val.get_as_integer()?); + let result = AmlValue::Integer(!(lhs.val.get_as_integer()? | rhs.val.get_as_integer()?)); + + ctx.modify(target.val, result.clone()); Ok(AmlParseType { - val: AmlValue::IntegerConstant(result), + val: result, len: 1 + lhs.len + rhs.len + target.len }) } fn parse_def_not(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Store the result, if appropriate parser_opcode!(data, 0x80); let operand = parse_term_arg(&data[1..], ctx)?; let target = parse_target(&data[1 + operand.len..], ctx)?; - let result = !operand.val.get_as_integer()?; + let result = AmlValue::Integer(!operand.val.get_as_integer()?); + + ctx.modify(target.val, result.clone()); Ok(AmlParseType { - val: AmlValue::IntegerConstant(result), + val: result, len: 1 + operand.len + target.len }) } From 980065d4d619a3f81b5f0cb32c7f89dc7461ab0c Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Wed, 5 Jul 2017 14:36:40 +0100 Subject: [PATCH 023/113] Fixed number of bugs --- src/acpi/aml/dataobj.rs | 6 +++--- src/acpi/aml/mod.rs | 2 +- src/acpi/aml/namedobj.rs | 6 +++++- src/acpi/aml/namespace.rs | 6 +++++- src/acpi/aml/namespacemodifier.rs | 6 +++--- src/acpi/aml/parsermacros.rs | 32 +++++-------------------------- src/acpi/aml/termlist.rs | 1 + src/acpi/aml/type2opcode.rs | 6 +++++- src/stop.rs | 1 + 9 files changed, 29 insertions(+), 37 deletions(-) diff --git a/src/acpi/aml/dataobj.rs b/src/acpi/aml/dataobj.rs index 4025f7f..1cd3904 100644 --- a/src/acpi/aml/dataobj.rs +++ b/src/acpi/aml/dataobj.rs @@ -125,11 +125,11 @@ fn parse_computational_data(data: &[u8], }, 0x00 => Ok(AmlParseType { val: AmlValue::IntegerConstant(0 as u64), - len: 9 as usize + len: 1 as usize }), 0x01 => Ok(AmlParseType { val: AmlValue::IntegerConstant(1 as u64), - len: 9 as usize + len: 1 as usize }), 0x5B => if data[1] == 0x30 { Ok(AmlParseType { @@ -141,7 +141,7 @@ fn parse_computational_data(data: &[u8], }, 0xFF => Ok(AmlParseType { val: AmlValue::IntegerConstant(0xFFFFFFFFFFFFFFFF), - len: 9 as usize + len: 1 as usize }), _ => parse_def_buffer(data, ctx) } diff --git a/src/acpi/aml/mod.rs b/src/acpi/aml/mod.rs index fa2e070..a6275db 100644 --- a/src/acpi/aml/mod.rs +++ b/src/acpi/aml/mod.rs @@ -41,7 +41,7 @@ pub fn parse_aml_table(sdt: &'static Sdt) -> Result, let data = sdt.data(); let mut ctx = AmlExecutionContext::new(String::from_str("\\").unwrap()); - let term_list = parse_term_list(data, &mut ctx)?; + parse_term_list(data, &mut ctx)?; Ok(ctx.namespace.clone()) } diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index 06ad1cf..3f6a569 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -474,10 +474,13 @@ fn parse_field_list(data: &[u8], selector: FieldSelector, flags: &mut FieldFlags) -> ParseResult { let mut current_offset: usize = 0; + let mut field_offset: usize = 0; let mut connection = AmlValue::Uninitialized; while current_offset < data.len() { - parse_field_element(&data[current_offset..], ctx, selector.clone(), &mut connection, flags, &mut current_offset)?; + let res = parse_field_element(&data[current_offset..], ctx, selector.clone(), &mut connection, flags, &mut field_offset)?; + + current_offset += res.len; } Ok(AmlParseType { @@ -503,6 +506,7 @@ fn parse_field_element(data: &[u8], length: field.val.length }); + *offset += field.val.length; field.len } else if let Ok(field) = parse_reserved_field(data, ctx) { *offset += field.val; diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index 54cef02..f2a5ffe 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -129,6 +129,10 @@ pub fn get_namespace_string(current: String, modifier_v: AmlValue) -> String { } let mut namespace = current.clone(); - namespace.push('.'); + + if !namespace.ends_with("\\") { + namespace.push('.'); + } + namespace + &modifier } diff --git a/src/acpi/aml/namespacemodifier.rs b/src/acpi/aml/namespacemodifier.rs index 35cd1a3..5d1bbf6 100644 --- a/src/acpi/aml/namespacemodifier.rs +++ b/src/acpi/aml/namespacemodifier.rs @@ -66,13 +66,13 @@ fn parse_scope_op(data: &[u8], let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; let name = parse_name_string(&data[1 + pkg_length_len..], ctx)?; - let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val.clone()); let containing_scope_string = ctx.scope.clone(); ctx.scope = local_scope_string; - parse_term_list(&data[1 + pkg_length_len + name.len..], ctx)?; + parse_term_list(&data[1 + pkg_length_len + name.len .. 1 + pkg_length], ctx)?; ctx.scope = containing_scope_string; - + Ok(AmlParseType { val: AmlValue::None, len: 1 + pkg_length diff --git a/src/acpi/aml/parsermacros.rs b/src/acpi/aml/parsermacros.rs index 3f8cf61..20cedd9 100644 --- a/src/acpi/aml/parsermacros.rs +++ b/src/acpi/aml/parsermacros.rs @@ -4,7 +4,10 @@ macro_rules! parser_selector { match $func($data, $ctx) { Ok(res) => return Ok(res), Err(AmlError::AmlInvalidOpCode) => (), - Err(e) => return Err(e) + Err(e) => { +// println!("This doesn't work for some reason"); + return Err(e); + } } }; {$data:expr, $ctx:expr, $func:expr, $($funcs:expr),+} => { @@ -13,6 +16,7 @@ macro_rules! parser_selector { }; } +#[macro_export] macro_rules! parser_selector_simple { {$data:expr, $func:expr} => { match $func($data) { @@ -27,21 +31,6 @@ macro_rules! parser_selector_simple { }; } -#[macro_export] -macro_rules! parser_wrap { - ($wrap:expr, $func:expr) => { - |data, namespace, scope| { - match $func(data) { - Ok(res) => Ok(AmlParseTypeGeneric { - val: $wrap(res.val), - len: res.len - }), - Err(e) => Err(e) - } - } - }; -} - #[macro_export] macro_rules! parser_opcode { ($data:expr, $opcode:expr) => { @@ -64,14 +53,3 @@ macro_rules! parser_opcode_extended { } }; } - -#[macro_export] -macro_rules! parser_verify_value { - ($val:expr) => { - match $val.val { - Some(s) => s, - None => return Err(AmlError::AmlValueError) - } - }; -} - diff --git a/src/acpi/aml/termlist.rs b/src/acpi/aml/termlist.rs index bbce0e4..cdf0b80 100644 --- a/src/acpi/aml/termlist.rs +++ b/src/acpi/aml/termlist.rs @@ -73,6 +73,7 @@ pub fn parse_method_invocation(data: &[u8], // TODO: If so, parse appropriate number of parameters // TODO: If not, add deferred load to ctx let name = parse_name_string(data, ctx)?; + Err(AmlError::AmlDeferredLoad) } diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index 475b942..94950c1 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -149,7 +149,11 @@ fn parse_package_elements_list(data: &[u8], let dro = if let Ok(e) = parse_data_ref_obj(&data[current_offset..], ctx) { e } else { - parse_name_string(&data[current_offset..], ctx)? + let d = parse_name_string(&data[current_offset..], ctx)?; + AmlParseType { + val: AmlValue::ObjectReference(ObjectReference::NamedObj(d.val.get_as_string()?)), + len: d.len + } }; elements.push(dro.val); diff --git a/src/stop.rs b/src/stop.rs index 6dec9a1..7e53f10 100644 --- a/src/stop.rs +++ b/src/stop.rs @@ -14,6 +14,7 @@ pub unsafe extern fn kstop() -> ! { if let Some(ref namespace) = acpi.namespace { if let Some(s) = namespace.get("\\_S5") { if let Ok(p) = s.get_as_package() { + println!("{:?}", p); 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"); From 00591235e1d75bf1d73ad8f0c47276d302af2ae4 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Fri, 7 Jul 2017 10:37:09 +0100 Subject: [PATCH 024/113] Implemented further opcodes in full, added get to context --- src/acpi/aml/namespace.rs | 13 ++- src/acpi/aml/parser.rs | 12 +++ src/acpi/aml/parsermacros.rs | 5 +- src/acpi/aml/type2opcode.rs | 188 +++++++++++++++++++++++++---------- 4 files changed, 159 insertions(+), 59 deletions(-) diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index f2a5ffe..746cd1e 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -34,10 +34,7 @@ pub enum ObjectReference { pub enum AmlValue { None, Uninitialized, - Buffer { - length: Box, - byte_list: Vec - }, + Buffer(Vec), BufferField { source_buf: Box, index: Box, @@ -81,13 +78,19 @@ pub enum AmlValue { } impl AmlValue { - // TODO: These should be able to throw errors rather than returning options pub fn get_as_string(&self) -> Result { match *self { AmlValue::String(ref s) => Ok(s.clone()), _ => Err(AmlError::AmlValueError) } } + + pub fn get_as_buffer(&self) -> Result, AmlError> { + match *self { + AmlValue::Buffer(ref b) => Ok(b.clone()), + _ => Err(AmlError::AmlValueError) + } + } pub fn get_as_package(&self) -> Result, AmlError> { match *self { diff --git a/src/acpi/aml/parser.rs b/src/acpi/aml/parser.rs index d918292..c71025d 100644 --- a/src/acpi/aml/parser.rs +++ b/src/acpi/aml/parser.rs @@ -56,4 +56,16 @@ impl AmlExecutionContext { _ => () } } + + pub fn get(&self, name: AmlValue) -> AmlValue { + match name { + AmlValue::None => AmlValue::None, + AmlValue::ObjectReference(r) => match r { + ObjectReference::ArgObj(i) => self.arg_vars[i as usize].clone(), + ObjectReference::LocalObj(i) => self.local_vars[i as usize].clone(), + _ => AmlValue::None + }, + _ => AmlValue::None + } + } } diff --git a/src/acpi/aml/parsermacros.rs b/src/acpi/aml/parsermacros.rs index 20cedd9..31a2338 100644 --- a/src/acpi/aml/parsermacros.rs +++ b/src/acpi/aml/parsermacros.rs @@ -4,10 +4,7 @@ macro_rules! parser_selector { match $func($data, $ctx) { Ok(res) => return Ok(res), Err(AmlError::AmlInvalidOpCode) => (), - Err(e) => { -// println!("This doesn't work for some reason"); - return Err(e); - } + Err(e) => return Err(e) } }; {$data:expr, $ctx:expr, $func:expr, $($funcs:expr),+} => { diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index 94950c1..721b36c 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -110,15 +110,22 @@ pub fn parse_def_object_type(data: &[u8], pub fn parse_def_package(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Handle deferred loads in here - // TODO: Truncate/extend array if necessary parser_opcode!(data, 0x12); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; - let num_elements = data[1 + pkg_length_len]; - let elements = parse_package_elements_list(&data[2 + pkg_length_len .. 1 + pkg_length], ctx)?; + let numelements = data[1 + pkg_length_len] as usize; + let mut elements = parse_package_elements_list(&data[2 + pkg_length_len .. 1 + pkg_length], ctx)?.val.get_as_package()?; + + if elements.len() > numelements { + elements = elements[0 .. numelements].to_vec(); + } else if numelements > elements.len() { + for i in 0..numelements - elements.len() { + elements.push(AmlValue::Uninitialized); + } + } Ok(AmlParseType { - val: elements.val, + val: AmlValue::Package(elements), len: 1 + pkg_length }) } @@ -126,16 +133,25 @@ pub fn parse_def_package(data: &[u8], pub fn parse_def_var_package(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Handle deferred loads in here - // TODO: Truncate/extend array if necessary parser_opcode!(data, 0x13); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; let num_elements = parse_term_arg(&data[1 + pkg_length_len .. 1 + pkg_length], ctx)?; - let elements = parse_package_elements_list(&data[1 + pkg_length_len + num_elements.len .. - 1 + pkg_length], ctx)?; + let mut elements = parse_package_elements_list(&data[1 + pkg_length_len + num_elements.len .. + 1 + pkg_length], ctx)?.val.get_as_package()?; + + let numelements = num_elements.val.get_as_integer()? as usize; + + if elements.len() > numelements { + elements = elements[0 .. numelements].to_vec(); + } else if numelements > elements.len() { + for i in 0..numelements - elements.len() { + elements.push(AmlValue::Uninitialized); + } + } Ok(AmlParseType { - val: elements.val, + val: AmlValue::Package(elements), len: 1 + pkg_length }) } @@ -224,14 +240,15 @@ fn parse_def_acquire(data: &[u8], fn parse_def_increment(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Store the result - // TODO: Perform computation parser_opcode!(data, 0x75); let obj = parse_super_name(&data[1..], ctx)?; + let value = AmlValue::Integer(ctx.get(obj.val.clone()).get_as_integer()? + 1); + + ctx.modify(obj.val, value.clone()); Ok(AmlParseType { - val: AmlValue::Uninitialized, + val: value, len: 1 + obj.len }) } @@ -464,16 +481,15 @@ fn parse_def_size_of(data: &[u8], fn parse_def_store(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Return the DRO parser_opcode!(data, 0x70); let operand = parse_term_arg(&data[1..], ctx)?; let target = parse_super_name(&data[1 + operand.len..], ctx)?; - ctx.modify(target.val, operand.val); + ctx.modify(target.val.clone(), operand.val); Ok(AmlParseType { - val: AmlValue::Uninitialized, + val: target.val, len: 1 + operand.len + target.len }) } @@ -664,61 +680,99 @@ fn parse_def_concat(data: &[u8], fn parse_def_decrement(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Compute the result - // TODO: Store the result parser_opcode!(data, 0x76); - let target = parse_super_name(&data[1..], ctx)?; + let obj = parse_super_name(&data[1..], ctx)?; + let value = AmlValue::Integer(ctx.get(obj.val.clone()).get_as_integer()? - 1); + ctx.modify(obj.val, value.clone()); + Ok(AmlParseType { - val: AmlValue::Uninitialized, - len: 1 + target.len + val: value, + len: 1 + obj.len }) } fn parse_def_divide(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Compute the result - // TODO: Store the result, if appropriate parser_opcode!(data, 0x78); let lhs = parse_term_arg(&data[1..], ctx)?; let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; let target_remainder = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; let target_quotient = parse_target(&data[1 + lhs.len + rhs.len + target_remainder.len..], ctx)?; + + let numerator = lhs.val.get_as_integer()?; + let denominator = rhs.val.get_as_integer()?; + + let remainder = numerator % denominator; + let quotient = (numerator - remainder) / denominator; + + ctx.modify(target_remainder.val, AmlValue::Integer(remainder)); + ctx.modify(target_quotient.val, AmlValue::Integer(quotient)); Ok(AmlParseType { - val: AmlValue::Uninitialized, + val: AmlValue::Integer(quotient), len: 1 + lhs.len + rhs.len + target_remainder.len + target_quotient.len }) } fn parse_def_find_set_left_bit(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Compute the result - // TODO: Store the result, if appropriate parser_opcode!(data, 0x81); let operand = parse_term_arg(&data[2..], ctx)?; let target = parse_target(&data[2 + operand.len..], ctx)?; + let mut first_bit = 32; + let mut test = operand.val.get_as_integer()?; + + while first_bit > 0{ + if test & 0x8000000000000000 > 0 { + break; + } + + test <<= 1; + first_bit -= 1; + } + + let result = AmlValue::Integer(first_bit); + ctx.modify(target.val, result.clone()); + Ok(AmlParseType { - val: AmlValue::Uninitialized, + val: result, len: 1 + operand.len + target.len }) } fn parse_def_find_set_right_bit(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Compute the result - // TODO: Store the result, if appropriate parser_opcode!(data, 0x82); let operand = parse_term_arg(&data[2..], ctx)?; let target = parse_target(&data[2 + operand.len..], ctx)?; + let mut first_bit = 1; + let mut test = operand.val.get_as_integer()?; + + while first_bit <= 32 { + if test & 1 > 0 { + break; + } + + test >>= 1; + first_bit += 1; + } + + if first_bit == 33 { + first_bit = 0; + } + + let result = AmlValue::Integer(first_bit); + ctx.modify(target.val, result.clone()); + Ok(AmlParseType { - val: AmlValue::Uninitialized, + val: result, len: 1 + operand.len + target.len }) } @@ -784,31 +838,25 @@ fn parse_def_match(data: &[u8], fn parse_def_from_bcd(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Clean up match block parser_opcode_extended!(data, 0x28); let operand = parse_term_arg(&data[2..], ctx)?; let target = parse_target(&data[2 + operand.len..], ctx)?; - - let result = AmlValue::Integer(match target.val.get_as_integer() { - Ok(i) => { - let mut i = i; - let mut ires = 0; - while i != 0 { - if i & 0x0F > 10 { - return Err(AmlError::AmlValueError); - } + let mut i = operand.val.get_as_integer()?; + let mut result = 0; - ires *= 10; - ires += i & 0x0F; - i >>= 4; - } + while i != 0 { + if i & 0x0F > 10 { + return Err(AmlError::AmlValueError); + } + + result *= 10; + result += i & 0x0F; + i >>= 4; + } - ires - }, - Err(e) => return Err(e) - }); + let result = AmlValue::Integer(result); ctx.modify(target.val, result.clone()); @@ -820,8 +868,6 @@ fn parse_def_from_bcd(data: &[u8], fn parse_def_mid(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Compute the result - // TODO: Store the result, if appropriate parser_opcode!(data, 0x9E); let source = parse_term_arg(&data[1..], ctx)?; @@ -829,21 +875,63 @@ fn parse_def_mid(data: &[u8], let length = parse_term_arg(&data[1 + source.len + index.len..], ctx)?; let target = parse_target(&data[1 + source.len + index.len + length.len..], ctx)?; + let idx = index.val.get_as_integer()? as usize; + let mut len = length.val.get_as_integer()? as usize; + + let result = match source.val { + AmlValue::String(s) => { + if idx > s.len() { + AmlValue::String(String::new()) + } else { + let mut res = s.clone().split_off(idx); + + if len < res.len() { + res.split_off(len); + } + + AmlValue::String(res) + } + }, + _ => { + // If it isn't a string already, treat it as a buffer. Must perform that check first, + // as Mid can operate on both strings and buffers, but a string can be cast as a buffer + // implicitly. + // Additionally, any type that can be converted to a buffer can also be converted to a + // string, so no information is lost + let b = source.val.get_as_buffer()?; + + if idx > b.len() { + AmlValue::Buffer(vec!()) + } else { + if idx + len > b.len() { + len = b.len() - idx; + } + + AmlValue::Buffer(b[idx .. idx + len].to_vec()) + } + } + }; + + ctx.modify(target.val, result.clone()); + Ok(AmlParseType { - val: AmlValue::Uninitialized, + val: result, len: 1 + source.len + index.len + length.len + target.len }) } fn parse_def_mod(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Fatal exception on rhs == 0 parser_opcode!(data, 0x85); let lhs = parse_term_arg(&data[1..], ctx)?; let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; + if rhs.val.get_as_integer()? == 0 { + return Err(AmlError::AmlValueError); + } + let result = AmlValue::Integer(lhs.val.get_as_integer()? % rhs.val.get_as_integer()?); ctx.modify(target.val, result.clone()); From 59936e25e6292dd1a6f66f1837eb8152ee241a31 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Fri, 7 Jul 2017 11:39:08 +0100 Subject: [PATCH 025/113] Implemented match --- src/acpi/aml/type2opcode.rs | 106 ++++++++++++++++++++++++++++++++++-- 1 file changed, 102 insertions(+), 4 deletions(-) diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index 721b36c..8956411 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -799,9 +799,7 @@ fn parse_def_load_table(data: &[u8], fn parse_def_match(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Compute the result - // TODO: Store the result, if appropriate - // TODO: Clean up match blocks + // TODO: Clean up parser_opcode!(data, 0x28); let search_pkg = parse_term_arg(&data[1..], ctx)?; @@ -830,8 +828,108 @@ fn parse_def_match(data: &[u8], let start_index = parse_term_arg(&data[3 + search_pkg.len + first_operand.len + second_operand.len..], ctx)?; + let pkg = search_pkg.val.get_as_package()?; + let mut idx = start_index.val.get_as_integer()? as usize; + + match first_operand.val { + AmlValue::Integer(i) => { + let j = second_operand.val.get_as_integer()?; + + while idx < pkg.len() { + let val = if let Ok(v) = pkg[idx].get_as_integer() { v } else { idx += 1; continue; }; + idx += 1; + + match first_operation { + MatchOpcode::MTR => (), + MatchOpcode::MEQ => if val != i { continue }, + MatchOpcode::MLE => if val > i { continue }, + MatchOpcode::MLT => if val >= i { continue }, + MatchOpcode::MGE => if val < i { continue }, + MatchOpcode::MGT => if val <= i { continue } + } + + match second_operation { + MatchOpcode::MTR => (), + MatchOpcode::MEQ => if val != i { continue }, + MatchOpcode::MLE => if val > i { continue }, + MatchOpcode::MLT => if val >= i { continue }, + MatchOpcode::MGE => if val < i { continue }, + MatchOpcode::MGT => if val <= i { continue } + } + + return Ok(AmlParseType { + val: AmlValue::Integer(idx as u64), + len: 3 + search_pkg.len + first_operand.len + second_operand.len + start_index.len + }); + } + }, + AmlValue::String(i) => { + let j = second_operand.val.get_as_string()?; + + while idx < pkg.len() { + let val = if let Ok(v) = pkg[idx].get_as_string() { v } else { idx += 1; continue; }; + idx += 1; + + match first_operation { + MatchOpcode::MTR => (), + MatchOpcode::MEQ => if val != i { continue }, + MatchOpcode::MLE => if val > i { continue }, + MatchOpcode::MLT => if val >= i { continue }, + MatchOpcode::MGE => if val < i { continue }, + MatchOpcode::MGT => if val <= i { continue } + } + + match second_operation { + MatchOpcode::MTR => (), + MatchOpcode::MEQ => if val != i { continue }, + MatchOpcode::MLE => if val > i { continue }, + MatchOpcode::MLT => if val >= i { continue }, + MatchOpcode::MGE => if val < i { continue }, + MatchOpcode::MGT => if val <= i { continue } + } + + return Ok(AmlParseType { + val: AmlValue::Integer(idx as u64), + len: 3 + search_pkg.len + first_operand.len + second_operand.len + start_index.len + }); + } + }, + _ => { + let i = first_operand.val.get_as_buffer()?; + let j = second_operand.val.get_as_buffer()?; + + while idx < pkg.len() { + let val = if let Ok(v) = pkg[idx].get_as_buffer() { v } else { idx += 1; continue; }; + idx += 1; + + match first_operation { + MatchOpcode::MTR => (), + MatchOpcode::MEQ => if val != i { continue }, + MatchOpcode::MLE => if val > i { continue }, + MatchOpcode::MLT => if val >= i { continue }, + MatchOpcode::MGE => if val < i { continue }, + MatchOpcode::MGT => if val <= i { continue } + } + + match second_operation { + MatchOpcode::MTR => (), + MatchOpcode::MEQ => if val != i { continue }, + MatchOpcode::MLE => if val > i { continue }, + MatchOpcode::MLT => if val >= i { continue }, + MatchOpcode::MGE => if val < i { continue }, + MatchOpcode::MGT => if val <= i { continue } + } + + return Ok(AmlParseType { + val: AmlValue::Integer(idx as u64), + len: 3 + search_pkg.len + first_operand.len + second_operand.len + start_index.len + }); + } + } + } + Ok(AmlParseType { - val: AmlValue::Uninitialized, + val: AmlValue::IntegerConstant(0xFFFFFFFFFFFFFFFF), len: 3 + search_pkg.len + first_operand.len + second_operand.len + start_index.len }) } From fa24650ca7ab7ebf7d84f728b11534f1438a37e0 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Sat, 8 Jul 2017 10:20:33 +0100 Subject: [PATCH 026/113] Implemented opcodes --- src/acpi/aml/type1opcode.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/acpi/aml/type1opcode.rs b/src/acpi/aml/type1opcode.rs index 7bc9546..d494205 100644 --- a/src/acpi/aml/type1opcode.rs +++ b/src/acpi/aml/type1opcode.rs @@ -48,7 +48,6 @@ fn parse_def_break(data: &[u8], fn parse_def_breakpoint(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Implement parser_opcode!(data, 0xCC); Ok(AmlParseType { From 07cf7385e9ae73a30d81490a852bc8ec224d7c10 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Mon, 19 Jun 2017 13:33:20 +0100 Subject: [PATCH 027/113] Moved Alias to the namespace --- src/acpi/aml/mod.rs | 18 +++--------------- src/acpi/aml/namespace.rs | 15 +++++++++++++++ src/acpi/aml/namespacemodifier.rs | 6 ++++++ src/start.rs | 2 ++ 4 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/acpi/aml/mod.rs b/src/acpi/aml/mod.rs index 296317d..bc0cee9 100644 --- a/src/acpi/aml/mod.rs +++ b/src/acpi/aml/mod.rs @@ -23,7 +23,7 @@ mod type1opcode; mod type2opcode; use self::termlist::{parse_term_list, TermObj}; -pub use self::namespace::{AmlNamespace, AmlValue}; +pub use self::namespace::{get_namespace_string, AmlNamespace, AmlValue}; use self::namespace::AmlNamespaceContents; // TODO: This should be able to take parameters, and may also return multiple values @@ -42,20 +42,6 @@ pub enum AmlError { AmlParseError(&'static str) } -pub fn get_namespace_string(current: String, modifier: String) -> String { - if modifier.starts_with("\\") { - return modifier; - } - - if modifier.starts_with("^") { - // TODO - } - - let mut namespace = current.clone(); - namespace.push('.'); - namespace + &modifier -} - pub fn parse_aml_table(sdt: &'static Sdt) -> Result { let data = sdt.data(); @@ -73,6 +59,8 @@ pub fn parse_aml_table(sdt: &'static Sdt) -> Result { let mut global_namespace = AmlNamespace::new_namespace(&global_namespace_specifier); term_list.execute(&mut global_namespace, global_namespace_specifier.clone()); + println!("{:#?}", global_namespace); + Ok(global_namespace) } diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index dc3c1c8..9f7343e 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -17,6 +17,7 @@ pub enum AmlNamespaceContents { Value(AmlValue), SubNamespace(Box), Namespace(Vec), + Alias(String), OpRegion { region: RegionSpace, offset: AmlValue, @@ -223,3 +224,17 @@ impl AmlNamespace { self.push_to(scope_string, AmlNamespaceContents::Namespace(vec!())); } } + +pub fn get_namespace_string(current: String, modifier: String) -> String { + if modifier.starts_with("\\") { + return modifier; + } + + if modifier.starts_with("^") { + // TODO + } + + let mut namespace = current.clone(); + namespace.push('.'); + namespace + &modifier +} diff --git a/src/acpi/aml/namespacemodifier.rs b/src/acpi/aml/namespacemodifier.rs index 217347a..d6a003f 100644 --- a/src/acpi/aml/namespacemodifier.rs +++ b/src/acpi/aml/namespacemodifier.rs @@ -43,6 +43,12 @@ impl AmlExecutable for NamespaceModifier { namespace.push_to(local_scope_string, AmlNamespaceContents::Value(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)); + }, _ => () } diff --git a/src/start.rs b/src/start.rs index c7a6dd4..8f88204 100644 --- a/src/start.rs +++ b/src/start.rs @@ -15,6 +15,8 @@ use memory; use paging::{self, entry, Page, VirtualAddress}; use paging::mapper::MapperFlushAll; +use stop; + /// Test of zero values in BSS. static BSS_TEST_ZERO: usize = 0; /// Test of non-zero values in data. From c58aa38247a08ab7b8370ea66cb8cf8700f59324 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Mon, 19 Jun 2017 13:49:37 +0100 Subject: [PATCH 028/113] Moved DefDevice and DefThermalZone to namespace --- src/acpi/aml/namedobj.rs | 8 ++++++++ src/acpi/aml/namespace.rs | 3 ++- src/acpi/aml/termlist.rs | 19 +++++++++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index 26cca7b..aeb2637 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -163,6 +163,14 @@ impl AmlExecutable for NamedObj { namespace.push_to(local_scope_string, AmlNamespaceContents::Value( 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); + }, + NamedObj::DefThermalZone { ref name, ref obj_list } => { + let local_scope_string = get_namespace_string(scope, name.clone()); + obj_list.execute(namespace, local_scope_string); + }, _ => () } diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index 9f7343e..f869cea 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -5,6 +5,7 @@ use collections::vec::Vec; use core::str::FromStr; use super::namedobj::{ RegionSpace, FieldFlags, Method }; +use super::termlist::Object; #[derive(Debug, Clone)] pub struct AmlNamespace { @@ -38,7 +39,7 @@ pub enum AmlValue { BufferField, DDBHandle, DebugObject, - Device, + Device(Vec), Event, FieldUnit, Integer, diff --git a/src/acpi/aml/termlist.rs b/src/acpi/aml/termlist.rs index b236584..b998784 100644 --- a/src/acpi/aml/termlist.rs +++ b/src/acpi/aml/termlist.rs @@ -37,6 +37,25 @@ pub struct MethodInvocation { } +impl AmlExecutable for Vec { + fn execute(&self, namespace: &mut AmlNamespace, scope: String) -> Option { + for term in self { + term.execute(namespace, scope.clone()); + } + + None + } +} + +impl AmlExecutable for Object { + fn execute(&self, namespace: &mut AmlNamespace, scope: String) -> Option { + match *self { + Object::NamespaceModifier(ref d) => d.execute(namespace, scope), + Object::NamedObj(ref d) => d.execute(namespace, scope) + } + } +} + impl AmlExecutable for Vec { fn execute(&self, namespace: &mut AmlNamespace, scope: String) -> Option { for term in self { From 73562b3f564bac713dd6e4205a7be98c72ee4def Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Mon, 19 Jun 2017 14:12:26 +0100 Subject: [PATCH 029/113] Moved ComputationalData::String into namespace --- src/acpi/aml/dataobj.rs | 1 + src/acpi/aml/namespace.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/acpi/aml/dataobj.rs b/src/acpi/aml/dataobj.rs index 4400c8d..042b9d5 100644 --- a/src/acpi/aml/dataobj.rs +++ b/src/acpi/aml/dataobj.rs @@ -71,6 +71,7 @@ impl AmlExecutable for ComputationalData { ComputationalData::Zero => Some(AmlValue::IntegerConstant(0)), ComputationalData::One => Some(AmlValue::IntegerConstant(1)), ComputationalData::Ones => Some(AmlValue::IntegerConstant(0xFFFFFFFFFFFFFFFF)), + ComputationalData::String(ref s) => Some(AmlValue::String(s.clone())), _ => Some(AmlValue::Integer) } } diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index f869cea..3e12e55 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -49,7 +49,7 @@ pub enum AmlValue { ObjectReference, OperationRegion, Package(Vec), - String, + String(String), PowerResource, Processor, RawDataBuffer, From b4ddaeadbb8da5b1213dab2e52f5710c86f0a0cc Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Wed, 21 Jun 2017 20:02:05 +0100 Subject: [PATCH 030/113] Moved Processor to namespace, and refactored namespace layout to use BTreeMap --- src/acpi/aml/dataobj.rs | 9 +- src/acpi/aml/mod.rs | 10 +- src/acpi/aml/namedobj.rs | 42 ++++-- src/acpi/aml/namespace.rs | 214 ++++-------------------------- src/acpi/aml/namespacemodifier.rs | 13 +- src/acpi/aml/termlist.rs | 13 +- src/acpi/aml/type1opcode.rs | 5 +- src/acpi/aml/type2opcode.rs | 7 +- src/acpi/mod.rs | 6 +- src/stop.rs | 2 +- 10 files changed, 96 insertions(+), 225 deletions(-) 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"); From e52d4c98a36bb73f9e194cad584ac2b338915e05 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Wed, 21 Jun 2017 20:13:44 +0100 Subject: [PATCH 031/113] Moved PowerResource into namespace --- src/acpi/aml/namedobj.rs | 12 ++++++++++++ src/acpi/aml/namespace.rs | 6 +++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index 8a9f978..8589d6f 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -193,6 +193,18 @@ impl AmlExecutable for NamedObj { obj_list: local_namespace }); }, + NamedObj::DefPowerRes { ref name, system_level, resource_order, 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::PowerResource { + system_level, + resource_order, + obj_list: local_namespace + }); + }, _ => () } diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index fc801fc..5d725da 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -36,7 +36,11 @@ pub enum AmlValue { }, Package(Vec), String(String), - PowerResource, + PowerResource { + system_level: u8, + resource_order: u16, + obj_list: BTreeMap + }, Processor { proc_id: u8, p_blk: Option, From 9575c6fed3526f825a45f1f150fdb3c643456454 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Wed, 21 Jun 2017 20:27:46 +0100 Subject: [PATCH 032/113] Moved Mutex to namespace --- src/acpi/aml/namedobj.rs | 4 ++++ src/acpi/aml/namespace.rs | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index 8589d6f..4fdd8f6 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -205,6 +205,10 @@ impl AmlExecutable for NamedObj { obj_list: local_namespace }); }, + NamedObj::DefMutex { ref name, sync_level } => { + let local_scope_string = get_namespace_string(scope, name.clone()); + namespace.insert(local_scope_string, AmlValue::Mutex(sync_level)); + }, _ => () } diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index 5d725da..ab49846 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -27,7 +27,7 @@ pub enum AmlValue { Integer, IntegerConstant(u64), Method(Method), - Mutex, + Mutex(u8), ObjectReference(SuperName), OperationRegion { region: RegionSpace, From 94b0e7de37bc9cef9e265cc751ed47c5813cbcfa Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Wed, 21 Jun 2017 20:50:08 +0100 Subject: [PATCH 033/113] Moved Event to namespace --- src/acpi/aml/.#namedobj.rs | 1 + src/acpi/aml/namedobj.rs | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 120000 src/acpi/aml/.#namedobj.rs diff --git a/src/acpi/aml/.#namedobj.rs b/src/acpi/aml/.#namedobj.rs new file mode 120000 index 0000000..66a0d21 --- /dev/null +++ b/src/acpi/aml/.#namedobj.rs @@ -0,0 +1 @@ +venos@Maponos.11470:1498034251 \ No newline at end of file diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index 4fdd8f6..24b6256 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -209,7 +209,11 @@ impl AmlExecutable for NamedObj { let local_scope_string = get_namespace_string(scope, name.clone()); namespace.insert(local_scope_string, AmlValue::Mutex(sync_level)); }, - _ => () + NamedObj::DefEvent { ref name } => { + let local_scope_string = get_namespace_string(scope, name.clone()); + namespace.insert(local_scope_string, AmlValue::Event); + }, +// _ => () } None From 61776f7af8918ecd6a467dee7da767c2cc1f0721 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Wed, 21 Jun 2017 20:54:29 +0100 Subject: [PATCH 034/113] Removed temporary files --- src/acpi/aml/.#namedobj.rs | 1 - src/acpi/aml/namedobj.rs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) delete mode 120000 src/acpi/aml/.#namedobj.rs diff --git a/src/acpi/aml/.#namedobj.rs b/src/acpi/aml/.#namedobj.rs deleted file mode 120000 index 66a0d21..0000000 --- a/src/acpi/aml/.#namedobj.rs +++ /dev/null @@ -1 +0,0 @@ -venos@Maponos.11470:1498034251 \ No newline at end of file diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index 24b6256..87c5bc7 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -213,7 +213,7 @@ impl AmlExecutable for NamedObj { let local_scope_string = get_namespace_string(scope, name.clone()); namespace.insert(local_scope_string, AmlValue::Event); }, -// _ => () + _ => () } None From 9ae9e3b19012c9aceee7360415fed11226bae7dd Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Thu, 22 Jun 2017 12:02:17 +0100 Subject: [PATCH 035/113] Moved BankField to the namespace --- src/acpi/aml/namedobj.rs | 29 +++++++++++++++++++++++++++++ src/acpi/aml/namespace.rs | 1 + 2 files changed, 30 insertions(+) diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index 87c5bc7..203d20a 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -120,6 +120,34 @@ pub struct Method { impl AmlExecutable for NamedObj { fn execute(&self, namespace: &mut BTreeMap, scope: String) -> Option { match *self { + NamedObj::DefBankField { ref region_name, ref bank_name, ref bank_value, ref flags, ref field_list } => { + let mut offset: usize = 0; + let bank_val = if let Some(b) = bank_value.execute(namespace, scope.clone()) { + Box::new(b) + } else { + return None; + }; + + for f in field_list { + match *f { + FieldElement::ReservedField { length } => offset += length, + FieldElement::NamedField { name: ref field_name, length } => { + let local_scope_string = get_namespace_string(scope.clone(), + field_name.clone()); + namespace.insert(local_scope_string, AmlValue::FieldUnit { + op_region: region_name.clone(), + bank_selector: Some((bank_name.clone(), bank_val.clone())), + flags: flags.clone(), + offset: offset.clone(), + length: length.clone() + }); + + offset += length; + }, + _ => () + } + } + }, NamedObj::DefOpRegion { ref name, ref region, ref offset, ref len } => { let local_scope_string = get_namespace_string(scope.clone(), name.clone()); @@ -150,6 +178,7 @@ impl AmlExecutable for NamedObj { field_name.clone()); namespace.insert(local_scope_string, AmlValue::FieldUnit { op_region: name.clone(), + bank_selector: None, flags: flags.clone(), offset: offset.clone(), length: length.clone() diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index ab49846..0e99aaf 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -20,6 +20,7 @@ pub enum AmlValue { Event, FieldUnit { op_region: String, + bank_selector: Option<(String, Box)>, flags: FieldFlags, offset: usize, length: usize From f2876389964265599f92bde947c1162331e57d78 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Thu, 22 Jun 2017 12:16:30 +0100 Subject: [PATCH 036/113] Moved BufferFields into namespace --- src/acpi/aml/namedobj.rs | 90 +++++++++++++++++++++++++++++++++++++++ src/acpi/aml/namespace.rs | 6 ++- 2 files changed, 95 insertions(+), 1 deletion(-) diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index 203d20a..1123535 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -148,6 +148,96 @@ impl AmlExecutable for NamedObj { } } }, + NamedObj::DefCreateBitField { ref name, ref source_buf, ref bit_index } => { + let local_scope_string = get_namespace_string(scope.clone(), name.clone()); + + let resolved_source_buf = match source_buf.execute(namespace, scope.clone()) { + Some(r) => Box::new(r), + _ => return None + }; + let resolved_index = match bit_index.execute(namespace, scope.clone()) { + Some(r) => Box::new(r), + _ => return None + }; + + namespace.insert(local_scope_string, AmlValue::BufferField { + source_buf: resolved_source_buf, + index: resolved_index, + length: 1 + }); + }, + NamedObj::DefCreateByteField { ref name, ref source_buf, ref byte_index } => { + let local_scope_string = get_namespace_string(scope.clone(), name.clone()); + + let resolved_source_buf = match source_buf.execute(namespace, scope.clone()) { + Some(r) => Box::new(r), + _ => return None + }; + let resolved_index = match byte_index.execute(namespace, scope.clone()) { + Some(r) => Box::new(r), + _ => return None + }; + + namespace.insert(local_scope_string, AmlValue::BufferField { + source_buf: resolved_source_buf, + index: resolved_index, + length: 8 + }); + }, + NamedObj::DefCreateWordField { ref name, ref source_buf, ref byte_index } => { + let local_scope_string = get_namespace_string(scope.clone(), name.clone()); + + let resolved_source_buf = match source_buf.execute(namespace, scope.clone()) { + Some(r) => Box::new(r), + _ => return None + }; + let resolved_index = match byte_index.execute(namespace, scope.clone()) { + Some(r) => Box::new(r), + _ => return None + }; + + namespace.insert(local_scope_string, AmlValue::BufferField { + source_buf: resolved_source_buf, + index: resolved_index, + length: 16 + }); + }, + NamedObj::DefCreateDWordField { ref name, ref source_buf, ref byte_index } => { + let local_scope_string = get_namespace_string(scope.clone(), name.clone()); + + let resolved_source_buf = match source_buf.execute(namespace, scope.clone()) { + Some(r) => Box::new(r), + _ => return None + }; + let resolved_index = match byte_index.execute(namespace, scope.clone()) { + Some(r) => Box::new(r), + _ => return None + }; + + namespace.insert(local_scope_string, AmlValue::BufferField { + source_buf: resolved_source_buf, + index: resolved_index, + length: 32 + }); + }, + NamedObj::DefCreateQWordField { ref name, ref source_buf, ref byte_index } => { + let local_scope_string = get_namespace_string(scope.clone(), name.clone()); + + let resolved_source_buf = match source_buf.execute(namespace, scope.clone()) { + Some(r) => Box::new(r), + _ => return None + }; + let resolved_index = match byte_index.execute(namespace, scope.clone()) { + Some(r) => Box::new(r), + _ => return None + }; + + namespace.insert(local_scope_string, AmlValue::BufferField { + source_buf: resolved_source_buf, + index: resolved_index, + length: 64 + }); + }, NamedObj::DefOpRegion { ref name, ref region, ref offset, ref len } => { let local_scope_string = get_namespace_string(scope.clone(), name.clone()); diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index 0e99aaf..f95a25a 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -13,7 +13,11 @@ use super::namestring::SuperName; pub enum AmlValue { Uninitialized, Buffer, - BufferField, + BufferField { + source_buf: Box, + index: Box, + length: usize + }, DDBHandle, DebugObject, Device(BTreeMap), From 79118539513c12ecceccd113afad75cc9205e029 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Thu, 22 Jun 2017 12:23:14 +0100 Subject: [PATCH 037/113] Moved arbitrary length buffer field into namespace --- src/acpi/aml/namedobj.rs | 32 +++++++++++++++++++++++++++----- src/acpi/aml/namespace.rs | 2 +- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index 1123535..dc206a1 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -163,7 +163,7 @@ impl AmlExecutable for NamedObj { namespace.insert(local_scope_string, AmlValue::BufferField { source_buf: resolved_source_buf, index: resolved_index, - length: 1 + length: Box::new(AmlValue::IntegerConstant(1)) }); }, NamedObj::DefCreateByteField { ref name, ref source_buf, ref byte_index } => { @@ -181,7 +181,7 @@ impl AmlExecutable for NamedObj { namespace.insert(local_scope_string, AmlValue::BufferField { source_buf: resolved_source_buf, index: resolved_index, - length: 8 + length: Box::new(AmlValue::IntegerConstant(8)) }); }, NamedObj::DefCreateWordField { ref name, ref source_buf, ref byte_index } => { @@ -199,7 +199,7 @@ impl AmlExecutable for NamedObj { namespace.insert(local_scope_string, AmlValue::BufferField { source_buf: resolved_source_buf, index: resolved_index, - length: 16 + length: Box::new(AmlValue::IntegerConstant(16)) }); }, NamedObj::DefCreateDWordField { ref name, ref source_buf, ref byte_index } => { @@ -217,7 +217,7 @@ impl AmlExecutable for NamedObj { namespace.insert(local_scope_string, AmlValue::BufferField { source_buf: resolved_source_buf, index: resolved_index, - length: 32 + length: Box::new(AmlValue::IntegerConstant(32)) }); }, NamedObj::DefCreateQWordField { ref name, ref source_buf, ref byte_index } => { @@ -235,7 +235,29 @@ impl AmlExecutable for NamedObj { namespace.insert(local_scope_string, AmlValue::BufferField { source_buf: resolved_source_buf, index: resolved_index, - length: 64 + length: Box::new(AmlValue::IntegerConstant(64)) + }); + }, + NamedObj::DefCreateField { ref name, ref source_buf, ref bit_index, ref num_bits } => { + let local_scope_string = get_namespace_string(scope.clone(), name.clone()); + + let resolved_source_buf = match source_buf.execute(namespace, scope.clone()) { + Some(r) => Box::new(r), + _ => return None + }; + let resolved_index = match bit_index.execute(namespace, scope.clone()) { + Some(r) => Box::new(r), + _ => return None + }; + let resolved_length = match num_bits.execute(namespace, scope.clone()) { + Some(r) => Box::new(r), + _ => return None + }; + + namespace.insert(local_scope_string, AmlValue::BufferField { + source_buf: resolved_source_buf, + index: resolved_index, + length: resolved_length }); }, NamedObj::DefOpRegion { ref name, ref region, ref offset, ref len } => { diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index f95a25a..f52206f 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -16,7 +16,7 @@ pub enum AmlValue { BufferField { source_buf: Box, index: Box, - length: usize + length: Box }, DDBHandle, DebugObject, From 94b8bd19d666a9e65992b5d40075004422fb251c Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Thu, 22 Jun 2017 12:45:58 +0100 Subject: [PATCH 038/113] Moved indexfield to namespace --- src/acpi/aml/namedobj.rs | 35 +++++++++++++++++++++++++++++++---- src/acpi/aml/namespace.rs | 16 ++++++++++++++-- 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index dc206a1..0a21504 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -6,6 +6,7 @@ use core::str::FromStr; use collections::btree_map::BTreeMap; use super::{AmlInternalError, AmlExecutable, AmlValue, get_namespace_string}; +use super::namespace::FieldSelector; 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; @@ -135,8 +136,35 @@ impl AmlExecutable for NamedObj { let local_scope_string = get_namespace_string(scope.clone(), field_name.clone()); namespace.insert(local_scope_string, AmlValue::FieldUnit { - op_region: region_name.clone(), - bank_selector: Some((bank_name.clone(), bank_val.clone())), + selector: FieldSelector::Bank { + region: region_name.clone(), + bank_selector: bank_val.clone() + }, + flags: flags.clone(), + offset: offset.clone(), + length: length.clone() + }); + + offset += length; + }, + _ => () + } + } + }, + NamedObj::DefIndexField { ref idx_name, ref data_name, ref flags, ref field_list } => { + let mut offset: usize = 0; + + for f in field_list { + match *f { + FieldElement::ReservedField { length } => offset += length, + FieldElement::NamedField { name: ref field_name, length } => { + let local_scope_string = get_namespace_string(scope.clone(), + field_name.clone()); + namespace.insert(local_scope_string, AmlValue::FieldUnit { + selector: FieldSelector::Index { + index_selector: idx_name.clone(), + data_selector: data_name.clone() + }, flags: flags.clone(), offset: offset.clone(), length: length.clone() @@ -289,8 +317,7 @@ impl AmlExecutable for NamedObj { let local_scope_string = get_namespace_string(scope.clone(), field_name.clone()); namespace.insert(local_scope_string, AmlValue::FieldUnit { - op_region: name.clone(), - bank_selector: None, + selector: FieldSelector::Region(name.clone()), flags: flags.clone(), offset: offset.clone(), length: length.clone() diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index f52206f..7d16ec0 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -9,6 +9,19 @@ use super::namedobj::{ RegionSpace, FieldFlags, Method }; use super::termlist::Object; use super::namestring::SuperName; +#[derive(Debug, Clone)] +pub enum FieldSelector { + Region(String), + Bank { + region: String, + bank_selector: Box + }, + Index { + index_selector: String, + data_selector: String + } +} + #[derive(Debug, Clone)] pub enum AmlValue { Uninitialized, @@ -23,8 +36,7 @@ pub enum AmlValue { Device(BTreeMap), Event, FieldUnit { - op_region: String, - bank_selector: Option<(String, Box)>, + selector: FieldSelector, flags: FieldFlags, offset: usize, length: usize From ee012a482b345b50c046d6b67e0aba63f551be0f Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Thu, 22 Jun 2017 13:34:05 +0100 Subject: [PATCH 039/113] Moved DataRegion into namespace - more infrastructure required --- src/acpi/aml/namedobj.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index 0a21504..7b40db4 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -288,6 +288,15 @@ impl AmlExecutable for NamedObj { length: resolved_length }); }, + NamedObj::DefDataRegion { ref name, ref signature, ref oem_id, ref oem_table_id } => { + let local_scope_string = get_namespace_string(scope.clone(), name.clone()); + + namespace.insert(local_scope_string, AmlValue::OperationRegion { + region: RegionSpace::SystemMemory, + offset: Box::new(AmlValue::IntegerConstant(0)), + len: Box::new(AmlValue::IntegerConstant(0)) + }); + }, NamedObj::DefOpRegion { ref name, ref region, ref offset, ref len } => { let local_scope_string = get_namespace_string(scope.clone(), name.clone()); From 1babfb4b329f335eb88d83a62c8f7136351f4570 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Thu, 22 Jun 2017 15:09:04 +0100 Subject: [PATCH 040/113] Moved ConnectFieldNameString into namespace --- src/acpi/aml/namedobj.rs | 14 +++++++++++++- src/acpi/aml/namespace.rs | 1 + 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index 7b40db4..40de06f 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -7,7 +7,7 @@ use collections::btree_map::BTreeMap; use super::{AmlInternalError, AmlExecutable, AmlValue, get_namespace_string}; use super::namespace::FieldSelector; -use super::namestring::{parse_name_string, parse_name_seg}; +use super::namestring::{parse_name_string, parse_name_seg, SuperName}; use super::termlist::{parse_term_arg, parse_term_list, parse_object_list, TermArg, TermObj, Object}; use super::pkglength::parse_pkg_length; use super::type2opcode::{parse_def_buffer, DefBuffer}; @@ -123,6 +123,7 @@ impl AmlExecutable for NamedObj { match *self { NamedObj::DefBankField { ref region_name, ref bank_name, ref bank_value, ref flags, ref field_list } => { let mut offset: usize = 0; + let mut connection = AmlValue::Uninitialized; let bank_val = if let Some(b) = bank_value.execute(namespace, scope.clone()) { Box::new(b) } else { @@ -132,6 +133,8 @@ impl AmlExecutable for NamedObj { for f in field_list { match *f { FieldElement::ReservedField { length } => offset += length, + FieldElement::ConnectFieldNameString(ref name) => connection = + AmlValue::ObjectReference(SuperName::NameString(name.clone())), FieldElement::NamedField { name: ref field_name, length } => { let local_scope_string = get_namespace_string(scope.clone(), field_name.clone()); @@ -140,6 +143,7 @@ impl AmlExecutable for NamedObj { region: region_name.clone(), bank_selector: bank_val.clone() }, + connection: Box::new(connection.clone()), flags: flags.clone(), offset: offset.clone(), length: length.clone() @@ -153,10 +157,13 @@ impl AmlExecutable for NamedObj { }, NamedObj::DefIndexField { ref idx_name, ref data_name, ref flags, ref field_list } => { let mut offset: usize = 0; + let mut connection = AmlValue::Uninitialized; for f in field_list { match *f { FieldElement::ReservedField { length } => offset += length, + FieldElement::ConnectFieldNameString(ref name) => connection = + AmlValue::ObjectReference(SuperName::NameString(name.clone())), FieldElement::NamedField { name: ref field_name, length } => { let local_scope_string = get_namespace_string(scope.clone(), field_name.clone()); @@ -165,6 +172,7 @@ impl AmlExecutable for NamedObj { index_selector: idx_name.clone(), data_selector: data_name.clone() }, + connection: Box::new(connection.clone()), flags: flags.clone(), offset: offset.clone(), length: length.clone() @@ -318,15 +326,19 @@ impl AmlExecutable for NamedObj { }, NamedObj::DefField { ref name, ref flags, ref field_list } => { let mut offset: usize = 0; + let mut connection = AmlValue::Uninitialized; for f in field_list { match *f { FieldElement::ReservedField { length } => offset += length, + FieldElement::ConnectFieldNameString(ref name) => connection = + AmlValue::ObjectReference(SuperName::NameString(name.clone())), FieldElement::NamedField { name: ref field_name, length } => { let local_scope_string = get_namespace_string(scope.clone(), field_name.clone()); namespace.insert(local_scope_string, AmlValue::FieldUnit { selector: FieldSelector::Region(name.clone()), + connection: Box::new(connection.clone()), flags: flags.clone(), offset: offset.clone(), length: length.clone() diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index 7d16ec0..375057e 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -37,6 +37,7 @@ pub enum AmlValue { Event, FieldUnit { selector: FieldSelector, + connection: Box, flags: FieldFlags, offset: usize, length: usize From 82124a59d5cc8bf4b14429403b6e5ac4ab31b5cc Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Thu, 22 Jun 2017 15:22:19 +0100 Subject: [PATCH 041/113] Moved ConnectFieldBufferData to the namespace --- src/acpi/aml/namedobj.rs | 18 ++++++++++++++++++ src/acpi/aml/namespace.rs | 5 ++++- src/acpi/aml/type2opcode.rs | 19 +++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index 40de06f..664b767 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -135,6 +135,12 @@ impl AmlExecutable for NamedObj { FieldElement::ReservedField { length } => offset += length, FieldElement::ConnectFieldNameString(ref name) => connection = AmlValue::ObjectReference(SuperName::NameString(name.clone())), + FieldElement::ConnectFieldBufferData(ref buf) => { + connection = match buf.execute(namespace, scope.clone()) { + Some(c) => c, + None => return None + }; + }, FieldElement::NamedField { name: ref field_name, length } => { let local_scope_string = get_namespace_string(scope.clone(), field_name.clone()); @@ -164,6 +170,12 @@ impl AmlExecutable for NamedObj { FieldElement::ReservedField { length } => offset += length, FieldElement::ConnectFieldNameString(ref name) => connection = AmlValue::ObjectReference(SuperName::NameString(name.clone())), + FieldElement::ConnectFieldBufferData(ref buf) => { + connection = match buf.execute(namespace, scope.clone()) { + Some(c) => c, + None => return None + }; + }, FieldElement::NamedField { name: ref field_name, length } => { let local_scope_string = get_namespace_string(scope.clone(), field_name.clone()); @@ -333,6 +345,12 @@ impl AmlExecutable for NamedObj { FieldElement::ReservedField { length } => offset += length, FieldElement::ConnectFieldNameString(ref name) => connection = AmlValue::ObjectReference(SuperName::NameString(name.clone())), + FieldElement::ConnectFieldBufferData(ref buf) => { + connection = match buf.execute(namespace, scope.clone()) { + Some(c) => c, + None => return None + }; + }, FieldElement::NamedField { name: ref field_name, length } => { let local_scope_string = get_namespace_string(scope.clone(), field_name.clone()); diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index 375057e..a492aab 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -25,7 +25,10 @@ pub enum FieldSelector { #[derive(Debug, Clone)] pub enum AmlValue { Uninitialized, - Buffer, + Buffer { + length: Box, + byte_list: Vec + }, BufferField { source_buf: Box, index: Box, diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index 0313d82..e96bdbc 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -207,6 +207,25 @@ impl AmlExecutable for Type2OpCode { } } +impl AmlExecutable for DefBuffer { + fn execute(&self, namespace: &mut BTreeMap, scope: String) -> Option { + match *self { + DefBuffer::Buffer { ref buffer_size, ref byte_list } => { + let length = match buffer_size.execute(namespace, scope.clone()) { + Some(l) => Box::new(l), + _ => return None + }; + + Some(AmlValue::Buffer { + length: length, + byte_list: byte_list.clone() + }) + }, + _ => None + } + } +} + #[derive(Debug, Clone)] pub enum DefObjectType { SuperName(SuperName), From a79e275cc006a00dbb13c825195f67afabfad031 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Thu, 22 Jun 2017 15:43:00 +0100 Subject: [PATCH 042/113] Moved AccessType into namespace --- src/acpi/aml/namedobj.rs | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index 664b767..66af6d6 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -124,6 +124,7 @@ impl AmlExecutable for NamedObj { NamedObj::DefBankField { ref region_name, ref bank_name, ref bank_value, ref flags, ref field_list } => { let mut offset: usize = 0; let mut connection = AmlValue::Uninitialized; + let mut flags = flags.clone(); let bank_val = if let Some(b) = bank_value.execute(namespace, scope.clone()) { Box::new(b) } else { @@ -141,6 +142,12 @@ impl AmlExecutable for NamedObj { None => return None }; }, + FieldElement::AccessField { ref access_type, ref access_attrib } => { + match *access_type { + AccessType::BufferAcc(_) => flags.access_type = AccessType::BufferAcc(access_attrib.clone()), + ref a => flags.access_type = a.clone() + } + }, FieldElement::NamedField { name: ref field_name, length } => { let local_scope_string = get_namespace_string(scope.clone(), field_name.clone()); @@ -157,13 +164,13 @@ impl AmlExecutable for NamedObj { offset += length; }, - _ => () } } }, NamedObj::DefIndexField { ref idx_name, ref data_name, ref flags, ref field_list } => { let mut offset: usize = 0; let mut connection = AmlValue::Uninitialized; + let mut flags = flags.clone(); for f in field_list { match *f { @@ -176,6 +183,12 @@ impl AmlExecutable for NamedObj { None => return None }; }, + FieldElement::AccessField { ref access_type, ref access_attrib } => { + match *access_type { + AccessType::BufferAcc(_) => flags.access_type = AccessType::BufferAcc(access_attrib.clone()), + ref a => flags.access_type = a.clone() + } + }, FieldElement::NamedField { name: ref field_name, length } => { let local_scope_string = get_namespace_string(scope.clone(), field_name.clone()); @@ -191,8 +204,7 @@ impl AmlExecutable for NamedObj { }); offset += length; - }, - _ => () + } } } }, @@ -339,6 +351,7 @@ impl AmlExecutable for NamedObj { NamedObj::DefField { ref name, ref flags, ref field_list } => { let mut offset: usize = 0; let mut connection = AmlValue::Uninitialized; + let mut flags = flags.clone(); for f in field_list { match *f { @@ -351,6 +364,12 @@ impl AmlExecutable for NamedObj { None => return None }; }, + FieldElement::AccessField { ref access_type, ref access_attrib } => { + match *access_type { + AccessType::BufferAcc(_) => flags.access_type = AccessType::BufferAcc(access_attrib.clone()), + ref a => flags.access_type = a.clone() + } + }, FieldElement::NamedField { name: ref field_name, length } => { let local_scope_string = get_namespace_string(scope.clone(), field_name.clone()); @@ -363,8 +382,7 @@ impl AmlExecutable for NamedObj { }); offset += length; - }, - _ => () + } } } }, @@ -456,7 +474,7 @@ pub enum AccessType { WordAcc, DWordAcc, QWordAcc, - BufferAcc + BufferAcc(AccessAttrib) } #[derive(Debug, Clone)] @@ -559,7 +577,7 @@ fn parse_def_bank_field(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalErr 2 => AccessType::WordAcc, 3 => AccessType::DWordAcc, 4 => AccessType::QWordAcc, - 5 => AccessType::BufferAcc, + 5 => AccessType::BufferAcc(AccessAttrib::AttribByte), _ => return Err(AmlInternalError::AmlParseError("BankField - invalid access type")) }, lock_rule: (flags_raw & 0x10) == 0x10, @@ -738,7 +756,7 @@ fn parse_def_field(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> { 2 => AccessType::WordAcc, 3 => AccessType::DWordAcc, 4 => AccessType::QWordAcc, - 5 => AccessType::BufferAcc, + 5 => AccessType::BufferAcc(AccessAttrib::AttribByte), _ => return Err(AmlInternalError::AmlParseError("Field - Invalid access type")) }, lock_rule: (flags_raw & 0x10) == 0x10, @@ -788,7 +806,7 @@ fn parse_def_index_field(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalEr 2 => AccessType::WordAcc, 3 => AccessType::DWordAcc, 4 => AccessType::QWordAcc, - 5 => AccessType::BufferAcc, + 5 => AccessType::BufferAcc(AccessAttrib::AttribByte), _ => return Err(AmlInternalError::AmlParseError("IndexField - Invalid access type")) }, lock_rule: (flags_raw & 0x10) == 0x10, @@ -870,7 +888,7 @@ fn parse_access_field(data: &[u8]) -> Result<(FieldElement, usize), AmlInternalE 2 => AccessType::WordAcc, 3 => AccessType::DWordAcc, 4 => AccessType::QWordAcc, - 5 => AccessType::BufferAcc, + 5 => AccessType::BufferAcc(AccessAttrib::AttribByte), _ => return Err(AmlInternalError::AmlParseError("AccessField - Invalid access type")) }; From 21c9d824cc7d2be106abdb3ecea6384214d4f529 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Thu, 22 Jun 2017 16:25:19 +0100 Subject: [PATCH 043/113] Finalized ACPIType --- src/acpi/aml/dataobj.rs | 6 +++--- src/acpi/aml/namespace.rs | 7 ++++--- src/acpi/aml/termlist.rs | 6 +++--- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/acpi/aml/dataobj.rs b/src/acpi/aml/dataobj.rs index 885396a..27f81f8 100644 --- a/src/acpi/aml/dataobj.rs +++ b/src/acpi/aml/dataobj.rs @@ -47,7 +47,7 @@ impl AmlExecutable for DataRefObj { fn execute(&self, namespace: &mut BTreeMap, scope: String) -> Option { match *self { DataRefObj::DataObj(ref cd) => cd.execute(namespace, scope), - _ => Some(AmlValue::Integer) + _ => Some(AmlValue::Uninitialized) } } } @@ -57,7 +57,7 @@ impl AmlExecutable for DataObj { match *self { DataObj::ComputationalData(ref cd) => cd.execute(namespace, scope), DataObj::DefPackage(ref pkg) => pkg.execute(namespace, scope), - _ => Some(AmlValue::Integer) + _ => Some(AmlValue::Uninitialized) } } } @@ -73,7 +73,7 @@ impl AmlExecutable for ComputationalData { ComputationalData::One => Some(AmlValue::IntegerConstant(1)), ComputationalData::Ones => Some(AmlValue::IntegerConstant(0xFFFFFFFFFFFFFFFF)), ComputationalData::String(ref s) => Some(AmlValue::String(s.clone())), - _ => Some(AmlValue::Integer) + _ => Some(AmlValue::Uninitialized) } } } diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index a492aab..be49f7b 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -8,6 +8,7 @@ use core::str::FromStr; use super::namedobj::{ RegionSpace, FieldFlags, Method }; use super::termlist::Object; use super::namestring::SuperName; +use super::type2opcode::Type2OpCode; #[derive(Debug, Clone)] pub enum FieldSelector { @@ -34,7 +35,7 @@ pub enum AmlValue { index: Box, length: Box }, - DDBHandle, + DDBHandle(u32), // Index into the XSDT DebugObject, Device(BTreeMap), Event, @@ -45,7 +46,7 @@ pub enum AmlValue { offset: usize, length: usize }, - Integer, + Integer(Type2OpCode), IntegerConstant(u64), Method(Method), Mutex(u8), @@ -67,7 +68,7 @@ pub enum AmlValue { p_blk: Option, obj_list: BTreeMap }, - RawDataBuffer, + RawDataBuffer(Vec), ThermalZone(BTreeMap) } diff --git a/src/acpi/aml/termlist.rs b/src/acpi/aml/termlist.rs index 72d876d..c7d0c5f 100644 --- a/src/acpi/aml/termlist.rs +++ b/src/acpi/aml/termlist.rs @@ -70,10 +70,10 @@ impl AmlExecutable for Vec { impl AmlExecutable for TermArg { fn execute(&self, namespace: &mut BTreeMap, scope: String) -> Option { match *self { - TermArg::LocalObj(ref l) => Some(AmlValue::Integer), + TermArg::LocalObj(ref l) => Some(AmlValue::Uninitialized), TermArg::DataObj(ref d) => d.execute(namespace, scope), - TermArg::ArgObj(ref a) => Some(AmlValue::Integer), - TermArg::Type2Opcode(ref o) => Some(AmlValue::Integer) + TermArg::ArgObj(ref a) => Some(AmlValue::Uninitialized), + TermArg::Type2Opcode(ref o) => Some(AmlValue::Uninitialized) } } } From 5213d59237b3b41e2e7156d410ee64b2f6f75622 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Thu, 22 Jun 2017 19:12:40 +0100 Subject: [PATCH 044/113] Namespaces can now be concatenated, handling of SSDTs is now performed --- src/acpi/aml/mod.rs | 4 +--- src/acpi/mod.rs | 13 ++++++++++--- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/acpi/aml/mod.rs b/src/acpi/aml/mod.rs index a50ec4c..7ad0473 100644 --- a/src/acpi/aml/mod.rs +++ b/src/acpi/aml/mod.rs @@ -59,13 +59,11 @@ pub fn parse_aml_table(sdt: &'static Sdt) -> Result, let mut global_namespace = BTreeMap::new(); term_list.execute(&mut global_namespace, global_namespace_specifier.clone()); - println!("{:#?}", global_namespace); - Ok(global_namespace) } pub fn is_aml_table(sdt: &'static Sdt) -> bool { - if &sdt.signature == b"DSDT" {//|| &sdt.signature == b"SSDT" { + if &sdt.signature == b"DSDT" || &sdt.signature == b"SSDT" { true } else { false diff --git a/src/acpi/mod.rs b/src/acpi/mod.rs index 9b07703..cb06f84 100644 --- a/src/acpi/mod.rs +++ b/src/acpi/mod.rs @@ -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 spin::Mutex; @@ -203,14 +204,20 @@ fn parse_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) { println!(": {}", hpet.hpet_number); ACPI_TABLE.lock().hpet = Some(hpet); } else if is_aml_table(sdt) { - ACPI_TABLE.lock().namespace = match parse_aml_table(sdt) { + match parse_aml_table(sdt) { Ok(res) => { println!(": Parsed"); - Some(res) + let ref mut namespace = ACPI_TABLE.lock().namespace; + + if let Some(ref mut ns) = *namespace { + let mut res = res.clone(); + ns.append(&mut res); + } else { + *namespace = Some(res); + } }, Err(AmlError::AmlParseError(e)) => { println!(": {}", e); - None } }; } else { From f131cc6f1f5bb888ff627443df2d4b9c66c44346 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Fri, 23 Jun 2017 14:02:40 +0100 Subject: [PATCH 045/113] Rolled parsing and execution steps into one for namespace modifiers --- src/acpi/aml/mod.rs | 10 +-- src/acpi/aml/namespacemodifier.rs | 119 +++++++++++------------------- src/acpi/aml/parser.rs | 16 ++++ src/acpi/aml/parsermacros.rs | 21 ++++-- src/acpi/aml/termlist.rs | 27 ++++--- 5 files changed, 95 insertions(+), 98 deletions(-) create mode 100644 src/acpi/aml/parser.rs diff --git a/src/acpi/aml/mod.rs b/src/acpi/aml/mod.rs index 7ad0473..a6d5a35 100644 --- a/src/acpi/aml/mod.rs +++ b/src/acpi/aml/mod.rs @@ -22,22 +22,16 @@ mod namedobj; mod dataobj; mod type1opcode; mod type2opcode; +mod parser; +use self::parser::{ParseResult, AmlInternalError}; use self::termlist::{parse_term_list, TermObj}; 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 BTreeMap, scope: String) -> Option; } -// TODO: make private -pub enum AmlInternalError { - AmlParseError(&'static str), - AmlInvalidOpCode, - AmlDeferredLoad -} - pub enum AmlError { AmlParseError(&'static str) } diff --git a/src/acpi/aml/namespacemodifier.rs b/src/acpi/aml/namespacemodifier.rs index c1e2395..8e7e2cc 100644 --- a/src/acpi/aml/namespacemodifier.rs +++ b/src/acpi/aml/namespacemodifier.rs @@ -9,55 +9,11 @@ use super::namestring::{parse_name_string, SuperName}; use super::termlist::{parse_term_list, TermObj}; use super::dataobj::{parse_data_ref_obj, DataRefObj}; -#[derive(Debug, Clone)] -pub enum NamespaceModifier { - Name { - name: String, - data_ref_obj: DataRefObj - }, - Scope { - name: String, - terms: Vec - }, - Alias { - source_name: String, - alias_name: String - }, - DeferredLoad(Vec) -} - -impl AmlExecutable for NamespaceModifier { - 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()); - terms.execute(namespace, local_scope_string); - }, - NamespaceModifier::Name { ref name, ref data_ref_obj } => { - let local_scope_string = get_namespace_string(scope.clone(), name.clone()); - let dro = match data_ref_obj.execute(namespace, scope) { - Some(s) => s, - None => return None - }; - - 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.insert(local_scope_string, AmlValue::ObjectReference(SuperName::NameString(local_alias_string))); - }, - _ => () - } - - None - } -} - -pub fn parse_namespace_modifier(data: &[u8]) -> Result<(NamespaceModifier, usize), AmlInternalError> { +pub fn parse_namespace_modifier(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_selector! { - data, + data, namespace, scope, parse_alias_op, parse_scope_op, parse_name_op @@ -66,42 +22,57 @@ pub fn parse_namespace_modifier(data: &[u8]) -> Result<(NamespaceModifier, usize Err(AmlInternalError::AmlInvalidOpCode) } -fn parse_alias_op(data: &[u8]) -> Result<(NamespaceModifier, usize), AmlInternalError> { +fn parse_alias_op(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode!(data, 0x06); - let (source_name, source_name_len) = parse_name_string(&data[1..])?; - let (alias_name, alias_name_len) = parse_name_string(&data[1 + source_name_len..])?; + let source_name = parse_name_string(&data[1..], namespace, scope)?; + let alias_name = parse_name_string(&data[1 + source_name_len..], namespace, scope)?; + + let local_scope_string = get_namespace_string(scope.clone(), parser_verify_value!(source_name)); + let local_alias_string = get_namespace_string(scope.clone(), parser_verify_value!(alias_name)); - Ok((NamespaceModifier::Alias {source_name, alias_name}, 1 + source_name_len + alias_name_len)) + namespace.insert(local_scope_string, AmlValue::ObjectReference( + SuperName::NameString(local_alias_string))); + + Ok(AmlParseType { + val: None, + len: 1 + source_name.len + alias_name.len + }) } -fn parse_name_op(data: &[u8]) -> Result<(NamespaceModifier, usize), AmlInternalError> { +fn parse_name_op(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode!(data, 0x08); + + let name = parse_name_string(&data[1..], namespace, scope)?; + let data_ref_obj = parse_data_ref_obj(&data[1 + name_len..], namespace, scope)?; + + let local_scope_string = get_namespace_string(scope.clone(), parser_verify_value!(name)); - let (name, name_len) = parse_name_string(&data[1..])?; - let (data_ref_obj, data_ref_obj_len) = parse_data_ref_obj(&data[1 + name_len..])?; - - Ok((NamespaceModifier::Name {name, data_ref_obj}, 1 + name_len + data_ref_obj_len)) + namespace.insert(local_scope_string, parser_verify_value!(data_ref_obj)); + + Ok(AmlParseType { + val: None, + len: 1 + name_len + data_ref_obj_len + }) } -fn parse_scope_op(data: &[u8]) -> Result<(NamespaceModifier, usize), AmlInternalError> { +fn parse_scope_op(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode!(data, 0x10); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; - let (name, name_len) = match parse_name_string(&data[1 + pkg_length_len..]) { - Ok(p) => p, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((NamespaceModifier::DeferredLoad(data[0 .. 1 + pkg_length].to_vec()), - 1 + pkg_length)), - Err(e) => return Err(e) - }; - let terms = match parse_term_list(&data[1 + pkg_length_len + name_len..]) { - Ok(p) => p, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((NamespaceModifier::DeferredLoad(data[0 .. 1 + pkg_length].to_vec()), - 1 + pkg_length)), - Err(e) => return Err(e) - }; - - Ok((NamespaceModifier::Scope {name, terms}, pkg_length + 1)) + let name = parse_name_string(&data[1 + pkg_length_len..], namespace, scope)?; + + let local_scope_string = get_namespace_string(scope, parser_verify_value!(name)); + parse_term_list(&data[1 + pkg_length_len + name_len..], namespace, local_scope_string)?; + + Ok(AmlParseType { + val: None, + len: 1 + pkg_length + }) } diff --git a/src/acpi/aml/parser.rs b/src/acpi/aml/parser.rs new file mode 100644 index 0000000..321f013 --- /dev/null +++ b/src/acpi/aml/parser.rs @@ -0,0 +1,16 @@ +use super::AmlValue; + +pub type ParseResult = Result; + +pub struct AmlParseType { + val: Option, + len: usize +} + +// TODO: make private +pub enum AmlInternalError { + AmlParseError(&'static str), + AmlInvalidOpCode, + AmlValueError, + AmlDeferredLoad +} diff --git a/src/acpi/aml/parsermacros.rs b/src/acpi/aml/parsermacros.rs index 50e3aed..7c9e101 100644 --- a/src/acpi/aml/parsermacros.rs +++ b/src/acpi/aml/parsermacros.rs @@ -1,15 +1,15 @@ #[macro_export] macro_rules! parser_selector { - {$data:expr, $func:expr} => { - match $func($data) { + {$data:expr, $namespace:expr, $scope:expr, $func:expr} => { + match $func($data, $namespace, $scope) { Ok(res) => return Ok(res), Err(AmlInternalError::AmlInvalidOpCode) => (), Err(e) => return Err(e) } }; - {$data:expr, $func:expr, $($funcs:expr),+} => { - parser_selector! {$data, $func}; - parser_selector! {$data, $($funcs),*}; + {$data:expr, $namespace:expr, $scope:expr, $func:expr, $($funcs:expr),+} => { + parser_selector! {$data, $namespace, $scope, $func}; + parser_selector! {$data, $namespace, $scope, $($funcs),*}; }; } @@ -47,3 +47,14 @@ macro_rules! parser_opcode_extended { } }; } + +#[macro_export] +macro_rules! parser_verify_value { + ($val:expr) => { + match $val.val { + Some(s) => s, + None => return Err(AmlInternalError::AmlValueError) + } + }; +} + diff --git a/src/acpi/aml/termlist.rs b/src/acpi/aml/termlist.rs index c7d0c5f..5e5482e 100644 --- a/src/acpi/aml/termlist.rs +++ b/src/acpi/aml/termlist.rs @@ -89,17 +89,20 @@ impl AmlExecutable for TermObj { } } -pub fn parse_term_list(data: &[u8]) -> Result, AmlInternalError> { - let mut terms: Vec = vec!(); +pub fn parse_term_list(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { let mut current_offset: usize = 0; while current_offset < data.len() { - let (res, len) = parse_term_obj(&data[current_offset..])?; - terms.push(res); + let (res, len) = parse_term_obj(&data[current_offset..], namespace, scope)?; current_offset += len; } - Ok(terms) + Ok(AmlParseType { + val: None, + len: data.len() + }) } pub fn parse_term_arg(data: &[u8]) -> Result<(TermArg, usize), AmlInternalError> { @@ -142,13 +145,15 @@ pub fn parse_method_invocation(data: &[u8]) -> Result<(MethodInvocation, usize), Err(AmlInternalError::AmlDeferredLoad) } -fn parse_term_obj(data: &[u8]) -> Result<(TermObj, usize), AmlInternalError> { +fn parse_term_obj(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_selector! { - data, - parser_wrap!(TermObj::NamespaceModifier, parser_wrap!(Box::new, parse_namespace_modifier)), - parser_wrap!(TermObj::NamedObj, parser_wrap!(Box::new, parse_named_obj)), - parser_wrap!(TermObj::Type1Opcode, parser_wrap!(Box::new, parse_type1_opcode)), - parser_wrap!(TermObj::Type2Opcode, parser_wrap!(Box::new, parse_type2_opcode)) + data, namespace, scope, + parse_namespace_modifier, + parse_named_obj, + parse_type1_opcode, + parse_type2_opcode }; Err(AmlInternalError::AmlInvalidOpCode) From 6c74a023825d054379c63ad66b6ef4a754298b56 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Sun, 2 Jul 2017 13:07:43 +0100 Subject: [PATCH 046/113] Refactored parser to execute in the parse step for efficiency and simplicity --- src/acpi/aml/dataobj.rs | 205 +++-- src/acpi/aml/mod.rs | 30 +- src/acpi/aml/namedobj.rs | 1175 ++++++++++---------------- src/acpi/aml/namespace.rs | 46 +- src/acpi/aml/namespacemodifier.rs | 46 +- src/acpi/aml/namestring.rs | 106 +-- src/acpi/aml/parser.rs | 20 +- src/acpi/aml/parsermacros.rs | 31 +- src/acpi/aml/pkglength.rs | 6 +- src/acpi/aml/termlist.rs | 153 +--- src/acpi/aml/type1opcode.rs | 404 ++++----- src/acpi/aml/type2opcode.rs | 1308 +++++++++++++++-------------- src/acpi/mod.rs | 8 +- src/stop.rs | 2 +- 14 files changed, 1622 insertions(+), 1918 deletions(-) diff --git a/src/acpi/aml/dataobj.rs b/src/acpi/aml/dataobj.rs index 27f81f8..77f7d2f 100644 --- a/src/acpi/aml/dataobj.rs +++ b/src/acpi/aml/dataobj.rs @@ -2,132 +2,99 @@ use collections::vec::Vec; use collections::string::String; use collections::btree_map::BTreeMap; -use super::{AmlInternalError, AmlExecutable, AmlValue, get_namespace_string}; +use super::AmlError; +use super::parser::{AmlParseType, ParseResult}; +use super::namespace::{AmlValue, ObjectReference}; -use super::type2opcode::{parse_def_buffer, parse_def_package, parse_def_var_package, - DefBuffer, DefPackage, DefVarPackage}; -use super::termlist::{parse_term_arg, TermArg}; -use super::namestring::{parse_super_name, SuperName}; +use super::type2opcode::{parse_def_buffer, parse_def_package, parse_def_var_package}; +use super::termlist::parse_term_arg; +use super::namestring::parse_super_name; -#[derive(Debug, Clone)] -pub enum DataObj { - ComputationalData(ComputationalData), - DefPackage(DefPackage), - DefVarPackage(DefVarPackage) -} - -#[derive(Debug, Clone)] -pub enum DataRefObj { - DataObj(DataObj), - ObjectReference(TermArg), - DDBHandle(SuperName) -} - -#[derive(Debug, Clone)] -pub struct ArgObj(u8); -#[derive(Debug, Clone)] -pub struct LocalObj(u8); -// Not actually doing anything to contain data, but does give us type guarantees, which is useful - -#[derive(Debug, Clone)] -pub enum ComputationalData { - Byte(u8), - Word(u16), - DWord(u32), - QWord(u64), - String(String), - Zero, - One, - Ones, - DefBuffer(DefBuffer), - RevisionOp -} - -impl AmlExecutable for DataRefObj { - fn execute(&self, namespace: &mut BTreeMap, scope: String) -> Option { - match *self { - DataRefObj::DataObj(ref cd) => cd.execute(namespace, scope), - _ => Some(AmlValue::Uninitialized) - } - } -} - -impl AmlExecutable for DataObj { - 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), - _ => Some(AmlValue::Uninitialized) - } - } -} - -impl AmlExecutable for ComputationalData { - 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)), - ComputationalData::DWord(d) => Some(AmlValue::IntegerConstant(d as u64)), - ComputationalData::QWord(q) => Some(AmlValue::IntegerConstant(q as u64)), - ComputationalData::Zero => Some(AmlValue::IntegerConstant(0)), - ComputationalData::One => Some(AmlValue::IntegerConstant(1)), - ComputationalData::Ones => Some(AmlValue::IntegerConstant(0xFFFFFFFFFFFFFFFF)), - ComputationalData::String(ref s) => Some(AmlValue::String(s.clone())), - _ => Some(AmlValue::Uninitialized) - } - } -} - -pub fn parse_data_obj(data: &[u8]) -> Result<(DataObj, usize), AmlInternalError> { +pub fn parse_data_obj(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_selector! { - data, - parser_wrap!(DataObj::ComputationalData, parse_computational_data), - parser_wrap!(DataObj::DefPackage, parse_def_package), - parser_wrap!(DataObj::DefVarPackage, parse_def_var_package) + data, namespace, scope.clone(), + parse_computational_data, + parse_def_package, + parse_def_var_package }; - Err(AmlInternalError::AmlInvalidOpCode) + Err(AmlError::AmlInvalidOpCode) } -pub fn parse_data_ref_obj(data: &[u8]) -> Result<(DataRefObj, usize), AmlInternalError> { +pub fn parse_data_ref_obj(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_selector! { - data, - parser_wrap!(DataRefObj::DataObj, parse_data_obj), - parser_wrap!(DataRefObj::ObjectReference, parse_term_arg), - parser_wrap!(DataRefObj::DDBHandle, parse_super_name) + data, namespace, scope.clone(), + parse_data_obj, + parse_term_arg }; - Err(AmlInternalError::AmlInvalidOpCode) -} - -pub fn parse_arg_obj(data: &[u8]) -> Result<(ArgObj, usize), AmlInternalError> { - match data[0] { - 0x68 ... 0x6E => Ok((ArgObj(data[0] - 0x68), 1 as usize)), - _ => Err(AmlInternalError::AmlInvalidOpCode) + match parse_super_name(data, namespace, scope.clone()) { + Ok(res) => match res.val { + AmlValue::String(s) => Ok(AmlParseType { + val: AmlValue::ObjectReference(ObjectReference::NamedObj(s)), + len: res.len + }), + _ => Ok(res) + }, + Err(e) => Err(e) } } -pub fn parse_local_obj(data: &[u8]) -> Result<(LocalObj, usize), AmlInternalError> { +pub fn parse_arg_obj(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { match data[0] { - 0x60 ... 0x67 => Ok((LocalObj(data[0] - 0x60), 1 as usize)), - _ => Err(AmlInternalError::AmlInvalidOpCode) + 0x68 ... 0x6E => Ok(AmlParseType { + val: AmlValue::ObjectReference(ObjectReference::ArgObj(data[0] - 0x68)), + len: 1 as usize + }), + _ => Err(AmlError::AmlInvalidOpCode) } } -fn parse_computational_data(data: &[u8]) -> Result<(ComputationalData, usize), AmlInternalError> { +pub fn parse_local_obj(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { match data[0] { - 0x0A => Ok((ComputationalData::Byte(data[1]), 2 as usize)), + 0x68 ... 0x6E => Ok(AmlParseType { + val: AmlValue::ObjectReference(ObjectReference::LocalObj(data[0] - 0x60)), + len: 1 as usize + }), + _ => Err(AmlError::AmlInvalidOpCode) + } +} + +fn parse_computational_data(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + match data[0] { + 0x0A => Ok(AmlParseType { + val: AmlValue::Integer(data[1] as u64), + len: 2 as usize + }), 0x0B => { let res = (data[1] as u16) + ((data[2] as u16) << 8); - Ok((ComputationalData::Word(res), 3 as usize)) + + Ok(AmlParseType { + val: AmlValue::Integer(res as u64), + len: 3 as usize + }) }, 0x0C => { let res = (data[1] as u32) + ((data[2] as u32) << 8) + ((data[3] as u32) << 16) + ((data[4] as u32) << 24); - Ok((ComputationalData::DWord(res), 5 as usize)) + + Ok(AmlParseType { + val: AmlValue::Integer(res as u64), + len: 5 as usize + }) }, 0x0D => { let mut cur_ptr: usize = 1; @@ -139,8 +106,11 @@ fn parse_computational_data(data: &[u8]) -> Result<(ComputationalData, usize), A } match String::from_utf8(cur_string) { - Ok(s) => Ok((ComputationalData::String(s.clone()), s.clone().len() + 2)), - Err(_) => Err(AmlInternalError::AmlParseError("String data - invalid string")) + Ok(s) => Ok(AmlParseType { + val: AmlValue::String(s.clone()), + len: s.clone().len() + 2 + }), + Err(_) => Err(AmlError::AmlParseError("String data - invalid string")) } }, 0x0E => { @@ -152,19 +122,32 @@ fn parse_computational_data(data: &[u8]) -> Result<(ComputationalData, usize), A ((data[6] as u64) << 40) + ((data[7] as u64) << 48) + ((data[8] as u64) << 56); - Ok((ComputationalData::QWord(res), 9 as usize)) + + Ok(AmlParseType { + val: AmlValue::Integer(res as u64), + len: 9 as usize + }) }, - 0x00 => Ok((ComputationalData::Zero, 1 as usize)), - 0x01 => Ok((ComputationalData::One, 1 as usize)), + 0x00 => Ok(AmlParseType { + val: AmlValue::IntegerConstant(0 as u64), + len: 9 as usize + }), + 0x01 => Ok(AmlParseType { + val: AmlValue::IntegerConstant(1 as u64), + len: 9 as usize + }), 0x5B => if data[1] == 0x30 { - Ok((ComputationalData::RevisionOp, 2 as usize)) + Ok(AmlParseType { + val: AmlValue::IntegerConstant(20170630 as u64), + len: 2 as usize + }) } else { - Err(AmlInternalError::AmlInvalidOpCode) + Err(AmlError::AmlInvalidOpCode) }, - 0xFF => Ok((ComputationalData::Ones, 1 as usize)), - _ => match parse_def_buffer(data) { - Ok((res, size)) => Ok((ComputationalData::DefBuffer(res), size)), - Err(e) => Err(e) - } + 0xFF => Ok(AmlParseType { + val: AmlValue::IntegerConstant(0xFFFFFFFFFFFFFFFF), + len: 9 as usize + }), + _ => parse_def_buffer(data, namespace, scope.clone()) } } diff --git a/src/acpi/aml/mod.rs b/src/acpi/aml/mod.rs index a6d5a35..a113c0b 100644 --- a/src/acpi/aml/mod.rs +++ b/src/acpi/aml/mod.rs @@ -24,34 +24,26 @@ mod type1opcode; mod type2opcode; mod parser; -use self::parser::{ParseResult, AmlInternalError}; -use self::termlist::{parse_term_list, TermObj}; -pub use self::namespace::{get_namespace_string, AmlValue}; - -pub trait AmlExecutable { - fn execute(&self, namespace: &mut BTreeMap, scope: String) -> Option; -} +use self::parser::ParseResult; +use self::termlist::parse_term_list; +pub use self::namespace::AmlValue; +#[derive(Debug)] pub enum AmlError { - AmlParseError(&'static str) + AmlParseError(&'static str), + AmlInvalidOpCode, + AmlValueError, + AmlDeferredLoad, + AmlFatalError(u8, u16, AmlValue) } pub fn parse_aml_table(sdt: &'static Sdt) -> Result, AmlError> { let data = sdt.data(); - let term_list = match parse_term_list(data) { - Ok(res) => res, - Err(AmlInternalError::AmlParseError(s)) => return Err(AmlError::AmlParseError(s)), - Err(AmlInternalError::AmlInvalidOpCode) => return Err(AmlError::AmlParseError("Unable to match opcode")), - Err(AmlInternalError::AmlDeferredLoad) => return Err(AmlError::AmlParseError("Deferred load reached top level")) - }; - let global_namespace_specifier = String::from_str("\\").unwrap(); - // 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 = BTreeMap::new(); - term_list.execute(&mut global_namespace, global_namespace_specifier.clone()); + + let term_list = parse_term_list(data, &mut global_namespace, global_namespace_specifier.clone())?; Ok(global_namespace) } diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index 66af6d6..c521893 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -5,444 +5,20 @@ use core::str::FromStr; use collections::btree_map::BTreeMap; -use super::{AmlInternalError, AmlExecutable, AmlValue, get_namespace_string}; -use super::namespace::FieldSelector; -use super::namestring::{parse_name_string, parse_name_seg, SuperName}; -use super::termlist::{parse_term_arg, parse_term_list, parse_object_list, TermArg, TermObj, Object}; +use super::AmlError; +use super::parser::{AmlParseType, ParseResult, AmlParseTypeGeneric}; +use super::namespace::{AmlValue, ObjectReference, FieldSelector, get_namespace_string}; +use super::namestring::{parse_name_string, parse_name_seg}; +use super::termlist::{parse_term_arg, parse_term_list, parse_object_list}; use super::pkglength::parse_pkg_length; -use super::type2opcode::{parse_def_buffer, DefBuffer}; - -#[derive(Debug, Clone)] -pub enum NamedObj { - DefBankField { - region_name: String, - bank_name: String, - bank_value: TermArg, - flags: FieldFlags, - field_list: Vec - }, - DefCreateBitField { - name: String, - source_buf: TermArg, - bit_index: TermArg - }, - DefCreateByteField { - name: String, - source_buf: TermArg, - byte_index: TermArg - }, - DefCreateWordField { - name: String, - source_buf: TermArg, - byte_index: TermArg - }, - DefCreateDWordField { - name: String, - source_buf: TermArg, - byte_index: TermArg - }, - DefCreateQWordField { - name: String, - source_buf: TermArg, - byte_index: TermArg - }, - DefCreateField { - name: String, - source_buf: TermArg, - bit_index: TermArg, - num_bits: TermArg - }, - DefDataRegion { - name: String, - signature: TermArg, - oem_id: TermArg, - oem_table_id: TermArg - }, - DefDevice { - name: String, - obj_list: Vec - }, - DefEvent { - name: String - }, - DefOpRegion { - name: String, - region: RegionSpace, - offset: TermArg, - len: TermArg - }, - DefField { - name: String, - flags: FieldFlags, - field_list: Vec - }, - DefIndexField { - idx_name: String, - data_name: String, - flags: FieldFlags, - field_list: Vec - }, - DefMethod { - name: String, - method: Method - }, - DefMutex { - name: String, - sync_level: u8 - }, - DefPowerRes { - name: String, - system_level: u8, - resource_order: u16, - obj_list: Vec - }, - DefProcessor { - name: String, - proc_id: u8, - p_blk_addr: u32, - p_blk_len: u8, - obj_list: Vec - }, - DefThermalZone { - name: String, - obj_list: Vec - }, - DeferredLoad(Vec) -} +use super::type2opcode::parse_def_buffer; #[derive(Debug, Clone)] pub struct Method { arg_count: u8, serialized: bool, sync_level: u8, - term_list: Vec -} - -impl AmlExecutable for NamedObj { - fn execute(&self, namespace: &mut BTreeMap, scope: String) -> Option { - match *self { - NamedObj::DefBankField { ref region_name, ref bank_name, ref bank_value, ref flags, ref field_list } => { - let mut offset: usize = 0; - let mut connection = AmlValue::Uninitialized; - let mut flags = flags.clone(); - let bank_val = if let Some(b) = bank_value.execute(namespace, scope.clone()) { - Box::new(b) - } else { - return None; - }; - - for f in field_list { - match *f { - FieldElement::ReservedField { length } => offset += length, - FieldElement::ConnectFieldNameString(ref name) => connection = - AmlValue::ObjectReference(SuperName::NameString(name.clone())), - FieldElement::ConnectFieldBufferData(ref buf) => { - connection = match buf.execute(namespace, scope.clone()) { - Some(c) => c, - None => return None - }; - }, - FieldElement::AccessField { ref access_type, ref access_attrib } => { - match *access_type { - AccessType::BufferAcc(_) => flags.access_type = AccessType::BufferAcc(access_attrib.clone()), - ref a => flags.access_type = a.clone() - } - }, - FieldElement::NamedField { name: ref field_name, length } => { - let local_scope_string = get_namespace_string(scope.clone(), - field_name.clone()); - namespace.insert(local_scope_string, AmlValue::FieldUnit { - selector: FieldSelector::Bank { - region: region_name.clone(), - bank_selector: bank_val.clone() - }, - connection: Box::new(connection.clone()), - flags: flags.clone(), - offset: offset.clone(), - length: length.clone() - }); - - offset += length; - }, - } - } - }, - NamedObj::DefIndexField { ref idx_name, ref data_name, ref flags, ref field_list } => { - let mut offset: usize = 0; - let mut connection = AmlValue::Uninitialized; - let mut flags = flags.clone(); - - for f in field_list { - match *f { - FieldElement::ReservedField { length } => offset += length, - FieldElement::ConnectFieldNameString(ref name) => connection = - AmlValue::ObjectReference(SuperName::NameString(name.clone())), - FieldElement::ConnectFieldBufferData(ref buf) => { - connection = match buf.execute(namespace, scope.clone()) { - Some(c) => c, - None => return None - }; - }, - FieldElement::AccessField { ref access_type, ref access_attrib } => { - match *access_type { - AccessType::BufferAcc(_) => flags.access_type = AccessType::BufferAcc(access_attrib.clone()), - ref a => flags.access_type = a.clone() - } - }, - FieldElement::NamedField { name: ref field_name, length } => { - let local_scope_string = get_namespace_string(scope.clone(), - field_name.clone()); - namespace.insert(local_scope_string, AmlValue::FieldUnit { - selector: FieldSelector::Index { - index_selector: idx_name.clone(), - data_selector: data_name.clone() - }, - connection: Box::new(connection.clone()), - flags: flags.clone(), - offset: offset.clone(), - length: length.clone() - }); - - offset += length; - } - } - } - }, - NamedObj::DefCreateBitField { ref name, ref source_buf, ref bit_index } => { - let local_scope_string = get_namespace_string(scope.clone(), name.clone()); - - let resolved_source_buf = match source_buf.execute(namespace, scope.clone()) { - Some(r) => Box::new(r), - _ => return None - }; - let resolved_index = match bit_index.execute(namespace, scope.clone()) { - Some(r) => Box::new(r), - _ => return None - }; - - namespace.insert(local_scope_string, AmlValue::BufferField { - source_buf: resolved_source_buf, - index: resolved_index, - length: Box::new(AmlValue::IntegerConstant(1)) - }); - }, - NamedObj::DefCreateByteField { ref name, ref source_buf, ref byte_index } => { - let local_scope_string = get_namespace_string(scope.clone(), name.clone()); - - let resolved_source_buf = match source_buf.execute(namespace, scope.clone()) { - Some(r) => Box::new(r), - _ => return None - }; - let resolved_index = match byte_index.execute(namespace, scope.clone()) { - Some(r) => Box::new(r), - _ => return None - }; - - namespace.insert(local_scope_string, AmlValue::BufferField { - source_buf: resolved_source_buf, - index: resolved_index, - length: Box::new(AmlValue::IntegerConstant(8)) - }); - }, - NamedObj::DefCreateWordField { ref name, ref source_buf, ref byte_index } => { - let local_scope_string = get_namespace_string(scope.clone(), name.clone()); - - let resolved_source_buf = match source_buf.execute(namespace, scope.clone()) { - Some(r) => Box::new(r), - _ => return None - }; - let resolved_index = match byte_index.execute(namespace, scope.clone()) { - Some(r) => Box::new(r), - _ => return None - }; - - namespace.insert(local_scope_string, AmlValue::BufferField { - source_buf: resolved_source_buf, - index: resolved_index, - length: Box::new(AmlValue::IntegerConstant(16)) - }); - }, - NamedObj::DefCreateDWordField { ref name, ref source_buf, ref byte_index } => { - let local_scope_string = get_namespace_string(scope.clone(), name.clone()); - - let resolved_source_buf = match source_buf.execute(namespace, scope.clone()) { - Some(r) => Box::new(r), - _ => return None - }; - let resolved_index = match byte_index.execute(namespace, scope.clone()) { - Some(r) => Box::new(r), - _ => return None - }; - - namespace.insert(local_scope_string, AmlValue::BufferField { - source_buf: resolved_source_buf, - index: resolved_index, - length: Box::new(AmlValue::IntegerConstant(32)) - }); - }, - NamedObj::DefCreateQWordField { ref name, ref source_buf, ref byte_index } => { - let local_scope_string = get_namespace_string(scope.clone(), name.clone()); - - let resolved_source_buf = match source_buf.execute(namespace, scope.clone()) { - Some(r) => Box::new(r), - _ => return None - }; - let resolved_index = match byte_index.execute(namespace, scope.clone()) { - Some(r) => Box::new(r), - _ => return None - }; - - namespace.insert(local_scope_string, AmlValue::BufferField { - source_buf: resolved_source_buf, - index: resolved_index, - length: Box::new(AmlValue::IntegerConstant(64)) - }); - }, - NamedObj::DefCreateField { ref name, ref source_buf, ref bit_index, ref num_bits } => { - let local_scope_string = get_namespace_string(scope.clone(), name.clone()); - - let resolved_source_buf = match source_buf.execute(namespace, scope.clone()) { - Some(r) => Box::new(r), - _ => return None - }; - let resolved_index = match bit_index.execute(namespace, scope.clone()) { - Some(r) => Box::new(r), - _ => return None - }; - let resolved_length = match num_bits.execute(namespace, scope.clone()) { - Some(r) => Box::new(r), - _ => return None - }; - - namespace.insert(local_scope_string, AmlValue::BufferField { - source_buf: resolved_source_buf, - index: resolved_index, - length: resolved_length - }); - }, - NamedObj::DefDataRegion { ref name, ref signature, ref oem_id, ref oem_table_id } => { - let local_scope_string = get_namespace_string(scope.clone(), name.clone()); - - namespace.insert(local_scope_string, AmlValue::OperationRegion { - region: RegionSpace::SystemMemory, - offset: Box::new(AmlValue::IntegerConstant(0)), - len: Box::new(AmlValue::IntegerConstant(0)) - }); - }, - NamedObj::DefOpRegion { ref name, ref region, ref offset, ref len } => { - let local_scope_string = get_namespace_string(scope.clone(), name.clone()); - - let resolved_offset = match offset.execute(namespace, scope.clone()) { - Some(r) => r, - _ => return None - }; - - let resolved_len = match len.execute(namespace, scope.clone()) { - Some(r) => r, - _ => return None - }; - - namespace.insert(local_scope_string, AmlValue::OperationRegion { - region: *region, - offset: Box::new(resolved_offset), - len: Box::new(resolved_len) - }); - }, - NamedObj::DefField { ref name, ref flags, ref field_list } => { - let mut offset: usize = 0; - let mut connection = AmlValue::Uninitialized; - let mut flags = flags.clone(); - - for f in field_list { - match *f { - FieldElement::ReservedField { length } => offset += length, - FieldElement::ConnectFieldNameString(ref name) => connection = - AmlValue::ObjectReference(SuperName::NameString(name.clone())), - FieldElement::ConnectFieldBufferData(ref buf) => { - connection = match buf.execute(namespace, scope.clone()) { - Some(c) => c, - None => return None - }; - }, - FieldElement::AccessField { ref access_type, ref access_attrib } => { - match *access_type { - AccessType::BufferAcc(_) => flags.access_type = AccessType::BufferAcc(access_attrib.clone()), - ref a => flags.access_type = a.clone() - } - }, - FieldElement::NamedField { name: ref field_name, length } => { - let local_scope_string = get_namespace_string(scope.clone(), - field_name.clone()); - namespace.insert(local_scope_string, AmlValue::FieldUnit { - selector: FieldSelector::Region(name.clone()), - connection: Box::new(connection.clone()), - flags: flags.clone(), - offset: offset.clone(), - length: length.clone() - }); - - offset += length; - } - } - } - }, - NamedObj::DefMethod { ref name, ref method } => { - let local_scope_string = get_namespace_string(scope.clone(), name.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()); - - 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()); - - 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 - }); - }, - NamedObj::DefPowerRes { ref name, system_level, resource_order, 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::PowerResource { - system_level, - resource_order, - obj_list: local_namespace - }); - }, - NamedObj::DefMutex { ref name, sync_level } => { - let local_scope_string = get_namespace_string(scope, name.clone()); - namespace.insert(local_scope_string, AmlValue::Mutex(sync_level)); - }, - NamedObj::DefEvent { ref name } => { - let local_scope_string = get_namespace_string(scope, name.clone()); - namespace.insert(local_scope_string, AmlValue::Event); - }, - _ => () - } - - None - } + term_list: Vec } #[derive(Debug, Copy, Clone)] @@ -485,20 +61,15 @@ pub enum UpdateRule { } #[derive(Debug, Clone)] -pub enum FieldElement { - NamedField { - name: String, - length: usize - }, - ReservedField { - length: usize - }, - AccessField { - access_type: AccessType, - access_attrib: AccessAttrib - }, - ConnectFieldNameString(String), - ConnectFieldBufferData(DefBuffer), +pub struct NamedField { + name: String, + length: usize +} + +#[derive(Debug, Clone)] +pub struct AccessField { + access_type: AccessType, + access_attrib: AccessAttrib } #[derive(Debug, Clone)] @@ -515,9 +86,11 @@ pub enum AccessAttrib { AttribBlockProcessCall } -pub fn parse_named_obj(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> { +pub fn parse_named_obj(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_selector! { - data, + data, namespace, scope.clone(), parse_def_bank_field, parse_def_create_bit_field, parse_def_create_byte_field, @@ -538,39 +111,26 @@ pub fn parse_named_obj(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalErro parse_def_thermal_zone }; - Err(AmlInternalError::AmlInvalidOpCode) + Err(AmlError::AmlInvalidOpCode) } -fn parse_def_bank_field(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> { +fn parse_def_bank_field(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Why isn't bank name used? parser_opcode_extended!(data, 0x87); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[2..])?; - let (region_name, region_name_len) = match parse_name_string( - &data[2 + pkg_length_len .. 2 + pkg_length]) { - Ok(res) => res, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_length].to_vec()), 2 + pkg_length)), - Err(e) => return Err(e) - }; + let data = &data[2 + pkg_length_len .. 2 + pkg_length]; + + let region_name = parse_name_string(data, namespace, scope.clone())?; + let bank_name = parse_name_string(&data[2 + pkg_length_len + region_name.len .. 2 + pkg_length], namespace, scope.clone())?; - let (bank_name, bank_name_len) = match parse_name_string( - &data[2 + pkg_length_len + region_name_len .. 2 + pkg_length]) { - Ok(res) => res, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_length].to_vec()), 2 + pkg_length)), - Err(e) => return Err(e) - }; + let bank_value = parse_term_arg( + &data[2 + pkg_length_len + region_name.len .. 2 + pkg_length], namespace, scope.clone())?; - let (bank_value, bank_value_len) = match parse_term_arg( - &data[2 + pkg_length_len + region_name_len .. 2 + pkg_length]) { - Ok(res) => res, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_length].to_vec()), 2 + pkg_length)), - Err(e) => return Err(e) - }; - - let flags_raw = data[2 + pkg_length_len + region_name_len + bank_name_len + bank_value_len]; - let flags = FieldFlags { + let flags_raw = data[2 + pkg_length_len + region_name.len + bank_name.len + bank_value.len]; + let mut flags = FieldFlags { access_type: match flags_raw & 0x0F { 0 => AccessType::AnyAcc, 1 => AccessType::ByteAcc, @@ -578,145 +138,239 @@ fn parse_def_bank_field(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalErr 3 => AccessType::DWordAcc, 4 => AccessType::QWordAcc, 5 => AccessType::BufferAcc(AccessAttrib::AttribByte), - _ => return Err(AmlInternalError::AmlParseError("BankField - invalid access type")) + _ => return Err(AmlError::AmlParseError("BankField - invalid access type")) }, lock_rule: (flags_raw & 0x10) == 0x10, update_rule: match (flags_raw & 0x60) >> 5 { 0 => UpdateRule::Preserve, 1 => UpdateRule::WriteAsOnes, 2 => UpdateRule::WriteAsZeros, - _ => return Err(AmlInternalError::AmlParseError("BankField - invalid update rule")) + _ => return Err(AmlError::AmlParseError("BankField - invalid update rule")) } }; - let field_list = match parse_field_list( - &data[3 + pkg_length_len + region_name_len + bank_name_len + bank_value_len .. - 2 + pkg_length]) { - Ok(p) => p, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_length].to_vec()), 2 + pkg_length)), - Err(e) => return Err(e) + let selector = FieldSelector::Bank { + region: region_name.val.get_as_string()?, + bank_selector: Box::new(bank_value.val) }; - Ok((NamedObj::DefBankField {region_name, bank_name, bank_value, flags, field_list}, - 2 + pkg_length)) + let field_list = parse_field_list( + &data[3 + pkg_length_len + region_name.len + bank_name.len + bank_value.len .. + 2 + pkg_length], namespace, scope, selector, &mut flags)?; + + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + pkg_length + }) } -fn parse_def_create_bit_field(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> { +fn parse_def_create_bit_field(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode!(data, 0x8D); - let (source_buf, source_buf_len) = parse_term_arg(&data[1..])?; - let (bit_index, bit_index_len) = parse_term_arg(&data[1 + source_buf_len..])?; - let (name, name_len) = parse_name_string(&data[1 + source_buf_len + bit_index_len..])?; + let source_buf = parse_term_arg(&data[2..], namespace, scope.clone())?; + let bit_index = parse_term_arg(&data[2 + source_buf.len..], namespace, scope.clone())?; + let name = parse_name_string(&data[1 + source_buf.len + bit_index.len..], namespace, scope.clone())?; + + let local_scope_string = get_namespace_string(scope.clone(), name.val); + + namespace.insert(local_scope_string, AmlValue::BufferField { + source_buf: Box::new(source_buf.val), + index: Box::new(bit_index.val), + length: Box::new(AmlValue::IntegerConstant(1)) + }); - Ok((NamedObj::DefCreateBitField {name, source_buf, bit_index}, - 1 + source_buf_len + bit_index_len + name_len)) + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + name.len + source_buf.len + bit_index.len + }) } -fn parse_def_create_byte_field(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> { +fn parse_def_create_byte_field(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode!(data, 0x8C); - let (source_buf, source_buf_len) = parse_term_arg(&data[1..])?; - let (byte_index, byte_index_len) = parse_term_arg(&data[1 + source_buf_len..])?; - let (name, name_len) = parse_name_string(&data[1 + source_buf_len + byte_index_len..])?; + let source_buf = parse_term_arg(&data[2..], namespace, scope.clone())?; + let bit_index = parse_term_arg(&data[2 + source_buf.len..], namespace, scope.clone())?; + let name = parse_name_string(&data[1 + source_buf.len + bit_index.len..], namespace, scope.clone())?; + + let local_scope_string = get_namespace_string(scope.clone(), name.val); + + namespace.insert(local_scope_string, AmlValue::BufferField { + source_buf: Box::new(source_buf.val), + index: Box::new(bit_index.val), + length: Box::new(AmlValue::IntegerConstant(8)) + }); - Ok((NamedObj::DefCreateByteField {name, source_buf, byte_index}, - 1 + source_buf_len + byte_index_len + name_len)) + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + name.len + source_buf.len + bit_index.len + }) } -fn parse_def_create_word_field(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> { +fn parse_def_create_word_field(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode!(data, 0x8B); - let (source_buf, source_buf_len) = parse_term_arg(&data[1..])?; - let (byte_index, byte_index_len) = parse_term_arg(&data[1 + source_buf_len..])?; - let (name, name_len) = parse_name_string(&data[1 + source_buf_len + byte_index_len..])?; + let source_buf = parse_term_arg(&data[2..], namespace, scope.clone())?; + let bit_index = parse_term_arg(&data[2 + source_buf.len..], namespace, scope.clone())?; + let name = parse_name_string(&data[1 + source_buf.len + bit_index.len..], namespace, scope.clone())?; + + let local_scope_string = get_namespace_string(scope.clone(), name.val); + + namespace.insert(local_scope_string, AmlValue::BufferField { + source_buf: Box::new(source_buf.val), + index: Box::new(bit_index.val), + length: Box::new(AmlValue::IntegerConstant(16)) + }); - Ok((NamedObj::DefCreateWordField {name, source_buf, byte_index}, - 1 + source_buf_len + byte_index_len + name_len)) + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + name.len + source_buf.len + bit_index.len + }) } -fn parse_def_create_dword_field(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> { +fn parse_def_create_dword_field(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode!(data, 0x8A); - let (source_buf, source_buf_len) = parse_term_arg(&data[1..])?; - let (byte_index, byte_index_len) = parse_term_arg(&data[1 + source_buf_len..])?; - let (name, name_len) = parse_name_string(&data[1 + source_buf_len + byte_index_len..])?; + let source_buf = parse_term_arg(&data[2..], namespace, scope.clone())?; + let bit_index = parse_term_arg(&data[2 + source_buf.len..], namespace, scope.clone())?; + let name = parse_name_string(&data[1 + source_buf.len + bit_index.len..], namespace, scope.clone())?; + + let local_scope_string = get_namespace_string(scope.clone(), name.val); + + namespace.insert(local_scope_string, AmlValue::BufferField { + source_buf: Box::new(source_buf.val), + index: Box::new(bit_index.val), + length: Box::new(AmlValue::IntegerConstant(32)) + }); - Ok((NamedObj::DefCreateDWordField {name, source_buf, byte_index}, - 1 + source_buf_len + byte_index_len + name_len)) + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + name.len + source_buf.len + bit_index.len + }) } -fn parse_def_create_qword_field(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> { +fn parse_def_create_qword_field(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode!(data, 0x8F); - let (source_buf, source_buf_len) = parse_term_arg(&data[1..])?; - let (byte_index, byte_index_len) = parse_term_arg(&data[1 + source_buf_len..])?; - let (name, name_len) = parse_name_string(&data[1 + source_buf_len + byte_index_len..])?; + let source_buf = parse_term_arg(&data[2..], namespace, scope.clone())?; + let bit_index = parse_term_arg(&data[2 + source_buf.len..], namespace, scope.clone())?; + let name = parse_name_string(&data[1 + source_buf.len + bit_index.len..], namespace, scope.clone())?; + + let local_scope_string = get_namespace_string(scope.clone(), name.val); + + namespace.insert(local_scope_string, AmlValue::BufferField { + source_buf: Box::new(source_buf.val), + index: Box::new(bit_index.val), + length: Box::new(AmlValue::IntegerConstant(64)) + }); - Ok((NamedObj::DefCreateQWordField {name, source_buf, byte_index}, - 1 + source_buf_len + byte_index_len + name_len)) + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + name.len + source_buf.len + bit_index.len + }) } -fn parse_def_create_field(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> { +fn parse_def_create_field(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode_extended!(data, 0x13); - let (source_buf, source_buf_len) = parse_term_arg(&data[2..])?; - let (bit_index, bit_index_len) = parse_term_arg(&data[2 + source_buf_len..])?; - let (num_bits, num_bits_len) = parse_term_arg(&data[2 + source_buf_len + bit_index_len..])?; - let (name, name_len) = parse_name_string( - &data[2 + source_buf_len + bit_index_len + num_bits_len..])?; - - Ok((NamedObj::DefCreateField {name, source_buf, bit_index, num_bits}, - 2 + source_buf_len + bit_index_len + num_bits_len + name_len)) + let source_buf = parse_term_arg(&data[2..], namespace, scope.clone())?; + let bit_index = parse_term_arg(&data[2 + source_buf.len..], namespace, scope.clone())?; + let num_bits = parse_term_arg(&data[2 + source_buf.len + bit_index.len..], namespace, scope.clone())?; + let name = parse_name_string(&data[2 + source_buf.len + bit_index.len + num_bits.len..], namespace, scope.clone())?; + + let local_scope_string = get_namespace_string(scope.clone(), name.val); + + namespace.insert(local_scope_string, AmlValue::BufferField { + source_buf: Box::new(source_buf.val), + index: Box::new(bit_index.val), + length: Box::new(num_bits.val) + }); + + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + name.len + source_buf.len + bit_index.len + num_bits.len + }) } -fn parse_def_data_region(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> { +fn parse_def_data_region(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Find the actual offset and length, once table mapping is implemented parser_opcode_extended!(data, 0x88); - let (name, name_len) = parse_name_string(&data[2..])?; - let (signature, signature_len) = parse_term_arg(&data[2 + name_len..])?; - let (oem_id, oem_id_len) = parse_term_arg(&data[2 + name_len + signature_len..])?; - let (oem_table_id, oem_table_id_len) = parse_term_arg( - &data[2 + name_len + signature_len + oem_id_len..])?; + let name = parse_name_string(&data[2..], namespace, scope.clone())?; + let signature = parse_term_arg(&data[2 + name.len..], namespace, scope.clone())?; + let oem_id = parse_term_arg(&data[2 + name.len + signature.len..], namespace, scope.clone())?; + let oem_table_id = parse_term_arg(&data[2 + name.len + signature.len + oem_id.len..], namespace, scope.clone())?; + + let local_scope_string = get_namespace_string(scope.clone(), name.val); - Ok((NamedObj::DefDataRegion {name, signature, oem_id, oem_table_id}, - 2 + name_len + signature_len + oem_id_len + oem_table_id_len)) + namespace.insert(local_scope_string, AmlValue::OperationRegion { + region: RegionSpace::SystemMemory, + offset: Box::new(AmlValue::IntegerConstant(0)), + len: Box::new(AmlValue::IntegerConstant(0)) + }); + + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + name.len + signature.len + oem_id.len + oem_table_id.len + }) } -fn parse_def_event(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> { +fn parse_def_event(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode_extended!(data, 0x02); - let (name, name_len) = parse_name_string(&data[2..])?; + let name = parse_name_string(&data[2..], namespace, scope.clone())?; + + let local_scope_string = get_namespace_string(scope, name.val); + namespace.insert(local_scope_string, AmlValue::Event); - Ok((NamedObj::DefEvent {name}, 2 + name_len)) + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + name.len + }) } -fn parse_def_device(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> { +fn parse_def_device(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode_extended!(data, 0x82); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[2..])?; - let (name, name_len) = match parse_name_string(&data[2 + pkg_length_len .. 2 + pkg_length]) { - Ok(p) => p, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_length].to_vec()), 2 + pkg_length)), - Err(e) => return Err(e) - }; + let name = parse_name_string(&data[2 + pkg_length_len .. 2 + pkg_length], namespace, scope.clone())?; + + let mut local_namespace = BTreeMap::new(); + let obj_list = parse_object_list(&data[2 + pkg_length_len + name.len .. 2 + pkg_length], &mut local_namespace, String::new())?; - let obj_list = match parse_object_list(&data[2 + pkg_length_len + name_len .. 2 + pkg_length]) { - Ok(p) => p, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_length].to_vec()), 2 + pkg_length)), - Err(e) => return Err(e) - }; + let local_scope_string = get_namespace_string(scope, name.val); + namespace.insert(local_scope_string, AmlValue::Device(local_namespace)); - Ok((NamedObj::DefDevice {name, obj_list}, 2 + pkg_length_len)) + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + pkg_length + }) } -fn parse_def_op_region(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> { +fn parse_def_op_region(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode_extended!(data, 0x80); - let (name, name_len) = parse_name_string(&data[2..])?; - let region = match data[2 + name_len] { + let name = parse_name_string(&data[2..], namespace, scope.clone())?; + let region = match data[2 + name.len] { 0x00 => RegionSpace::SystemMemory, 0x01 => RegionSpace::SystemIO, 0x02 => RegionSpace::PCIConfig, @@ -727,29 +381,36 @@ fn parse_def_op_region(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalErro 0x07 => RegionSpace::IPMI, 0x08 => RegionSpace::GeneralPurposeIO, 0x09 => RegionSpace::GenericSerialBus, - 0x80 ... 0xFF => RegionSpace::UserDefined(data[2 + name_len]), - _ => return Err(AmlInternalError::AmlParseError("OpRegion - invalid region")) + 0x80 ... 0xFF => RegionSpace::UserDefined(data[2 + name.len]), + _ => return Err(AmlError::AmlParseError("OpRegion - invalid region")) }; - let (offset, offset_len) = parse_term_arg(&data[3 + name_len..])?; - let (len, len_len) = parse_term_arg(&data[3 + name_len + offset_len..])?; + let offset = parse_term_arg(&data[3 + name.len..], namespace, scope.clone())?; + let len = parse_term_arg(&data[3 + name.len + offset.len..], namespace, scope.clone())?; - Ok((NamedObj::DefOpRegion {name, region, offset, len}, 3 + name_len + offset_len + len_len)) + let local_scope_string = get_namespace_string(scope.clone(), name.val); + namespace.insert(local_scope_string, AmlValue::OperationRegion { + region: region, + offset: Box::new(offset.val), + len: Box::new(len.val) + }); + + Ok(AmlParseType { + val: AmlValue::None, + len: 3 + name.len + offset.len + len.len + }) } -fn parse_def_field(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> { +fn parse_def_field(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode_extended!(data, 0x81); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[2..])?; - let (name, name_len) = match parse_name_string(&data[2 + pkg_length_len .. 2 + pkg_length]) { - Ok(p) => p, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_length].to_vec()), 2 + pkg_length)), - Err(e) => return Err(e) - }; + let name = parse_name_string(&data[2 + pkg_length_len .. 2 + pkg_length], namespace, scope.clone())?; - let flags_raw = data[2 + pkg_length_len + name_len]; - let flags = FieldFlags { + let flags_raw = data[2 + pkg_length_len + name.len]; + let mut flags = FieldFlags { access_type: match flags_raw & 0x0F { 0 => AccessType::AnyAcc, 1 => AccessType::ByteAcc, @@ -757,49 +418,38 @@ fn parse_def_field(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> { 3 => AccessType::DWordAcc, 4 => AccessType::QWordAcc, 5 => AccessType::BufferAcc(AccessAttrib::AttribByte), - _ => return Err(AmlInternalError::AmlParseError("Field - Invalid access type")) + _ => return Err(AmlError::AmlParseError("Field - Invalid access type")) }, lock_rule: (flags_raw & 0x10) == 0x10, update_rule: match (flags_raw & 0x60) >> 5 { 0 => UpdateRule::Preserve, 1 => UpdateRule::WriteAsOnes, 2 => UpdateRule::WriteAsZeros, - _ => return Err(AmlInternalError::AmlParseError("Field - Invalid update rule")) + _ => return Err(AmlError::AmlParseError("Field - Invalid update rule")) } }; - let field_list = match parse_field_list(&data[3 + pkg_length_len + name_len .. 2 + pkg_length]) { - Ok(p) => p, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_length].to_vec()), 2 + pkg_length)), - Err(e) => return Err(e) - }; + let selector = FieldSelector::Region(name.val.get_as_string()?); - Ok((NamedObj::DefField {name, flags, field_list}, 2 + pkg_length)) + let field_list = parse_field_list(&data[3 + pkg_length_len + name.len .. 2 + pkg_length], namespace, scope, selector, &mut flags)?; + + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + pkg_length + }) } -fn parse_def_index_field(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> { +fn parse_def_index_field(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode_extended!(data, 0x86); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[2..])?; - let (idx_name, idx_name_len) = match parse_name_string( - &data[2 + pkg_length_len .. 2 + pkg_length]) { - Ok(p) => p, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_length].to_vec()), 2 + pkg_length)), - Err(e) => return Err(e) - }; + let idx_name = parse_name_string( &data[2 + pkg_length_len .. 2 + pkg_length], namespace, scope.clone())?; + let data_name = parse_name_string(&data[2 + pkg_length_len + idx_name.len .. 2 + pkg_length], namespace, scope.clone())?; - let (data_name, data_name_len) = match parse_name_string( - &data[2 + pkg_length_len + idx_name_len .. 2 + pkg_length]) { - Ok(p) => p, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_length].to_vec()), 2 + pkg_length)), - Err(e) => return Err(e) - }; - - let flags_raw = data[2 + pkg_length_len + idx_name_len + data_name_len]; - let flags = FieldFlags { + let flags_raw = data[2 + pkg_length_len + idx_name.len + data_name.len]; + let mut flags = FieldFlags { access_type: match flags_raw & 0x0F { 0 => AccessType::AnyAcc, 1 => AccessType::ByteAcc, @@ -807,78 +457,129 @@ fn parse_def_index_field(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalEr 3 => AccessType::DWordAcc, 4 => AccessType::QWordAcc, 5 => AccessType::BufferAcc(AccessAttrib::AttribByte), - _ => return Err(AmlInternalError::AmlParseError("IndexField - Invalid access type")) + _ => return Err(AmlError::AmlParseError("IndexField - Invalid access type")) }, lock_rule: (flags_raw & 0x10) == 0x10, update_rule: match (flags_raw & 0x60) >> 5 { 0 => UpdateRule::Preserve, 1 => UpdateRule::WriteAsOnes, 2 => UpdateRule::WriteAsZeros, - _ => return Err(AmlInternalError::AmlParseError("IndexField - Invalid update rule")) + _ => return Err(AmlError::AmlParseError("IndexField - Invalid update rule")) } }; - let field_list = match parse_field_list( - &data[3 + pkg_length_len + idx_name_len + data_name_len .. 2 + pkg_length]) { - Ok(p) => p, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_length].to_vec()), 2 + pkg_length)), - Err(e) => return Err(e) + let selector = FieldSelector::Index { + index_selector: idx_name.val.get_as_string()?, + data_selector: data_name.val.get_as_string()? }; - Ok((NamedObj::DefIndexField {idx_name, data_name, flags, field_list}, 2 + pkg_length)) + let field_list = parse_field_list( + &data[3 + pkg_length_len + idx_name.len + data_name.len .. 2 + pkg_length], namespace, scope, selector, &mut flags)?; + + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + pkg_length + }) } -fn parse_field_list(data: &[u8]) -> Result, AmlInternalError> { - let mut terms: Vec = vec!(); +fn parse_field_list(data: &[u8], + namespace: &mut BTreeMap, + scope: String, + selector: FieldSelector, + flags: &mut FieldFlags) -> ParseResult { let mut current_offset: usize = 0; + let mut connection = AmlValue::Uninitialized; while current_offset < data.len() { - let (res, len) = match parse_field_element(&data[current_offset..]) { - Ok(r) => r, - Err(AmlInternalError::AmlInvalidOpCode) => - return Err(AmlInternalError::AmlParseError("FieldList - no valid field")), + match parse_field_element(&data[current_offset..], namespace, scope.clone(), selector.clone(), + &mut connection, flags, &mut current_offset) { + Ok(_) => (), + Err(AmlError::AmlInvalidOpCode) => + return Err(AmlError::AmlParseError("FieldList - no valid field")), Err(e) => return Err(e) - }; - - terms.push(res); - current_offset += len; + } } - Ok(terms) + Ok(AmlParseType { + val: AmlValue::None, + len: data.len() + }) } -fn parse_field_element(data: &[u8]) -> Result<(FieldElement, usize), AmlInternalError> { - parser_selector! { - data, - parse_named_field, - parse_reserved_field, - parse_access_field, - parse_connect_field +fn parse_field_element(data: &[u8], + namespace: &mut BTreeMap, + scope: String, + selector: FieldSelector, + connection: &mut AmlValue, + flags: &mut FieldFlags, + offset: &mut usize) -> ParseResult { + let length = if let Ok(field) = parse_named_field(data, namespace, scope.clone()) { + let local_scope_string = get_namespace_string(scope.clone(), AmlValue::String(field.val.name.clone())); + + namespace.insert(local_scope_string, AmlValue::FieldUnit { + selector: selector.clone(), + connection: Box::new(connection.clone()), + flags: flags.clone(), + offset: offset.clone(), + length: field.val.length + }); + + field.len + } else if let Ok(field) = parse_reserved_field(data, namespace, scope.clone()) { + *offset += field.val; + field.len + } else if let Ok(field) = parse_access_field(data, namespace, scope.clone()) { + match field.val.access_type { + AccessType::BufferAcc(_) => + flags.access_type = AccessType::BufferAcc(field.val.access_attrib.clone()), + ref a => flags.access_type = a.clone() + } + + field.len + } else if let Ok(field) = parse_connect_field(data, namespace, scope.clone()) { + *connection = field.val.clone(); + field.len + } else { + return Err(AmlError::AmlInvalidOpCode); }; - - Err(AmlInternalError::AmlInvalidOpCode) + + Ok(AmlParseType { + val: AmlValue::None, + len: length + }) } -fn parse_named_field(data: &[u8]) -> Result<(FieldElement, usize), AmlInternalError> { +fn parse_named_field(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> Result, AmlError> { let (name_seg, name_seg_len) = parse_name_seg(&data[0..4])?; let name = match String::from_utf8(name_seg) { Ok(s) => s, - Err(_) => return Err(AmlInternalError::AmlParseError("NamedField - invalid name")) + Err(_) => return Err(AmlError::AmlParseError("NamedField - invalid name")) }; let (length, length_len) = parse_pkg_length(&data[4..])?; - Ok((FieldElement::NamedField {name, length}, 4 + length_len)) + Ok(AmlParseTypeGeneric { + val: NamedField { name, length }, + len: 4 + length_len + }) } -fn parse_reserved_field(data: &[u8]) -> Result<(FieldElement, usize), AmlInternalError> { +fn parse_reserved_field(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> Result, AmlError> { parser_opcode!(data, 0x00); let (length, length_len) = parse_pkg_length(&data[1..])?; - Ok((FieldElement::ReservedField {length}, 1 + length_len)) + Ok(AmlParseTypeGeneric { + val: length, + len: 1 + length_len + }) } -fn parse_access_field(data: &[u8]) -> Result<(FieldElement, usize), AmlInternalError> { +fn parse_access_field(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> Result, AmlError> { parser_opcode!(data, 0x01, 0x03); let flags_raw = data[1]; @@ -889,7 +590,7 @@ fn parse_access_field(data: &[u8]) -> Result<(FieldElement, usize), AmlInternalE 3 => AccessType::DWordAcc, 4 => AccessType::QWordAcc, 5 => AccessType::BufferAcc(AccessAttrib::AttribByte), - _ => return Err(AmlInternalError::AmlParseError("AccessField - Invalid access type")) + _ => return Err(AmlError::AmlParseError("AccessField - Invalid access type")) }; let access_attrib = match (flags_raw & 0xC0) >> 6 { @@ -904,155 +605,169 @@ fn parse_access_field(data: &[u8]) -> Result<(FieldElement, usize), AmlInternalE 0x0D => AccessAttrib::AttribBlockProcessCall, 0x0E => AccessAttrib::AttribRawBytes(data[3]), 0x0F => AccessAttrib::AttribRawProcessBytes(data[3]), - _ => return Err(AmlInternalError::AmlParseError("AccessField - Invalid access attrib")) + _ => return Err(AmlError::AmlParseError("AccessField - Invalid access attrib")) }, 1 => AccessAttrib::AttribBytes(data[2]), 2 => AccessAttrib::AttribRawBytes(data[2]), 3 => AccessAttrib::AttribRawProcessBytes(data[2]), - _ => return Err(AmlInternalError::AmlParseError("AccessField - Invalid access attrib")) + _ => return Err(AmlError::AmlParseError("AccessField - Invalid access attrib")) // This should never happen but the compiler bitches if I don't cover this }; - return Ok((FieldElement::AccessField {access_type, access_attrib}, if data[0] == 0x01 { - 3 as usize - } else { - 4 as usize - })) + Ok(AmlParseTypeGeneric { + val: AccessField { access_type, access_attrib }, + len: if data[0] == 0x01 { + 3 as usize + } else { + 4 as usize + } + }) } -fn parse_connect_field(data: &[u8]) -> Result<(FieldElement, usize), AmlInternalError> { +fn parse_connect_field(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode!(data, 0x02); - match parse_def_buffer(&data[1..]) { - Ok((buf, buf_len)) => return Ok((FieldElement::ConnectFieldBufferData(buf), buf_len + 1)), - Err(AmlInternalError::AmlInvalidOpCode) => (), - Err(e) => return Err(e) - } - - match parse_name_string(&data[1..]) { - Ok((name, name_len)) => Ok((FieldElement::ConnectFieldNameString(name), name_len + 1)), - Err(AmlInternalError::AmlInvalidOpCode) => Err(AmlInternalError::AmlParseError("ConnectField - unable to match field")), - Err(e) => Err(e) + if let Ok(e) = parse_def_buffer(&data[1..], namespace, scope.clone()) { + Ok(AmlParseType { + val: e.val, + len: e.len + 1 + }) + } else { + let name = parse_name_string(&data[1..], namespace, scope.clone())?; + Ok(AmlParseType { + val: AmlValue::ObjectReference(ObjectReference::NamedObj(name.val.get_as_string()?)), + len: name.len + 1 + }) } } -fn parse_def_method(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> { +fn parse_def_method(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode!(data, 0x14); let (pkg_len, pkg_len_len) = parse_pkg_length(&data[1..])?; - let (name, name_len) = match parse_name_string(&data[1 + pkg_len_len..]) { - Ok(p) => p, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((NamedObj::DeferredLoad(data[0 .. 1 + pkg_len].to_vec()), 1 + pkg_len)), - Err(e) => return Err(e) - }; - let flags = data[1 + pkg_len_len + name_len]; + let name = parse_name_string(&data[1 + pkg_len_len..], namespace, scope.clone())?; + let flags = data[1 + pkg_len_len + name.len]; let arg_count = flags & 0x07; let serialized = (flags & 0x08) == 0x08; let sync_level = flags & 0xF0 >> 4; - let term_list = match parse_term_list(&data[2 + pkg_len_len + name_len .. 1 + pkg_len]) { - Ok(p) => p, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((NamedObj::DeferredLoad(data[0 .. 1 + pkg_len].to_vec()), 1 + pkg_len)), - Err(e) => return Err(e) - }; + let term_list = &data[2 + pkg_len_len + name.len .. 1 + pkg_len]; + + let local_scope_string = get_namespace_string(scope.clone(), name.val); + namespace.insert(local_scope_string, AmlValue::Method(Method { + arg_count, + serialized, + sync_level, + term_list: term_list.to_vec() + })); - Ok((NamedObj::DefMethod { - name: name, - method: Method { - arg_count, - serialized, - sync_level, - term_list - } - }, pkg_len + 1)) + Ok(AmlParseType { + val: AmlValue::None, + len: 1 + pkg_len + }) } -fn parse_def_mutex(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> { +fn parse_def_mutex(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode_extended!(data, 0x01); - let (name, name_len) = match parse_name_string(&data[2 ..]) { - Ok(p) => p, - Err(e) => return Err(e), - }; - let flags = data[2 + name_len]; + let name = parse_name_string(&data[2 ..], namespace, scope.clone())?; + let flags = data[2 + name.len]; let sync_level = flags & 0x0F; + + let local_scope_string = get_namespace_string(scope, name.val); + namespace.insert(local_scope_string, AmlValue::Mutex(sync_level)); - Ok((NamedObj::DefMutex {name, sync_level}, name_len + 3)) + Ok(AmlParseType { + val: AmlValue::None, + len: 3 + name.len + }) } -fn parse_def_power_res(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> { +fn parse_def_power_res(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode_extended!(data, 0x84); let (pkg_len, pkg_len_len) = parse_pkg_length(&data[2..])?; - let (name, name_len) = match parse_name_string(&data[2 + pkg_len_len..]) { - Ok(p) => p, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_len].to_vec()), 2 + pkg_len)), - Err(e) => return Err(e) - }; + let name = parse_name_string(&data[2 + pkg_len_len..], namespace, scope.clone())?; + + let local_scope_string = get_namespace_string(scope, name.val); + let mut local_namespace = BTreeMap::new(); - let system_level = data[2 + pkg_len_len + name_len]; - let resource_order: u16 = (data[3 + pkg_len_len + name_len] as u16) + - ((data[4 + pkg_len_len + name_len] as u16) << 8); + let system_level = data[2 + pkg_len_len + name.len]; + let resource_order: u16 = (data[3 + pkg_len_len + name.len] as u16) + + ((data[4 + pkg_len_len + name.len] as u16) << 8); - let obj_list = match parse_object_list(&data[5 + pkg_len_len + name_len .. 2 + pkg_len]) { - Ok(p) => p, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_len].to_vec()), 2 + pkg_len)), - Err(e) => return Err(e) - }; + parse_object_list(&data[5 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_namespace, String::new())?; + + namespace.insert(local_scope_string, AmlValue::PowerResource { + system_level, + resource_order, + obj_list: local_namespace + }); - Ok((NamedObj::DefPowerRes {name, system_level, resource_order, obj_list}, 2 + pkg_len)) + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + pkg_len + }) } -fn parse_def_processor(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> { +fn parse_def_processor(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode_extended!(data, 0x83); let (pkg_len, pkg_len_len) = parse_pkg_length(&data[2..])?; - let (name, name_len) = match parse_name_string(&data[2 + pkg_len_len..]) { - Ok(p) => p, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_len].to_vec()), 2 + pkg_len)), - Err(e) => return Err(e) - }; + let name = parse_name_string(&data[2 + pkg_len_len..], namespace, scope.clone())?; + + let local_scope_string = get_namespace_string(scope, name.val); + let mut local_namespace = BTreeMap::new(); + + let proc_id = data[2 + pkg_len_len + name.len]; + let p_blk_addr: u32 = (data[3 + pkg_len_len + name.len] as u32) + + ((data[4 + pkg_len_len + name.len] as u32) << 8) + + ((data[5 + pkg_len_len + name.len] as u32) << 16) + + ((data[6 + pkg_len_len + name.len] as u32) << 24); + let p_blk_len = data[7 + pkg_len_len + name.len]; - let proc_id = data[2 + pkg_len_len + name_len]; - let p_blk_addr: u32 = (data[3 + pkg_len_len + name_len] as u32) + - ((data[4 + pkg_len_len + name_len] as u32) << 8) + - ((data[5 + pkg_len_len + name_len] as u32) << 16) + - ((data[6 + pkg_len_len + name_len] as u32) << 24); - let p_blk_len = data[7 + pkg_len_len + name_len]; + parse_object_list(&data[8 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_namespace, String::new())?; - let obj_list = match parse_object_list(&data[8 + pkg_len_len + name_len .. 2 + pkg_len]) { - Ok(p) => p, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_len].to_vec()), 2 + pkg_len)), - Err(e) => return Err(e) - }; + 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 + }); - Ok((NamedObj::DefProcessor {name, proc_id, p_blk_addr, p_blk_len, obj_list}, 2 + pkg_len)) + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + pkg_len + }) } -fn parse_def_thermal_zone(data: &[u8]) -> Result<(NamedObj, usize), AmlInternalError> { - parser_opcode_extended!(data, 0x85); - +fn parse_def_thermal_zone(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + parser_opcode_extended!(data, 0x85); + let (pkg_len, pkg_len_len) = parse_pkg_length(&data[2..])?; - let (name, name_len) = match parse_name_string(&data[2 + pkg_len_len..]) { - Ok(p) => p, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_len].to_vec()), 2 + pkg_len)), - Err(e) => return Err(e) - }; + let name = parse_name_string(&data[2 + pkg_len_len .. 2 + pkg_len], namespace, scope.clone())?; + + let local_scope_string = get_namespace_string(scope, name.val); + let mut local_namespace = BTreeMap::new(); + + parse_object_list(&data[2 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_namespace, String::new())?; + + namespace.insert(local_scope_string, AmlValue::ThermalZone(local_namespace)); - let obj_list = match parse_object_list(&data[2 + pkg_len_len + name_len .. 2 + pkg_len]) { - Ok(p) => p, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((NamedObj::DeferredLoad(data[0 .. 2 + pkg_len].to_vec()), 2 + pkg_len)), - Err(e) => return Err(e) - }; - - Ok((NamedObj::DefThermalZone {name, obj_list}, 2 + pkg_len)) + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + pkg_len + }) } diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index be49f7b..d2ac417 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -6,9 +6,7 @@ use collections::btree_map::BTreeMap; use core::str::FromStr; use super::namedobj::{ RegionSpace, FieldFlags, Method }; -use super::termlist::Object; -use super::namestring::SuperName; -use super::type2opcode::Type2OpCode; +use super::AmlError; #[derive(Debug, Clone)] pub enum FieldSelector { @@ -23,8 +21,17 @@ pub enum FieldSelector { } } +#[derive(Debug, Clone)] +pub enum ObjectReference { + ArgObj(u8), + LocalObj(u8), + NamedObj(String), + Object(Box) +} + #[derive(Debug, Clone)] pub enum AmlValue { + None, Uninitialized, Buffer { length: Box, @@ -46,11 +53,11 @@ pub enum AmlValue { offset: usize, length: usize }, - Integer(Type2OpCode), + Integer(u64), IntegerConstant(u64), Method(Method), Mutex(u8), - ObjectReference(SuperName), + ObjectReference(ObjectReference), OperationRegion { region: RegionSpace, offset: Box, @@ -73,22 +80,37 @@ pub enum AmlValue { } impl AmlValue { - pub fn get_as_package(&self) -> Option> { + // TODO: These should be able to throw errors rather than returning options + pub fn get_as_string(&self) -> Result { match *self { - AmlValue::Package(ref p) => Some(p.clone()), - _ => None + AmlValue::String(ref s) => Ok(s.clone()), + _ => Err(AmlError::AmlValueError) + } + } + + pub fn get_as_package(&self) -> Result, AmlError> { + match *self { + AmlValue::Package(ref p) => Ok(p.clone()), + _ => Err(AmlError::AmlValueError) } } - pub fn get_as_integer(&self) -> Option { + pub fn get_as_integer(&self) -> Result { match *self { - AmlValue::IntegerConstant(ref i) => Some(i.clone()), - _ => None + AmlValue::IntegerConstant(ref i) => Ok(i.clone()), + _ => Err(AmlError::AmlValueError) } } } -pub fn get_namespace_string(current: String, modifier: String) -> String { +pub fn get_namespace_string(current: String, modifier_v: AmlValue) -> String { + // TODO: Type error if modifier not string + let modifier = if let Ok(s) = modifier_v.get_as_string() { + s + } else { + return current; + }; + if current.len() == 0 { return modifier; } diff --git a/src/acpi/aml/namespacemodifier.rs b/src/acpi/aml/namespacemodifier.rs index 8e7e2cc..b04d405 100644 --- a/src/acpi/aml/namespacemodifier.rs +++ b/src/acpi/aml/namespacemodifier.rs @@ -3,23 +3,25 @@ use collections::string::String; use collections::vec::Vec; use collections::btree_map::BTreeMap; -use super::{AmlInternalError, AmlExecutable, AmlValue, get_namespace_string}; +use super::AmlError; +use super::parser::{AmlParseType, ParseResult, AmlParseTypeGeneric}; +use super::namespace::{AmlValue, ObjectReference, FieldSelector, get_namespace_string}; use super::pkglength::parse_pkg_length; -use super::namestring::{parse_name_string, SuperName}; -use super::termlist::{parse_term_list, TermObj}; -use super::dataobj::{parse_data_ref_obj, DataRefObj}; +use super::namestring::parse_name_string; +use super::termlist::parse_term_list; +use super::dataobj::parse_data_ref_obj; pub fn parse_namespace_modifier(data: &[u8], namespace: &mut BTreeMap, scope: String) -> ParseResult { parser_selector! { - data, namespace, scope, + data, namespace, scope.clone(), parse_alias_op, parse_scope_op, parse_name_op }; - Err(AmlInternalError::AmlInvalidOpCode) + Err(AmlError::AmlInvalidOpCode) } fn parse_alias_op(data: &[u8], @@ -27,17 +29,17 @@ fn parse_alias_op(data: &[u8], scope: String) -> ParseResult { parser_opcode!(data, 0x06); - let source_name = parse_name_string(&data[1..], namespace, scope)?; - let alias_name = parse_name_string(&data[1 + source_name_len..], namespace, scope)?; + let source_name = parse_name_string(&data[1..], namespace, scope.clone())?; + let alias_name = parse_name_string(&data[1 + source_name.len..], namespace, scope.clone())?; - let local_scope_string = get_namespace_string(scope.clone(), parser_verify_value!(source_name)); - let local_alias_string = get_namespace_string(scope.clone(), parser_verify_value!(alias_name)); + let local_scope_string = get_namespace_string(scope.clone(), source_name.val); + let local_alias_string = get_namespace_string(scope.clone(), alias_name.val); namespace.insert(local_scope_string, AmlValue::ObjectReference( - SuperName::NameString(local_alias_string))); + ObjectReference::NamedObj(local_alias_string))); Ok(AmlParseType { - val: None, + val: AmlValue::None, len: 1 + source_name.len + alias_name.len }) } @@ -47,16 +49,16 @@ fn parse_name_op(data: &[u8], scope: String) -> ParseResult { parser_opcode!(data, 0x08); - let name = parse_name_string(&data[1..], namespace, scope)?; - let data_ref_obj = parse_data_ref_obj(&data[1 + name_len..], namespace, scope)?; + let name = parse_name_string(&data[1..], namespace, scope.clone())?; + let data_ref_obj = parse_data_ref_obj(&data[1 + name.len..], namespace, scope.clone())?; - let local_scope_string = get_namespace_string(scope.clone(), parser_verify_value!(name)); + let local_scope_string = get_namespace_string(scope.clone(), name.val); - namespace.insert(local_scope_string, parser_verify_value!(data_ref_obj)); + namespace.insert(local_scope_string, data_ref_obj.val); Ok(AmlParseType { - val: None, - len: 1 + name_len + data_ref_obj_len + val: AmlValue::None, + len: 1 + name.len + data_ref_obj.len }) } @@ -66,13 +68,13 @@ fn parse_scope_op(data: &[u8], parser_opcode!(data, 0x10); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; - let name = parse_name_string(&data[1 + pkg_length_len..], namespace, scope)?; + let name = parse_name_string(&data[1 + pkg_length_len..], namespace, scope.clone())?; - let local_scope_string = get_namespace_string(scope, parser_verify_value!(name)); - parse_term_list(&data[1 + pkg_length_len + name_len..], namespace, local_scope_string)?; + let local_scope_string = get_namespace_string(scope, name.val); + parse_term_list(&data[1 + pkg_length_len + name.len..], namespace, local_scope_string)?; Ok(AmlParseType { - val: None, + val: AmlValue::None, len: 1 + pkg_length }) } diff --git a/src/acpi/aml/namestring.rs b/src/acpi/aml/namestring.rs index 8015a8c..ccbdcce 100644 --- a/src/acpi/aml/namestring.rs +++ b/src/acpi/aml/namestring.rs @@ -1,27 +1,16 @@ use collections::vec::Vec; use collections::string::String; +use collections::btree_map::BTreeMap; -use super::AmlInternalError; +use super::AmlError; +use super::parser::{AmlParseType, ParseResult, AmlParseTypeGeneric}; +use super::namespace::{AmlValue, ObjectReference, FieldSelector, get_namespace_string}; +use super::dataobj::{parse_arg_obj, parse_local_obj}; +use super::type2opcode::parse_type6_opcode; -use super::dataobj::{parse_arg_obj, parse_local_obj, ArgObj, LocalObj}; -use super::type2opcode::{parse_type6_opcode, Type6OpCode}; - -#[derive(Debug, Clone)] -pub enum SuperName { - NameString(String), - ArgObj(ArgObj), - LocalObj(LocalObj), - DebugObj, - Type6OpCode(Type6OpCode) -} - -#[derive(Debug, Clone)] -pub enum Target { - SuperName(SuperName), - Null -} - -pub fn parse_name_string(data: &[u8]) -> Result<(String, usize), AmlInternalError> { +pub fn parse_name_string(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { let mut characters: Vec = vec!(); let mut starting_index: usize = 0; @@ -36,7 +25,7 @@ pub fn parse_name_string(data: &[u8]) -> Result<(String, usize), AmlInternalErro } let sel = |data| { - parser_selector! { + parser_selector_simple! { data, parse_dual_name_path, parse_multi_name_path, @@ -44,7 +33,7 @@ pub fn parse_name_string(data: &[u8]) -> Result<(String, usize), AmlInternalErro parse_name_seg }; - Err(AmlInternalError::AmlInvalidOpCode) + Err(AmlError::AmlInvalidOpCode) }; let (mut chr, len) = sel(&data[starting_index..])?; characters.append(&mut chr); @@ -52,35 +41,38 @@ pub fn parse_name_string(data: &[u8]) -> Result<(String, usize), AmlInternalErro let name_string = String::from_utf8(characters); match name_string { - Ok(s) => Ok((s.clone(), len + starting_index)), - Err(_) => Err(AmlInternalError::AmlParseError("Namestring - Name is invalid")) + Ok(s) => Ok(AmlParseType { + val: AmlValue::String(s.clone()), + len: len + starting_index + }), + Err(_) => Err(AmlError::AmlParseError("Namestring - Name is invalid")) } } -fn parse_null_name(data: &[u8]) -> Result<(Vec, usize), AmlInternalError> { +fn parse_null_name(data: &[u8]) -> Result<(Vec, usize), AmlError> { parser_opcode!(data, 0x00); Ok((vec!(), 1 as usize)) } -pub fn parse_name_seg(data: &[u8]) -> Result<(Vec, usize), AmlInternalError> { +pub fn parse_name_seg(data: &[u8]) -> Result<(Vec, usize), AmlError> { match data[0] { 0x41 ... 0x5A | 0x5F => (), - _ => return Err(AmlInternalError::AmlInvalidOpCode) + _ => return Err(AmlError::AmlInvalidOpCode) } match data[1] { 0x30 ... 0x39 | 0x41 ... 0x5A | 0x5F => (), - _ => return Err(AmlInternalError::AmlInvalidOpCode) + _ => return Err(AmlError::AmlInvalidOpCode) } match data[2] { 0x30 ... 0x39 | 0x41 ... 0x5A | 0x5F => (), - _ => return Err(AmlInternalError::AmlInvalidOpCode) + _ => return Err(AmlError::AmlInvalidOpCode) } match data[3] { 0x30 ... 0x39 | 0x41 ... 0x5A | 0x5F => (), - _ => return Err(AmlInternalError::AmlInvalidOpCode) + _ => return Err(AmlError::AmlInvalidOpCode) } let mut name_seg = vec!(data[0], data[1], data[2], data[3]); @@ -91,7 +83,7 @@ pub fn parse_name_seg(data: &[u8]) -> Result<(Vec, usize), AmlInternalError> Ok((name_seg, 4 as usize)) } -fn parse_dual_name_path(data: &[u8]) -> Result<(Vec, usize), AmlInternalError> { +fn parse_dual_name_path(data: &[u8]) -> Result<(Vec, usize), AmlError> { parser_opcode!(data, 0x2E); let mut characters: Vec = vec!(); @@ -118,12 +110,12 @@ fn parse_dual_name_path(data: &[u8]) -> Result<(Vec, usize), AmlInternalErro Ok((characters, dual_len)) } -fn parse_multi_name_path(data: &[u8]) -> Result<(Vec, usize), AmlInternalError> { +fn parse_multi_name_path(data: &[u8]) -> Result<(Vec, usize), AmlError> { parser_opcode!(data, 0x2F); let seg_count = data[1]; if seg_count == 0x00 { - return Err(AmlInternalError::AmlParseError("MultiName Path - can't have zero name segments")); + return Err(AmlError::AmlParseError("MultiName Path - can't have zero name segments")); } let mut current_seg = 0; @@ -149,40 +141,52 @@ fn parse_multi_name_path(data: &[u8]) -> Result<(Vec, usize), AmlInternalErr Ok((characters, multi_len)) } -pub fn parse_super_name(data: &[u8]) -> Result<(SuperName, usize), AmlInternalError> { +pub fn parse_super_name(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_selector! { - data, + data, namespace, scope.clone(), parse_simple_name, - parser_wrap!(SuperName::Type6OpCode, parse_type6_opcode), + parse_type6_opcode, parse_debug_obj }; - Err(AmlInternalError::AmlInvalidOpCode) + Err(AmlError::AmlInvalidOpCode) } -fn parse_debug_obj(data: &[u8]) -> Result<(SuperName, usize), AmlInternalError> { +fn parse_debug_obj(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode_extended!(data, 0x31); - Ok((SuperName::DebugObj, 2 as usize)) + + Ok(AmlParseType { + val: AmlValue::DebugObject, + len: 2 as usize + }) } -pub fn parse_simple_name(data: &[u8]) -> Result<(SuperName, usize), AmlInternalError> { +pub fn parse_simple_name(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_selector! { - data, - parser_wrap!(SuperName::NameString, parse_name_string), - parser_wrap!(SuperName::ArgObj, parse_arg_obj), - parser_wrap!(SuperName::LocalObj, parse_local_obj) + data, namespace, scope.clone(), + parse_name_string, + parse_arg_obj, + parse_local_obj }; - Err(AmlInternalError::AmlInvalidOpCode) + Err(AmlError::AmlInvalidOpCode) } -pub fn parse_target(data: &[u8]) -> Result<(Target, usize), AmlInternalError> { +pub fn parse_target(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { if data[0] == 0x00 { - Ok((Target::Null, 1 as usize)) + Ok(AmlParseType { + val: AmlValue::None, + len: 1 as usize + }) } else { - match parse_super_name(data) { - Ok((name, name_len)) => Ok((Target::SuperName(name), name_len)), - Err(e) => Err(e) - } + parse_super_name(data, namespace, scope.clone()) } } diff --git a/src/acpi/aml/parser.rs b/src/acpi/aml/parser.rs index 321f013..080a1ae 100644 --- a/src/acpi/aml/parser.rs +++ b/src/acpi/aml/parser.rs @@ -1,16 +1,10 @@ -use super::AmlValue; +use super::namespace::AmlValue; +use super::AmlError; -pub type ParseResult = Result; +pub type ParseResult = Result; +pub type AmlParseType = AmlParseTypeGeneric; -pub struct AmlParseType { - val: Option, - len: usize -} - -// TODO: make private -pub enum AmlInternalError { - AmlParseError(&'static str), - AmlInvalidOpCode, - AmlValueError, - AmlDeferredLoad +pub struct AmlParseTypeGeneric { + pub val: T, + pub len: usize } diff --git a/src/acpi/aml/parsermacros.rs b/src/acpi/aml/parsermacros.rs index 7c9e101..6b9555a 100644 --- a/src/acpi/aml/parsermacros.rs +++ b/src/acpi/aml/parsermacros.rs @@ -3,7 +3,7 @@ macro_rules! parser_selector { {$data:expr, $namespace:expr, $scope:expr, $func:expr} => { match $func($data, $namespace, $scope) { Ok(res) => return Ok(res), - Err(AmlInternalError::AmlInvalidOpCode) => (), + Err(AmlError::AmlInvalidOpCode) => (), Err(e) => return Err(e) } }; @@ -13,12 +13,29 @@ macro_rules! parser_selector { }; } +macro_rules! parser_selector_simple { + {$data:expr, $func:expr} => { + match $func($data) { + Ok(res) => return Ok(res), + Err(AmlError::AmlInvalidOpCode) => (), + Err(e) => return Err(e) + } + }; + {$data:expr, $func:expr, $($funcs:expr),+} => { + parser_selector_simple! {$data, $func}; + parser_selector_simple! {$data, $($funcs),*}; + }; +} + #[macro_export] macro_rules! parser_wrap { ($wrap:expr, $func:expr) => { - |data| { + |data, namespace, scope| { match $func(data) { - Ok((res, size)) => Ok(($wrap(res), size)), + Ok(res) => Ok(AmlParseTypeGeneric { + val: $wrap(res.val), + len: res.len + }), Err(e) => Err(e) } } @@ -29,12 +46,12 @@ macro_rules! parser_wrap { macro_rules! parser_opcode { ($data:expr, $opcode:expr) => { if $data[0] != $opcode { - return Err(AmlInternalError::AmlInvalidOpCode); + return Err(AmlError::AmlInvalidOpCode); } }; ($data:expr, $opcode:expr, $alternate_opcode:expr) => { if $data[0] != $opcode && $data[0] != $alternate_opcode { - return Err(AmlInternalError::AmlInvalidOpCode); + return Err(AmlError::AmlInvalidOpCode); } }; } @@ -43,7 +60,7 @@ macro_rules! parser_opcode { macro_rules! parser_opcode_extended { ($data:expr, $opcode:expr) => { if $data[0] != 0x5B || $data[1] != $opcode { - return Err(AmlInternalError::AmlInvalidOpCode); + return Err(AmlError::AmlInvalidOpCode); } }; } @@ -53,7 +70,7 @@ macro_rules! parser_verify_value { ($val:expr) => { match $val.val { Some(s) => s, - None => return Err(AmlInternalError::AmlValueError) + None => return Err(AmlError::AmlValueError) } }; } diff --git a/src/acpi/aml/pkglength.rs b/src/acpi/aml/pkglength.rs index 7c4ace8..b93939f 100644 --- a/src/acpi/aml/pkglength.rs +++ b/src/acpi/aml/pkglength.rs @@ -1,6 +1,6 @@ -use super::AmlInternalError; +use super::AmlError; -pub fn parse_pkg_length(data: &[u8]) -> Result<(usize, usize), AmlInternalError> { +pub fn parse_pkg_length(data: &[u8]) -> Result<(usize, usize), AmlError> { let lead_byte = data[0]; let count_bytes: usize = (lead_byte >> 6) as usize; @@ -10,7 +10,7 @@ pub fn parse_pkg_length(data: &[u8]) -> Result<(usize, usize), AmlInternalError> let upper_two = (lead_byte >> 4) & 0x03; if upper_two != 0 { - return Err(AmlInternalError::AmlParseError("Invalid package length")); + return Err(AmlError::AmlParseError("Invalid package length")); } let mut current_byte = 0; diff --git a/src/acpi/aml/termlist.rs b/src/acpi/aml/termlist.rs index 5e5482e..bc2a747 100644 --- a/src/acpi/aml/termlist.rs +++ b/src/acpi/aml/termlist.rs @@ -3,158 +3,91 @@ use collections::string::String; use collections::vec::Vec; use collections::btree_map::BTreeMap; -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}; -use super::type1opcode::{parse_type1_opcode, Type1OpCode}; -use super::type2opcode::{parse_type2_opcode, Type2OpCode}; +use super::AmlError; +use super::parser::{AmlParseType, ParseResult, AmlParseTypeGeneric}; +use super::namespace::{AmlValue, ObjectReference, FieldSelector, get_namespace_string}; +use super::namespacemodifier::parse_namespace_modifier; +use super::namedobj::parse_named_obj; +use super::dataobj::{parse_data_obj, parse_arg_obj, parse_local_obj}; +use super::type1opcode::parse_type1_opcode; +use super::type2opcode::parse_type2_opcode; use super::namestring::parse_name_string; -#[derive(Debug, Clone)] -pub enum TermArg { - LocalObj(Box), - DataObj(Box), - ArgObj(Box), - Type2Opcode(Box) -} - -#[derive(Debug, Clone)] -pub enum TermObj { - NamespaceModifier(Box), - NamedObj(Box), - Type1Opcode(Box), - Type2Opcode(Box) -} - -#[derive(Debug, Clone)] -pub enum Object { - NamespaceModifier(Box), - NamedObj(Box) -} - -#[derive(Debug, Clone)] -pub struct MethodInvocation { - -} - -impl AmlExecutable for Vec { - fn execute(&self, namespace: &mut BTreeMap, scope: String) -> Option { - for term in self { - term.execute(namespace, scope.clone()); - } - - None - } -} - -impl AmlExecutable for Object { - 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) - } - } -} - -impl AmlExecutable for Vec { - fn execute(&self, namespace: &mut BTreeMap, scope: String) -> Option { - for term in self { - term.execute(namespace, scope.clone()); - } - - None - } -} - -impl AmlExecutable for TermArg { - fn execute(&self, namespace: &mut BTreeMap, scope: String) -> Option { - match *self { - TermArg::LocalObj(ref l) => Some(AmlValue::Uninitialized), - TermArg::DataObj(ref d) => d.execute(namespace, scope), - TermArg::ArgObj(ref a) => Some(AmlValue::Uninitialized), - TermArg::Type2Opcode(ref o) => Some(AmlValue::Uninitialized) - } - } -} - -impl AmlExecutable for TermObj { - 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()), - TermObj::Type1Opcode(ref res) => res.execute(namespace, scope.clone()), - TermObj::Type2Opcode(ref res) => res.execute(namespace, scope.clone()) - } - } -} - pub fn parse_term_list(data: &[u8], namespace: &mut BTreeMap, scope: String) -> ParseResult { let mut current_offset: usize = 0; while current_offset < data.len() { - let (res, len) = parse_term_obj(&data[current_offset..], namespace, scope)?; - current_offset += len; + let res = parse_term_obj(&data[current_offset..], namespace, scope.clone())?; + current_offset += res.len; } Ok(AmlParseType { - val: None, + val: AmlValue::None, len: data.len() }) } -pub fn parse_term_arg(data: &[u8]) -> Result<(TermArg, usize), AmlInternalError> { +pub fn parse_term_arg(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_selector! { - data, - parser_wrap!(TermArg::LocalObj, parser_wrap!(Box::new, parse_local_obj)), - parser_wrap!(TermArg::DataObj, parser_wrap!(Box::new, parse_data_obj)), - parser_wrap!(TermArg::ArgObj, parser_wrap!(Box::new, parse_arg_obj)), - parser_wrap!(TermArg::Type2Opcode, parser_wrap!(Box::new, parse_type2_opcode)) + data, namespace, scope.clone(), + parse_local_obj, + parse_data_obj, + parse_arg_obj, + parse_type2_opcode }; - Err(AmlInternalError::AmlInvalidOpCode) + Err(AmlError::AmlInvalidOpCode) } -pub fn parse_object_list(data: &[u8]) -> Result, AmlInternalError> { - let mut terms: Vec = vec!(); +pub fn parse_object_list(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { let mut current_offset: usize = 0; while current_offset < data.len() { - let (res, len) = parse_object(&data[current_offset..])?; - terms.push(res); - current_offset += len; + let res = parse_object(&data[current_offset..], namespace, scope.clone())?; + current_offset += res.len; } - Ok(terms) + Ok(AmlParseType { + val: AmlValue::None, + len: data.len() + }) } -fn parse_object(data: &[u8]) -> Result<(Object, usize), AmlInternalError> { +fn parse_object(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_selector! { - data, - parser_wrap!(Object::NamespaceModifier, parser_wrap!(Box::new, parse_namespace_modifier)), - parser_wrap!(Object::NamedObj, parser_wrap!(Box::new, parse_named_obj)) + data, namespace, scope.clone(), + parse_namespace_modifier, + parse_named_obj }; - Err(AmlInternalError::AmlInvalidOpCode) + Err(AmlError::AmlInvalidOpCode) } -pub fn parse_method_invocation(data: &[u8]) -> Result<(MethodInvocation, usize), AmlInternalError> { - let (name, name_len) = parse_name_string(data)?; - Err(AmlInternalError::AmlDeferredLoad) +pub fn parse_method_invocation(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + let name = parse_name_string(data, namespace, scope)?; + Err(AmlError::AmlDeferredLoad) } fn parse_term_obj(data: &[u8], namespace: &mut BTreeMap, scope: String) -> ParseResult { parser_selector! { - data, namespace, scope, + data, namespace, scope.clone(), parse_namespace_modifier, parse_named_obj, parse_type1_opcode, parse_type2_opcode }; - Err(AmlInternalError::AmlInvalidOpCode) + Err(AmlError::AmlInvalidOpCode) } diff --git a/src/acpi/aml/type1opcode.rs b/src/acpi/aml/type1opcode.rs index d476a24..b32acf8 100644 --- a/src/acpi/aml/type1opcode.rs +++ b/src/acpi/aml/type1opcode.rs @@ -3,76 +3,22 @@ use collections::string::String; use collections::vec::Vec; use collections::btree_map::BTreeMap; -use super::{AmlInternalError, AmlExecutable, AmlValue}; +use super::AmlError; +use super::parser::{AmlParseType, ParseResult}; +use super::namespace::{AmlValue, ObjectReference}; 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}; - -#[derive(Debug, Clone)] -pub enum Type1OpCode { - DefBreak, - DefBreakPoint, - DefContinue, - DefFatal { - fatal_type: u8, - fatal_code: u16, - fatal_arg: TermArg - }, - DefNoop, - DefIfElse { - if_block: IfBlock, - else_block: IfBlock - }, - DefLoad { - name: String, - ddb_handle_object: SuperName - }, - DefNotify { - object: SuperName, - value: TermArg - }, - DefRelease(SuperName), - DefReset(SuperName), - DefSignal(SuperName), - DefSleep(TermArg), - DefStall(TermArg), - DefUnload(SuperName), - DefWhile { - predicate: TermArg, - block: Vec - }, - DefReturn(TermArg), - DeferredLoad(Vec) -} - -impl AmlExecutable for Type1OpCode { - fn execute(&self, namespace: &mut BTreeMap, scope: String) -> Option { - None - } -} - -#[derive(Debug, Clone)] -pub enum IfBlock { - If { - predicate: TermArg, - if_block: Vec - }, - Else(Vec), - NoBlock, - DeferredLoad(Vec) -} - -pub fn parse_type1_opcode(data: &[u8]) -> Result<(Type1OpCode, usize), AmlInternalError> { - match data[0] { - 0xA5 => return Ok((Type1OpCode::DefBreak, 1 as usize)), - 0xCC => return Ok((Type1OpCode::DefBreakPoint, 1 as usize)), - 0x9F => return Ok((Type1OpCode::DefContinue, 1 as usize)), - 0xA3 => return Ok((Type1OpCode::DefNoop, 1 as usize)), - _ => () - } +use super::termlist::{parse_term_arg, parse_term_list}; +use super::namestring::{parse_name_string, parse_super_name}; +pub fn parse_type1_opcode(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_selector! { - data, + data, namespace, scope.clone(), + parse_def_break, + parse_def_breakpoint, + parse_def_continue, + parse_def_noop, parse_def_fatal, parse_def_if_else, parse_def_load, @@ -87,174 +33,248 @@ pub fn parse_type1_opcode(data: &[u8]) -> Result<(Type1OpCode, usize), AmlIntern parse_def_while }; - Err(AmlInternalError::AmlInvalidOpCode) + Err(AmlError::AmlInvalidOpCode) } -fn parse_def_fatal(data: &[u8]) -> Result<(Type1OpCode, usize), AmlInternalError> { - if data[0] != 0x5B || data[1] != 0x32 { - return Err(AmlInternalError::AmlInvalidOpCode); - } +fn parse_def_break(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Implement + parser_opcode!(data, 0xA5); + + Ok(AmlParseType { + val: AmlValue::None, + len: 1 as usize + }) +} + +fn parse_def_breakpoint(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Implement + parser_opcode!(data, 0xCC); + + Ok(AmlParseType { + val: AmlValue::None, + len: 1 as usize + }) +} + +fn parse_def_continue(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Implement + parser_opcode!(data, 0x9F); + + Ok(AmlParseType { + val: AmlValue::None, + len: 1 as usize + }) +} + +fn parse_def_noop(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + parser_opcode!(data, 0xA3); + + Ok(AmlParseType { + val: AmlValue::None, + len: 1 as usize + }) +} + +fn parse_def_fatal(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + parser_opcode_extended!(data, 0x32); let fatal_type = data[2]; - let fatal_code: u16 = (data[3] as u16) + - ((data[4] as u16) << 8); - let (fatal_arg, fatal_arg_len) = parse_term_arg(&data[5..])?; + let fatal_code: u16 = (data[3] as u16) + ((data[4] as u16) << 8); + let fatal_arg = parse_term_arg(&data[5..], namespace, scope.clone())?; - Ok((Type1OpCode::DefFatal {fatal_type, fatal_code, fatal_arg}, fatal_arg_len + 5)) + Err(AmlError::AmlFatalError(fatal_type, fatal_code, fatal_arg.val)) } -fn parse_def_load(data: &[u8]) -> Result<(Type1OpCode, usize), AmlInternalError> { - if data[0] != 0x5B || data[1] != 0x20 { - return Err(AmlInternalError::AmlInvalidOpCode); - } +fn parse_def_load(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Load in the table pointed to by `name` + // TODO: Set DDB_Handle to the handle returned by loading in the table + // TODO: Run the AML parser on the table, in a secondary namespace + parser_opcode_extended!(data, 0x20); - let (name, name_len) = parse_name_string(&data[2..])?; - let (ddb_handle_object, ddb_handle_object_len) = parse_super_name(&data[2 + name_len..])?; - - Ok((Type1OpCode::DefLoad {name, ddb_handle_object}, 2 + name_len + ddb_handle_object_len)) + let name = parse_name_string(&data[2..], namespace, scope.clone())?; + let ddb_handle_object = parse_super_name(&data[2 + name.len..], namespace, scope.clone())?; + + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + name.len + ddb_handle_object.len + }) } -fn parse_def_notify(data: &[u8]) -> Result<(Type1OpCode, usize), AmlInternalError> { - if data[0] != 0x86 { - return Err(AmlInternalError::AmlInvalidOpCode); - } +fn parse_def_notify(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: This requires significantly more infrastructure from the OS itself, see 5.6.6 + parser_opcode!(data, 0x86); - let (object, object_len) = parse_super_name(&data[1..])?; - let (value, value_len) = parse_term_arg(&data[1 + object_len..])?; + let object = parse_super_name(&data[1..], namespace, scope.clone())?; + let value = parse_term_arg(&data[1 + object.len..], namespace, scope.clone())?; - Ok((Type1OpCode::DefNotify {object, value}, 1 + object_len + value_len)) + Ok(AmlParseType { + val: AmlValue::None, + len: 1 + object.len + value.len + }) } -fn parse_def_release(data: &[u8]) -> Result<(Type1OpCode, usize), AmlInternalError> { - if data[0] != 0x5B || data[1] != 0x27 { - return Err(AmlInternalError::AmlInvalidOpCode); - } +fn parse_def_release(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Check ownership of the mutex pointed to + // TODO: FATAL if not owned + // TODO: Release if it is + parser_opcode_extended!(data, 0x27); - let (object, object_len) = parse_super_name(&data[2..])?; + let object = parse_super_name(&data[2..], namespace, scope.clone())?; - Ok((Type1OpCode::DefRelease(object), 2 + object_len)) + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + object.len + }) } -fn parse_def_reset(data: &[u8]) -> Result<(Type1OpCode, usize), AmlInternalError> { - if data[0] != 0x5B || data[1] != 0x26 { - return Err(AmlInternalError::AmlInvalidOpCode); - } +fn parse_def_reset(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: object (of type Event) is a semaphore. Reset the resource count to 0 + parser_opcode_extended!(data, 0x26); - let (object, object_len) = parse_super_name(&data[2..])?; + let object = parse_super_name(&data[2..], namespace, scope.clone())?; - Ok((Type1OpCode::DefReset(object), 2 + object_len)) + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + object.len + }) } -fn parse_def_signal(data: &[u8]) -> Result<(Type1OpCode, usize), AmlInternalError> { - if data[0] != 0x5B || data[1] != 0x24 { - return Err(AmlInternalError::AmlInvalidOpCode); - } +fn parse_def_signal(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Increment the resource count of the semaphore + parser_opcode_extended!(data, 0x24); - let (object, object_len) = parse_super_name(&data[2..])?; + let object = parse_super_name(&data[2..], namespace, scope.clone())?; - Ok((Type1OpCode::DefSignal(object), 2 + object_len)) + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + object.len + }) } -fn parse_def_sleep(data: &[u8]) -> Result<(Type1OpCode, usize), AmlInternalError> { - if data[0] != 0x5B || data[1] != 0x22 { - return Err(AmlInternalError::AmlInvalidOpCode); - } +fn parse_def_sleep(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Sleep the processor for the specified number of milliseconds (minimum) + parser_opcode_extended!(data, 0x22); - let (time, time_len) = parse_term_arg(&data[2..])?; + let time = parse_term_arg(&data[2..], namespace, scope.clone())?; - Ok((Type1OpCode::DefSleep(time), 2 + time_len)) + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + time.len + }) } -fn parse_def_stall(data: &[u8]) -> Result<(Type1OpCode, usize), AmlInternalError> { - if data[0] != 0x5B || data[1] != 0x21 { - return Err(AmlInternalError::AmlInvalidOpCode); - } +fn parse_def_stall(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Sleep the processor for the specified number of microseconds (minimum) + parser_opcode_extended!(data, 0x21); - let (time, time_len) = parse_term_arg(&data[2..])?; + let time = parse_term_arg(&data[2..], namespace, scope.clone())?; - Ok((Type1OpCode::DefStall(time), 2 + time_len)) + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + time.len + }) } -fn parse_def_unload(data: &[u8]) -> Result<(Type1OpCode, usize), AmlInternalError> { - if data[0] != 0x5B || data[1] != 0x2A { - return Err(AmlInternalError::AmlInvalidOpCode); - } +fn parse_def_unload(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: remove from namespace all values added when `object` was loaded + // TODO: globally synchronous (how?) + parser_opcode_extended!(data, 0x2A); - let (object, object_len) = parse_super_name(&data[2..])?; + let object = parse_super_name(&data[2..], namespace, scope.clone())?; - Ok((Type1OpCode::DefUnload(object), 2 + object_len)) + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + object.len + }) } -fn parse_def_if_else(data: &[u8]) -> Result<(Type1OpCode, usize), AmlInternalError> { - if data[0] != 0xA0 { - return Err(AmlInternalError::AmlInvalidOpCode); +fn parse_def_if_else(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + parser_opcode!(data, 0xA0); + + let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; + let if_condition = parse_term_arg(&data[1 + pkg_length_len .. 1 + pkg_length], namespace, scope.clone())?; + + let (else_length, else_length_len) = if data.len() > 1 + pkg_length && data[1 + pkg_length] == 0xA1 { + parse_pkg_length(&data[2 + pkg_length..])? + } else { + (0 as usize, 0 as usize) + }; + + if if_condition.val.get_as_integer()? > 0 { + parse_term_list(&data[1 + pkg_length_len + if_condition.len .. 1 + pkg_length], + namespace, scope.clone())?; + } else if else_length > 0 { + parse_term_list(&data[2 + pkg_length + else_length_len .. 2 + pkg_length + else_length], + namespace, scope.clone())?; } + Ok(AmlParseType { + val: AmlValue::None, + len: 1 + pkg_length + if else_length > 0 { 1 + else_length } else { 0 } + }) +} + +fn parse_def_while(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + parser_opcode!(data, 0xA2); + let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; - let if_block = match parse_term_arg(&data[1 + pkg_length_len..]) { - Ok((predicate, predicate_len)) => { - match parse_term_list(&data[1 + pkg_length_len + predicate_len .. 1 + pkg_length]) { - Ok(if_block) => IfBlock::If {predicate, if_block}, - Err(AmlInternalError::AmlDeferredLoad) => - IfBlock::DeferredLoad(data[0 .. 1 + pkg_length].to_vec()), - Err(e) => return Err(e) - } - }, - Err(AmlInternalError::AmlDeferredLoad) => - IfBlock::DeferredLoad(data[0 .. 1 + pkg_length].to_vec()), - Err(e) => return Err(e) - }; - - let (else_block, else_block_len) = parse_def_else(&data[1 + pkg_length..])?; - - return Ok((Type1OpCode::DefIfElse {if_block, else_block}, - pkg_length + else_block_len + 1)); + loop { + let predicate = parse_term_arg(&data[1 + pkg_length_len..], namespace, scope.clone())?; + if predicate.val.get_as_integer()? == 0 { + break; + } + + parse_term_list(&data[1 + pkg_length_len + predicate.len .. 1 + pkg_length], namespace, scope.clone())?; + } + + Ok(AmlParseType { + val: AmlValue::None, + len: 1 + pkg_length + }) } -fn parse_def_else(data: &[u8]) -> Result<(IfBlock, usize), AmlInternalError> { - if data.len() == 0 || data[0] != 0xA1 { - // We might be at the very end of a buffer, in which case there isn't an else - return Ok((IfBlock::NoBlock, 0)); - } +fn parse_def_return(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Return to the calling context + // TODO: We need contexts for that + parser_opcode!(data, 0xA4); - let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; - match parse_term_list(&data[1 + pkg_length_len .. 1 + pkg_length]) { - Ok(term_list) => Ok((IfBlock::Else(term_list), 1 + pkg_length)), - Err(AmlInternalError::AmlDeferredLoad) => - Ok((IfBlock::DeferredLoad(data[0 .. 1 + pkg_length].to_vec()), 1 + pkg_length)), - Err(e) => return Err(e) - } -} - -fn parse_def_while(data: &[u8]) -> Result<(Type1OpCode, usize), AmlInternalError> { - if data[0] != 0xA2 { - return Err(AmlInternalError::AmlInvalidOpCode); - } - - let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; - let (predicate, predicate_len) = match parse_term_arg(&data[1 + pkg_length_len..]) { - Ok(p) => p, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((Type1OpCode::DeferredLoad(data[0 .. 1 + pkg_length].to_vec()), 1 + pkg_length)), - Err(e) => return Err(e) - }; - let block = match parse_term_list(&data[1 + pkg_length_len + predicate_len .. 1 + pkg_length]) { - Ok(p) => p, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((Type1OpCode::DeferredLoad(data[0 .. 1 + pkg_length].to_vec()), 1 + pkg_length)), - Err(e) => return Err(e) - }; - - Ok((Type1OpCode::DefWhile {predicate, block}, pkg_length + 1)) -} - -fn parse_def_return(data: &[u8]) -> Result<(Type1OpCode, usize), AmlInternalError> { - if data[0] != 0xA4 { - return Err(AmlInternalError::AmlInvalidOpCode); - } - - let (arg_object, arg_object_len) = parse_term_arg(&data[1..])?; - - Ok((Type1OpCode::DefReturn(arg_object), 1 + arg_object_len)) + let arg_object = parse_term_arg(&data[1..], namespace, scope.clone())?; + + Ok(AmlParseType { + val: AmlValue::None, + len: 1 + arg_object.len + }) } diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index e96bdbc..eef85e1 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -3,236 +3,13 @@ use collections::string::String; use collections::vec::Vec; use collections::btree_map::BTreeMap; -use super::{AmlInternalError, AmlExecutable, AmlValue}; +use super::AmlError; +use super::parser::{AmlParseType, ParseResult}; +use super::namespace::{AmlValue, ObjectReference}; 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, - SuperName, Target}; -use super::dataobj::{parse_data_ref_obj, DataRefObj}; - -#[derive(Debug, Clone)] -pub enum Type2OpCode { - DefAcquire { - object: SuperName, - timeout: u16 - }, - DefBuffer(DefBuffer), - DefPackage(DefPackage), - DefVarPackage(DefVarPackage), - DefDerefOf(TermArg), - DefRefOf(SuperName), - DefIncrement(SuperName), - DefIndex(DefIndex), - DefDecrement(SuperName), - DefFindSetLeftBit { - operand: TermArg, - target: Target - }, - DefFindSetRightBit { - operand: TermArg, - target: Target - }, - DefFromBCD { - operand: TermArg, - target: Target - }, - DefDivide { - dividend: TermArg, - divisor: TermArg, - remainder: Target, - quotient: Target - }, - DefCondRefOf { - operand: SuperName, - target: Target - }, - DefCopyObject { - source: TermArg, - destination: SuperName - }, - DefLAnd { - lhs: TermArg, - rhs: TermArg - }, - DefLEqual { - lhs: TermArg, - rhs: TermArg - }, - DefLGreater { - lhs: TermArg, - rhs: TermArg - }, - DefLLess { - lhs: TermArg, - rhs: TermArg - }, - DefLNot(TermArg), - DefLOr { - lhs: TermArg, - rhs: TermArg - }, - DefSizeOf(SuperName), - DefStore { - operand: TermArg, - target: SuperName - }, - DefSubtract { - minuend: TermArg, - subtrahend: TermArg, - target: Target - }, - DefToBuffer { - operand: TermArg, - target: Target - }, - DefToHexString { - operand: TermArg, - target: Target - }, - DefToBCD { - operand: TermArg, - target: Target - }, - DefToDecimalString { - operand: TermArg, - target: Target - }, - DefToInteger { - operand: TermArg, - target: Target - }, - DefToString { - operand: TermArg, - length: TermArg, - target: Target - }, - DefConcat { - lhs: TermArg, - rhs: TermArg, - target: Target - }, - DefConcatRes { - lhs: TermArg, - rhs: TermArg, - target: Target - }, - DefShiftLeft { - lhs: TermArg, - rhs: TermArg, - target: Target - }, - DefShiftRight { - lhs: TermArg, - rhs: TermArg, - target: Target - }, - DefAdd { - lhs: TermArg, - rhs: TermArg, - target: Target - }, - DefMultiply { - lhs: TermArg, - rhs: TermArg, - target: Target - }, - DefMod { - dividend: TermArg, - divisor: TermArg, - target: Target - }, - DefAnd { - lhs: TermArg, - rhs: TermArg, - target: Target - }, - DefNAnd { - lhs: TermArg, - rhs: TermArg, - target: Target - }, - DefOr { - lhs: TermArg, - rhs: TermArg, - target: Target - }, - DefXor { - lhs: TermArg, - rhs: TermArg, - target: Target - }, - DefNOr { - lhs: TermArg, - rhs: TermArg, - target: Target - }, - DefNot { - operand: TermArg, - target: Target - }, - DefLoadTable { - signature: TermArg, - oem_id: TermArg, - oem_table_id: TermArg, - root_path: TermArg, - parameter_path: TermArg, - parameter_data: TermArg - }, - DefMatch { - search_pkg: TermArg, - first_operation: MatchOpcode, - first_operand: TermArg, - second_operation: MatchOpcode, - second_operand: TermArg, - start_index: TermArg - }, - DefMid { - source: TermArg, - index: TermArg, - length: TermArg, - target: Target - }, - DefWait { - event_object: SuperName, - operand: TermArg - }, - DefObjectType(DefObjectType), - DefTimer, - MethodInvocation(MethodInvocation) -} - -impl AmlExecutable for Type2OpCode { - fn execute(&self, namespace: &mut BTreeMap, scope: String) -> Option { - None - } -} - -impl AmlExecutable for DefBuffer { - fn execute(&self, namespace: &mut BTreeMap, scope: String) -> Option { - match *self { - DefBuffer::Buffer { ref buffer_size, ref byte_list } => { - let length = match buffer_size.execute(namespace, scope.clone()) { - Some(l) => Box::new(l), - _ => return None - }; - - Some(AmlValue::Buffer { - length: length, - byte_list: byte_list.clone() - }) - }, - _ => None - } - } -} - -#[derive(Debug, Clone)] -pub enum DefObjectType { - SuperName(SuperName), - DefIndex(DefIndex), - DefRefOf(SuperName), - DefDerefOf(TermArg) -} +use super::termlist::{parse_term_arg, parse_method_invocation}; +use super::namestring::{parse_super_name, parse_target, parse_name_string, parse_simple_name}; +use super::dataobj::parse_data_ref_obj; #[derive(Debug, Clone)] pub enum MatchOpcode { @@ -244,84 +21,11 @@ pub enum MatchOpcode { MGT } -#[derive(Debug, Clone)] -pub enum Type6OpCode { - DefDerefOf(TermArg), - DefRefOf(Box), - DefIndex(DefIndex), - MethodInvocation(MethodInvocation) -} - -#[derive(Debug, Clone)] -pub struct DefIndex { - obj: TermArg, - idx: TermArg, - target: Box -} - -#[derive(Debug, Clone)] -pub enum DefBuffer { - Buffer { - buffer_size: TermArg, - byte_list: Vec - }, - DeferredLoad(Vec) -} - -#[derive(Debug, Clone)] -pub enum DefPackage { - Package { - num_elements: u8, - elements: Vec - }, - DeferredLoad(Vec) -} - -#[derive(Debug, Clone)] -pub enum DefVarPackage { - Package { - num_elements: TermArg, - elements: Vec - }, - DeferredLoad(Vec) -} - -#[derive(Debug, Clone)] -pub enum PackageElement { - DataRefObj(DataRefObj), - NameString(String) -} - -impl AmlExecutable for DefPackage { - fn execute(&self, namespace: &mut BTreeMap, scope: String) -> Option { - match *self { - DefPackage::Package { ref num_elements, ref elements } => { - let mut values: Vec = vec!(); - - for element in elements { - match *element { - PackageElement::DataRefObj(ref d) => { - let elem = match d.execute(namespace, scope.clone()) { - Some(e) => e, - None => continue - }; - - values.push(elem); - }, - _ => return None - } - } - - Some(AmlValue::Package(values)) - }, - _ => None - } - } -} - -pub fn parse_type2_opcode(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +pub fn parse_type2_opcode(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_selector! { - data, + data, namespace, scope.clone(), parse_def_increment, parse_def_acquire, parse_def_wait, @@ -364,589 +68,905 @@ pub fn parse_type2_opcode(data: &[u8]) -> Result<(Type2OpCode, usize), AmlIntern parse_def_nor, parse_def_not, parse_def_timer, - parser_wrap!(Type2OpCode::DefBuffer, parse_def_buffer), - parser_wrap!(Type2OpCode::DefPackage, parse_def_package), - parser_wrap!(Type2OpCode::DefVarPackage, parse_def_var_package), - parser_wrap!(Type2OpCode::DefObjectType, parse_def_object_type), - parser_wrap!(Type2OpCode::DefDerefOf, parse_def_deref_of), - parser_wrap!(Type2OpCode::DefRefOf, parse_def_ref_of), - parser_wrap!(Type2OpCode::DefIndex, parse_def_index), - parser_wrap!(Type2OpCode::MethodInvocation, parse_method_invocation) + parse_def_buffer, + parse_def_package, + parse_def_var_package, + parse_def_object_type, + parse_def_deref_of, + parse_def_ref_of, + parse_def_index, + parse_method_invocation }; - Err(AmlInternalError::AmlInvalidOpCode) + Err(AmlError::AmlInvalidOpCode) } -pub fn parse_type6_opcode(data: &[u8]) -> Result<(Type6OpCode, usize), AmlInternalError> { +pub fn parse_type6_opcode(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_selector! { - data, - parser_wrap!(Type6OpCode::DefDerefOf, parse_def_deref_of), - parser_wrap!(Type6OpCode::DefRefOf, parser_wrap!(Box::new, parse_def_ref_of)), - parser_wrap!(Type6OpCode::DefIndex, parse_def_index), - parser_wrap!(Type6OpCode::MethodInvocation, parse_method_invocation) + data, namespace, scope.clone(), + parse_def_deref_of, + parse_def_ref_of, + parse_def_index, + parse_method_invocation }; - Err(AmlInternalError::AmlInvalidOpCode) + Err(AmlError::AmlInvalidOpCode) } -pub fn parse_def_object_type(data: &[u8]) -> Result<(DefObjectType, usize), AmlInternalError> { +pub fn parse_def_object_type(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode!(data, 0x8E); parser_selector! { - data, - parser_wrap!(DefObjectType::SuperName, parse_super_name), - parser_wrap!(DefObjectType::DefRefOf, parse_def_ref_of), - parser_wrap!(DefObjectType::DefDerefOf, parse_def_deref_of), - parser_wrap!(DefObjectType::DefIndex, parse_def_index) + data, namespace, scope.clone(), + parse_super_name, + parse_def_ref_of, + parse_def_deref_of, + parse_def_index } - Err(AmlInternalError::AmlInvalidOpCode) + Err(AmlError::AmlInvalidOpCode) } -pub fn parse_def_package(data: &[u8]) -> Result<(DefPackage, usize), AmlInternalError> { +pub fn parse_def_package(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Handle deferred loads in here + // TODO: Truncate/extend array if necessary parser_opcode!(data, 0x12); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; let num_elements = data[1 + pkg_length_len]; - - let elements = match parse_package_elements_list(&data[2 + pkg_length_len .. 1 + pkg_length]) { - Ok(e) => e, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((DefPackage::DeferredLoad(data[0 .. 1 + pkg_length].to_vec()), 1 + pkg_length)), - Err(e) => return Err(e) - }; - - Ok((DefPackage::Package {num_elements, elements}, 1 + pkg_length)) + let elements = parse_package_elements_list(&data[2 + pkg_length_len .. 1 + pkg_length], + namespace, scope.clone())?; + + Ok(AmlParseType { + val: elements.val, + len: 1 + pkg_length + }) } -pub fn parse_def_var_package(data: &[u8]) -> Result<(DefVarPackage, usize), AmlInternalError> { +pub fn parse_def_var_package(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Handle deferred loads in here + // TODO: Truncate/extend array if necessary parser_opcode!(data, 0x13); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; - let (num_elements, num_elements_len) = parse_term_arg(&data[1 + pkg_length_len ..])?; - - let elements = match parse_package_elements_list(&data[1 + pkg_length_len + num_elements_len .. - 1 + pkg_length]) { - Ok(e) => e, - Err(AmlInternalError::AmlDeferredLoad) => - return Ok((DefVarPackage::DeferredLoad(data[0 .. 1 + pkg_length].to_vec()), - 1 + pkg_length)), - Err(e) => return Err(e) - }; - - Ok((DefVarPackage::Package {num_elements, elements}, 1 + pkg_length)) + let num_elements = parse_term_arg(&data[1 + pkg_length_len .. 1 + pkg_length], namespace, scope.clone())?; + let elements = parse_package_elements_list(&data[1 + pkg_length_len + num_elements.len .. + 1 + pkg_length], namespace, scope.clone())?; + + Ok(AmlParseType { + val: elements.val, + len: 1 + pkg_length + }) } -fn parse_package_elements_list(data: &[u8]) -> Result, AmlInternalError> { +fn parse_package_elements_list(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { let mut current_offset: usize = 0; - let mut elements: Vec = vec!(); + let mut elements: Vec = vec!(); while current_offset < data.len() { - match parse_data_ref_obj(&data[current_offset ..]) { - Ok((data_ref_obj, data_ref_obj_len)) => { - elements.push(PackageElement::DataRefObj(data_ref_obj)); - current_offset += data_ref_obj_len; - }, - Err(AmlInternalError::AmlInvalidOpCode) => - match parse_name_string(&data[current_offset ..]) { - Ok((name_string, name_string_len)) => { - elements.push(PackageElement::NameString(name_string)); - current_offset += name_string_len; - }, - Err(e) => return Err(e) - }, - Err(e) => return Err(e) - } + let dro = if let Ok(e) = parse_data_ref_obj(&data[current_offset..], namespace, scope.clone()) { + e + } else { + parse_name_string(&data[current_offset..], namespace, scope.clone())? + }; + + elements.push(dro.val); + current_offset += dro.len; } - Ok(elements) + Ok(AmlParseType { + val: AmlValue::Package(elements), + len: data.len() + }) } -pub fn parse_def_buffer(data: &[u8]) -> Result<(DefBuffer, usize), AmlInternalError> { +pub fn parse_def_buffer(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Perform computation parser_opcode!(data, 0x11); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; - let (buffer_size, buffer_size_len) = match parse_term_arg(&data[1 + pkg_length_len..]) { - Ok(s) => s, - Err(AmlInternalError::AmlDeferredLoad) => return Ok((DefBuffer::DeferredLoad( - data[0 .. 1 + pkg_length].to_vec() - ), 1 + pkg_length)), - Err(e) => return Err(e), - }; - let byte_list = data[1 + pkg_length_len + buffer_size_len .. 1 + pkg_length].to_vec(); + let buffer_size = parse_term_arg(&data[1 + pkg_length_len..], namespace, scope.clone())?; + let byte_list = data[1 + pkg_length_len + buffer_size.len .. 1 + pkg_length].to_vec(); - Ok((DefBuffer::Buffer {buffer_size, byte_list}, pkg_length + 1)) + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 1 + pkg_length + }) } -fn parse_def_ref_of(data: &[u8]) -> Result<(SuperName, usize), AmlInternalError> { +fn parse_def_ref_of(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Perform computation parser_opcode!(data, 0x71); - let (obj_reference, obj_reference_len) = parse_super_name(&data[1..])?; - Ok((obj_reference, obj_reference_len + 1)) + let obj = parse_super_name(&data[1..], namespace, scope.clone())?; + + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 1 + obj.len + }) } -fn parse_def_deref_of(data: &[u8]) -> Result<(TermArg, usize), AmlInternalError> { +fn parse_def_deref_of(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Perform computation parser_opcode!(data, 0x83); - let (obj_reference, obj_reference_len) = parse_term_arg(&data[1..])?; - Ok((obj_reference, obj_reference_len + 1)) + let obj = parse_term_arg(&data[1..], namespace, scope.clone())?; + + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 1 + obj.len + }) } -fn parse_def_acquire(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_acquire(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Store the result + // TODO: Perform computation parser_opcode_extended!(data, 0x23); - let (object, object_len) = parse_super_name(&data[2..])?; - let timeout = (data[2 + object_len] as u16) + - ((data[3 + object_len] as u16) << 8); - - Ok((Type2OpCode::DefAcquire {object, timeout}, object_len + 4)) + let obj = parse_super_name(&data[1..], namespace, scope.clone())?; + let timeout = (data[2 + obj.len] as u16) + ((data[3 + obj.len] as u16) << 8); + + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 4 + obj.len + }) } -fn parse_def_increment(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_increment(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Store the result + // TODO: Perform computation parser_opcode!(data, 0x75); - let (obj, obj_len) = parse_super_name(&data[1..])?; - Ok((Type2OpCode::DefIncrement(obj), obj_len + 1)) + let obj = parse_super_name(&data[1..], namespace, scope.clone())?; + + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 1 + obj.len + }) } -fn parse_def_index(data: &[u8]) -> Result<(DefIndex, usize), AmlInternalError> { +fn parse_def_index(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Store the result, if appropriate + // TODO: Perform computation parser_opcode!(data, 0x88); - let (obj, obj_len) = parse_term_arg(&data[1..])?; - let (idx, idx_len) = parse_term_arg(&data[1 + obj_len..])?; - let (target, target_len) = parse_target(&data[1 + obj_len + idx_len..])?; - - Ok((DefIndex {obj, idx, target: Box::new(target)}, 1 + obj_len + idx_len + target_len)) + let obj = parse_term_arg(&data[1..], namespace, scope.clone())?; + let idx = parse_term_arg(&data[1 + obj.len..], namespace, scope.clone())?; + let target = parse_target(&data[1 + obj.len + idx.len..], namespace, scope.clone())?; + + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 1 + obj.len + idx.len + target.len + }) } -fn parse_def_land(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_land(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode!(data, 0x90); - let (lhs, lhs_len) = parse_term_arg(&data[1..])?; - let (rhs, rhs_len) = parse_term_arg(&data[1 + lhs_len..])?; + let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; + let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefLAnd {lhs, rhs}, 1 + lhs_len + rhs_len)) + let result = if lhs.val.get_as_integer()? > 0 && rhs.val.get_as_integer()? > 0 { 1 } else { 0 }; + + Ok(AmlParseType { + val: AmlValue::IntegerConstant(result), + len: 1 + lhs.len + rhs.len + }) } -fn parse_def_lequal(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_lequal(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode!(data, 0x93); - let (lhs, lhs_len) = parse_term_arg(&data[1..])?; - let (rhs, rhs_len) = parse_term_arg(&data[1 + lhs_len..])?; + let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; + let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefLEqual {lhs, rhs}, 1 + lhs_len + rhs_len)) + let result = if lhs.val.get_as_integer()? == rhs.val.get_as_integer()? { 1 } else { 0 }; + + Ok(AmlParseType { + val: AmlValue::IntegerConstant(result), + len: 1 + lhs.len + rhs.len + }) } -fn parse_def_lgreater(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_lgreater(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode!(data, 0x94); - let (lhs, lhs_len) = parse_term_arg(&data[1..])?; - let (rhs, rhs_len) = parse_term_arg(&data[1 + lhs_len..])?; + let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; + let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefLGreater {lhs, rhs}, 1 + lhs_len + rhs_len)) + let result = if lhs.val.get_as_integer()? > rhs.val.get_as_integer()? { 1 } else { 0 }; + + Ok(AmlParseType { + val: AmlValue::IntegerConstant(result), + len: 1 + lhs.len + rhs.len + }) } -fn parse_def_lless(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_lless(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode!(data, 0x95); - let (lhs, lhs_len) = parse_term_arg(&data[1..])?; - let (rhs, rhs_len) = parse_term_arg(&data[1 + lhs_len..])?; + let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; + let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefLLess {lhs, rhs}, 1 + lhs_len + rhs_len)) + let result = if lhs.val.get_as_integer()? < rhs.val.get_as_integer()? { 1 } else { 0 }; + + Ok(AmlParseType { + val: AmlValue::IntegerConstant(result), + len: 1 + lhs.len + rhs.len + }) } -fn parse_def_lnot(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_lnot(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode!(data, 0x92); - let (operand, operand_len) = parse_term_arg(&data[1..])?; - - Ok((Type2OpCode::DefLNot(operand), 1 + operand_len)) + let operand = parse_term_arg(&data[1..], namespace, scope.clone())?; + let result = if operand.val.get_as_integer()? == 0 { 1 } else { 0 }; + + Ok(AmlParseType { + val: AmlValue::IntegerConstant(result), + len: 1 + operand.len + }) } -fn parse_def_lor(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_lor(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { parser_opcode!(data, 0x91); - let (lhs, lhs_len) = parse_term_arg(&data[1..])?; - let (rhs, rhs_len) = parse_term_arg(&data[1 + lhs_len..])?; + let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; + let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefLOr {lhs, rhs}, 1 + lhs_len + rhs_len)) + let result = if lhs.val.get_as_integer()? > 0 || rhs.val.get_as_integer()? > 0 { 1 } else { 0 }; + + Ok(AmlParseType { + val: AmlValue::IntegerConstant(result), + len: 1 + lhs.len + rhs.len + }) } -fn parse_def_to_hex_string(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_to_hex_string(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Compute the result + // TODO: Store the result, if appropriate parser_opcode!(data, 0x98); - let (operand, operand_len) = parse_term_arg(&data[1..])?; - let (target, target_len) = parse_target(&data[1 + operand_len..])?; + let operand = parse_term_arg(&data[2..], namespace, scope.clone())?; + let target = parse_target(&data[2 + operand.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefToHexString {operand, target}, 1 + operand_len + target_len)) + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 1 + operand.len + target.len + }) } -fn parse_def_to_buffer(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_to_buffer(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Compute the result + // TODO: Store the result, if appropriate parser_opcode!(data, 0x96); - let (operand, operand_len) = parse_term_arg(&data[1..])?; - let (target, target_len) = parse_target(&data[1 + operand_len..])?; + let operand = parse_term_arg(&data[2..], namespace, scope.clone())?; + let target = parse_target(&data[2 + operand.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefToBuffer {operand, target}, 1 + operand_len + target_len)) + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 1 + operand.len + target.len + }) } -fn parse_def_to_bcd(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_to_bcd(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Compute the result + // TODO: Store the result, if appropriate parser_opcode_extended!(data, 0x29); - let (operand, operand_len) = parse_term_arg(&data[2..])?; - let (target, target_len) = parse_target(&data[2 + operand_len..])?; + let operand = parse_term_arg(&data[2..], namespace, scope.clone())?; + let target = parse_target(&data[2 + operand.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefToBCD {operand, target}, 2 + operand_len + target_len)) + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 1 + operand.len + target.len + }) } -fn parse_def_to_decimal_string(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_to_decimal_string(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Compute the result + // TODO: Store the result, if appropriate parser_opcode!(data, 0x97); - let (operand, operand_len) = parse_term_arg(&data[1..])?; - let (target, target_len) = parse_target(&data[1 + operand_len..])?; + let operand = parse_term_arg(&data[2..], namespace, scope.clone())?; + let target = parse_target(&data[2 + operand.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefToDecimalString {operand, target}, 1 + operand_len + target_len)) + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 1 + operand.len + target.len + }) } -fn parse_def_to_integer(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_to_integer(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Compute the result + // TODO: Store the result, if appropriate parser_opcode!(data, 0x99); - let (operand, operand_len) = parse_term_arg(&data[1..])?; - let (target, target_len) = parse_target(&data[1 + operand_len..])?; + let operand = parse_term_arg(&data[2..], namespace, scope.clone())?; + let target = parse_target(&data[2 + operand.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefToInteger {operand, target}, 1 + operand_len + target_len)) + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 1 + operand.len + target.len + }) } -fn parse_def_to_string(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_to_string(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Compute the result + // TODO: Store the result, if appropriate parser_opcode!(data, 0x9C); - let (operand, operand_len) = parse_term_arg(&data[1..])?; - let (length, length_len) = parse_term_arg(&data[1 + operand_len..])?; - let (target, target_len) = parse_target(&data[1 + operand_len + length_len..])?; + let operand = parse_term_arg(&data[1..], namespace, scope.clone())?; + let length = parse_term_arg(&data[1 + operand.len..], namespace, scope.clone())?; + let target = parse_target(&data[1 + operand.len + length.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefToString {operand, length, target}, 1 + operand_len + length_len + target_len)) + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 1 + operand.len + length.len + target.len + }) } -fn parse_def_subtract(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_subtract(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Store the result, if appropriate parser_opcode!(data, 0x74); - let (minuend, minuend_len) = parse_term_arg(&data[1..])?; - let (subtrahend, subtrahend_len) = parse_term_arg(&data[1 + minuend_len..])?; - let (target, target_len) = parse_target(&data[1 + minuend_len + subtrahend_len..])?; + let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; + let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefSubtract {minuend, subtrahend, target}, 1 + minuend_len + subtrahend_len + target_len)) + let result = lhs.val.get_as_integer()? - rhs.val.get_as_integer()?; + + Ok(AmlParseType { + val: AmlValue::IntegerConstant(result), + len: 1 + lhs.len + rhs.len + target.len + }) } -fn parse_def_size_of(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_size_of(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Perform the computation parser_opcode!(data, 0x87); - let (name, name_len) = parse_super_name(&data[1..])?; - Ok((Type2OpCode::DefSizeOf(name), name_len + 1)) + let name = parse_super_name(&data[1..], namespace, scope.clone())?; + + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 1 + name.len + }) } -fn parse_def_store(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_store(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Perform the store parser_opcode!(data, 0x70); - let (operand, operand_len) = parse_term_arg(&data[1..])?; - let (target, target_len) = parse_super_name(&data[1 + operand_len..])?; - - Ok((Type2OpCode::DefStore {operand, target}, operand_len + target_len + 1)) + let operand = parse_term_arg(&data[1..], namespace, scope.clone())?; + let target = parse_super_name(&data[1 + operand.len..], namespace, scope.clone())?; + + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 1 + operand.len + target.len + }) } -fn parse_def_or(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_or(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Store the result, if appropriate parser_opcode!(data, 0x7D); - let (lhs, lhs_len) = parse_term_arg(&data[1..])?; - let (rhs, rhs_len) = parse_term_arg(&data[1 + lhs_len..])?; - let (target, target_len) = parse_target(&data[1 + lhs_len + rhs_len..])?; - - Ok((Type2OpCode::DefOr {lhs, rhs, target}, 1 + lhs_len + rhs_len + target_len)) + let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; + let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; + + let result = lhs.val.get_as_integer()? | rhs.val.get_as_integer()?; + + Ok(AmlParseType { + val: AmlValue::IntegerConstant(result), + len: 1 + lhs.len + rhs.len + target.len + }) } -fn parse_def_shift_left(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_shift_left(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Store the result, if appropriate parser_opcode!(data, 0x79); - let (lhs, lhs_len) = parse_term_arg(&data[1..])?; - let (rhs, rhs_len) = parse_term_arg(&data[1 + lhs_len..])?; - let (target, target_len) = parse_target(&data[1 + lhs_len + rhs_len..])?; - - Ok((Type2OpCode::DefShiftLeft {lhs, rhs, target}, 1 + lhs_len + rhs_len + target_len)) + let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; + let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; + + let result = lhs.val.get_as_integer()? >> rhs.val.get_as_integer()?; + + Ok(AmlParseType { + val: AmlValue::IntegerConstant(result), + len: 1 + lhs.len + rhs.len + target.len + }) } -fn parse_def_shift_right(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_shift_right(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Store the result, if appropriate parser_opcode!(data, 0x7A); - let (lhs, lhs_len) = parse_term_arg(&data[1..])?; - let (rhs, rhs_len) = parse_term_arg(&data[1 + lhs_len..])?; - let (target, target_len) = parse_target(&data[1 + lhs_len + rhs_len..])?; - - Ok((Type2OpCode::DefShiftRight {lhs, rhs, target}, 1 + lhs_len + rhs_len + target_len)) + let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; + let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; + + let result = lhs.val.get_as_integer()? << rhs.val.get_as_integer()?; + + Ok(AmlParseType { + val: AmlValue::IntegerConstant(result), + len: 1 + lhs.len + rhs.len + target.len + }) } -fn parse_def_add(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_add(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Store the result, if appropriate parser_opcode!(data, 0x72); - let (lhs, lhs_len) = parse_term_arg(&data[1..])?; - let (rhs, rhs_len) = parse_term_arg(&data[1 + lhs_len..])?; - let (target, target_len) = parse_target(&data[1 + lhs_len + rhs_len..])?; - - Ok((Type2OpCode::DefAdd {lhs, rhs, target}, 1 + lhs_len + rhs_len + target_len)) + let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; + let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; + + let result = lhs.val.get_as_integer()? + rhs.val.get_as_integer()?; + + Ok(AmlParseType { + val: AmlValue::IntegerConstant(result), + len: 1 + lhs.len + rhs.len + target.len + }) } -fn parse_def_and(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_and(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Store the result, if appropriate parser_opcode!(data, 0x7B); - let (lhs, lhs_len) = parse_term_arg(&data[1..])?; - let (rhs, rhs_len) = parse_term_arg(&data[1 + lhs_len..])?; - let (target, target_len) = parse_target(&data[1 + lhs_len + rhs_len..])?; - - Ok((Type2OpCode::DefAnd {lhs, rhs, target}, 1 + lhs_len + rhs_len + target_len)) + let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; + let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; + + let result = lhs.val.get_as_integer()? & rhs.val.get_as_integer()?; + + Ok(AmlParseType { + val: AmlValue::IntegerConstant(result), + len: 1 + lhs.len + rhs.len + target.len + }) } -fn parse_def_xor(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_xor(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Store the result, if appropriate parser_opcode!(data, 0x7F); - let (lhs, lhs_len) = parse_term_arg(&data[1..])?; - let (rhs, rhs_len) = parse_term_arg(&data[1 + lhs_len..])?; - let (target, target_len) = parse_target(&data[1 + lhs_len + rhs_len..])?; - - Ok((Type2OpCode::DefXor {lhs, rhs, target}, 1 + lhs_len + rhs_len + target_len)) + let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; + let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; + + let result = lhs.val.get_as_integer()? ^ rhs.val.get_as_integer()?; + + Ok(AmlParseType { + val: AmlValue::IntegerConstant(result), + len: 1 + lhs.len + rhs.len + target.len + }) } -fn parse_def_concat_res(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_concat_res(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Compute the result + // TODO: Store the result, if appropriate parser_opcode!(data, 0x84); - let (lhs, lhs_len) = parse_term_arg(&data[1..])?; - let (rhs, rhs_len) = parse_term_arg(&data[1 + lhs_len..])?; - let (target, target_len) = parse_target(&data[1 + lhs_len + rhs_len..])?; - - Ok((Type2OpCode::DefConcatRes {lhs, rhs, target}, 1 + lhs_len + rhs_len + target_len)) + let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; + let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; + + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 1 + lhs.len + rhs.len + target.len + }) } -fn parse_def_wait(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_wait(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Compute the result parser_opcode_extended!(data, 0x25); - let (event_object, event_object_len) = parse_super_name(&data[2..])?; - let (operand, operand_len) = parse_term_arg(&data[2 + event_object_len..])?; + let event_object = parse_super_name(&data[2..], namespace, scope.clone())?; + let operand = parse_term_arg(&data[2 + event_object.len..], namespace, scope.clone())?; - - Ok((Type2OpCode::DefWait {event_object, operand}, 2 + event_object_len + operand_len)) + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 2 + event_object.len + operand.len + }) } -fn parse_def_cond_ref_of(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_cond_ref_of(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Compute the result + // TODO: Store the result parser_opcode_extended!(data, 0x12); - let (operand, operand_len) = parse_super_name(&data[2..])?; - let (target, target_len) = parse_target(&data[2 + operand_len..])?; + let operand = parse_super_name(&data[2..], namespace, scope.clone())?; + let target = parse_target(&data[2 + operand.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefCondRefOf {operand, target}, 2 + operand_len + target_len)) + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 2 + operand.len + target.len + }) } -fn parse_def_copy_object(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_copy_object(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Compute the result + // TODO: Store the result parser_opcode!(data, 0x9D); - let (source, source_len) = parse_term_arg(&data[1..])?; - let (destination, destination_len) = parse_simple_name(&data[1 + source_len..])?; + let source = parse_term_arg(&data[1..], namespace, scope.clone())?; + let destination = parse_simple_name(&data[1 + source.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefCopyObject {source, destination}, 1 + source_len + destination_len)) + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 1 + source.len + destination.len + }) } -fn parse_def_concat(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_concat(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Compute the result + // TODO: Store the result parser_opcode!(data, 0x73); - let (lhs, lhs_len) = parse_term_arg(&data[1..])?; - let (rhs, rhs_len) = parse_term_arg(&data[1 + lhs_len..])?; - let (target, target_len) = parse_target(&data[1 + lhs_len + rhs_len..])?; + let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; + let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefConcat {lhs, rhs, target}, 1 + lhs_len + rhs_len + target_len)) + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 1 + lhs.len + rhs.len + target.len + }) } -fn parse_def_decrement(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_decrement(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Compute the result + // TODO: Store the result parser_opcode!(data, 0x76); - let (target, target_len) = parse_super_name(&data[1..])?; + let target = parse_super_name(&data[1..], namespace, scope.clone())?; - Ok((Type2OpCode::DefDecrement(target), 1 + target_len)) + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 1 + target.len + }) } -fn parse_def_divide(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_divide(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Compute the result + // TODO: Store the result, if appropriate parser_opcode!(data, 0x78); - let (dividend, dividend_len) = parse_term_arg(&data[1..])?; - let (divisor, divisor_len) = parse_term_arg(&data[1 + dividend_len..])?; - let (remainder, remainder_len) = parse_target(&data[1 + dividend_len + divisor_len..])?; - let (quotient, quotient_len) = parse_target(&data[1 + dividend_len + divisor_len + remainder_len..])?; - - Ok((Type2OpCode::DefDivide {dividend, divisor, remainder, quotient}, - 1 + dividend_len + divisor_len + remainder_len + quotient_len)) + let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; + let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; + let target_remainder = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; + let target_quotient = parse_target(&data[1 + lhs.len + rhs.len + target_remainder.len..], namespace, scope.clone())?; + + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 1 + lhs.len + rhs.len + target_remainder.len + target_quotient.len + }) } -fn parse_def_find_set_left_bit(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { +fn parse_def_find_set_left_bit(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Compute the result + // TODO: Store the result, if appropriate parser_opcode!(data, 0x81); - let (operand, operand_len) = parse_term_arg(&data[1..])?; - let (target, target_len) = parse_target(&data[1 + operand_len..])?; + let operand = parse_term_arg(&data[2..], namespace, scope.clone())?; + let target = parse_target(&data[2 + operand.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefFindSetLeftBit {operand, target}, 1 + operand_len + target_len)) + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 1 + operand.len + target.len + }) } -fn parse_def_find_set_right_bit(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { - if data[0] != 0x82 { - return Err(AmlInternalError::AmlInvalidOpCode); - } +fn parse_def_find_set_right_bit(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Compute the result + // TODO: Store the result, if appropriate + parser_opcode!(data, 0x82); - let (operand, operand_len) = parse_term_arg(&data[1..])?; - let (target, target_len) = parse_target(&data[1 + operand_len..])?; + let operand = parse_term_arg(&data[2..], namespace, scope.clone())?; + let target = parse_target(&data[2 + operand.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefFindSetRightBit {operand, target}, 1 + operand_len + target_len)) + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 1 + operand.len + target.len + }) } -fn parse_def_load_table(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { - if data[0] != 0x5B || data[1] != 0x1F { - return Err(AmlInternalError::AmlInvalidOpCode); - } +fn parse_def_load_table(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Compute the result + // TODO: Store the result, if appropriate + // TODO: Clean up + parser_opcode_extended!(data, 0x1F); - let (signature, signature_len) = parse_term_arg(&data[2..])?; - let (oem_id, oem_id_len) = parse_term_arg(&data[2 + signature_len..])?; - let (oem_table_id, oem_table_id_len) = parse_term_arg(&data[2 + signature_len + oem_id_len..])?; - let (root_path, root_path_len) = - parse_term_arg(&data[2 + signature_len + oem_id_len + oem_table_id_len..])?; - let (parameter_path, parameter_path_len) = - parse_term_arg(&data[2 + signature_len + oem_id_len + oem_table_id_len + root_path_len..])?; - let (parameter_data, parameter_data_len) = - parse_term_arg(&data[2 + signature_len + oem_id_len + oem_table_id_len + root_path_len + - parameter_path_len..])?; + let signature = parse_term_arg(&data[2..], namespace, scope.clone())?; + let oem_id = parse_term_arg(&data[2 + signature.len..], namespace, scope.clone())?; + let oem_table_id = parse_term_arg(&data[2 + signature.len + oem_id.len..], namespace, scope.clone())?; + let root_path = parse_term_arg(&data[2 + signature.len + oem_id.len + oem_table_id.len..], namespace, scope.clone())?; + let parameter_path = parse_term_arg(&data[2 + signature.len + oem_id.len + oem_table_id.len + root_path.len..], namespace, scope.clone())?; + let parameter_data = parse_term_arg(&data[2 + signature.len + oem_id.len + oem_table_id.len + root_path.len + parameter_path.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefLoadTable {signature, oem_id, oem_table_id, root_path, - parameter_path, parameter_data}, - 2 + signature_len + oem_id_len + oem_table_id_len + root_path_len + - parameter_path_len + parameter_data_len)) + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 2 + signature.len + oem_id.len + oem_table_id.len + root_path.len + parameter_path.len + parameter_data.len + }) } -fn parse_def_match(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { - if data[0] != 0x89 { - return Err(AmlInternalError::AmlInvalidOpCode); - } - - let (search_pkg, search_pkg_len) = parse_term_arg(&data[1..])?; - let first_operation = match data[1 + search_pkg_len] { +fn parse_def_match(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Compute the result + // TODO: Store the result, if appropriate + // TODO: Clean up match blocks + parser_opcode!(data, 0x28); + + let search_pkg = parse_term_arg(&data[1..], namespace, scope.clone())?; + + let first_operation = match data[1 + search_pkg.len] { 0 => MatchOpcode::MTR, 1 => MatchOpcode::MEQ, 2 => MatchOpcode::MLE, 3 => MatchOpcode::MLT, 4 => MatchOpcode::MGE, 5 => MatchOpcode::MGT, - _ => return Err(AmlInternalError::AmlParseError("DefMatch - Invalid Opcode")) + _ => return Err(AmlError::AmlParseError("DefMatch - Invalid Opcode")) }; - let (first_operand, first_operand_len) = parse_term_arg(&data[2 + search_pkg_len..])?; + let first_operand = parse_term_arg(&data[2 + search_pkg.len..], namespace, scope.clone())?; - let second_operation = match data[2 + search_pkg_len + first_operand_len] { + let second_operation = match data[2 + search_pkg.len + first_operand.len] { 0 => MatchOpcode::MTR, 1 => MatchOpcode::MEQ, 2 => MatchOpcode::MLE, 3 => MatchOpcode::MLT, 4 => MatchOpcode::MGE, 5 => MatchOpcode::MGT, - _ => return Err(AmlInternalError::AmlParseError("DefMatch - Invalid Opcode")) + _ => return Err(AmlError::AmlParseError("DefMatch - Invalid Opcode")) }; - let (second_operand, second_operand_len) = - parse_term_arg(&data[3 + search_pkg_len + first_operand_len..])?; + let second_operand = parse_term_arg(&data[3 + search_pkg.len + first_operand.len..], namespace, scope.clone())?; + + let start_index = parse_term_arg(&data[3 + search_pkg.len + first_operand.len + second_operand.len..], namespace, scope.clone())?; - let (start_index, start_index_len) = - parse_term_arg(&data[3 + search_pkg_len + first_operand_len + second_operand_len..])?; - - Ok((Type2OpCode::DefMatch {search_pkg, first_operation, first_operand, - second_operation, second_operand, start_index}, - 3 + search_pkg_len + first_operand_len + second_operand_len + start_index_len)) + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 3 + search_pkg.len + first_operand.len + second_operand.len + start_index.len + }) } -fn parse_def_from_bcd(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { - if data[0] != 0x5B || data[1] != 0x28 { - return Err(AmlInternalError::AmlInvalidOpCode); - } +fn parse_def_from_bcd(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Store the result, if appropriate + // TODO: Clean up match block + parser_opcode_extended!(data, 0x28); - let (operand, operand_len) = parse_term_arg(&data[2..])?; - let (target, target_len) = parse_target(&data[2 + operand_len..])?; + let operand = parse_term_arg(&data[2..], namespace, scope.clone())?; + let target = parse_target(&data[2 + operand.len..], namespace, scope.clone())?; + + let result = match target.val.get_as_integer() { + Ok(i) => { + let mut i = i; + let mut ires = 0; - Ok((Type2OpCode::DefFromBCD {operand, target}, 2 + operand_len + target_len)) + while i != 0 { + if i & 0x0F > 10 { + return Err(AmlError::AmlValueError); + } + + ires *= 10; + ires += i & 0x0F; + i >>= 4; + } + + ires + }, + Err(e) => return Err(e) + }; + + Ok(AmlParseType { + val: AmlValue::IntegerConstant(result), + len: 2 + operand.len + target.len + }) } -fn parse_def_mid(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { - if data[0] != 0x9E { - return Err(AmlInternalError::AmlInvalidOpCode); - } +fn parse_def_mid(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Compute the result + // TODO: Store the result, if appropriate + parser_opcode!(data, 0x9E); - let (source, source_len) = parse_term_arg(&data[1..])?; - let (index, index_len) = parse_term_arg(&data[1 + source_len..])?; - let (length, length_len) = parse_term_arg(&data[1 + source_len + index_len..])?; - let (target, target_len) = parse_target(&data[1 + source_len + index_len + length_len..])?; + let source = parse_term_arg(&data[1..], namespace, scope.clone())?; + let index = parse_term_arg(&data[1 + source.len..], namespace, scope.clone())?; + let length = parse_term_arg(&data[1 + source.len + index.len..], namespace, scope.clone())?; + let target = parse_target(&data[1 + source.len + index.len + length.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefMid {source, index, length, target}, - 1 + source_len + index_len + length_len + target_len)) + Ok(AmlParseType { + val: AmlValue::Uninitialized, + len: 1 + source.len + index.len + length.len + target.len + }) } -fn parse_def_mod(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { - if data[0] != 0x85 { - return Err(AmlInternalError::AmlInvalidOpCode); - } +fn parse_def_mod(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Store the result, if appropriate + // TODO: Fatal exception on rhs == 0 + parser_opcode!(data, 0x85); - let (dividend, dividend_len) = parse_term_arg(&data[1..])?; - let (divisor, divisor_len) = parse_term_arg(&data[1 + dividend_len..])?; - let (target, target_len) = parse_target(&data[1 + dividend_len + divisor_len..])?; + let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; + let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefMod {dividend, divisor, target}, 1 + dividend_len + divisor_len + target_len)) + let result = lhs.val.get_as_integer()? % rhs.val.get_as_integer()?; + + Ok(AmlParseType { + val: AmlValue::IntegerConstant(result), + len: 1 + lhs.len + rhs.len + target.len + }) } -fn parse_def_multiply(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { - if data[0] != 0x77 { - return Err(AmlInternalError::AmlInvalidOpCode); - } +fn parse_def_multiply(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Store the result, if appropriate + // TODO: Handle overflow + parser_opcode!(data, 0x77); - let (lhs, lhs_len) = parse_term_arg(&data[1..])?; - let (rhs, rhs_len) = parse_term_arg(&data[1 + lhs_len..])?; - let (target, target_len) = parse_target(&data[1 + lhs_len + rhs_len..])?; + let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; + let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefMultiply {lhs, rhs, target}, 1 + lhs_len + rhs_len + target_len)) + let result = lhs.val.get_as_integer()? * rhs.val.get_as_integer()?; + + Ok(AmlParseType { + val: AmlValue::IntegerConstant(result), + len: 1 + lhs.len + rhs.len + target.len + }) } -fn parse_def_nand(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { - if data[0] != 0x7C { - return Err(AmlInternalError::AmlInvalidOpCode); - } +fn parse_def_nand(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Store the result, if appropriate + parser_opcode!(data, 0x7C); - let (lhs, lhs_len) = parse_term_arg(&data[1..])?; - let (rhs, rhs_len) = parse_term_arg(&data[1 + lhs_len..])?; - let (target, target_len) = parse_target(&data[1 + lhs_len + rhs_len..])?; + let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; + let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefNAnd {lhs, rhs, target}, 1 + lhs_len + rhs_len + target_len)) + let result = !(lhs.val.get_as_integer()? & rhs.val.get_as_integer()?); + + Ok(AmlParseType { + val: AmlValue::IntegerConstant(result), + len: 1 + lhs.len + rhs.len + target.len + }) } -fn parse_def_nor(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { - if data[0] != 0x7E { - return Err(AmlInternalError::AmlInvalidOpCode); - } +fn parse_def_nor(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Store the result, if appropriate + parser_opcode!(data, 0x7E); - let (lhs, lhs_len) = parse_term_arg(&data[1..])?; - let (rhs, rhs_len) = parse_term_arg(&data[1 + lhs_len..])?; - let (target, target_len) = parse_target(&data[1 + lhs_len + rhs_len..])?; + let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; + let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefNOr {lhs, rhs, target}, 1 + lhs_len + rhs_len + target_len)) + let result = !(lhs.val.get_as_integer()? | rhs.val.get_as_integer()?); + + Ok(AmlParseType { + val: AmlValue::IntegerConstant(result), + len: 1 + lhs.len + rhs.len + target.len + }) } -fn parse_def_not(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { - if data[0] != 0x80 { - return Err(AmlInternalError::AmlInvalidOpCode); - } +fn parse_def_not(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Store the result, if appropriate + parser_opcode!(data, 0x80); - let (operand, operand_len) = parse_term_arg(&data[1..])?; - let (target, target_len) = parse_target(&data[1 + operand_len..])?; + let operand = parse_term_arg(&data[1..], namespace, scope.clone())?; + let target = parse_target(&data[1 + operand.len..], namespace, scope.clone())?; - Ok((Type2OpCode::DefNot {operand, target}, 1 + operand_len + target_len)) + let result = !operand.val.get_as_integer()?; + + Ok(AmlParseType { + val: AmlValue::IntegerConstant(result), + len: 1 + operand.len + target.len + }) } -fn parse_def_timer(data: &[u8]) -> Result<(Type2OpCode, usize), AmlInternalError> { - if data[0] != 0x5B || data[1] != 0x33 { - return Err(AmlInternalError::AmlInvalidOpCode) - } - - Ok((Type2OpCode::DefTimer, 2 as usize)) +fn parse_def_timer(data: &[u8], + namespace: &mut BTreeMap, + scope: String) -> ParseResult { + // TODO: Read from the hardware timer, and split into 100ns intervals + parser_opcode_extended!(data, 0x33); + + Ok(AmlParseType { + val: AmlValue::IntegerConstant(0), + len: 2 as usize + }) } diff --git a/src/acpi/mod.rs b/src/acpi/mod.rs index cb06f84..b9f7ba3 100644 --- a/src/acpi/mod.rs +++ b/src/acpi/mod.rs @@ -216,9 +216,11 @@ fn parse_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) { *namespace = Some(res); } }, - Err(AmlError::AmlParseError(e)) => { - println!(": {}", e); - } + Err(AmlError::AmlParseError(e)) => println!(": {}", e), + Err(AmlError::AmlInvalidOpCode) => println!(": Invalid opcode"), + Err(AmlError::AmlValueError) => println!(": Type constraints or value bounds not met"), + Err(AmlError::AmlDeferredLoad) => println!(": Deferred load reached top level"), + Err(AmlError::AmlFatalError(_, _, _)) => println!(": Fatal error occurred") }; } else { println!(": Unknown"); diff --git a/src/stop.rs b/src/stop.rs index 4f152bf..6dec9a1 100644 --- a/src/stop.rs +++ b/src/stop.rs @@ -13,7 +13,7 @@ pub unsafe extern fn kstop() -> ! { let mut val = 1 << 13; if let Some(ref namespace) = acpi.namespace { if let Some(s) = namespace.get("\\_S5") { - if let Some(p) = s.get_as_package() { + if let Ok(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"); From 75279150275972e41dcb9c0c7803e4861dfaa715 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Mon, 3 Jul 2017 10:31:01 +0100 Subject: [PATCH 047/113] Added a context manager --- src/acpi/aml/dataobj.rs | 27 +-- src/acpi/aml/mod.rs | 15 +- src/acpi/aml/namedobj.rs | 294 +++++++++++----------- src/acpi/aml/namespace.rs | 1 + src/acpi/aml/namespacemodifier.rs | 44 ++-- src/acpi/aml/namestring.rs | 23 +- src/acpi/aml/parser.rs | 8 + src/acpi/aml/parsermacros.rs | 10 +- src/acpi/aml/termlist.rs | 35 ++- src/acpi/aml/type1opcode.rs | 91 +++---- src/acpi/aml/type2opcode.rs | 389 +++++++++++++----------------- 11 files changed, 425 insertions(+), 512 deletions(-) diff --git a/src/acpi/aml/dataobj.rs b/src/acpi/aml/dataobj.rs index 77f7d2f..4025f7f 100644 --- a/src/acpi/aml/dataobj.rs +++ b/src/acpi/aml/dataobj.rs @@ -3,18 +3,17 @@ use collections::string::String; use collections::btree_map::BTreeMap; use super::AmlError; -use super::parser::{AmlParseType, ParseResult}; -use super::namespace::{AmlValue, ObjectReference}; +use super::parser::{ AmlParseType, ParseResult, AmlExecutionContext }; +use super::namespace::{ AmlValue, ObjectReference }; use super::type2opcode::{parse_def_buffer, parse_def_package, parse_def_var_package}; use super::termlist::parse_term_arg; use super::namestring::parse_super_name; pub fn parse_data_obj(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_selector! { - data, namespace, scope.clone(), + data, ctx, parse_computational_data, parse_def_package, parse_def_var_package @@ -24,15 +23,14 @@ pub fn parse_data_obj(data: &[u8], } pub fn parse_data_ref_obj(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_selector! { - data, namespace, scope.clone(), + data, ctx, parse_data_obj, parse_term_arg }; - match parse_super_name(data, namespace, scope.clone()) { + match parse_super_name(data, ctx) { Ok(res) => match res.val { AmlValue::String(s) => Ok(AmlParseType { val: AmlValue::ObjectReference(ObjectReference::NamedObj(s)), @@ -45,8 +43,7 @@ pub fn parse_data_ref_obj(data: &[u8], } pub fn parse_arg_obj(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { match data[0] { 0x68 ... 0x6E => Ok(AmlParseType { val: AmlValue::ObjectReference(ObjectReference::ArgObj(data[0] - 0x68)), @@ -57,8 +54,7 @@ pub fn parse_arg_obj(data: &[u8], } pub fn parse_local_obj(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { match data[0] { 0x68 ... 0x6E => Ok(AmlParseType { val: AmlValue::ObjectReference(ObjectReference::LocalObj(data[0] - 0x60)), @@ -69,8 +65,7 @@ pub fn parse_local_obj(data: &[u8], } fn parse_computational_data(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { match data[0] { 0x0A => Ok(AmlParseType { val: AmlValue::Integer(data[1] as u64), @@ -148,6 +143,6 @@ fn parse_computational_data(data: &[u8], val: AmlValue::IntegerConstant(0xFFFFFFFFFFFFFFFF), len: 9 as usize }), - _ => parse_def_buffer(data, namespace, scope.clone()) + _ => parse_def_buffer(data, ctx) } } diff --git a/src/acpi/aml/mod.rs b/src/acpi/aml/mod.rs index a113c0b..d20ce4c 100644 --- a/src/acpi/aml/mod.rs +++ b/src/acpi/aml/mod.rs @@ -24,7 +24,7 @@ mod type1opcode; mod type2opcode; mod parser; -use self::parser::ParseResult; +use self::parser::{ ParseResult, AmlExecutionContext }; use self::termlist::parse_term_list; pub use self::namespace::AmlValue; @@ -39,13 +39,14 @@ pub enum AmlError { pub fn parse_aml_table(sdt: &'static Sdt) -> Result, AmlError> { let data = sdt.data(); + let mut ctx = AmlExecutionContext { + namespace: &mut BTreeMap::new(), + scope: String::from_str("\\").unwrap() + }; + + let term_list = parse_term_list(data, &mut ctx)?; - let global_namespace_specifier = String::from_str("\\").unwrap(); - let mut global_namespace = BTreeMap::new(); - - let term_list = parse_term_list(data, &mut global_namespace, global_namespace_specifier.clone())?; - - Ok(global_namespace) + Ok(ctx.namespace.clone()) } pub fn is_aml_table(sdt: &'static Sdt) -> bool { diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index c521893..3c4605b 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -6,8 +6,8 @@ use core::str::FromStr; use collections::btree_map::BTreeMap; use super::AmlError; -use super::parser::{AmlParseType, ParseResult, AmlParseTypeGeneric}; -use super::namespace::{AmlValue, ObjectReference, FieldSelector, get_namespace_string}; +use super::parser::{ AmlParseType, ParseResult, AmlParseTypeGeneric, AmlExecutionContext }; +use super::namespace::{ AmlValue, ObjectReference, FieldSelector, get_namespace_string }; use super::namestring::{parse_name_string, parse_name_seg}; use super::termlist::{parse_term_arg, parse_term_list, parse_object_list}; use super::pkglength::parse_pkg_length; @@ -87,10 +87,9 @@ pub enum AccessAttrib { } pub fn parse_named_obj(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_selector! { - data, namespace, scope.clone(), + data, ctx, parse_def_bank_field, parse_def_create_bit_field, parse_def_create_byte_field, @@ -115,19 +114,17 @@ pub fn parse_named_obj(data: &[u8], } fn parse_def_bank_field(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Why isn't bank name used? parser_opcode_extended!(data, 0x87); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[2..])?; let data = &data[2 + pkg_length_len .. 2 + pkg_length]; - let region_name = parse_name_string(data, namespace, scope.clone())?; - let bank_name = parse_name_string(&data[2 + pkg_length_len + region_name.len .. 2 + pkg_length], namespace, scope.clone())?; + let region_name = parse_name_string(data, ctx)?; + let bank_name = parse_name_string(&data[2 + pkg_length_len + region_name.len .. 2 + pkg_length], ctx)?; - let bank_value = parse_term_arg( - &data[2 + pkg_length_len + region_name.len .. 2 + pkg_length], namespace, scope.clone())?; + let bank_value = parse_term_arg(&data[2 + pkg_length_len + region_name.len .. 2 + pkg_length], ctx)?; let flags_raw = data[2 + pkg_length_len + region_name.len + bank_name.len + bank_value.len]; let mut flags = FieldFlags { @@ -156,7 +153,7 @@ fn parse_def_bank_field(data: &[u8], let field_list = parse_field_list( &data[3 + pkg_length_len + region_name.len + bank_name.len + bank_value.len .. - 2 + pkg_length], namespace, scope, selector, &mut flags)?; + 2 + pkg_length], ctx, selector, &mut flags)?; Ok(AmlParseType { val: AmlValue::None, @@ -165,17 +162,16 @@ fn parse_def_bank_field(data: &[u8], } fn parse_def_create_bit_field(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode!(data, 0x8D); - let source_buf = parse_term_arg(&data[2..], namespace, scope.clone())?; - let bit_index = parse_term_arg(&data[2 + source_buf.len..], namespace, scope.clone())?; - let name = parse_name_string(&data[1 + source_buf.len + bit_index.len..], namespace, scope.clone())?; + let source_buf = parse_term_arg(&data[2..], ctx)?; + let bit_index = parse_term_arg(&data[2 + source_buf.len..], ctx)?; + let name = parse_name_string(&data[1 + source_buf.len + bit_index.len..], ctx)?; - let local_scope_string = get_namespace_string(scope.clone(), name.val); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); - namespace.insert(local_scope_string, AmlValue::BufferField { + ctx.namespace.insert(local_scope_string, AmlValue::BufferField { source_buf: Box::new(source_buf.val), index: Box::new(bit_index.val), length: Box::new(AmlValue::IntegerConstant(1)) @@ -188,17 +184,16 @@ fn parse_def_create_bit_field(data: &[u8], } fn parse_def_create_byte_field(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode!(data, 0x8C); - let source_buf = parse_term_arg(&data[2..], namespace, scope.clone())?; - let bit_index = parse_term_arg(&data[2 + source_buf.len..], namespace, scope.clone())?; - let name = parse_name_string(&data[1 + source_buf.len + bit_index.len..], namespace, scope.clone())?; + let source_buf = parse_term_arg(&data[2..], ctx)?; + let bit_index = parse_term_arg(&data[2 + source_buf.len..], ctx)?; + let name = parse_name_string(&data[1 + source_buf.len + bit_index.len..], ctx)?; - let local_scope_string = get_namespace_string(scope.clone(), name.val); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); - namespace.insert(local_scope_string, AmlValue::BufferField { + ctx.namespace.insert(local_scope_string, AmlValue::BufferField { source_buf: Box::new(source_buf.val), index: Box::new(bit_index.val), length: Box::new(AmlValue::IntegerConstant(8)) @@ -211,17 +206,16 @@ fn parse_def_create_byte_field(data: &[u8], } fn parse_def_create_word_field(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode!(data, 0x8B); - let source_buf = parse_term_arg(&data[2..], namespace, scope.clone())?; - let bit_index = parse_term_arg(&data[2 + source_buf.len..], namespace, scope.clone())?; - let name = parse_name_string(&data[1 + source_buf.len + bit_index.len..], namespace, scope.clone())?; + let source_buf = parse_term_arg(&data[2..], ctx)?; + let bit_index = parse_term_arg(&data[2 + source_buf.len..], ctx)?; + let name = parse_name_string(&data[1 + source_buf.len + bit_index.len..], ctx)?; - let local_scope_string = get_namespace_string(scope.clone(), name.val); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); - namespace.insert(local_scope_string, AmlValue::BufferField { + ctx.namespace.insert(local_scope_string, AmlValue::BufferField { source_buf: Box::new(source_buf.val), index: Box::new(bit_index.val), length: Box::new(AmlValue::IntegerConstant(16)) @@ -234,17 +228,16 @@ fn parse_def_create_word_field(data: &[u8], } fn parse_def_create_dword_field(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode!(data, 0x8A); - let source_buf = parse_term_arg(&data[2..], namespace, scope.clone())?; - let bit_index = parse_term_arg(&data[2 + source_buf.len..], namespace, scope.clone())?; - let name = parse_name_string(&data[1 + source_buf.len + bit_index.len..], namespace, scope.clone())?; + let source_buf = parse_term_arg(&data[2..], ctx)?; + let bit_index = parse_term_arg(&data[2 + source_buf.len..], ctx)?; + let name = parse_name_string(&data[1 + source_buf.len + bit_index.len..], ctx)?; - let local_scope_string = get_namespace_string(scope.clone(), name.val); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); - namespace.insert(local_scope_string, AmlValue::BufferField { + ctx.namespace.insert(local_scope_string, AmlValue::BufferField { source_buf: Box::new(source_buf.val), index: Box::new(bit_index.val), length: Box::new(AmlValue::IntegerConstant(32)) @@ -257,17 +250,16 @@ fn parse_def_create_dword_field(data: &[u8], } fn parse_def_create_qword_field(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode!(data, 0x8F); - let source_buf = parse_term_arg(&data[2..], namespace, scope.clone())?; - let bit_index = parse_term_arg(&data[2 + source_buf.len..], namespace, scope.clone())?; - let name = parse_name_string(&data[1 + source_buf.len + bit_index.len..], namespace, scope.clone())?; + let source_buf = parse_term_arg(&data[2..], ctx)?; + let bit_index = parse_term_arg(&data[2 + source_buf.len..], ctx)?; + let name = parse_name_string(&data[1 + source_buf.len + bit_index.len..], ctx)?; - let local_scope_string = get_namespace_string(scope.clone(), name.val); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); - namespace.insert(local_scope_string, AmlValue::BufferField { + ctx.namespace.insert(local_scope_string, AmlValue::BufferField { source_buf: Box::new(source_buf.val), index: Box::new(bit_index.val), length: Box::new(AmlValue::IntegerConstant(64)) @@ -280,18 +272,17 @@ fn parse_def_create_qword_field(data: &[u8], } fn parse_def_create_field(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode_extended!(data, 0x13); - let source_buf = parse_term_arg(&data[2..], namespace, scope.clone())?; - let bit_index = parse_term_arg(&data[2 + source_buf.len..], namespace, scope.clone())?; - let num_bits = parse_term_arg(&data[2 + source_buf.len + bit_index.len..], namespace, scope.clone())?; - let name = parse_name_string(&data[2 + source_buf.len + bit_index.len + num_bits.len..], namespace, scope.clone())?; + let source_buf = parse_term_arg(&data[2..], ctx)?; + let bit_index = parse_term_arg(&data[2 + source_buf.len..], ctx)?; + let num_bits = parse_term_arg(&data[2 + source_buf.len + bit_index.len..], ctx)?; + let name = parse_name_string(&data[2 + source_buf.len + bit_index.len + num_bits.len..], ctx)?; - let local_scope_string = get_namespace_string(scope.clone(), name.val); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); - namespace.insert(local_scope_string, AmlValue::BufferField { + ctx.namespace.insert(local_scope_string, AmlValue::BufferField { source_buf: Box::new(source_buf.val), index: Box::new(bit_index.val), length: Box::new(num_bits.val) @@ -304,19 +295,18 @@ fn parse_def_create_field(data: &[u8], } fn parse_def_data_region(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Find the actual offset and length, once table mapping is implemented parser_opcode_extended!(data, 0x88); - let name = parse_name_string(&data[2..], namespace, scope.clone())?; - let signature = parse_term_arg(&data[2 + name.len..], namespace, scope.clone())?; - let oem_id = parse_term_arg(&data[2 + name.len + signature.len..], namespace, scope.clone())?; - let oem_table_id = parse_term_arg(&data[2 + name.len + signature.len + oem_id.len..], namespace, scope.clone())?; - - let local_scope_string = get_namespace_string(scope.clone(), name.val); + let name = parse_name_string(&data[2..], ctx)?; + let signature = parse_term_arg(&data[2 + name.len..], ctx)?; + let oem_id = parse_term_arg(&data[2 + name.len + signature.len..], ctx)?; + let oem_table_id = parse_term_arg(&data[2 + name.len + signature.len + oem_id.len..], ctx)?; - namespace.insert(local_scope_string, AmlValue::OperationRegion { + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); + + ctx.namespace.insert(local_scope_string, AmlValue::OperationRegion { region: RegionSpace::SystemMemory, offset: Box::new(AmlValue::IntegerConstant(0)), len: Box::new(AmlValue::IntegerConstant(0)) @@ -329,14 +319,13 @@ fn parse_def_data_region(data: &[u8], } fn parse_def_event(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode_extended!(data, 0x02); - let name = parse_name_string(&data[2..], namespace, scope.clone())?; + let name = parse_name_string(&data[2..], ctx)?; - let local_scope_string = get_namespace_string(scope, name.val); - namespace.insert(local_scope_string, AmlValue::Event); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); + ctx.namespace.insert(local_scope_string, AmlValue::Event); Ok(AmlParseType { val: AmlValue::None, @@ -345,18 +334,23 @@ fn parse_def_event(data: &[u8], } fn parse_def_device(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { + // TODO: How to handle local context deferreds + // TODO: How to also handle local context reference to calling context parser_opcode_extended!(data, 0x82); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[2..])?; - let name = parse_name_string(&data[2 + pkg_length_len .. 2 + pkg_length], namespace, scope.clone())?; - - let mut local_namespace = BTreeMap::new(); - let obj_list = parse_object_list(&data[2 + pkg_length_len + name.len .. 2 + pkg_length], &mut local_namespace, String::new())?; + let name = parse_name_string(&data[2 + pkg_length_len .. 2 + pkg_length], ctx)?; - let local_scope_string = get_namespace_string(scope, name.val); - namespace.insert(local_scope_string, AmlValue::Device(local_namespace)); + let mut local_ctx = AmlExecutionContext { + namespace: &mut BTreeMap::new(), + scope: String::new() + }; + + let obj_list = parse_object_list(&data[2 + pkg_length_len + name.len .. 2 + pkg_length], &mut local_ctx)?; + + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); + ctx.namespace.insert(local_scope_string, AmlValue::Device(local_ctx.namespace.clone())); Ok(AmlParseType { val: AmlValue::None, @@ -365,11 +359,10 @@ fn parse_def_device(data: &[u8], } fn parse_def_op_region(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode_extended!(data, 0x80); - let name = parse_name_string(&data[2..], namespace, scope.clone())?; + let name = parse_name_string(&data[2..], ctx)?; let region = match data[2 + name.len] { 0x00 => RegionSpace::SystemMemory, 0x01 => RegionSpace::SystemIO, @@ -385,11 +378,11 @@ fn parse_def_op_region(data: &[u8], _ => return Err(AmlError::AmlParseError("OpRegion - invalid region")) }; - let offset = parse_term_arg(&data[3 + name.len..], namespace, scope.clone())?; - let len = parse_term_arg(&data[3 + name.len + offset.len..], namespace, scope.clone())?; + let offset = parse_term_arg(&data[3 + name.len..], ctx)?; + let len = parse_term_arg(&data[3 + name.len + offset.len..], ctx)?; - let local_scope_string = get_namespace_string(scope.clone(), name.val); - namespace.insert(local_scope_string, AmlValue::OperationRegion { + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); + ctx.namespace.insert(local_scope_string, AmlValue::OperationRegion { region: region, offset: Box::new(offset.val), len: Box::new(len.val) @@ -402,12 +395,11 @@ fn parse_def_op_region(data: &[u8], } fn parse_def_field(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode_extended!(data, 0x81); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[2..])?; - let name = parse_name_string(&data[2 + pkg_length_len .. 2 + pkg_length], namespace, scope.clone())?; + let name = parse_name_string(&data[2 + pkg_length_len .. 2 + pkg_length], ctx)?; let flags_raw = data[2 + pkg_length_len + name.len]; let mut flags = FieldFlags { @@ -431,7 +423,7 @@ fn parse_def_field(data: &[u8], let selector = FieldSelector::Region(name.val.get_as_string()?); - let field_list = parse_field_list(&data[3 + pkg_length_len + name.len .. 2 + pkg_length], namespace, scope, selector, &mut flags)?; + let field_list = parse_field_list(&data[3 + pkg_length_len + name.len .. 2 + pkg_length], ctx, selector, &mut flags)?; Ok(AmlParseType { val: AmlValue::None, @@ -440,13 +432,12 @@ fn parse_def_field(data: &[u8], } fn parse_def_index_field(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode_extended!(data, 0x86); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[2..])?; - let idx_name = parse_name_string( &data[2 + pkg_length_len .. 2 + pkg_length], namespace, scope.clone())?; - let data_name = parse_name_string(&data[2 + pkg_length_len + idx_name.len .. 2 + pkg_length], namespace, scope.clone())?; + let idx_name = parse_name_string(&data[2 + pkg_length_len .. 2 + pkg_length], ctx)?; + let data_name = parse_name_string(&data[2 + pkg_length_len + idx_name.len .. 2 + pkg_length], ctx)?; let flags_raw = data[2 + pkg_length_len + idx_name.len + data_name.len]; let mut flags = FieldFlags { @@ -474,7 +465,7 @@ fn parse_def_index_field(data: &[u8], }; let field_list = parse_field_list( - &data[3 + pkg_length_len + idx_name.len + data_name.len .. 2 + pkg_length], namespace, scope, selector, &mut flags)?; + &data[3 + pkg_length_len + idx_name.len + data_name.len .. 2 + pkg_length], ctx, selector, &mut flags)?; Ok(AmlParseType { val: AmlValue::None, @@ -483,21 +474,14 @@ fn parse_def_index_field(data: &[u8], } fn parse_field_list(data: &[u8], - namespace: &mut BTreeMap, - scope: String, + ctx: &mut AmlExecutionContext, selector: FieldSelector, flags: &mut FieldFlags) -> ParseResult { let mut current_offset: usize = 0; let mut connection = AmlValue::Uninitialized; while current_offset < data.len() { - match parse_field_element(&data[current_offset..], namespace, scope.clone(), selector.clone(), - &mut connection, flags, &mut current_offset) { - Ok(_) => (), - Err(AmlError::AmlInvalidOpCode) => - return Err(AmlError::AmlParseError("FieldList - no valid field")), - Err(e) => return Err(e) - } + parse_field_element(&data[current_offset..], ctx, selector.clone(), &mut connection, flags, &mut current_offset)?; } Ok(AmlParseType { @@ -507,16 +491,15 @@ fn parse_field_list(data: &[u8], } fn parse_field_element(data: &[u8], - namespace: &mut BTreeMap, - scope: String, + ctx: &mut AmlExecutionContext, selector: FieldSelector, connection: &mut AmlValue, flags: &mut FieldFlags, offset: &mut usize) -> ParseResult { - let length = if let Ok(field) = parse_named_field(data, namespace, scope.clone()) { - let local_scope_string = get_namespace_string(scope.clone(), AmlValue::String(field.val.name.clone())); + let length = if let Ok(field) = parse_named_field(data, ctx) { + let local_scope_string = get_namespace_string(ctx.scope.clone(), AmlValue::String(field.val.name.clone())); - namespace.insert(local_scope_string, AmlValue::FieldUnit { + ctx.namespace.insert(local_scope_string, AmlValue::FieldUnit { selector: selector.clone(), connection: Box::new(connection.clone()), flags: flags.clone(), @@ -525,10 +508,10 @@ fn parse_field_element(data: &[u8], }); field.len - } else if let Ok(field) = parse_reserved_field(data, namespace, scope.clone()) { + } else if let Ok(field) = parse_reserved_field(data, ctx) { *offset += field.val; field.len - } else if let Ok(field) = parse_access_field(data, namespace, scope.clone()) { + } else if let Ok(field) = parse_access_field(data, ctx) { match field.val.access_type { AccessType::BufferAcc(_) => flags.access_type = AccessType::BufferAcc(field.val.access_attrib.clone()), @@ -536,7 +519,7 @@ fn parse_field_element(data: &[u8], } field.len - } else if let Ok(field) = parse_connect_field(data, namespace, scope.clone()) { + } else if let Ok(field) = parse_connect_field(data, ctx) { *connection = field.val.clone(); field.len } else { @@ -550,8 +533,7 @@ fn parse_field_element(data: &[u8], } fn parse_named_field(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> Result, AmlError> { + ctx: &mut AmlExecutionContext) -> Result, AmlError> { let (name_seg, name_seg_len) = parse_name_seg(&data[0..4])?; let name = match String::from_utf8(name_seg) { Ok(s) => s, @@ -566,8 +548,7 @@ fn parse_named_field(data: &[u8], } fn parse_reserved_field(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> Result, AmlError> { + ctx: &mut AmlExecutionContext) -> Result, AmlError> { parser_opcode!(data, 0x00); let (length, length_len) = parse_pkg_length(&data[1..])?; @@ -578,8 +559,7 @@ fn parse_reserved_field(data: &[u8], } fn parse_access_field(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> Result, AmlError> { + ctx: &mut AmlExecutionContext) -> Result, AmlError> { parser_opcode!(data, 0x01, 0x03); let flags_raw = data[1]; @@ -625,17 +605,16 @@ fn parse_access_field(data: &[u8], } fn parse_connect_field(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode!(data, 0x02); - if let Ok(e) = parse_def_buffer(&data[1..], namespace, scope.clone()) { + if let Ok(e) = parse_def_buffer(&data[1..], ctx) { Ok(AmlParseType { val: e.val, len: e.len + 1 }) } else { - let name = parse_name_string(&data[1..], namespace, scope.clone())?; + let name = parse_name_string(&data[1..], ctx)?; Ok(AmlParseType { val: AmlValue::ObjectReference(ObjectReference::NamedObj(name.val.get_as_string()?)), len: name.len + 1 @@ -644,12 +623,11 @@ fn parse_connect_field(data: &[u8], } fn parse_def_method(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode!(data, 0x14); let (pkg_len, pkg_len_len) = parse_pkg_length(&data[1..])?; - let name = parse_name_string(&data[1 + pkg_len_len..], namespace, scope.clone())?; + let name = parse_name_string(&data[1 + pkg_len_len..], ctx)?; let flags = data[1 + pkg_len_len + name.len]; let arg_count = flags & 0x07; @@ -658,8 +636,8 @@ fn parse_def_method(data: &[u8], let term_list = &data[2 + pkg_len_len + name.len .. 1 + pkg_len]; - let local_scope_string = get_namespace_string(scope.clone(), name.val); - namespace.insert(local_scope_string, AmlValue::Method(Method { + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); + ctx.namespace.insert(local_scope_string, AmlValue::Method(Method { arg_count, serialized, sync_level, @@ -673,16 +651,15 @@ fn parse_def_method(data: &[u8], } fn parse_def_mutex(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode_extended!(data, 0x01); - let name = parse_name_string(&data[2 ..], namespace, scope.clone())?; + let name = parse_name_string(&data[2 ..], ctx)?; let flags = data[2 + name.len]; let sync_level = flags & 0x0F; - let local_scope_string = get_namespace_string(scope, name.val); - namespace.insert(local_scope_string, AmlValue::Mutex(sync_level)); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); + ctx.namespace.insert(local_scope_string, AmlValue::Mutex(sync_level)); Ok(AmlParseType { val: AmlValue::None, @@ -691,26 +668,31 @@ fn parse_def_mutex(data: &[u8], } fn parse_def_power_res(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { + // TODO: How to handle local context deferreds + // TODO: How to also handle local context reference to calling context parser_opcode_extended!(data, 0x84); let (pkg_len, pkg_len_len) = parse_pkg_length(&data[2..])?; - let name = parse_name_string(&data[2 + pkg_len_len..], namespace, scope.clone())?; + let name = parse_name_string(&data[2 + pkg_len_len..], ctx)?; - let local_scope_string = get_namespace_string(scope, name.val); - let mut local_namespace = BTreeMap::new(); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); let system_level = data[2 + pkg_len_len + name.len]; let resource_order: u16 = (data[3 + pkg_len_len + name.len] as u16) + ((data[4 + pkg_len_len + name.len] as u16) << 8); - parse_object_list(&data[5 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_namespace, String::new())?; + let mut local_ctx = AmlExecutionContext { + namespace: &mut BTreeMap::new(), + scope: String::new() + }; + + parse_object_list(&data[5 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_ctx)?; - namespace.insert(local_scope_string, AmlValue::PowerResource { + ctx.namespace.insert(local_scope_string, AmlValue::PowerResource { system_level, resource_order, - obj_list: local_namespace + obj_list: local_ctx.namespace.clone() }); Ok(AmlParseType { @@ -720,15 +702,13 @@ fn parse_def_power_res(data: &[u8], } fn parse_def_processor(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode_extended!(data, 0x83); let (pkg_len, pkg_len_len) = parse_pkg_length(&data[2..])?; - let name = parse_name_string(&data[2 + pkg_len_len..], namespace, scope.clone())?; + let name = parse_name_string(&data[2 + pkg_len_len..], ctx)?; - let local_scope_string = get_namespace_string(scope, name.val); - let mut local_namespace = BTreeMap::new(); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); let proc_id = data[2 + pkg_len_len + name.len]; let p_blk_addr: u32 = (data[3 + pkg_len_len + name.len] as u32) + @@ -737,12 +717,17 @@ fn parse_def_processor(data: &[u8], ((data[6 + pkg_len_len + name.len] as u32) << 24); let p_blk_len = data[7 + pkg_len_len + name.len]; - parse_object_list(&data[8 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_namespace, String::new())?; + let mut local_ctx = AmlExecutionContext { + namespace: &mut BTreeMap::new(), + scope: String::new() + }; - namespace.insert(local_scope_string, AmlValue::Processor { + parse_object_list(&data[8 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_ctx)?; + + ctx.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 + obj_list: local_ctx.namespace.clone() }); Ok(AmlParseType { @@ -752,19 +737,22 @@ fn parse_def_processor(data: &[u8], } fn parse_def_thermal_zone(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode_extended!(data, 0x85); let (pkg_len, pkg_len_len) = parse_pkg_length(&data[2..])?; - let name = parse_name_string(&data[2 + pkg_len_len .. 2 + pkg_len], namespace, scope.clone())?; + let name = parse_name_string(&data[2 + pkg_len_len .. 2 + pkg_len], ctx)?; - let local_scope_string = get_namespace_string(scope, name.val); - let mut local_namespace = BTreeMap::new(); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); + + let mut local_ctx = AmlExecutionContext { + namespace: &mut BTreeMap::new(), + scope: String::new() + }; - parse_object_list(&data[2 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_namespace, String::new())?; + parse_object_list(&data[2 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_ctx)?; - namespace.insert(local_scope_string, AmlValue::ThermalZone(local_namespace)); + ctx.namespace.insert(local_scope_string, AmlValue::ThermalZone(local_ctx.namespace.clone())); Ok(AmlParseType { val: AmlValue::None, diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index d2ac417..54cef02 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -6,6 +6,7 @@ use collections::btree_map::BTreeMap; use core::str::FromStr; use super::namedobj::{ RegionSpace, FieldFlags, Method }; +use super::parser::AmlExecutionContext; use super::AmlError; #[derive(Debug, Clone)] diff --git a/src/acpi/aml/namespacemodifier.rs b/src/acpi/aml/namespacemodifier.rs index b04d405..35cd1a3 100644 --- a/src/acpi/aml/namespacemodifier.rs +++ b/src/acpi/aml/namespacemodifier.rs @@ -4,7 +4,7 @@ use collections::vec::Vec; use collections::btree_map::BTreeMap; use super::AmlError; -use super::parser::{AmlParseType, ParseResult, AmlParseTypeGeneric}; +use super::parser::{AmlParseType, ParseResult, AmlParseTypeGeneric, AmlExecutionContext}; use super::namespace::{AmlValue, ObjectReference, FieldSelector, get_namespace_string}; use super::pkglength::parse_pkg_length; use super::namestring::parse_name_string; @@ -12,10 +12,9 @@ use super::termlist::parse_term_list; use super::dataobj::parse_data_ref_obj; pub fn parse_namespace_modifier(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_selector! { - data, namespace, scope.clone(), + data, ctx, parse_alias_op, parse_scope_op, parse_name_op @@ -25,17 +24,16 @@ pub fn parse_namespace_modifier(data: &[u8], } fn parse_alias_op(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode!(data, 0x06); - let source_name = parse_name_string(&data[1..], namespace, scope.clone())?; - let alias_name = parse_name_string(&data[1 + source_name.len..], namespace, scope.clone())?; + let source_name = parse_name_string(&data[1..], ctx)?; + let alias_name = parse_name_string(&data[1 + source_name.len..], ctx)?; - let local_scope_string = get_namespace_string(scope.clone(), source_name.val); - let local_alias_string = get_namespace_string(scope.clone(), alias_name.val); + let local_scope_string = get_namespace_string(ctx.scope.clone(), source_name.val); + let local_alias_string = get_namespace_string(ctx.scope.clone(), alias_name.val); - namespace.insert(local_scope_string, AmlValue::ObjectReference( + ctx.namespace.insert(local_scope_string, AmlValue::ObjectReference( ObjectReference::NamedObj(local_alias_string))); Ok(AmlParseType { @@ -45,16 +43,15 @@ fn parse_alias_op(data: &[u8], } fn parse_name_op(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode!(data, 0x08); - let name = parse_name_string(&data[1..], namespace, scope.clone())?; - let data_ref_obj = parse_data_ref_obj(&data[1 + name.len..], namespace, scope.clone())?; + let name = parse_name_string(&data[1..], ctx)?; + let data_ref_obj = parse_data_ref_obj(&data[1 + name.len..], ctx)?; - let local_scope_string = get_namespace_string(scope.clone(), name.val); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); - namespace.insert(local_scope_string, data_ref_obj.val); + ctx.namespace.insert(local_scope_string, data_ref_obj.val); Ok(AmlParseType { val: AmlValue::None, @@ -63,15 +60,18 @@ fn parse_name_op(data: &[u8], } fn parse_scope_op(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode!(data, 0x10); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; - let name = parse_name_string(&data[1 + pkg_length_len..], namespace, scope.clone())?; + let name = parse_name_string(&data[1 + pkg_length_len..], ctx)?; - let local_scope_string = get_namespace_string(scope, name.val); - parse_term_list(&data[1 + pkg_length_len + name.len..], namespace, local_scope_string)?; + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); + let containing_scope_string = ctx.scope.clone(); + + ctx.scope = local_scope_string; + parse_term_list(&data[1 + pkg_length_len + name.len..], ctx)?; + ctx.scope = containing_scope_string; Ok(AmlParseType { val: AmlValue::None, diff --git a/src/acpi/aml/namestring.rs b/src/acpi/aml/namestring.rs index ccbdcce..e63a9b0 100644 --- a/src/acpi/aml/namestring.rs +++ b/src/acpi/aml/namestring.rs @@ -3,14 +3,13 @@ use collections::string::String; use collections::btree_map::BTreeMap; use super::AmlError; -use super::parser::{AmlParseType, ParseResult, AmlParseTypeGeneric}; +use super::parser::{AmlParseType, ParseResult, AmlParseTypeGeneric, AmlExecutionContext}; use super::namespace::{AmlValue, ObjectReference, FieldSelector, get_namespace_string}; use super::dataobj::{parse_arg_obj, parse_local_obj}; use super::type2opcode::parse_type6_opcode; pub fn parse_name_string(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { let mut characters: Vec = vec!(); let mut starting_index: usize = 0; @@ -142,10 +141,9 @@ fn parse_multi_name_path(data: &[u8]) -> Result<(Vec, usize), AmlError> { } pub fn parse_super_name(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_selector! { - data, namespace, scope.clone(), + data, ctx, parse_simple_name, parse_type6_opcode, parse_debug_obj @@ -155,8 +153,7 @@ pub fn parse_super_name(data: &[u8], } fn parse_debug_obj(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode_extended!(data, 0x31); Ok(AmlParseType { @@ -166,10 +163,9 @@ fn parse_debug_obj(data: &[u8], } pub fn parse_simple_name(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_selector! { - data, namespace, scope.clone(), + data, ctx, parse_name_string, parse_arg_obj, parse_local_obj @@ -179,14 +175,13 @@ pub fn parse_simple_name(data: &[u8], } pub fn parse_target(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { if data[0] == 0x00 { Ok(AmlParseType { val: AmlValue::None, len: 1 as usize }) } else { - parse_super_name(data, namespace, scope.clone()) + parse_super_name(data, ctx) } } diff --git a/src/acpi/aml/parser.rs b/src/acpi/aml/parser.rs index 080a1ae..b316319 100644 --- a/src/acpi/aml/parser.rs +++ b/src/acpi/aml/parser.rs @@ -1,3 +1,6 @@ +use collections::string::String; +use collections::btree_map::BTreeMap; + use super::namespace::AmlValue; use super::AmlError; @@ -8,3 +11,8 @@ pub struct AmlParseTypeGeneric { pub val: T, pub len: usize } + +pub struct AmlExecutionContext<'a> { + pub namespace: &'a mut BTreeMap, + pub scope: String +} diff --git a/src/acpi/aml/parsermacros.rs b/src/acpi/aml/parsermacros.rs index 6b9555a..3f8cf61 100644 --- a/src/acpi/aml/parsermacros.rs +++ b/src/acpi/aml/parsermacros.rs @@ -1,15 +1,15 @@ #[macro_export] macro_rules! parser_selector { - {$data:expr, $namespace:expr, $scope:expr, $func:expr} => { - match $func($data, $namespace, $scope) { + {$data:expr, $ctx:expr, $func:expr} => { + match $func($data, $ctx) { Ok(res) => return Ok(res), Err(AmlError::AmlInvalidOpCode) => (), Err(e) => return Err(e) } }; - {$data:expr, $namespace:expr, $scope:expr, $func:expr, $($funcs:expr),+} => { - parser_selector! {$data, $namespace, $scope, $func}; - parser_selector! {$data, $namespace, $scope, $($funcs),*}; + {$data:expr, $ctx:expr, $func:expr, $($funcs:expr),+} => { + parser_selector! {$data, $ctx, $func}; + parser_selector! {$data, $ctx, $($funcs),*}; }; } diff --git a/src/acpi/aml/termlist.rs b/src/acpi/aml/termlist.rs index bc2a747..bbce0e4 100644 --- a/src/acpi/aml/termlist.rs +++ b/src/acpi/aml/termlist.rs @@ -4,7 +4,7 @@ use collections::vec::Vec; use collections::btree_map::BTreeMap; use super::AmlError; -use super::parser::{AmlParseType, ParseResult, AmlParseTypeGeneric}; +use super::parser::{ AmlParseType, ParseResult, AmlParseTypeGeneric, AmlExecutionContext }; use super::namespace::{AmlValue, ObjectReference, FieldSelector, get_namespace_string}; use super::namespacemodifier::parse_namespace_modifier; use super::namedobj::parse_named_obj; @@ -14,12 +14,11 @@ use super::type2opcode::parse_type2_opcode; use super::namestring::parse_name_string; pub fn parse_term_list(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { let mut current_offset: usize = 0; while current_offset < data.len() { - let res = parse_term_obj(&data[current_offset..], namespace, scope.clone())?; + let res = parse_term_obj(&data[current_offset..], ctx)?; current_offset += res.len; } @@ -30,10 +29,9 @@ pub fn parse_term_list(data: &[u8], } pub fn parse_term_arg(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_selector! { - data, namespace, scope.clone(), + data, ctx, parse_local_obj, parse_data_obj, parse_arg_obj, @@ -44,12 +42,11 @@ pub fn parse_term_arg(data: &[u8], } pub fn parse_object_list(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { let mut current_offset: usize = 0; while current_offset < data.len() { - let res = parse_object(&data[current_offset..], namespace, scope.clone())?; + let res = parse_object(&data[current_offset..], ctx)?; current_offset += res.len; } @@ -60,10 +57,9 @@ pub fn parse_object_list(data: &[u8], } fn parse_object(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_selector! { - data, namespace, scope.clone(), + data, ctx, parse_namespace_modifier, parse_named_obj }; @@ -72,17 +68,18 @@ fn parse_object(data: &[u8], } pub fn parse_method_invocation(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { - let name = parse_name_string(data, namespace, scope)?; + ctx: &mut AmlExecutionContext) -> ParseResult { + // TODO: Check if method exists in namespace + // TODO: If so, parse appropriate number of parameters + // TODO: If not, add deferred load to ctx + let name = parse_name_string(data, ctx)?; Err(AmlError::AmlDeferredLoad) } fn parse_term_obj(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_selector! { - data, namespace, scope.clone(), + data, ctx, parse_namespace_modifier, parse_named_obj, parse_type1_opcode, diff --git a/src/acpi/aml/type1opcode.rs b/src/acpi/aml/type1opcode.rs index b32acf8..7bc9546 100644 --- a/src/acpi/aml/type1opcode.rs +++ b/src/acpi/aml/type1opcode.rs @@ -4,17 +4,16 @@ use collections::vec::Vec; use collections::btree_map::BTreeMap; use super::AmlError; -use super::parser::{AmlParseType, ParseResult}; +use super::parser::{AmlParseType, ParseResult, AmlExecutionContext}; use super::namespace::{AmlValue, ObjectReference}; use super::pkglength::parse_pkg_length; use super::termlist::{parse_term_arg, parse_term_list}; use super::namestring::{parse_name_string, parse_super_name}; pub fn parse_type1_opcode(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_selector! { - data, namespace, scope.clone(), + data, ctx, parse_def_break, parse_def_breakpoint, parse_def_continue, @@ -37,8 +36,7 @@ pub fn parse_type1_opcode(data: &[u8], } fn parse_def_break(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Implement parser_opcode!(data, 0xA5); @@ -49,8 +47,7 @@ fn parse_def_break(data: &[u8], } fn parse_def_breakpoint(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Implement parser_opcode!(data, 0xCC); @@ -61,8 +58,7 @@ fn parse_def_breakpoint(data: &[u8], } fn parse_def_continue(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Implement parser_opcode!(data, 0x9F); @@ -73,8 +69,7 @@ fn parse_def_continue(data: &[u8], } fn parse_def_noop(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode!(data, 0xA3); Ok(AmlParseType { @@ -84,27 +79,25 @@ fn parse_def_noop(data: &[u8], } fn parse_def_fatal(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode_extended!(data, 0x32); let fatal_type = data[2]; let fatal_code: u16 = (data[3] as u16) + ((data[4] as u16) << 8); - let fatal_arg = parse_term_arg(&data[5..], namespace, scope.clone())?; + let fatal_arg = parse_term_arg(&data[5..], ctx)?; Err(AmlError::AmlFatalError(fatal_type, fatal_code, fatal_arg.val)) } fn parse_def_load(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Load in the table pointed to by `name` // TODO: Set DDB_Handle to the handle returned by loading in the table // TODO: Run the AML parser on the table, in a secondary namespace parser_opcode_extended!(data, 0x20); - let name = parse_name_string(&data[2..], namespace, scope.clone())?; - let ddb_handle_object = parse_super_name(&data[2 + name.len..], namespace, scope.clone())?; + let name = parse_name_string(&data[2..], ctx)?; + let ddb_handle_object = parse_super_name(&data[2 + name.len..], ctx)?; Ok(AmlParseType { val: AmlValue::None, @@ -113,13 +106,12 @@ fn parse_def_load(data: &[u8], } fn parse_def_notify(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: This requires significantly more infrastructure from the OS itself, see 5.6.6 parser_opcode!(data, 0x86); - let object = parse_super_name(&data[1..], namespace, scope.clone())?; - let value = parse_term_arg(&data[1 + object.len..], namespace, scope.clone())?; + let object = parse_super_name(&data[1..], ctx)?; + let value = parse_term_arg(&data[1 + object.len..], ctx)?; Ok(AmlParseType { val: AmlValue::None, @@ -128,14 +120,13 @@ fn parse_def_notify(data: &[u8], } fn parse_def_release(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Check ownership of the mutex pointed to // TODO: FATAL if not owned // TODO: Release if it is parser_opcode_extended!(data, 0x27); - let object = parse_super_name(&data[2..], namespace, scope.clone())?; + let object = parse_super_name(&data[2..], ctx)?; Ok(AmlParseType { val: AmlValue::None, @@ -144,12 +135,11 @@ fn parse_def_release(data: &[u8], } fn parse_def_reset(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: object (of type Event) is a semaphore. Reset the resource count to 0 parser_opcode_extended!(data, 0x26); - let object = parse_super_name(&data[2..], namespace, scope.clone())?; + let object = parse_super_name(&data[2..], ctx)?; Ok(AmlParseType { val: AmlValue::None, @@ -158,12 +148,11 @@ fn parse_def_reset(data: &[u8], } fn parse_def_signal(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Increment the resource count of the semaphore parser_opcode_extended!(data, 0x24); - let object = parse_super_name(&data[2..], namespace, scope.clone())?; + let object = parse_super_name(&data[2..], ctx)?; Ok(AmlParseType { val: AmlValue::None, @@ -172,12 +161,11 @@ fn parse_def_signal(data: &[u8], } fn parse_def_sleep(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Sleep the processor for the specified number of milliseconds (minimum) parser_opcode_extended!(data, 0x22); - let time = parse_term_arg(&data[2..], namespace, scope.clone())?; + let time = parse_term_arg(&data[2..], ctx)?; Ok(AmlParseType { val: AmlValue::None, @@ -186,12 +174,11 @@ fn parse_def_sleep(data: &[u8], } fn parse_def_stall(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Sleep the processor for the specified number of microseconds (minimum) parser_opcode_extended!(data, 0x21); - let time = parse_term_arg(&data[2..], namespace, scope.clone())?; + let time = parse_term_arg(&data[2..], ctx)?; Ok(AmlParseType { val: AmlValue::None, @@ -200,13 +187,12 @@ fn parse_def_stall(data: &[u8], } fn parse_def_unload(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // 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..], namespace, scope.clone())?; + let object = parse_super_name(&data[2..], ctx)?; Ok(AmlParseType { val: AmlValue::None, @@ -215,12 +201,11 @@ fn parse_def_unload(data: &[u8], } fn parse_def_if_else(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode!(data, 0xA0); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; - let if_condition = parse_term_arg(&data[1 + pkg_length_len .. 1 + pkg_length], namespace, scope.clone())?; + let if_condition = parse_term_arg(&data[1 + pkg_length_len .. 1 + pkg_length], ctx)?; let (else_length, else_length_len) = if data.len() > 1 + pkg_length && data[1 + pkg_length] == 0xA1 { parse_pkg_length(&data[2 + pkg_length..])? @@ -229,11 +214,9 @@ fn parse_def_if_else(data: &[u8], }; if if_condition.val.get_as_integer()? > 0 { - parse_term_list(&data[1 + pkg_length_len + if_condition.len .. 1 + pkg_length], - namespace, scope.clone())?; + parse_term_list(&data[1 + pkg_length_len + if_condition.len .. 1 + pkg_length], ctx)?; } else if else_length > 0 { - parse_term_list(&data[2 + pkg_length + else_length_len .. 2 + pkg_length + else_length], - namespace, scope.clone())?; + parse_term_list(&data[2 + pkg_length + else_length_len .. 2 + pkg_length + else_length], ctx)?; } Ok(AmlParseType { @@ -243,19 +226,18 @@ fn parse_def_if_else(data: &[u8], } fn parse_def_while(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode!(data, 0xA2); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; loop { - let predicate = parse_term_arg(&data[1 + pkg_length_len..], namespace, scope.clone())?; + let predicate = parse_term_arg(&data[1 + pkg_length_len..], ctx)?; if predicate.val.get_as_integer()? == 0 { break; } - parse_term_list(&data[1 + pkg_length_len + predicate.len .. 1 + pkg_length], namespace, scope.clone())?; + parse_term_list(&data[1 + pkg_length_len + predicate.len .. 1 + pkg_length], ctx)?; } Ok(AmlParseType { @@ -265,13 +247,12 @@ fn parse_def_while(data: &[u8], } fn parse_def_return(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Return to the calling context // TODO: We need contexts for that parser_opcode!(data, 0xA4); - let arg_object = parse_term_arg(&data[1..], namespace, scope.clone())?; + let arg_object = parse_term_arg(&data[1..], ctx)?; Ok(AmlParseType { val: AmlValue::None, diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index eef85e1..0685251 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -4,7 +4,7 @@ use collections::vec::Vec; use collections::btree_map::BTreeMap; use super::AmlError; -use super::parser::{AmlParseType, ParseResult}; +use super::parser::{AmlParseType, ParseResult, AmlExecutionContext}; use super::namespace::{AmlValue, ObjectReference}; use super::pkglength::parse_pkg_length; use super::termlist::{parse_term_arg, parse_method_invocation}; @@ -22,10 +22,9 @@ pub enum MatchOpcode { } pub fn parse_type2_opcode(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_selector! { - data, namespace, scope.clone(), + data, ctx, parse_def_increment, parse_def_acquire, parse_def_wait, @@ -82,10 +81,9 @@ pub fn parse_type2_opcode(data: &[u8], } pub fn parse_type6_opcode(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_selector! { - data, namespace, scope.clone(), + data, ctx, parse_def_deref_of, parse_def_ref_of, parse_def_index, @@ -96,11 +94,10 @@ pub fn parse_type6_opcode(data: &[u8], } pub fn parse_def_object_type(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode!(data, 0x8E); parser_selector! { - data, namespace, scope.clone(), + data, ctx, parse_super_name, parse_def_ref_of, parse_def_deref_of, @@ -111,16 +108,14 @@ pub fn parse_def_object_type(data: &[u8], } pub fn parse_def_package(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Handle deferred loads in here // TODO: Truncate/extend array if necessary parser_opcode!(data, 0x12); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; let num_elements = data[1 + pkg_length_len]; - let elements = parse_package_elements_list(&data[2 + pkg_length_len .. 1 + pkg_length], - namespace, scope.clone())?; + let elements = parse_package_elements_list(&data[2 + pkg_length_len .. 1 + pkg_length], ctx)?; Ok(AmlParseType { val: elements.val, @@ -129,16 +124,15 @@ pub fn parse_def_package(data: &[u8], } pub fn parse_def_var_package(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Handle deferred loads in here // TODO: Truncate/extend array if necessary parser_opcode!(data, 0x13); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; - let num_elements = parse_term_arg(&data[1 + pkg_length_len .. 1 + pkg_length], namespace, scope.clone())?; + let num_elements = parse_term_arg(&data[1 + pkg_length_len .. 1 + pkg_length], ctx)?; let elements = parse_package_elements_list(&data[1 + pkg_length_len + num_elements.len .. - 1 + pkg_length], namespace, scope.clone())?; + 1 + pkg_length], ctx)?; Ok(AmlParseType { val: elements.val, @@ -147,16 +141,15 @@ pub fn parse_def_var_package(data: &[u8], } fn parse_package_elements_list(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { let mut current_offset: usize = 0; let mut elements: Vec = vec!(); while current_offset < data.len() { - let dro = if let Ok(e) = parse_data_ref_obj(&data[current_offset..], namespace, scope.clone()) { + let dro = if let Ok(e) = parse_data_ref_obj(&data[current_offset..], ctx) { e } else { - parse_name_string(&data[current_offset..], namespace, scope.clone())? + parse_name_string(&data[current_offset..], ctx)? }; elements.push(dro.val); @@ -170,13 +163,12 @@ fn parse_package_elements_list(data: &[u8], } pub fn parse_def_buffer(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Perform computation parser_opcode!(data, 0x11); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; - let buffer_size = parse_term_arg(&data[1 + pkg_length_len..], namespace, scope.clone())?; + let buffer_size = parse_term_arg(&data[1 + pkg_length_len..], ctx)?; let byte_list = data[1 + pkg_length_len + buffer_size.len .. 1 + pkg_length].to_vec(); Ok(AmlParseType { @@ -186,12 +178,11 @@ pub fn parse_def_buffer(data: &[u8], } fn parse_def_ref_of(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Perform computation parser_opcode!(data, 0x71); - let obj = parse_super_name(&data[1..], namespace, scope.clone())?; + let obj = parse_super_name(&data[1..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -200,12 +191,11 @@ fn parse_def_ref_of(data: &[u8], } fn parse_def_deref_of(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Perform computation parser_opcode!(data, 0x83); - let obj = parse_term_arg(&data[1..], namespace, scope.clone())?; + let obj = parse_term_arg(&data[1..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -214,13 +204,12 @@ fn parse_def_deref_of(data: &[u8], } fn parse_def_acquire(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Store the result // TODO: Perform computation parser_opcode_extended!(data, 0x23); - let obj = parse_super_name(&data[1..], namespace, scope.clone())?; + let obj = parse_super_name(&data[1..], ctx)?; let timeout = (data[2 + obj.len] as u16) + ((data[3 + obj.len] as u16) << 8); Ok(AmlParseType { @@ -230,13 +219,12 @@ fn parse_def_acquire(data: &[u8], } fn parse_def_increment(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Store the result // TODO: Perform computation parser_opcode!(data, 0x75); - let obj = parse_super_name(&data[1..], namespace, scope.clone())?; + let obj = parse_super_name(&data[1..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -245,15 +233,14 @@ fn parse_def_increment(data: &[u8], } fn parse_def_index(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Store the result, if appropriate // TODO: Perform computation parser_opcode!(data, 0x88); - let obj = parse_term_arg(&data[1..], namespace, scope.clone())?; - let idx = parse_term_arg(&data[1 + obj.len..], namespace, scope.clone())?; - let target = parse_target(&data[1 + obj.len + idx.len..], namespace, scope.clone())?; + let obj = parse_term_arg(&data[1..], ctx)?; + let idx = parse_term_arg(&data[1 + obj.len..], ctx)?; + let target = parse_target(&data[1 + obj.len + idx.len..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -262,12 +249,11 @@ fn parse_def_index(data: &[u8], } fn parse_def_land(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode!(data, 0x90); - let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; - let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; + let lhs = parse_term_arg(&data[1..], ctx)?; + let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; let result = if lhs.val.get_as_integer()? > 0 && rhs.val.get_as_integer()? > 0 { 1 } else { 0 }; @@ -278,12 +264,11 @@ fn parse_def_land(data: &[u8], } fn parse_def_lequal(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode!(data, 0x93); - let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; - let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; + let lhs = parse_term_arg(&data[1..], ctx)?; + let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; let result = if lhs.val.get_as_integer()? == rhs.val.get_as_integer()? { 1 } else { 0 }; @@ -294,12 +279,11 @@ fn parse_def_lequal(data: &[u8], } fn parse_def_lgreater(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode!(data, 0x94); - let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; - let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; + let lhs = parse_term_arg(&data[1..], ctx)?; + let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; let result = if lhs.val.get_as_integer()? > rhs.val.get_as_integer()? { 1 } else { 0 }; @@ -310,12 +294,11 @@ fn parse_def_lgreater(data: &[u8], } fn parse_def_lless(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode!(data, 0x95); - let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; - let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; + let lhs = parse_term_arg(&data[1..], ctx)?; + let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; let result = if lhs.val.get_as_integer()? < rhs.val.get_as_integer()? { 1 } else { 0 }; @@ -326,11 +309,10 @@ fn parse_def_lless(data: &[u8], } fn parse_def_lnot(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode!(data, 0x92); - let operand = parse_term_arg(&data[1..], namespace, scope.clone())?; + let operand = parse_term_arg(&data[1..], ctx)?; let result = if operand.val.get_as_integer()? == 0 { 1 } else { 0 }; Ok(AmlParseType { @@ -340,12 +322,11 @@ fn parse_def_lnot(data: &[u8], } fn parse_def_lor(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { parser_opcode!(data, 0x91); - let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; - let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; + let lhs = parse_term_arg(&data[1..], ctx)?; + let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; let result = if lhs.val.get_as_integer()? > 0 || rhs.val.get_as_integer()? > 0 { 1 } else { 0 }; @@ -356,14 +337,13 @@ fn parse_def_lor(data: &[u8], } fn parse_def_to_hex_string(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Compute the result // TODO: Store the result, if appropriate parser_opcode!(data, 0x98); - let operand = parse_term_arg(&data[2..], namespace, scope.clone())?; - let target = parse_target(&data[2 + operand.len..], namespace, scope.clone())?; + let operand = parse_term_arg(&data[2..], ctx)?; + let target = parse_target(&data[2 + operand.len..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -372,14 +352,13 @@ fn parse_def_to_hex_string(data: &[u8], } fn parse_def_to_buffer(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Compute the result // TODO: Store the result, if appropriate parser_opcode!(data, 0x96); - let operand = parse_term_arg(&data[2..], namespace, scope.clone())?; - let target = parse_target(&data[2 + operand.len..], namespace, scope.clone())?; + let operand = parse_term_arg(&data[2..], ctx)?; + let target = parse_target(&data[2 + operand.len..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -388,14 +367,13 @@ fn parse_def_to_buffer(data: &[u8], } fn parse_def_to_bcd(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Compute the result // TODO: Store the result, if appropriate parser_opcode_extended!(data, 0x29); - let operand = parse_term_arg(&data[2..], namespace, scope.clone())?; - let target = parse_target(&data[2 + operand.len..], namespace, scope.clone())?; + let operand = parse_term_arg(&data[2..], ctx)?; + let target = parse_target(&data[2 + operand.len..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -404,14 +382,13 @@ fn parse_def_to_bcd(data: &[u8], } fn parse_def_to_decimal_string(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Compute the result // TODO: Store the result, if appropriate parser_opcode!(data, 0x97); - let operand = parse_term_arg(&data[2..], namespace, scope.clone())?; - let target = parse_target(&data[2 + operand.len..], namespace, scope.clone())?; + let operand = parse_term_arg(&data[2..], ctx)?; + let target = parse_target(&data[2 + operand.len..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -420,14 +397,13 @@ fn parse_def_to_decimal_string(data: &[u8], } fn parse_def_to_integer(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Compute the result // TODO: Store the result, if appropriate parser_opcode!(data, 0x99); - let operand = parse_term_arg(&data[2..], namespace, scope.clone())?; - let target = parse_target(&data[2 + operand.len..], namespace, scope.clone())?; + let operand = parse_term_arg(&data[2..], ctx)?; + let target = parse_target(&data[2 + operand.len..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -436,15 +412,14 @@ fn parse_def_to_integer(data: &[u8], } fn parse_def_to_string(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Compute the result // TODO: Store the result, if appropriate parser_opcode!(data, 0x9C); - let operand = parse_term_arg(&data[1..], namespace, scope.clone())?; - let length = parse_term_arg(&data[1 + operand.len..], namespace, scope.clone())?; - let target = parse_target(&data[1 + operand.len + length.len..], namespace, scope.clone())?; + let operand = parse_term_arg(&data[1..], ctx)?; + let length = parse_term_arg(&data[1 + operand.len..], ctx)?; + let target = parse_target(&data[1 + operand.len + length.len..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -453,14 +428,13 @@ fn parse_def_to_string(data: &[u8], } fn parse_def_subtract(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Store the result, if appropriate parser_opcode!(data, 0x74); - let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; - let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; - let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; + let lhs = parse_term_arg(&data[1..], ctx)?; + let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; let result = lhs.val.get_as_integer()? - rhs.val.get_as_integer()?; @@ -471,12 +445,11 @@ fn parse_def_subtract(data: &[u8], } fn parse_def_size_of(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Perform the computation parser_opcode!(data, 0x87); - let name = parse_super_name(&data[1..], namespace, scope.clone())?; + let name = parse_super_name(&data[1..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -485,13 +458,12 @@ fn parse_def_size_of(data: &[u8], } fn parse_def_store(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Perform the store parser_opcode!(data, 0x70); - let operand = parse_term_arg(&data[1..], namespace, scope.clone())?; - let target = parse_super_name(&data[1 + operand.len..], namespace, scope.clone())?; + let operand = parse_term_arg(&data[1..], ctx)?; + let target = parse_super_name(&data[1 + operand.len..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -500,14 +472,13 @@ fn parse_def_store(data: &[u8], } fn parse_def_or(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Store the result, if appropriate parser_opcode!(data, 0x7D); - let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; - let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; - let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; + let lhs = parse_term_arg(&data[1..], ctx)?; + let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; let result = lhs.val.get_as_integer()? | rhs.val.get_as_integer()?; @@ -518,14 +489,13 @@ fn parse_def_or(data: &[u8], } fn parse_def_shift_left(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Store the result, if appropriate parser_opcode!(data, 0x79); - let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; - let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; - let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; + let lhs = parse_term_arg(&data[1..], ctx)?; + let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; let result = lhs.val.get_as_integer()? >> rhs.val.get_as_integer()?; @@ -536,14 +506,13 @@ fn parse_def_shift_left(data: &[u8], } fn parse_def_shift_right(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Store the result, if appropriate parser_opcode!(data, 0x7A); - let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; - let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; - let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; + let lhs = parse_term_arg(&data[1..], ctx)?; + let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; let result = lhs.val.get_as_integer()? << rhs.val.get_as_integer()?; @@ -554,14 +523,13 @@ fn parse_def_shift_right(data: &[u8], } fn parse_def_add(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Store the result, if appropriate parser_opcode!(data, 0x72); - let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; - let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; - let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; + let lhs = parse_term_arg(&data[1..], ctx)?; + let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; let result = lhs.val.get_as_integer()? + rhs.val.get_as_integer()?; @@ -572,14 +540,13 @@ fn parse_def_add(data: &[u8], } fn parse_def_and(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Store the result, if appropriate parser_opcode!(data, 0x7B); - let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; - let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; - let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; + let lhs = parse_term_arg(&data[1..], ctx)?; + let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; let result = lhs.val.get_as_integer()? & rhs.val.get_as_integer()?; @@ -590,14 +557,13 @@ fn parse_def_and(data: &[u8], } fn parse_def_xor(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Store the result, if appropriate parser_opcode!(data, 0x7F); - let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; - let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; - let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; + let lhs = parse_term_arg(&data[1..], ctx)?; + let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; let result = lhs.val.get_as_integer()? ^ rhs.val.get_as_integer()?; @@ -608,15 +574,14 @@ fn parse_def_xor(data: &[u8], } fn parse_def_concat_res(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Compute the result // TODO: Store the result, if appropriate parser_opcode!(data, 0x84); - let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; - let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; - let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; + let lhs = parse_term_arg(&data[1..], ctx)?; + let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -625,13 +590,12 @@ fn parse_def_concat_res(data: &[u8], } fn parse_def_wait(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Compute the result parser_opcode_extended!(data, 0x25); - let event_object = parse_super_name(&data[2..], namespace, scope.clone())?; - let operand = parse_term_arg(&data[2 + event_object.len..], namespace, scope.clone())?; + let event_object = parse_super_name(&data[2..], ctx)?; + let operand = parse_term_arg(&data[2 + event_object.len..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -640,14 +604,13 @@ fn parse_def_wait(data: &[u8], } fn parse_def_cond_ref_of(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Compute the result // TODO: Store the result parser_opcode_extended!(data, 0x12); - let operand = parse_super_name(&data[2..], namespace, scope.clone())?; - let target = parse_target(&data[2 + operand.len..], namespace, scope.clone())?; + let operand = parse_super_name(&data[2..], ctx)?; + let target = parse_target(&data[2 + operand.len..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -656,14 +619,13 @@ fn parse_def_cond_ref_of(data: &[u8], } fn parse_def_copy_object(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Compute the result // TODO: Store the result parser_opcode!(data, 0x9D); - let source = parse_term_arg(&data[1..], namespace, scope.clone())?; - let destination = parse_simple_name(&data[1 + source.len..], namespace, scope.clone())?; + let source = parse_term_arg(&data[1..], ctx)?; + let destination = parse_simple_name(&data[1 + source.len..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -672,15 +634,14 @@ fn parse_def_copy_object(data: &[u8], } fn parse_def_concat(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Compute the result // TODO: Store the result parser_opcode!(data, 0x73); - let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; - let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; - let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; + let lhs = parse_term_arg(&data[1..], ctx)?; + let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -689,13 +650,12 @@ fn parse_def_concat(data: &[u8], } fn parse_def_decrement(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Compute the result // TODO: Store the result parser_opcode!(data, 0x76); - let target = parse_super_name(&data[1..], namespace, scope.clone())?; + let target = parse_super_name(&data[1..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -704,16 +664,15 @@ fn parse_def_decrement(data: &[u8], } fn parse_def_divide(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Compute the result // TODO: Store the result, if appropriate parser_opcode!(data, 0x78); - let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; - let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; - let target_remainder = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; - let target_quotient = parse_target(&data[1 + lhs.len + rhs.len + target_remainder.len..], namespace, scope.clone())?; + let lhs = parse_term_arg(&data[1..], ctx)?; + let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; + let target_remainder = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; + let target_quotient = parse_target(&data[1 + lhs.len + rhs.len + target_remainder.len..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -722,14 +681,13 @@ fn parse_def_divide(data: &[u8], } fn parse_def_find_set_left_bit(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Compute the result // TODO: Store the result, if appropriate parser_opcode!(data, 0x81); - let operand = parse_term_arg(&data[2..], namespace, scope.clone())?; - let target = parse_target(&data[2 + operand.len..], namespace, scope.clone())?; + let operand = parse_term_arg(&data[2..], ctx)?; + let target = parse_target(&data[2 + operand.len..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -738,14 +696,13 @@ fn parse_def_find_set_left_bit(data: &[u8], } fn parse_def_find_set_right_bit(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Compute the result // TODO: Store the result, if appropriate parser_opcode!(data, 0x82); - let operand = parse_term_arg(&data[2..], namespace, scope.clone())?; - let target = parse_target(&data[2 + operand.len..], namespace, scope.clone())?; + let operand = parse_term_arg(&data[2..], ctx)?; + let target = parse_target(&data[2 + operand.len..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -754,19 +711,18 @@ fn parse_def_find_set_right_bit(data: &[u8], } fn parse_def_load_table(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Compute the result // TODO: Store the result, if appropriate // TODO: Clean up parser_opcode_extended!(data, 0x1F); - let signature = parse_term_arg(&data[2..], namespace, scope.clone())?; - let oem_id = parse_term_arg(&data[2 + signature.len..], namespace, scope.clone())?; - let oem_table_id = parse_term_arg(&data[2 + signature.len + oem_id.len..], namespace, scope.clone())?; - let root_path = parse_term_arg(&data[2 + signature.len + oem_id.len + oem_table_id.len..], namespace, scope.clone())?; - let parameter_path = parse_term_arg(&data[2 + signature.len + oem_id.len + oem_table_id.len + root_path.len..], namespace, scope.clone())?; - let parameter_data = parse_term_arg(&data[2 + signature.len + oem_id.len + oem_table_id.len + root_path.len + parameter_path.len..], namespace, scope.clone())?; + let signature = parse_term_arg(&data[2..], ctx)?; + let oem_id = parse_term_arg(&data[2 + signature.len..], ctx)?; + let oem_table_id = parse_term_arg(&data[2 + signature.len + oem_id.len..], ctx)?; + let root_path = parse_term_arg(&data[2 + signature.len + oem_id.len + oem_table_id.len..], ctx)?; + 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)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -775,14 +731,13 @@ fn parse_def_load_table(data: &[u8], } fn parse_def_match(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Compute the result // TODO: Store the result, if appropriate // TODO: Clean up match blocks parser_opcode!(data, 0x28); - let search_pkg = parse_term_arg(&data[1..], namespace, scope.clone())?; + let search_pkg = parse_term_arg(&data[1..], ctx)?; let first_operation = match data[1 + search_pkg.len] { 0 => MatchOpcode::MTR, @@ -793,7 +748,7 @@ fn parse_def_match(data: &[u8], 5 => MatchOpcode::MGT, _ => return Err(AmlError::AmlParseError("DefMatch - Invalid Opcode")) }; - let first_operand = parse_term_arg(&data[2 + search_pkg.len..], namespace, scope.clone())?; + let first_operand = parse_term_arg(&data[2 + search_pkg.len..], ctx)?; let second_operation = match data[2 + search_pkg.len + first_operand.len] { 0 => MatchOpcode::MTR, @@ -804,9 +759,9 @@ fn parse_def_match(data: &[u8], 5 => MatchOpcode::MGT, _ => return Err(AmlError::AmlParseError("DefMatch - Invalid Opcode")) }; - let second_operand = parse_term_arg(&data[3 + search_pkg.len + first_operand.len..], namespace, scope.clone())?; + let second_operand = parse_term_arg(&data[3 + search_pkg.len + first_operand.len..], ctx)?; - let start_index = parse_term_arg(&data[3 + search_pkg.len + first_operand.len + second_operand.len..], namespace, scope.clone())?; + let start_index = parse_term_arg(&data[3 + search_pkg.len + first_operand.len + second_operand.len..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -815,14 +770,13 @@ fn parse_def_match(data: &[u8], } fn parse_def_from_bcd(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Store the result, if appropriate // TODO: Clean up match block parser_opcode_extended!(data, 0x28); - let operand = parse_term_arg(&data[2..], namespace, scope.clone())?; - let target = parse_target(&data[2 + operand.len..], namespace, scope.clone())?; + let operand = parse_term_arg(&data[2..], ctx)?; + let target = parse_target(&data[2 + operand.len..], ctx)?; let result = match target.val.get_as_integer() { Ok(i) => { @@ -851,16 +805,15 @@ fn parse_def_from_bcd(data: &[u8], } fn parse_def_mid(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Compute the result // TODO: Store the result, if appropriate parser_opcode!(data, 0x9E); - let source = parse_term_arg(&data[1..], namespace, scope.clone())?; - let index = parse_term_arg(&data[1 + source.len..], namespace, scope.clone())?; - let length = parse_term_arg(&data[1 + source.len + index.len..], namespace, scope.clone())?; - let target = parse_target(&data[1 + source.len + index.len + length.len..], namespace, scope.clone())?; + let source = parse_term_arg(&data[1..], ctx)?; + let index = parse_term_arg(&data[1 + source.len..], ctx)?; + let length = parse_term_arg(&data[1 + source.len + index.len..], ctx)?; + let target = parse_target(&data[1 + source.len + index.len + length.len..], ctx)?; Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -869,15 +822,14 @@ fn parse_def_mid(data: &[u8], } fn parse_def_mod(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Store the result, if appropriate // TODO: Fatal exception on rhs == 0 parser_opcode!(data, 0x85); - let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; - let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; - let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; + let lhs = parse_term_arg(&data[1..], ctx)?; + let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; let result = lhs.val.get_as_integer()? % rhs.val.get_as_integer()?; @@ -888,15 +840,14 @@ fn parse_def_mod(data: &[u8], } fn parse_def_multiply(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Store the result, if appropriate // TODO: Handle overflow parser_opcode!(data, 0x77); - let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; - let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; - let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; + let lhs = parse_term_arg(&data[1..], ctx)?; + let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; let result = lhs.val.get_as_integer()? * rhs.val.get_as_integer()?; @@ -907,14 +858,13 @@ fn parse_def_multiply(data: &[u8], } fn parse_def_nand(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Store the result, if appropriate parser_opcode!(data, 0x7C); - let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; - let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; - let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; + let lhs = parse_term_arg(&data[1..], ctx)?; + let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; let result = !(lhs.val.get_as_integer()? & rhs.val.get_as_integer()?); @@ -925,14 +875,13 @@ fn parse_def_nand(data: &[u8], } fn parse_def_nor(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Store the result, if appropriate parser_opcode!(data, 0x7E); - let lhs = parse_term_arg(&data[1..], namespace, scope.clone())?; - let rhs = parse_term_arg(&data[1 + lhs.len..], namespace, scope.clone())?; - let target = parse_target(&data[1 + lhs.len + rhs.len..], namespace, scope.clone())?; + let lhs = parse_term_arg(&data[1..], ctx)?; + let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; + let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; let result = !(lhs.val.get_as_integer()? | rhs.val.get_as_integer()?); @@ -943,13 +892,12 @@ fn parse_def_nor(data: &[u8], } fn parse_def_not(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Store the result, if appropriate parser_opcode!(data, 0x80); - let operand = parse_term_arg(&data[1..], namespace, scope.clone())?; - let target = parse_target(&data[1 + operand.len..], namespace, scope.clone())?; + let operand = parse_term_arg(&data[1..], ctx)?; + let target = parse_target(&data[1 + operand.len..], ctx)?; let result = !operand.val.get_as_integer()?; @@ -960,8 +908,7 @@ fn parse_def_not(data: &[u8], } fn parse_def_timer(data: &[u8], - namespace: &mut BTreeMap, - scope: String) -> ParseResult { + ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Read from the hardware timer, and split into 100ns intervals parser_opcode_extended!(data, 0x33); From 2a6bbeb584324b95b1a7531977b26a1ebee8876b Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Mon, 3 Jul 2017 11:11:07 +0100 Subject: [PATCH 048/113] Added object modification --- src/acpi/aml/mod.rs | 5 +- src/acpi/aml/namedobj.rs | 24 ++------- src/acpi/aml/parser.rs | 49 +++++++++++++++-- src/acpi/aml/type2opcode.rs | 101 +++++++++++++++++++++--------------- 4 files changed, 108 insertions(+), 71 deletions(-) diff --git a/src/acpi/aml/mod.rs b/src/acpi/aml/mod.rs index d20ce4c..fa2e070 100644 --- a/src/acpi/aml/mod.rs +++ b/src/acpi/aml/mod.rs @@ -39,10 +39,7 @@ pub enum AmlError { pub fn parse_aml_table(sdt: &'static Sdt) -> Result, AmlError> { let data = sdt.data(); - let mut ctx = AmlExecutionContext { - namespace: &mut BTreeMap::new(), - scope: String::from_str("\\").unwrap() - }; + let mut ctx = AmlExecutionContext::new(String::from_str("\\").unwrap()); let term_list = parse_term_list(data, &mut ctx)?; diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index 3c4605b..06ad1cf 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -342,11 +342,7 @@ fn parse_def_device(data: &[u8], let (pkg_length, pkg_length_len) = parse_pkg_length(&data[2..])?; let name = parse_name_string(&data[2 + pkg_length_len .. 2 + pkg_length], ctx)?; - let mut local_ctx = AmlExecutionContext { - namespace: &mut BTreeMap::new(), - scope: String::new() - }; - + let mut local_ctx = AmlExecutionContext::new(String::new()); let obj_list = parse_object_list(&data[2 + pkg_length_len + name.len .. 2 + pkg_length], &mut local_ctx)?; let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); @@ -682,11 +678,7 @@ fn parse_def_power_res(data: &[u8], let resource_order: u16 = (data[3 + pkg_len_len + name.len] as u16) + ((data[4 + pkg_len_len + name.len] as u16) << 8); - let mut local_ctx = AmlExecutionContext { - namespace: &mut BTreeMap::new(), - scope: String::new() - }; - + let mut local_ctx = AmlExecutionContext::new(String::new()); parse_object_list(&data[5 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_ctx)?; ctx.namespace.insert(local_scope_string, AmlValue::PowerResource { @@ -717,11 +709,7 @@ fn parse_def_processor(data: &[u8], ((data[6 + pkg_len_len + name.len] as u32) << 24); let p_blk_len = data[7 + pkg_len_len + name.len]; - let mut local_ctx = AmlExecutionContext { - namespace: &mut BTreeMap::new(), - scope: String::new() - }; - + let mut local_ctx = AmlExecutionContext::new(String::new()); parse_object_list(&data[8 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_ctx)?; ctx.namespace.insert(local_scope_string, AmlValue::Processor { @@ -745,11 +733,7 @@ fn parse_def_thermal_zone(data: &[u8], let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); - let mut local_ctx = AmlExecutionContext { - namespace: &mut BTreeMap::new(), - scope: String::new() - }; - + let mut local_ctx = AmlExecutionContext::new(String::new()); parse_object_list(&data[2 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_ctx)?; ctx.namespace.insert(local_scope_string, AmlValue::ThermalZone(local_ctx.namespace.clone())); diff --git a/src/acpi/aml/parser.rs b/src/acpi/aml/parser.rs index b316319..d918292 100644 --- a/src/acpi/aml/parser.rs +++ b/src/acpi/aml/parser.rs @@ -1,7 +1,7 @@ use collections::string::String; use collections::btree_map::BTreeMap; -use super::namespace::AmlValue; +use super::namespace::{ AmlValue, ObjectReference }; use super::AmlError; pub type ParseResult = Result; @@ -12,7 +12,48 @@ pub struct AmlParseTypeGeneric { pub len: usize } -pub struct AmlExecutionContext<'a> { - pub namespace: &'a mut BTreeMap, - pub scope: String +pub struct AmlExecutionContext { + pub namespace: BTreeMap, + pub scope: String, + pub local_vars: [AmlValue; 8], + pub arg_vars: [AmlValue; 8] +} + +impl AmlExecutionContext { + pub fn new(scope: String) -> AmlExecutionContext { + AmlExecutionContext { + namespace: BTreeMap::new(), + scope: scope, + local_vars: [AmlValue::Uninitialized, + AmlValue::Uninitialized, + AmlValue::Uninitialized, + AmlValue::Uninitialized, + AmlValue::Uninitialized, + AmlValue::Uninitialized, + AmlValue::Uninitialized, + AmlValue::Uninitialized], + arg_vars: [AmlValue::Uninitialized, + AmlValue::Uninitialized, + AmlValue::Uninitialized, + AmlValue::Uninitialized, + AmlValue::Uninitialized, + AmlValue::Uninitialized, + AmlValue::Uninitialized, + AmlValue::Uninitialized] + } + } + + pub fn modify(&mut self, name: AmlValue, value: AmlValue) { + // TODO: throw errors + // TODO: return DRO + match name { + AmlValue::None => (), + AmlValue::ObjectReference(r) => match r { + ObjectReference::ArgObj(i) => (), + ObjectReference::LocalObj(i) => self.local_vars[i as usize] = value, + _ => () + }, + _ => () + } + } } diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index 0685251..475b942 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -429,17 +429,18 @@ fn parse_def_to_string(data: &[u8], fn parse_def_subtract(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Store the result, if appropriate parser_opcode!(data, 0x74); let lhs = parse_term_arg(&data[1..], ctx)?; let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; - let result = lhs.val.get_as_integer()? - rhs.val.get_as_integer()?; + let result = AmlValue::Integer(lhs.val.get_as_integer()? - rhs.val.get_as_integer()?); + + ctx.modify(target.val, result.clone()); Ok(AmlParseType { - val: AmlValue::IntegerConstant(result), + val: result, len: 1 + lhs.len + rhs.len + target.len }) } @@ -459,11 +460,13 @@ fn parse_def_size_of(data: &[u8], fn parse_def_store(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Perform the store + // TODO: Return the DRO parser_opcode!(data, 0x70); let operand = parse_term_arg(&data[1..], ctx)?; let target = parse_super_name(&data[1 + operand.len..], ctx)?; + + ctx.modify(target.val, operand.val); Ok(AmlParseType { val: AmlValue::Uninitialized, @@ -473,102 +476,108 @@ fn parse_def_store(data: &[u8], fn parse_def_or(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Store the result, if appropriate parser_opcode!(data, 0x7D); let lhs = parse_term_arg(&data[1..], ctx)?; let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; - let result = lhs.val.get_as_integer()? | rhs.val.get_as_integer()?; + let result = AmlValue::Integer(lhs.val.get_as_integer()? | rhs.val.get_as_integer()?); + + ctx.modify(target.val, result.clone()); Ok(AmlParseType { - val: AmlValue::IntegerConstant(result), + val: result, len: 1 + lhs.len + rhs.len + target.len }) } fn parse_def_shift_left(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Store the result, if appropriate parser_opcode!(data, 0x79); let lhs = parse_term_arg(&data[1..], ctx)?; let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; - let result = lhs.val.get_as_integer()? >> rhs.val.get_as_integer()?; + let result = AmlValue::Integer(lhs.val.get_as_integer()? >> rhs.val.get_as_integer()?); + + ctx.modify(target.val, result.clone()); Ok(AmlParseType { - val: AmlValue::IntegerConstant(result), + val: result, len: 1 + lhs.len + rhs.len + target.len }) } fn parse_def_shift_right(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Store the result, if appropriate parser_opcode!(data, 0x7A); let lhs = parse_term_arg(&data[1..], ctx)?; let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; - - let result = lhs.val.get_as_integer()? << rhs.val.get_as_integer()?; - + + let result = AmlValue::Integer(lhs.val.get_as_integer()? << rhs.val.get_as_integer()?); + + ctx.modify(target.val, result.clone()); + Ok(AmlParseType { - val: AmlValue::IntegerConstant(result), + val: result, len: 1 + lhs.len + rhs.len + target.len }) } fn parse_def_add(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Store the result, if appropriate parser_opcode!(data, 0x72); let lhs = parse_term_arg(&data[1..], ctx)?; let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; - let result = lhs.val.get_as_integer()? + rhs.val.get_as_integer()?; + let result = AmlValue::Integer(lhs.val.get_as_integer()? + rhs.val.get_as_integer()?); + + ctx.modify(target.val, result.clone()); Ok(AmlParseType { - val: AmlValue::IntegerConstant(result), + val: result, len: 1 + lhs.len + rhs.len + target.len }) } fn parse_def_and(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Store the result, if appropriate parser_opcode!(data, 0x7B); let lhs = parse_term_arg(&data[1..], ctx)?; let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; - let result = lhs.val.get_as_integer()? & rhs.val.get_as_integer()?; + let result = AmlValue::Integer(lhs.val.get_as_integer()? & rhs.val.get_as_integer()?); + + ctx.modify(target.val, result.clone()); Ok(AmlParseType { - val: AmlValue::IntegerConstant(result), + val: result, len: 1 + lhs.len + rhs.len + target.len }) } fn parse_def_xor(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Store the result, if appropriate parser_opcode!(data, 0x7F); let lhs = parse_term_arg(&data[1..], ctx)?; let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; - let result = lhs.val.get_as_integer()? ^ rhs.val.get_as_integer()?; + let result = AmlValue::Integer(lhs.val.get_as_integer()? ^ rhs.val.get_as_integer()?); + + ctx.modify(target.val, result.clone()); Ok(AmlParseType { - val: AmlValue::IntegerConstant(result), + val: result, len: 1 + lhs.len + rhs.len + target.len }) } @@ -771,14 +780,13 @@ fn parse_def_match(data: &[u8], fn parse_def_from_bcd(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Store the result, if appropriate // TODO: Clean up match block parser_opcode_extended!(data, 0x28); let operand = parse_term_arg(&data[2..], ctx)?; let target = parse_target(&data[2 + operand.len..], ctx)?; - let result = match target.val.get_as_integer() { + let result = AmlValue::Integer(match target.val.get_as_integer() { Ok(i) => { let mut i = i; let mut ires = 0; @@ -796,10 +804,12 @@ fn parse_def_from_bcd(data: &[u8], ires }, Err(e) => return Err(e) - }; + }); + + ctx.modify(target.val, result.clone()); Ok(AmlParseType { - val: AmlValue::IntegerConstant(result), + val: result, len: 2 + operand.len + target.len }) } @@ -823,7 +833,6 @@ fn parse_def_mid(data: &[u8], fn parse_def_mod(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Store the result, if appropriate // TODO: Fatal exception on rhs == 0 parser_opcode!(data, 0x85); @@ -831,17 +840,18 @@ fn parse_def_mod(data: &[u8], let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; - let result = lhs.val.get_as_integer()? % rhs.val.get_as_integer()?; + let result = AmlValue::Integer(lhs.val.get_as_integer()? % rhs.val.get_as_integer()?); + + ctx.modify(target.val, result.clone()); Ok(AmlParseType { - val: AmlValue::IntegerConstant(result), + val: result, len: 1 + lhs.len + rhs.len + target.len }) } fn parse_def_multiply(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Store the result, if appropriate // TODO: Handle overflow parser_opcode!(data, 0x77); @@ -849,60 +859,65 @@ fn parse_def_multiply(data: &[u8], let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; - let result = lhs.val.get_as_integer()? * rhs.val.get_as_integer()?; + let result = AmlValue::Integer(lhs.val.get_as_integer()? * rhs.val.get_as_integer()?); + + ctx.modify(target.val, result.clone()); Ok(AmlParseType { - val: AmlValue::IntegerConstant(result), + val: result, len: 1 + lhs.len + rhs.len + target.len }) } fn parse_def_nand(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Store the result, if appropriate parser_opcode!(data, 0x7C); let lhs = parse_term_arg(&data[1..], ctx)?; let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; - let result = !(lhs.val.get_as_integer()? & rhs.val.get_as_integer()?); + let result = AmlValue::Integer(!(lhs.val.get_as_integer()? & rhs.val.get_as_integer()?)); + + ctx.modify(target.val, result.clone()); Ok(AmlParseType { - val: AmlValue::IntegerConstant(result), + val: result, len: 1 + lhs.len + rhs.len + target.len }) } fn parse_def_nor(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Store the result, if appropriate parser_opcode!(data, 0x7E); let lhs = parse_term_arg(&data[1..], ctx)?; let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; - let result = !(lhs.val.get_as_integer()? | rhs.val.get_as_integer()?); + let result = AmlValue::Integer(!(lhs.val.get_as_integer()? | rhs.val.get_as_integer()?)); + + ctx.modify(target.val, result.clone()); Ok(AmlParseType { - val: AmlValue::IntegerConstant(result), + val: result, len: 1 + lhs.len + rhs.len + target.len }) } fn parse_def_not(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Store the result, if appropriate parser_opcode!(data, 0x80); let operand = parse_term_arg(&data[1..], ctx)?; let target = parse_target(&data[1 + operand.len..], ctx)?; - let result = !operand.val.get_as_integer()?; + let result = AmlValue::Integer(!operand.val.get_as_integer()?); + + ctx.modify(target.val, result.clone()); Ok(AmlParseType { - val: AmlValue::IntegerConstant(result), + val: result, len: 1 + operand.len + target.len }) } From 38263bf7002386ab5d7f9fb6537f3e321ec296b6 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Wed, 5 Jul 2017 14:36:40 +0100 Subject: [PATCH 049/113] Fixed number of bugs --- src/acpi/aml/dataobj.rs | 6 +++--- src/acpi/aml/mod.rs | 2 +- src/acpi/aml/namedobj.rs | 6 +++++- src/acpi/aml/namespace.rs | 6 +++++- src/acpi/aml/namespacemodifier.rs | 6 +++--- src/acpi/aml/parsermacros.rs | 32 +++++-------------------------- src/acpi/aml/termlist.rs | 1 + src/acpi/aml/type2opcode.rs | 6 +++++- src/stop.rs | 1 + 9 files changed, 29 insertions(+), 37 deletions(-) diff --git a/src/acpi/aml/dataobj.rs b/src/acpi/aml/dataobj.rs index 4025f7f..1cd3904 100644 --- a/src/acpi/aml/dataobj.rs +++ b/src/acpi/aml/dataobj.rs @@ -125,11 +125,11 @@ fn parse_computational_data(data: &[u8], }, 0x00 => Ok(AmlParseType { val: AmlValue::IntegerConstant(0 as u64), - len: 9 as usize + len: 1 as usize }), 0x01 => Ok(AmlParseType { val: AmlValue::IntegerConstant(1 as u64), - len: 9 as usize + len: 1 as usize }), 0x5B => if data[1] == 0x30 { Ok(AmlParseType { @@ -141,7 +141,7 @@ fn parse_computational_data(data: &[u8], }, 0xFF => Ok(AmlParseType { val: AmlValue::IntegerConstant(0xFFFFFFFFFFFFFFFF), - len: 9 as usize + len: 1 as usize }), _ => parse_def_buffer(data, ctx) } diff --git a/src/acpi/aml/mod.rs b/src/acpi/aml/mod.rs index fa2e070..a6275db 100644 --- a/src/acpi/aml/mod.rs +++ b/src/acpi/aml/mod.rs @@ -41,7 +41,7 @@ pub fn parse_aml_table(sdt: &'static Sdt) -> Result, let data = sdt.data(); let mut ctx = AmlExecutionContext::new(String::from_str("\\").unwrap()); - let term_list = parse_term_list(data, &mut ctx)?; + parse_term_list(data, &mut ctx)?; Ok(ctx.namespace.clone()) } diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index 06ad1cf..3f6a569 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -474,10 +474,13 @@ fn parse_field_list(data: &[u8], selector: FieldSelector, flags: &mut FieldFlags) -> ParseResult { let mut current_offset: usize = 0; + let mut field_offset: usize = 0; let mut connection = AmlValue::Uninitialized; while current_offset < data.len() { - parse_field_element(&data[current_offset..], ctx, selector.clone(), &mut connection, flags, &mut current_offset)?; + let res = parse_field_element(&data[current_offset..], ctx, selector.clone(), &mut connection, flags, &mut field_offset)?; + + current_offset += res.len; } Ok(AmlParseType { @@ -503,6 +506,7 @@ fn parse_field_element(data: &[u8], length: field.val.length }); + *offset += field.val.length; field.len } else if let Ok(field) = parse_reserved_field(data, ctx) { *offset += field.val; diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index 54cef02..f2a5ffe 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -129,6 +129,10 @@ pub fn get_namespace_string(current: String, modifier_v: AmlValue) -> String { } let mut namespace = current.clone(); - namespace.push('.'); + + if !namespace.ends_with("\\") { + namespace.push('.'); + } + namespace + &modifier } diff --git a/src/acpi/aml/namespacemodifier.rs b/src/acpi/aml/namespacemodifier.rs index 35cd1a3..5d1bbf6 100644 --- a/src/acpi/aml/namespacemodifier.rs +++ b/src/acpi/aml/namespacemodifier.rs @@ -66,13 +66,13 @@ fn parse_scope_op(data: &[u8], let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; let name = parse_name_string(&data[1 + pkg_length_len..], ctx)?; - let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val.clone()); let containing_scope_string = ctx.scope.clone(); ctx.scope = local_scope_string; - parse_term_list(&data[1 + pkg_length_len + name.len..], ctx)?; + parse_term_list(&data[1 + pkg_length_len + name.len .. 1 + pkg_length], ctx)?; ctx.scope = containing_scope_string; - + Ok(AmlParseType { val: AmlValue::None, len: 1 + pkg_length diff --git a/src/acpi/aml/parsermacros.rs b/src/acpi/aml/parsermacros.rs index 3f8cf61..20cedd9 100644 --- a/src/acpi/aml/parsermacros.rs +++ b/src/acpi/aml/parsermacros.rs @@ -4,7 +4,10 @@ macro_rules! parser_selector { match $func($data, $ctx) { Ok(res) => return Ok(res), Err(AmlError::AmlInvalidOpCode) => (), - Err(e) => return Err(e) + Err(e) => { +// println!("This doesn't work for some reason"); + return Err(e); + } } }; {$data:expr, $ctx:expr, $func:expr, $($funcs:expr),+} => { @@ -13,6 +16,7 @@ macro_rules! parser_selector { }; } +#[macro_export] macro_rules! parser_selector_simple { {$data:expr, $func:expr} => { match $func($data) { @@ -27,21 +31,6 @@ macro_rules! parser_selector_simple { }; } -#[macro_export] -macro_rules! parser_wrap { - ($wrap:expr, $func:expr) => { - |data, namespace, scope| { - match $func(data) { - Ok(res) => Ok(AmlParseTypeGeneric { - val: $wrap(res.val), - len: res.len - }), - Err(e) => Err(e) - } - } - }; -} - #[macro_export] macro_rules! parser_opcode { ($data:expr, $opcode:expr) => { @@ -64,14 +53,3 @@ macro_rules! parser_opcode_extended { } }; } - -#[macro_export] -macro_rules! parser_verify_value { - ($val:expr) => { - match $val.val { - Some(s) => s, - None => return Err(AmlError::AmlValueError) - } - }; -} - diff --git a/src/acpi/aml/termlist.rs b/src/acpi/aml/termlist.rs index bbce0e4..cdf0b80 100644 --- a/src/acpi/aml/termlist.rs +++ b/src/acpi/aml/termlist.rs @@ -73,6 +73,7 @@ pub fn parse_method_invocation(data: &[u8], // TODO: If so, parse appropriate number of parameters // TODO: If not, add deferred load to ctx let name = parse_name_string(data, ctx)?; + Err(AmlError::AmlDeferredLoad) } diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index 475b942..94950c1 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -149,7 +149,11 @@ fn parse_package_elements_list(data: &[u8], let dro = if let Ok(e) = parse_data_ref_obj(&data[current_offset..], ctx) { e } else { - parse_name_string(&data[current_offset..], ctx)? + let d = parse_name_string(&data[current_offset..], ctx)?; + AmlParseType { + val: AmlValue::ObjectReference(ObjectReference::NamedObj(d.val.get_as_string()?)), + len: d.len + } }; elements.push(dro.val); diff --git a/src/stop.rs b/src/stop.rs index 6dec9a1..7e53f10 100644 --- a/src/stop.rs +++ b/src/stop.rs @@ -14,6 +14,7 @@ pub unsafe extern fn kstop() -> ! { if let Some(ref namespace) = acpi.namespace { if let Some(s) = namespace.get("\\_S5") { if let Ok(p) = s.get_as_package() { + println!("{:?}", p); 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"); From e0bd497bb88e7f9d07998538c7140e4a15710992 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Fri, 7 Jul 2017 10:37:09 +0100 Subject: [PATCH 050/113] Implemented further opcodes in full, added get to context --- src/acpi/aml/namespace.rs | 13 ++- src/acpi/aml/parser.rs | 12 +++ src/acpi/aml/parsermacros.rs | 5 +- src/acpi/aml/type2opcode.rs | 188 +++++++++++++++++++++++++---------- 4 files changed, 159 insertions(+), 59 deletions(-) diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index f2a5ffe..746cd1e 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -34,10 +34,7 @@ pub enum ObjectReference { pub enum AmlValue { None, Uninitialized, - Buffer { - length: Box, - byte_list: Vec - }, + Buffer(Vec), BufferField { source_buf: Box, index: Box, @@ -81,13 +78,19 @@ pub enum AmlValue { } impl AmlValue { - // TODO: These should be able to throw errors rather than returning options pub fn get_as_string(&self) -> Result { match *self { AmlValue::String(ref s) => Ok(s.clone()), _ => Err(AmlError::AmlValueError) } } + + pub fn get_as_buffer(&self) -> Result, AmlError> { + match *self { + AmlValue::Buffer(ref b) => Ok(b.clone()), + _ => Err(AmlError::AmlValueError) + } + } pub fn get_as_package(&self) -> Result, AmlError> { match *self { diff --git a/src/acpi/aml/parser.rs b/src/acpi/aml/parser.rs index d918292..c71025d 100644 --- a/src/acpi/aml/parser.rs +++ b/src/acpi/aml/parser.rs @@ -56,4 +56,16 @@ impl AmlExecutionContext { _ => () } } + + pub fn get(&self, name: AmlValue) -> AmlValue { + match name { + AmlValue::None => AmlValue::None, + AmlValue::ObjectReference(r) => match r { + ObjectReference::ArgObj(i) => self.arg_vars[i as usize].clone(), + ObjectReference::LocalObj(i) => self.local_vars[i as usize].clone(), + _ => AmlValue::None + }, + _ => AmlValue::None + } + } } diff --git a/src/acpi/aml/parsermacros.rs b/src/acpi/aml/parsermacros.rs index 20cedd9..31a2338 100644 --- a/src/acpi/aml/parsermacros.rs +++ b/src/acpi/aml/parsermacros.rs @@ -4,10 +4,7 @@ macro_rules! parser_selector { match $func($data, $ctx) { Ok(res) => return Ok(res), Err(AmlError::AmlInvalidOpCode) => (), - Err(e) => { -// println!("This doesn't work for some reason"); - return Err(e); - } + Err(e) => return Err(e) } }; {$data:expr, $ctx:expr, $func:expr, $($funcs:expr),+} => { diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index 94950c1..721b36c 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -110,15 +110,22 @@ pub fn parse_def_object_type(data: &[u8], pub fn parse_def_package(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Handle deferred loads in here - // TODO: Truncate/extend array if necessary parser_opcode!(data, 0x12); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; - let num_elements = data[1 + pkg_length_len]; - let elements = parse_package_elements_list(&data[2 + pkg_length_len .. 1 + pkg_length], ctx)?; + let numelements = data[1 + pkg_length_len] as usize; + let mut elements = parse_package_elements_list(&data[2 + pkg_length_len .. 1 + pkg_length], ctx)?.val.get_as_package()?; + + if elements.len() > numelements { + elements = elements[0 .. numelements].to_vec(); + } else if numelements > elements.len() { + for i in 0..numelements - elements.len() { + elements.push(AmlValue::Uninitialized); + } + } Ok(AmlParseType { - val: elements.val, + val: AmlValue::Package(elements), len: 1 + pkg_length }) } @@ -126,16 +133,25 @@ pub fn parse_def_package(data: &[u8], pub fn parse_def_var_package(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { // TODO: Handle deferred loads in here - // TODO: Truncate/extend array if necessary parser_opcode!(data, 0x13); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; let num_elements = parse_term_arg(&data[1 + pkg_length_len .. 1 + pkg_length], ctx)?; - let elements = parse_package_elements_list(&data[1 + pkg_length_len + num_elements.len .. - 1 + pkg_length], ctx)?; + let mut elements = parse_package_elements_list(&data[1 + pkg_length_len + num_elements.len .. + 1 + pkg_length], ctx)?.val.get_as_package()?; + + let numelements = num_elements.val.get_as_integer()? as usize; + + if elements.len() > numelements { + elements = elements[0 .. numelements].to_vec(); + } else if numelements > elements.len() { + for i in 0..numelements - elements.len() { + elements.push(AmlValue::Uninitialized); + } + } Ok(AmlParseType { - val: elements.val, + val: AmlValue::Package(elements), len: 1 + pkg_length }) } @@ -224,14 +240,15 @@ fn parse_def_acquire(data: &[u8], fn parse_def_increment(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Store the result - // TODO: Perform computation parser_opcode!(data, 0x75); let obj = parse_super_name(&data[1..], ctx)?; + let value = AmlValue::Integer(ctx.get(obj.val.clone()).get_as_integer()? + 1); + + ctx.modify(obj.val, value.clone()); Ok(AmlParseType { - val: AmlValue::Uninitialized, + val: value, len: 1 + obj.len }) } @@ -464,16 +481,15 @@ fn parse_def_size_of(data: &[u8], fn parse_def_store(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Return the DRO parser_opcode!(data, 0x70); let operand = parse_term_arg(&data[1..], ctx)?; let target = parse_super_name(&data[1 + operand.len..], ctx)?; - ctx.modify(target.val, operand.val); + ctx.modify(target.val.clone(), operand.val); Ok(AmlParseType { - val: AmlValue::Uninitialized, + val: target.val, len: 1 + operand.len + target.len }) } @@ -664,61 +680,99 @@ fn parse_def_concat(data: &[u8], fn parse_def_decrement(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Compute the result - // TODO: Store the result parser_opcode!(data, 0x76); - let target = parse_super_name(&data[1..], ctx)?; + let obj = parse_super_name(&data[1..], ctx)?; + let value = AmlValue::Integer(ctx.get(obj.val.clone()).get_as_integer()? - 1); + ctx.modify(obj.val, value.clone()); + Ok(AmlParseType { - val: AmlValue::Uninitialized, - len: 1 + target.len + val: value, + len: 1 + obj.len }) } fn parse_def_divide(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Compute the result - // TODO: Store the result, if appropriate parser_opcode!(data, 0x78); let lhs = parse_term_arg(&data[1..], ctx)?; let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; let target_remainder = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; let target_quotient = parse_target(&data[1 + lhs.len + rhs.len + target_remainder.len..], ctx)?; + + let numerator = lhs.val.get_as_integer()?; + let denominator = rhs.val.get_as_integer()?; + + let remainder = numerator % denominator; + let quotient = (numerator - remainder) / denominator; + + ctx.modify(target_remainder.val, AmlValue::Integer(remainder)); + ctx.modify(target_quotient.val, AmlValue::Integer(quotient)); Ok(AmlParseType { - val: AmlValue::Uninitialized, + val: AmlValue::Integer(quotient), len: 1 + lhs.len + rhs.len + target_remainder.len + target_quotient.len }) } fn parse_def_find_set_left_bit(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Compute the result - // TODO: Store the result, if appropriate parser_opcode!(data, 0x81); let operand = parse_term_arg(&data[2..], ctx)?; let target = parse_target(&data[2 + operand.len..], ctx)?; + let mut first_bit = 32; + let mut test = operand.val.get_as_integer()?; + + while first_bit > 0{ + if test & 0x8000000000000000 > 0 { + break; + } + + test <<= 1; + first_bit -= 1; + } + + let result = AmlValue::Integer(first_bit); + ctx.modify(target.val, result.clone()); + Ok(AmlParseType { - val: AmlValue::Uninitialized, + val: result, len: 1 + operand.len + target.len }) } fn parse_def_find_set_right_bit(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Compute the result - // TODO: Store the result, if appropriate parser_opcode!(data, 0x82); let operand = parse_term_arg(&data[2..], ctx)?; let target = parse_target(&data[2 + operand.len..], ctx)?; + let mut first_bit = 1; + let mut test = operand.val.get_as_integer()?; + + while first_bit <= 32 { + if test & 1 > 0 { + break; + } + + test >>= 1; + first_bit += 1; + } + + if first_bit == 33 { + first_bit = 0; + } + + let result = AmlValue::Integer(first_bit); + ctx.modify(target.val, result.clone()); + Ok(AmlParseType { - val: AmlValue::Uninitialized, + val: result, len: 1 + operand.len + target.len }) } @@ -784,31 +838,25 @@ fn parse_def_match(data: &[u8], fn parse_def_from_bcd(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Clean up match block parser_opcode_extended!(data, 0x28); let operand = parse_term_arg(&data[2..], ctx)?; let target = parse_target(&data[2 + operand.len..], ctx)?; - - let result = AmlValue::Integer(match target.val.get_as_integer() { - Ok(i) => { - let mut i = i; - let mut ires = 0; - while i != 0 { - if i & 0x0F > 10 { - return Err(AmlError::AmlValueError); - } + let mut i = operand.val.get_as_integer()?; + let mut result = 0; - ires *= 10; - ires += i & 0x0F; - i >>= 4; - } + while i != 0 { + if i & 0x0F > 10 { + return Err(AmlError::AmlValueError); + } + + result *= 10; + result += i & 0x0F; + i >>= 4; + } - ires - }, - Err(e) => return Err(e) - }); + let result = AmlValue::Integer(result); ctx.modify(target.val, result.clone()); @@ -820,8 +868,6 @@ fn parse_def_from_bcd(data: &[u8], fn parse_def_mid(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Compute the result - // TODO: Store the result, if appropriate parser_opcode!(data, 0x9E); let source = parse_term_arg(&data[1..], ctx)?; @@ -829,21 +875,63 @@ fn parse_def_mid(data: &[u8], let length = parse_term_arg(&data[1 + source.len + index.len..], ctx)?; let target = parse_target(&data[1 + source.len + index.len + length.len..], ctx)?; + let idx = index.val.get_as_integer()? as usize; + let mut len = length.val.get_as_integer()? as usize; + + let result = match source.val { + AmlValue::String(s) => { + if idx > s.len() { + AmlValue::String(String::new()) + } else { + let mut res = s.clone().split_off(idx); + + if len < res.len() { + res.split_off(len); + } + + AmlValue::String(res) + } + }, + _ => { + // If it isn't a string already, treat it as a buffer. Must perform that check first, + // as Mid can operate on both strings and buffers, but a string can be cast as a buffer + // implicitly. + // Additionally, any type that can be converted to a buffer can also be converted to a + // string, so no information is lost + let b = source.val.get_as_buffer()?; + + if idx > b.len() { + AmlValue::Buffer(vec!()) + } else { + if idx + len > b.len() { + len = b.len() - idx; + } + + AmlValue::Buffer(b[idx .. idx + len].to_vec()) + } + } + }; + + ctx.modify(target.val, result.clone()); + Ok(AmlParseType { - val: AmlValue::Uninitialized, + val: result, len: 1 + source.len + index.len + length.len + target.len }) } fn parse_def_mod(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Fatal exception on rhs == 0 parser_opcode!(data, 0x85); let lhs = parse_term_arg(&data[1..], ctx)?; let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; + if rhs.val.get_as_integer()? == 0 { + return Err(AmlError::AmlValueError); + } + let result = AmlValue::Integer(lhs.val.get_as_integer()? % rhs.val.get_as_integer()?); ctx.modify(target.val, result.clone()); From eeea65f5c1253fc69b8b1a7ea5655e0be906ccbd Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Fri, 7 Jul 2017 11:39:08 +0100 Subject: [PATCH 051/113] Implemented match --- src/acpi/aml/type2opcode.rs | 106 ++++++++++++++++++++++++++++++++++-- 1 file changed, 102 insertions(+), 4 deletions(-) diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index 721b36c..8956411 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -799,9 +799,7 @@ fn parse_def_load_table(data: &[u8], fn parse_def_match(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Compute the result - // TODO: Store the result, if appropriate - // TODO: Clean up match blocks + // TODO: Clean up parser_opcode!(data, 0x28); let search_pkg = parse_term_arg(&data[1..], ctx)?; @@ -830,8 +828,108 @@ fn parse_def_match(data: &[u8], let start_index = parse_term_arg(&data[3 + search_pkg.len + first_operand.len + second_operand.len..], ctx)?; + let pkg = search_pkg.val.get_as_package()?; + let mut idx = start_index.val.get_as_integer()? as usize; + + match first_operand.val { + AmlValue::Integer(i) => { + let j = second_operand.val.get_as_integer()?; + + while idx < pkg.len() { + let val = if let Ok(v) = pkg[idx].get_as_integer() { v } else { idx += 1; continue; }; + idx += 1; + + match first_operation { + MatchOpcode::MTR => (), + MatchOpcode::MEQ => if val != i { continue }, + MatchOpcode::MLE => if val > i { continue }, + MatchOpcode::MLT => if val >= i { continue }, + MatchOpcode::MGE => if val < i { continue }, + MatchOpcode::MGT => if val <= i { continue } + } + + match second_operation { + MatchOpcode::MTR => (), + MatchOpcode::MEQ => if val != i { continue }, + MatchOpcode::MLE => if val > i { continue }, + MatchOpcode::MLT => if val >= i { continue }, + MatchOpcode::MGE => if val < i { continue }, + MatchOpcode::MGT => if val <= i { continue } + } + + return Ok(AmlParseType { + val: AmlValue::Integer(idx as u64), + len: 3 + search_pkg.len + first_operand.len + second_operand.len + start_index.len + }); + } + }, + AmlValue::String(i) => { + let j = second_operand.val.get_as_string()?; + + while idx < pkg.len() { + let val = if let Ok(v) = pkg[idx].get_as_string() { v } else { idx += 1; continue; }; + idx += 1; + + match first_operation { + MatchOpcode::MTR => (), + MatchOpcode::MEQ => if val != i { continue }, + MatchOpcode::MLE => if val > i { continue }, + MatchOpcode::MLT => if val >= i { continue }, + MatchOpcode::MGE => if val < i { continue }, + MatchOpcode::MGT => if val <= i { continue } + } + + match second_operation { + MatchOpcode::MTR => (), + MatchOpcode::MEQ => if val != i { continue }, + MatchOpcode::MLE => if val > i { continue }, + MatchOpcode::MLT => if val >= i { continue }, + MatchOpcode::MGE => if val < i { continue }, + MatchOpcode::MGT => if val <= i { continue } + } + + return Ok(AmlParseType { + val: AmlValue::Integer(idx as u64), + len: 3 + search_pkg.len + first_operand.len + second_operand.len + start_index.len + }); + } + }, + _ => { + let i = first_operand.val.get_as_buffer()?; + let j = second_operand.val.get_as_buffer()?; + + while idx < pkg.len() { + let val = if let Ok(v) = pkg[idx].get_as_buffer() { v } else { idx += 1; continue; }; + idx += 1; + + match first_operation { + MatchOpcode::MTR => (), + MatchOpcode::MEQ => if val != i { continue }, + MatchOpcode::MLE => if val > i { continue }, + MatchOpcode::MLT => if val >= i { continue }, + MatchOpcode::MGE => if val < i { continue }, + MatchOpcode::MGT => if val <= i { continue } + } + + match second_operation { + MatchOpcode::MTR => (), + MatchOpcode::MEQ => if val != i { continue }, + MatchOpcode::MLE => if val > i { continue }, + MatchOpcode::MLT => if val >= i { continue }, + MatchOpcode::MGE => if val < i { continue }, + MatchOpcode::MGT => if val <= i { continue } + } + + return Ok(AmlParseType { + val: AmlValue::Integer(idx as u64), + len: 3 + search_pkg.len + first_operand.len + second_operand.len + start_index.len + }); + } + } + } + Ok(AmlParseType { - val: AmlValue::Uninitialized, + val: AmlValue::IntegerConstant(0xFFFFFFFFFFFFFFFF), len: 3 + search_pkg.len + first_operand.len + second_operand.len + start_index.len }) } From fe681d57a15d58576aeaedaf7470f04f7d5f98d8 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Sat, 8 Jul 2017 10:20:33 +0100 Subject: [PATCH 052/113] Implemented opcodes --- src/acpi/aml/type1opcode.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/acpi/aml/type1opcode.rs b/src/acpi/aml/type1opcode.rs index 7bc9546..d494205 100644 --- a/src/acpi/aml/type1opcode.rs +++ b/src/acpi/aml/type1opcode.rs @@ -48,7 +48,6 @@ fn parse_def_break(data: &[u8], fn parse_def_breakpoint(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Implement parser_opcode!(data, 0xCC); Ok(AmlParseType { From af80bfa258baf0cb624b8b0218f5c0f2fa071ae0 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Sat, 15 Jul 2017 10:51:59 +0100 Subject: [PATCH 053/113] Timer now returns monotonic counter --- src/acpi/aml/type2opcode.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index 8956411..4662010 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -11,6 +11,8 @@ use super::termlist::{parse_term_arg, parse_method_invocation}; use super::namestring::{parse_super_name, parse_target, parse_name_string, parse_simple_name}; use super::dataobj::parse_data_ref_obj; +use time::monotonic; + #[derive(Debug, Clone)] pub enum MatchOpcode { MTR, @@ -1114,11 +1116,13 @@ fn parse_def_not(data: &[u8], fn parse_def_timer(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Read from the hardware timer, and split into 100ns intervals parser_opcode_extended!(data, 0x33); + + let (seconds, nanoseconds) = monotonic(); + let monotonic_ns = nanoseconds + (seconds * 1000000000); Ok(AmlParseType { - val: AmlValue::IntegerConstant(0), + val: AmlValue::Integer(monotonic_ns), len: 2 as usize }) } From d38b1d7aa95edf8b2116081cf7060eca75118ef9 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Mon, 17 Jul 2017 11:26:33 +0100 Subject: [PATCH 054/113] Implemented loop control --- src/acpi/aml/dataobj.rs | 37 ++- src/acpi/aml/namedobj.rs | 165 +++++++++++++- src/acpi/aml/namespacemodifier.rs | 30 ++- src/acpi/aml/namestring.rs | 37 ++- src/acpi/aml/parser.rs | 14 +- src/acpi/aml/termlist.rs | 60 ++++- src/acpi/aml/type1opcode.rs | 139 +++++++++++- src/acpi/aml/type2opcode.rs | 359 +++++++++++++++++++++++++++++- 8 files changed, 829 insertions(+), 12 deletions(-) diff --git a/src/acpi/aml/dataobj.rs b/src/acpi/aml/dataobj.rs index 1cd3904..411c3ff 100644 --- a/src/acpi/aml/dataobj.rs +++ b/src/acpi/aml/dataobj.rs @@ -3,7 +3,7 @@ use collections::string::String; use collections::btree_map::BTreeMap; use super::AmlError; -use super::parser::{ AmlParseType, ParseResult, AmlExecutionContext }; +use super::parser::{ AmlParseType, ParseResult, AmlExecutionContext, ExecutionState }; use super::namespace::{ AmlValue, ObjectReference }; use super::type2opcode::{parse_def_buffer, parse_def_package, parse_def_var_package}; @@ -12,6 +12,13 @@ use super::namestring::parse_super_name; pub fn parse_data_obj(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_selector! { data, ctx, parse_computational_data, @@ -24,6 +31,13 @@ pub fn parse_data_obj(data: &[u8], pub fn parse_data_ref_obj(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_selector! { data, ctx, parse_data_obj, @@ -44,6 +58,13 @@ pub fn parse_data_ref_obj(data: &[u8], pub fn parse_arg_obj(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + match data[0] { 0x68 ... 0x6E => Ok(AmlParseType { val: AmlValue::ObjectReference(ObjectReference::ArgObj(data[0] - 0x68)), @@ -55,6 +76,13 @@ pub fn parse_arg_obj(data: &[u8], pub fn parse_local_obj(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + match data[0] { 0x68 ... 0x6E => Ok(AmlParseType { val: AmlValue::ObjectReference(ObjectReference::LocalObj(data[0] - 0x60)), @@ -66,6 +94,13 @@ pub fn parse_local_obj(data: &[u8], fn parse_computational_data(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + match data[0] { 0x0A => Ok(AmlParseType { val: AmlValue::Integer(data[1] as u64), diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index 3f6a569..a4f1ab0 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -6,7 +6,7 @@ use core::str::FromStr; use collections::btree_map::BTreeMap; use super::AmlError; -use super::parser::{ AmlParseType, ParseResult, AmlParseTypeGeneric, AmlExecutionContext }; +use super::parser::{ AmlParseType, ParseResult, AmlParseTypeGeneric, AmlExecutionContext, ExecutionState }; use super::namespace::{ AmlValue, ObjectReference, FieldSelector, get_namespace_string }; use super::namestring::{parse_name_string, parse_name_seg}; use super::termlist::{parse_term_arg, parse_term_list, parse_object_list}; @@ -88,6 +88,13 @@ pub enum AccessAttrib { pub fn parse_named_obj(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_selector! { data, ctx, parse_def_bank_field, @@ -115,6 +122,13 @@ pub fn parse_named_obj(data: &[u8], fn parse_def_bank_field(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + // TODO: Why isn't bank name used? parser_opcode_extended!(data, 0x87); @@ -163,6 +177,13 @@ fn parse_def_bank_field(data: &[u8], fn parse_def_create_bit_field(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode!(data, 0x8D); let source_buf = parse_term_arg(&data[2..], ctx)?; @@ -185,6 +206,13 @@ fn parse_def_create_bit_field(data: &[u8], fn parse_def_create_byte_field(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode!(data, 0x8C); let source_buf = parse_term_arg(&data[2..], ctx)?; @@ -207,6 +235,13 @@ fn parse_def_create_byte_field(data: &[u8], fn parse_def_create_word_field(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode!(data, 0x8B); let source_buf = parse_term_arg(&data[2..], ctx)?; @@ -229,6 +264,13 @@ fn parse_def_create_word_field(data: &[u8], fn parse_def_create_dword_field(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode!(data, 0x8A); let source_buf = parse_term_arg(&data[2..], ctx)?; @@ -251,6 +293,13 @@ fn parse_def_create_dword_field(data: &[u8], fn parse_def_create_qword_field(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode!(data, 0x8F); let source_buf = parse_term_arg(&data[2..], ctx)?; @@ -273,6 +322,13 @@ fn parse_def_create_qword_field(data: &[u8], fn parse_def_create_field(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode_extended!(data, 0x13); let source_buf = parse_term_arg(&data[2..], ctx)?; @@ -296,6 +352,13 @@ fn parse_def_create_field(data: &[u8], fn parse_def_data_region(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + // TODO: Find the actual offset and length, once table mapping is implemented parser_opcode_extended!(data, 0x88); @@ -320,6 +383,13 @@ fn parse_def_data_region(data: &[u8], fn parse_def_event(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode_extended!(data, 0x02); let name = parse_name_string(&data[2..], ctx)?; @@ -335,6 +405,13 @@ fn parse_def_event(data: &[u8], fn parse_def_device(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + // TODO: How to handle local context deferreds // TODO: How to also handle local context reference to calling context parser_opcode_extended!(data, 0x82); @@ -356,6 +433,13 @@ fn parse_def_device(data: &[u8], fn parse_def_op_region(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode_extended!(data, 0x80); let name = parse_name_string(&data[2..], ctx)?; @@ -392,6 +476,13 @@ fn parse_def_op_region(data: &[u8], fn parse_def_field(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode_extended!(data, 0x81); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[2..])?; @@ -429,6 +520,13 @@ fn parse_def_field(data: &[u8], fn parse_def_index_field(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode_extended!(data, 0x86); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[2..])?; @@ -473,13 +571,27 @@ fn parse_field_list(data: &[u8], ctx: &mut AmlExecutionContext, selector: FieldSelector, flags: &mut FieldFlags) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + let mut current_offset: usize = 0; let mut field_offset: usize = 0; let mut connection = AmlValue::Uninitialized; while current_offset < data.len() { let res = parse_field_element(&data[current_offset..], ctx, selector.clone(), &mut connection, flags, &mut field_offset)?; - + + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + current_offset += res.len; } @@ -495,6 +607,13 @@ fn parse_field_element(data: &[u8], connection: &mut AmlValue, flags: &mut FieldFlags, offset: &mut usize) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + let length = if let Ok(field) = parse_named_field(data, ctx) { let local_scope_string = get_namespace_string(ctx.scope.clone(), AmlValue::String(field.val.name.clone())); @@ -606,6 +725,13 @@ fn parse_access_field(data: &[u8], fn parse_connect_field(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode!(data, 0x02); if let Ok(e) = parse_def_buffer(&data[1..], ctx) { @@ -624,6 +750,13 @@ fn parse_connect_field(data: &[u8], fn parse_def_method(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode!(data, 0x14); let (pkg_len, pkg_len_len) = parse_pkg_length(&data[1..])?; @@ -652,6 +785,13 @@ fn parse_def_method(data: &[u8], fn parse_def_mutex(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode_extended!(data, 0x01); let name = parse_name_string(&data[2 ..], ctx)?; @@ -669,6 +809,13 @@ fn parse_def_mutex(data: &[u8], fn parse_def_power_res(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + // TODO: How to handle local context deferreds // TODO: How to also handle local context reference to calling context parser_opcode_extended!(data, 0x84); @@ -699,6 +846,13 @@ fn parse_def_power_res(data: &[u8], fn parse_def_processor(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode_extended!(data, 0x83); let (pkg_len, pkg_len_len) = parse_pkg_length(&data[2..])?; @@ -730,6 +884,13 @@ fn parse_def_processor(data: &[u8], fn parse_def_thermal_zone(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode_extended!(data, 0x85); let (pkg_len, pkg_len_len) = parse_pkg_length(&data[2..])?; diff --git a/src/acpi/aml/namespacemodifier.rs b/src/acpi/aml/namespacemodifier.rs index 5d1bbf6..8ca0c9e 100644 --- a/src/acpi/aml/namespacemodifier.rs +++ b/src/acpi/aml/namespacemodifier.rs @@ -4,7 +4,7 @@ use collections::vec::Vec; use collections::btree_map::BTreeMap; use super::AmlError; -use super::parser::{AmlParseType, ParseResult, AmlParseTypeGeneric, AmlExecutionContext}; +use super::parser::{AmlParseType, ParseResult, AmlParseTypeGeneric, AmlExecutionContext, ExecutionState}; use super::namespace::{AmlValue, ObjectReference, FieldSelector, get_namespace_string}; use super::pkglength::parse_pkg_length; use super::namestring::parse_name_string; @@ -13,6 +13,13 @@ use super::dataobj::parse_data_ref_obj; pub fn parse_namespace_modifier(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_selector! { data, ctx, parse_alias_op, @@ -25,6 +32,13 @@ pub fn parse_namespace_modifier(data: &[u8], fn parse_alias_op(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode!(data, 0x06); let source_name = parse_name_string(&data[1..], ctx)?; @@ -44,6 +58,13 @@ fn parse_alias_op(data: &[u8], fn parse_name_op(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode!(data, 0x08); let name = parse_name_string(&data[1..], ctx)?; @@ -61,6 +82,13 @@ fn parse_name_op(data: &[u8], fn parse_scope_op(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode!(data, 0x10); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; diff --git a/src/acpi/aml/namestring.rs b/src/acpi/aml/namestring.rs index e63a9b0..b1c2301 100644 --- a/src/acpi/aml/namestring.rs +++ b/src/acpi/aml/namestring.rs @@ -3,13 +3,20 @@ use collections::string::String; use collections::btree_map::BTreeMap; use super::AmlError; -use super::parser::{AmlParseType, ParseResult, AmlParseTypeGeneric, AmlExecutionContext}; +use super::parser::{AmlParseType, ParseResult, AmlParseTypeGeneric, AmlExecutionContext, ExecutionState}; use super::namespace::{AmlValue, ObjectReference, FieldSelector, get_namespace_string}; use super::dataobj::{parse_arg_obj, parse_local_obj}; use super::type2opcode::parse_type6_opcode; pub fn parse_name_string(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + let mut characters: Vec = vec!(); let mut starting_index: usize = 0; @@ -142,6 +149,13 @@ fn parse_multi_name_path(data: &[u8]) -> Result<(Vec, usize), AmlError> { pub fn parse_super_name(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_selector! { data, ctx, parse_simple_name, @@ -154,6 +168,13 @@ pub fn parse_super_name(data: &[u8], fn parse_debug_obj(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode_extended!(data, 0x31); Ok(AmlParseType { @@ -164,6 +185,13 @@ fn parse_debug_obj(data: &[u8], pub fn parse_simple_name(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_selector! { data, ctx, parse_name_string, @@ -176,6 +204,13 @@ pub fn parse_simple_name(data: &[u8], pub fn parse_target(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + if data[0] == 0x00 { Ok(AmlParseType { val: AmlValue::None, diff --git a/src/acpi/aml/parser.rs b/src/acpi/aml/parser.rs index c71025d..094028b 100644 --- a/src/acpi/aml/parser.rs +++ b/src/acpi/aml/parser.rs @@ -12,11 +12,20 @@ pub struct AmlParseTypeGeneric { pub len: usize } +#[derive(PartialEq)] +pub enum ExecutionState { + EXECUTING, + CONTINUE, + BREAK, + RETURN +} + pub struct AmlExecutionContext { pub namespace: BTreeMap, pub scope: String, pub local_vars: [AmlValue; 8], - pub arg_vars: [AmlValue; 8] + pub arg_vars: [AmlValue; 8], + pub state: ExecutionState } impl AmlExecutionContext { @@ -39,7 +48,8 @@ impl AmlExecutionContext { AmlValue::Uninitialized, AmlValue::Uninitialized, AmlValue::Uninitialized, - AmlValue::Uninitialized] + AmlValue::Uninitialized], + state: ExecutionState::EXECUTING } } diff --git a/src/acpi/aml/termlist.rs b/src/acpi/aml/termlist.rs index cdf0b80..87021d4 100644 --- a/src/acpi/aml/termlist.rs +++ b/src/acpi/aml/termlist.rs @@ -4,7 +4,7 @@ use collections::vec::Vec; use collections::btree_map::BTreeMap; use super::AmlError; -use super::parser::{ AmlParseType, ParseResult, AmlParseTypeGeneric, AmlExecutionContext }; +use super::parser::{ AmlParseType, ParseResult, AmlParseTypeGeneric, AmlExecutionContext, ExecutionState }; use super::namespace::{AmlValue, ObjectReference, FieldSelector, get_namespace_string}; use super::namespacemodifier::parse_namespace_modifier; use super::namedobj::parse_named_obj; @@ -15,10 +15,25 @@ use super::namestring::parse_name_string; pub fn parse_term_list(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: data.len() + }); + } + let mut current_offset: usize = 0; while current_offset < data.len() { let res = parse_term_obj(&data[current_offset..], ctx)?; + + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: data.len() + }); + } + current_offset += res.len; } @@ -30,6 +45,13 @@ pub fn parse_term_list(data: &[u8], pub fn parse_term_arg(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_selector! { data, ctx, parse_local_obj, @@ -43,10 +65,25 @@ pub fn parse_term_arg(data: &[u8], pub fn parse_object_list(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: data.len() + }); + } + let mut current_offset: usize = 0; while current_offset < data.len() { let res = parse_object(&data[current_offset..], ctx)?; + + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: data.len() + }); + } + current_offset += res.len; } @@ -58,6 +95,13 @@ pub fn parse_object_list(data: &[u8], fn parse_object(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_selector! { data, ctx, parse_namespace_modifier, @@ -69,6 +113,13 @@ fn parse_object(data: &[u8], pub fn parse_method_invocation(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + // TODO: Check if method exists in namespace // TODO: If so, parse appropriate number of parameters // TODO: If not, add deferred load to ctx @@ -79,6 +130,13 @@ pub fn parse_method_invocation(data: &[u8], fn parse_term_obj(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_selector! { data, ctx, parse_namespace_modifier, diff --git a/src/acpi/aml/type1opcode.rs b/src/acpi/aml/type1opcode.rs index d494205..35c7e0c 100644 --- a/src/acpi/aml/type1opcode.rs +++ b/src/acpi/aml/type1opcode.rs @@ -4,7 +4,7 @@ use collections::vec::Vec; use collections::btree_map::BTreeMap; use super::AmlError; -use super::parser::{AmlParseType, ParseResult, AmlExecutionContext}; +use super::parser::{AmlParseType, ParseResult, AmlExecutionContext, ExecutionState}; use super::namespace::{AmlValue, ObjectReference}; use super::pkglength::parse_pkg_length; use super::termlist::{parse_term_arg, parse_term_list}; @@ -12,6 +12,13 @@ use super::namestring::{parse_name_string, parse_super_name}; pub fn parse_type1_opcode(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_selector! { data, ctx, parse_def_break, @@ -37,8 +44,15 @@ pub fn parse_type1_opcode(data: &[u8], fn parse_def_break(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Implement + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode!(data, 0xA5); + ctx.state = ExecutionState::BREAK; Ok(AmlParseType { val: AmlValue::None, @@ -48,6 +62,13 @@ fn parse_def_break(data: &[u8], fn parse_def_breakpoint(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode!(data, 0xCC); Ok(AmlParseType { @@ -58,8 +79,15 @@ fn parse_def_breakpoint(data: &[u8], fn parse_def_continue(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - // TODO: Implement + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode!(data, 0x9F); + ctx.state = ExecutionState::CONTINUE; Ok(AmlParseType { val: AmlValue::None, @@ -69,6 +97,13 @@ fn parse_def_continue(data: &[u8], fn parse_def_noop(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode!(data, 0xA3); Ok(AmlParseType { @@ -79,6 +114,13 @@ fn parse_def_noop(data: &[u8], fn parse_def_fatal(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode_extended!(data, 0x32); let fatal_type = data[2]; @@ -90,6 +132,13 @@ fn parse_def_fatal(data: &[u8], fn parse_def_load(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + // TODO: Load in the table pointed to by `name` // TODO: Set DDB_Handle to the handle returned by loading in the table // TODO: Run the AML parser on the table, in a secondary namespace @@ -106,6 +155,13 @@ fn parse_def_load(data: &[u8], fn parse_def_notify(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + // TODO: This requires significantly more infrastructure from the OS itself, see 5.6.6 parser_opcode!(data, 0x86); @@ -120,6 +176,13 @@ fn parse_def_notify(data: &[u8], fn parse_def_release(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + // TODO: Check ownership of the mutex pointed to // TODO: FATAL if not owned // TODO: Release if it is @@ -135,6 +198,13 @@ fn parse_def_release(data: &[u8], fn parse_def_reset(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + // TODO: object (of type Event) is a semaphore. Reset the resource count to 0 parser_opcode_extended!(data, 0x26); @@ -148,6 +218,13 @@ fn parse_def_reset(data: &[u8], fn parse_def_signal(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + // TODO: Increment the resource count of the semaphore parser_opcode_extended!(data, 0x24); @@ -161,6 +238,13 @@ fn parse_def_signal(data: &[u8], fn parse_def_sleep(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + // TODO: Sleep the processor for the specified number of milliseconds (minimum) parser_opcode_extended!(data, 0x22); @@ -174,6 +258,13 @@ fn parse_def_sleep(data: &[u8], fn parse_def_stall(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + // TODO: Sleep the processor for the specified number of microseconds (minimum) parser_opcode_extended!(data, 0x21); @@ -187,6 +278,13 @@ fn parse_def_stall(data: &[u8], fn parse_def_unload(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + // TODO: remove from namespace all values added when `object` was loaded // TODO: globally synchronous (how?) parser_opcode_extended!(data, 0x2A); @@ -201,6 +299,13 @@ fn parse_def_unload(data: &[u8], fn parse_def_if_else(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode!(data, 0xA0); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; @@ -226,17 +331,38 @@ fn parse_def_if_else(data: &[u8], fn parse_def_while(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode!(data, 0xA2); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; loop { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + let predicate = parse_term_arg(&data[1 + pkg_length_len..], ctx)?; if predicate.val.get_as_integer()? == 0 { break; } parse_term_list(&data[1 + pkg_length_len + predicate.len .. 1 + pkg_length], ctx)?; + + if ctx.state == ExecutionState::BREAK { + ctx.state = ExecutionState::EXECUTING; + break; + } else if ctx.state == ExecutionState::CONTINUE { + ctx.state = ExecutionState::EXECUTING; + } } Ok(AmlParseType { @@ -247,6 +373,13 @@ fn parse_def_while(data: &[u8], fn parse_def_return(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + // TODO: Return to the calling context // TODO: We need contexts for that parser_opcode!(data, 0xA4); diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index 4662010..2ef678e 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -4,7 +4,7 @@ use collections::vec::Vec; use collections::btree_map::BTreeMap; use super::AmlError; -use super::parser::{AmlParseType, ParseResult, AmlExecutionContext}; +use super::parser::{AmlParseType, ParseResult, AmlExecutionContext, ExecutionState}; use super::namespace::{AmlValue, ObjectReference}; use super::pkglength::parse_pkg_length; use super::termlist::{parse_term_arg, parse_method_invocation}; @@ -25,6 +25,13 @@ pub enum MatchOpcode { pub fn parse_type2_opcode(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_selector! { data, ctx, parse_def_increment, @@ -84,6 +91,13 @@ pub fn parse_type2_opcode(data: &[u8], pub fn parse_type6_opcode(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_selector! { data, ctx, parse_def_deref_of, @@ -97,6 +111,13 @@ pub fn parse_type6_opcode(data: &[u8], pub fn parse_def_object_type(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode!(data, 0x8E); parser_selector! { data, ctx, @@ -111,6 +132,13 @@ pub fn parse_def_object_type(data: &[u8], pub fn parse_def_package(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + // TODO: Handle deferred loads in here parser_opcode!(data, 0x12); @@ -134,6 +162,13 @@ pub fn parse_def_package(data: &[u8], pub fn parse_def_var_package(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + // TODO: Handle deferred loads in here parser_opcode!(data, 0x13); @@ -160,6 +195,13 @@ pub fn parse_def_var_package(data: &[u8], fn parse_package_elements_list(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + let mut current_offset: usize = 0; let mut elements: Vec = vec!(); @@ -186,6 +228,13 @@ fn parse_package_elements_list(data: &[u8], pub fn parse_def_buffer(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + // TODO: Perform computation parser_opcode!(data, 0x11); @@ -201,6 +250,13 @@ pub fn parse_def_buffer(data: &[u8], fn parse_def_ref_of(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + // TODO: Perform computation parser_opcode!(data, 0x71); @@ -214,6 +270,13 @@ fn parse_def_ref_of(data: &[u8], fn parse_def_deref_of(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + // TODO: Perform computation parser_opcode!(data, 0x83); @@ -227,6 +290,13 @@ fn parse_def_deref_of(data: &[u8], fn parse_def_acquire(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + // TODO: Store the result // TODO: Perform computation parser_opcode_extended!(data, 0x23); @@ -242,6 +312,13 @@ fn parse_def_acquire(data: &[u8], fn parse_def_increment(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode!(data, 0x75); let obj = parse_super_name(&data[1..], ctx)?; @@ -257,6 +334,13 @@ fn parse_def_increment(data: &[u8], fn parse_def_index(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + // TODO: Store the result, if appropriate // TODO: Perform computation parser_opcode!(data, 0x88); @@ -273,6 +357,13 @@ fn parse_def_index(data: &[u8], fn parse_def_land(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode!(data, 0x90); let lhs = parse_term_arg(&data[1..], ctx)?; @@ -288,6 +379,13 @@ fn parse_def_land(data: &[u8], fn parse_def_lequal(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode!(data, 0x93); let lhs = parse_term_arg(&data[1..], ctx)?; @@ -303,6 +401,13 @@ fn parse_def_lequal(data: &[u8], fn parse_def_lgreater(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode!(data, 0x94); let lhs = parse_term_arg(&data[1..], ctx)?; @@ -318,6 +423,13 @@ fn parse_def_lgreater(data: &[u8], fn parse_def_lless(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode!(data, 0x95); let lhs = parse_term_arg(&data[1..], ctx)?; @@ -333,6 +445,13 @@ fn parse_def_lless(data: &[u8], fn parse_def_lnot(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode!(data, 0x92); let operand = parse_term_arg(&data[1..], ctx)?; @@ -346,6 +465,13 @@ fn parse_def_lnot(data: &[u8], fn parse_def_lor(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode!(data, 0x91); let lhs = parse_term_arg(&data[1..], ctx)?; @@ -361,6 +487,13 @@ fn parse_def_lor(data: &[u8], fn parse_def_to_hex_string(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + // TODO: Compute the result // TODO: Store the result, if appropriate parser_opcode!(data, 0x98); @@ -376,6 +509,13 @@ fn parse_def_to_hex_string(data: &[u8], fn parse_def_to_buffer(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + // TODO: Compute the result // TODO: Store the result, if appropriate parser_opcode!(data, 0x96); @@ -391,6 +531,13 @@ fn parse_def_to_buffer(data: &[u8], fn parse_def_to_bcd(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + // TODO: Compute the result // TODO: Store the result, if appropriate parser_opcode_extended!(data, 0x29); @@ -406,6 +553,13 @@ fn parse_def_to_bcd(data: &[u8], fn parse_def_to_decimal_string(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + // TODO: Compute the result // TODO: Store the result, if appropriate parser_opcode!(data, 0x97); @@ -421,6 +575,13 @@ fn parse_def_to_decimal_string(data: &[u8], fn parse_def_to_integer(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + // TODO: Compute the result // TODO: Store the result, if appropriate parser_opcode!(data, 0x99); @@ -436,6 +597,13 @@ fn parse_def_to_integer(data: &[u8], fn parse_def_to_string(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + // TODO: Compute the result // TODO: Store the result, if appropriate parser_opcode!(data, 0x9C); @@ -452,6 +620,13 @@ fn parse_def_to_string(data: &[u8], fn parse_def_subtract(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode!(data, 0x74); let lhs = parse_term_arg(&data[1..], ctx)?; @@ -470,6 +645,13 @@ fn parse_def_subtract(data: &[u8], fn parse_def_size_of(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + // TODO: Perform the computation parser_opcode!(data, 0x87); @@ -483,6 +665,13 @@ fn parse_def_size_of(data: &[u8], fn parse_def_store(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode!(data, 0x70); let operand = parse_term_arg(&data[1..], ctx)?; @@ -498,6 +687,13 @@ fn parse_def_store(data: &[u8], fn parse_def_or(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode!(data, 0x7D); let lhs = parse_term_arg(&data[1..], ctx)?; @@ -516,6 +712,13 @@ fn parse_def_or(data: &[u8], fn parse_def_shift_left(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode!(data, 0x79); let lhs = parse_term_arg(&data[1..], ctx)?; @@ -534,6 +737,13 @@ fn parse_def_shift_left(data: &[u8], fn parse_def_shift_right(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode!(data, 0x7A); let lhs = parse_term_arg(&data[1..], ctx)?; @@ -552,6 +762,13 @@ fn parse_def_shift_right(data: &[u8], fn parse_def_add(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode!(data, 0x72); let lhs = parse_term_arg(&data[1..], ctx)?; @@ -570,6 +787,13 @@ fn parse_def_add(data: &[u8], fn parse_def_and(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode!(data, 0x7B); let lhs = parse_term_arg(&data[1..], ctx)?; @@ -588,6 +812,13 @@ fn parse_def_and(data: &[u8], fn parse_def_xor(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode!(data, 0x7F); let lhs = parse_term_arg(&data[1..], ctx)?; @@ -606,6 +837,13 @@ fn parse_def_xor(data: &[u8], fn parse_def_concat_res(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + // TODO: Compute the result // TODO: Store the result, if appropriate parser_opcode!(data, 0x84); @@ -622,6 +860,13 @@ fn parse_def_concat_res(data: &[u8], fn parse_def_wait(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + // TODO: Compute the result parser_opcode_extended!(data, 0x25); @@ -636,6 +881,13 @@ fn parse_def_wait(data: &[u8], fn parse_def_cond_ref_of(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + // TODO: Compute the result // TODO: Store the result parser_opcode_extended!(data, 0x12); @@ -651,6 +903,13 @@ fn parse_def_cond_ref_of(data: &[u8], fn parse_def_copy_object(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + // TODO: Compute the result // TODO: Store the result parser_opcode!(data, 0x9D); @@ -666,6 +925,13 @@ fn parse_def_copy_object(data: &[u8], fn parse_def_concat(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + // TODO: Compute the result // TODO: Store the result parser_opcode!(data, 0x73); @@ -682,6 +948,13 @@ fn parse_def_concat(data: &[u8], fn parse_def_decrement(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode!(data, 0x76); let obj = parse_super_name(&data[1..], ctx)?; @@ -697,6 +970,13 @@ fn parse_def_decrement(data: &[u8], fn parse_def_divide(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode!(data, 0x78); let lhs = parse_term_arg(&data[1..], ctx)?; @@ -721,6 +1001,13 @@ fn parse_def_divide(data: &[u8], fn parse_def_find_set_left_bit(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode!(data, 0x81); let operand = parse_term_arg(&data[2..], ctx)?; @@ -749,6 +1036,13 @@ fn parse_def_find_set_left_bit(data: &[u8], fn parse_def_find_set_right_bit(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode!(data, 0x82); let operand = parse_term_arg(&data[2..], ctx)?; @@ -781,6 +1075,13 @@ fn parse_def_find_set_right_bit(data: &[u8], fn parse_def_load_table(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + // TODO: Compute the result // TODO: Store the result, if appropriate // TODO: Clean up @@ -938,6 +1239,13 @@ fn parse_def_match(data: &[u8], fn parse_def_from_bcd(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode_extended!(data, 0x28); let operand = parse_term_arg(&data[2..], ctx)?; @@ -968,6 +1276,13 @@ fn parse_def_from_bcd(data: &[u8], fn parse_def_mid(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode!(data, 0x9E); let source = parse_term_arg(&data[1..], ctx)?; @@ -1022,6 +1337,13 @@ fn parse_def_mid(data: &[u8], fn parse_def_mod(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode!(data, 0x85); let lhs = parse_term_arg(&data[1..], ctx)?; @@ -1044,6 +1366,13 @@ fn parse_def_mod(data: &[u8], fn parse_def_multiply(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + // TODO: Handle overflow parser_opcode!(data, 0x77); @@ -1063,6 +1392,13 @@ fn parse_def_multiply(data: &[u8], fn parse_def_nand(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode!(data, 0x7C); let lhs = parse_term_arg(&data[1..], ctx)?; @@ -1081,6 +1417,13 @@ fn parse_def_nand(data: &[u8], fn parse_def_nor(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode!(data, 0x7E); let lhs = parse_term_arg(&data[1..], ctx)?; @@ -1099,6 +1442,13 @@ fn parse_def_nor(data: &[u8], fn parse_def_not(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode!(data, 0x80); let operand = parse_term_arg(&data[1..], ctx)?; @@ -1116,6 +1466,13 @@ fn parse_def_not(data: &[u8], fn parse_def_timer(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + if ctx.state != ExecutionState::EXECUTING { + return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }); + } + parser_opcode_extended!(data, 0x33); let (seconds, nanoseconds) = monotonic(); From d315914f29fc212b24edd1f5afdf055c1d96c021 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Mon, 17 Jul 2017 11:54:19 +0100 Subject: [PATCH 055/113] Implmented method execution and method invocations --- src/acpi/aml/namedobj.rs | 10 +--------- src/acpi/aml/namespace.rs | 29 ++++++++++++++++++++++++++++- src/acpi/aml/parser.rs | 13 +++++++++++++ src/acpi/aml/termlist.rs | 28 ++++++++++++++++++++++++---- 4 files changed, 66 insertions(+), 14 deletions(-) diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index a4f1ab0..27695bb 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -7,20 +7,12 @@ use collections::btree_map::BTreeMap; use super::AmlError; use super::parser::{ AmlParseType, ParseResult, AmlParseTypeGeneric, AmlExecutionContext, ExecutionState }; -use super::namespace::{ AmlValue, ObjectReference, FieldSelector, get_namespace_string }; +use super::namespace::{ AmlValue, ObjectReference, FieldSelector, Method, get_namespace_string }; use super::namestring::{parse_name_string, parse_name_seg}; use super::termlist::{parse_term_arg, parse_term_list, parse_object_list}; use super::pkglength::parse_pkg_length; use super::type2opcode::parse_def_buffer; -#[derive(Debug, Clone)] -pub struct Method { - arg_count: u8, - serialized: bool, - sync_level: u8, - term_list: Vec -} - #[derive(Debug, Copy, Clone)] pub enum RegionSpace { SystemMemory, diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index 746cd1e..8aed913 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -5,7 +5,8 @@ use collections::btree_map::BTreeMap; use core::str::FromStr; -use super::namedobj::{ RegionSpace, FieldFlags, Method }; +use super::termlist::parse_term_list; +use super::namedobj::{ RegionSpace, FieldFlags }; use super::parser::AmlExecutionContext; use super::AmlError; @@ -30,6 +31,14 @@ pub enum ObjectReference { Object(Box) } +#[derive(Debug, Clone)] +pub struct Method { + pub arg_count: u8, + pub serialized: bool, + pub sync_level: u8, + pub term_list: Vec +} + #[derive(Debug, Clone)] pub enum AmlValue { None, @@ -105,6 +114,24 @@ impl AmlValue { _ => Err(AmlError::AmlValueError) } } + + pub fn get_as_method(&self) -> Result { + match *self { + AmlValue::Method(ref m) => Ok(m.clone()), + _ => Err(AmlError::AmlValueError) + } + } +} + +impl Method { + pub fn execute(&self, scope: String, parameters: Vec) -> AmlValue { + let mut ctx = AmlExecutionContext::new(scope); + ctx.init_arg_vars(parameters); + + parse_term_list(&self.term_list[..], &mut ctx); + + AmlValue::None + } } pub fn get_namespace_string(current: String, modifier_v: AmlValue) -> String { diff --git a/src/acpi/aml/parser.rs b/src/acpi/aml/parser.rs index 094028b..a358328 100644 --- a/src/acpi/aml/parser.rs +++ b/src/acpi/aml/parser.rs @@ -1,5 +1,6 @@ use collections::string::String; use collections::btree_map::BTreeMap; +use collections::vec::Vec; use super::namespace::{ AmlValue, ObjectReference }; use super::AmlError; @@ -53,6 +54,18 @@ impl AmlExecutionContext { } } + pub fn init_arg_vars(&mut self, parameters: Vec) { + if parameters.len() > 8 { + return; + } + + let mut cur = 0; + while cur < parameters.len() { + self.arg_vars[cur] = parameters[cur].clone(); + cur += 1; + } + } + pub fn modify(&mut self, name: AmlValue, value: AmlValue) { // TODO: throw errors // TODO: return DRO diff --git a/src/acpi/aml/termlist.rs b/src/acpi/aml/termlist.rs index 87021d4..e8a59fc 100644 --- a/src/acpi/aml/termlist.rs +++ b/src/acpi/aml/termlist.rs @@ -120,12 +120,32 @@ pub fn parse_method_invocation(data: &[u8], }); } - // TODO: Check if method exists in namespace - // TODO: If so, parse appropriate number of parameters - // TODO: If not, add deferred load to ctx let name = parse_name_string(data, ctx)?; + let method = ctx.get(name.val.clone()); + + let method = match method { + AmlValue::None => return Err(AmlError::AmlDeferredLoad), + _ => method.get_as_method()? + }; - Err(AmlError::AmlDeferredLoad) + let mut cur = 0; + let mut params: Vec = vec!(); + + let mut current_offset = name.len; + + while cur < method.arg_count { + let res = parse_term_arg(&data[current_offset..], ctx)?; + + current_offset += res.len; + cur += 1; + + params.push(res.val); + } + + Ok(AmlParseType { + val: method.execute(get_namespace_string(ctx.scope.clone(), name.val), params), + len: current_offset + }) } fn parse_term_obj(data: &[u8], From c01a04148b2d2b27331a4c20be7903cf64e8189f Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Mon, 17 Jul 2017 12:20:04 +0100 Subject: [PATCH 056/113] Implemented method return values --- src/acpi/aml/dataobj.rs | 35 +-- src/acpi/aml/namedobj.rs | 161 +++++++------ src/acpi/aml/namespace.rs | 7 +- src/acpi/aml/namespacemodifier.rs | 28 ++- src/acpi/aml/namestring.rs | 35 +-- src/acpi/aml/parser.rs | 3 +- src/acpi/aml/termlist.rs | 60 ++--- src/acpi/aml/type1opcode.rs | 145 ++++++------ src/acpi/aml/type2opcode.rs | 371 +++++++++++++++++------------- 9 files changed, 483 insertions(+), 362 deletions(-) diff --git a/src/acpi/aml/dataobj.rs b/src/acpi/aml/dataobj.rs index 411c3ff..7bb50d3 100644 --- a/src/acpi/aml/dataobj.rs +++ b/src/acpi/aml/dataobj.rs @@ -12,11 +12,12 @@ use super::namestring::parse_super_name; pub fn parse_data_obj(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_selector! { @@ -31,11 +32,12 @@ pub fn parse_data_obj(data: &[u8], pub fn parse_data_ref_obj(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_selector! { @@ -58,11 +60,12 @@ pub fn parse_data_ref_obj(data: &[u8], pub fn parse_arg_obj(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } match data[0] { @@ -76,11 +79,12 @@ pub fn parse_arg_obj(data: &[u8], pub fn parse_local_obj(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } match data[0] { @@ -94,11 +98,12 @@ pub fn parse_local_obj(data: &[u8], fn parse_computational_data(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } match data[0] { diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index 27695bb..f9a308d 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -80,11 +80,12 @@ pub enum AccessAttrib { pub fn parse_named_obj(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_selector! { @@ -114,11 +115,12 @@ pub fn parse_named_obj(data: &[u8], fn parse_def_bank_field(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } // TODO: Why isn't bank name used? @@ -169,11 +171,12 @@ fn parse_def_bank_field(data: &[u8], fn parse_def_create_bit_field(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode!(data, 0x8D); @@ -198,11 +201,12 @@ fn parse_def_create_bit_field(data: &[u8], fn parse_def_create_byte_field(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode!(data, 0x8C); @@ -227,11 +231,12 @@ fn parse_def_create_byte_field(data: &[u8], fn parse_def_create_word_field(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode!(data, 0x8B); @@ -256,11 +261,12 @@ fn parse_def_create_word_field(data: &[u8], fn parse_def_create_dword_field(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode!(data, 0x8A); @@ -285,11 +291,12 @@ fn parse_def_create_dword_field(data: &[u8], fn parse_def_create_qword_field(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode!(data, 0x8F); @@ -314,11 +321,12 @@ fn parse_def_create_qword_field(data: &[u8], fn parse_def_create_field(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode_extended!(data, 0x13); @@ -344,11 +352,12 @@ fn parse_def_create_field(data: &[u8], fn parse_def_data_region(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } // TODO: Find the actual offset and length, once table mapping is implemented @@ -375,11 +384,12 @@ fn parse_def_data_region(data: &[u8], fn parse_def_event(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode_extended!(data, 0x02); @@ -397,11 +407,12 @@ fn parse_def_event(data: &[u8], fn parse_def_device(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } // TODO: How to handle local context deferreds @@ -425,11 +436,12 @@ fn parse_def_device(data: &[u8], fn parse_def_op_region(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode_extended!(data, 0x80); @@ -468,11 +480,12 @@ fn parse_def_op_region(data: &[u8], fn parse_def_field(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode_extended!(data, 0x81); @@ -512,11 +525,12 @@ fn parse_def_field(data: &[u8], fn parse_def_index_field(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode_extended!(data, 0x86); @@ -563,11 +577,12 @@ fn parse_field_list(data: &[u8], ctx: &mut AmlExecutionContext, selector: FieldSelector, flags: &mut FieldFlags) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } let mut current_offset: usize = 0; @@ -577,11 +592,12 @@ fn parse_field_list(data: &[u8], while current_offset < data.len() { let res = parse_field_element(&data[current_offset..], ctx, selector.clone(), &mut connection, flags, &mut field_offset)?; - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } current_offset += res.len; @@ -599,11 +615,12 @@ fn parse_field_element(data: &[u8], connection: &mut AmlValue, flags: &mut FieldFlags, offset: &mut usize) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } let length = if let Ok(field) = parse_named_field(data, ctx) { @@ -717,11 +734,12 @@ fn parse_access_field(data: &[u8], fn parse_connect_field(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode!(data, 0x02); @@ -742,11 +760,12 @@ fn parse_connect_field(data: &[u8], fn parse_def_method(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode!(data, 0x14); @@ -777,11 +796,12 @@ fn parse_def_method(data: &[u8], fn parse_def_mutex(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode_extended!(data, 0x01); @@ -801,11 +821,12 @@ fn parse_def_mutex(data: &[u8], fn parse_def_power_res(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } // TODO: How to handle local context deferreds @@ -838,11 +859,12 @@ fn parse_def_power_res(data: &[u8], fn parse_def_processor(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode_extended!(data, 0x83); @@ -876,11 +898,12 @@ fn parse_def_processor(data: &[u8], fn parse_def_thermal_zone(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode_extended!(data, 0x85); diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index 8aed913..0332b03 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -7,7 +7,7 @@ use core::str::FromStr; use super::termlist::parse_term_list; use super::namedobj::{ RegionSpace, FieldFlags }; -use super::parser::AmlExecutionContext; +use super::parser::{AmlExecutionContext, ExecutionState}; use super::AmlError; #[derive(Debug, Clone)] @@ -130,7 +130,10 @@ impl Method { parse_term_list(&self.term_list[..], &mut ctx); - AmlValue::None + match ctx.state { + ExecutionState::RETURN(v) => v, + _ => AmlValue::IntegerConstant(0) + } } } diff --git a/src/acpi/aml/namespacemodifier.rs b/src/acpi/aml/namespacemodifier.rs index 8ca0c9e..1c72e0a 100644 --- a/src/acpi/aml/namespacemodifier.rs +++ b/src/acpi/aml/namespacemodifier.rs @@ -13,11 +13,12 @@ use super::dataobj::parse_data_ref_obj; pub fn parse_namespace_modifier(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_selector! { @@ -32,11 +33,12 @@ pub fn parse_namespace_modifier(data: &[u8], fn parse_alias_op(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode!(data, 0x06); @@ -58,11 +60,12 @@ fn parse_alias_op(data: &[u8], fn parse_name_op(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode!(data, 0x08); @@ -82,11 +85,12 @@ fn parse_name_op(data: &[u8], fn parse_scope_op(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode!(data, 0x10); diff --git a/src/acpi/aml/namestring.rs b/src/acpi/aml/namestring.rs index b1c2301..389e650 100644 --- a/src/acpi/aml/namestring.rs +++ b/src/acpi/aml/namestring.rs @@ -10,11 +10,12 @@ use super::type2opcode::parse_type6_opcode; pub fn parse_name_string(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } let mut characters: Vec = vec!(); @@ -149,11 +150,12 @@ fn parse_multi_name_path(data: &[u8]) -> Result<(Vec, usize), AmlError> { pub fn parse_super_name(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_selector! { @@ -168,11 +170,12 @@ pub fn parse_super_name(data: &[u8], fn parse_debug_obj(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode_extended!(data, 0x31); @@ -185,11 +188,12 @@ fn parse_debug_obj(data: &[u8], pub fn parse_simple_name(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_selector! { @@ -204,11 +208,12 @@ pub fn parse_simple_name(data: &[u8], pub fn parse_target(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } if data[0] == 0x00 { diff --git a/src/acpi/aml/parser.rs b/src/acpi/aml/parser.rs index a358328..269bd6a 100644 --- a/src/acpi/aml/parser.rs +++ b/src/acpi/aml/parser.rs @@ -13,12 +13,11 @@ pub struct AmlParseTypeGeneric { pub len: usize } -#[derive(PartialEq)] pub enum ExecutionState { EXECUTING, CONTINUE, BREAK, - RETURN + RETURN(AmlValue) } pub struct AmlExecutionContext { diff --git a/src/acpi/aml/termlist.rs b/src/acpi/aml/termlist.rs index e8a59fc..9152f56 100644 --- a/src/acpi/aml/termlist.rs +++ b/src/acpi/aml/termlist.rs @@ -15,11 +15,12 @@ use super::namestring::parse_name_string; pub fn parse_term_list(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, - len: data.len() - }); + len: 0 as usize + }) } let mut current_offset: usize = 0; @@ -27,11 +28,12 @@ pub fn parse_term_list(data: &[u8], while current_offset < data.len() { let res = parse_term_obj(&data[current_offset..], ctx)?; - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: data.len() - }); + }) } current_offset += res.len; @@ -45,11 +47,12 @@ pub fn parse_term_list(data: &[u8], pub fn parse_term_arg(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_selector! { @@ -65,11 +68,12 @@ pub fn parse_term_arg(data: &[u8], pub fn parse_object_list(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, - len: data.len() - }); + len: 0 as usize + }) } let mut current_offset: usize = 0; @@ -77,11 +81,12 @@ pub fn parse_object_list(data: &[u8], while current_offset < data.len() { let res = parse_object(&data[current_offset..], ctx)?; - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: data.len() - }); + }) } current_offset += res.len; @@ -95,11 +100,12 @@ pub fn parse_object_list(data: &[u8], fn parse_object(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_selector! { @@ -113,11 +119,12 @@ fn parse_object(data: &[u8], pub fn parse_method_invocation(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } let name = parse_name_string(data, ctx)?; @@ -150,11 +157,12 @@ pub fn parse_method_invocation(data: &[u8], fn parse_term_obj(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_selector! { diff --git a/src/acpi/aml/type1opcode.rs b/src/acpi/aml/type1opcode.rs index 35c7e0c..b09b868 100644 --- a/src/acpi/aml/type1opcode.rs +++ b/src/acpi/aml/type1opcode.rs @@ -12,11 +12,12 @@ use super::namestring::{parse_name_string, parse_super_name}; pub fn parse_type1_opcode(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_selector! { @@ -44,11 +45,12 @@ pub fn parse_type1_opcode(data: &[u8], fn parse_def_break(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode!(data, 0xA5); @@ -62,11 +64,12 @@ fn parse_def_break(data: &[u8], fn parse_def_breakpoint(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode!(data, 0xCC); @@ -79,11 +82,12 @@ fn parse_def_breakpoint(data: &[u8], fn parse_def_continue(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode!(data, 0x9F); @@ -97,11 +101,12 @@ fn parse_def_continue(data: &[u8], fn parse_def_noop(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode!(data, 0xA3); @@ -114,11 +119,12 @@ fn parse_def_noop(data: &[u8], fn parse_def_fatal(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode_extended!(data, 0x32); @@ -132,11 +138,12 @@ fn parse_def_fatal(data: &[u8], fn parse_def_load(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } // TODO: Load in the table pointed to by `name` @@ -155,11 +162,12 @@ fn parse_def_load(data: &[u8], fn parse_def_notify(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } // TODO: This requires significantly more infrastructure from the OS itself, see 5.6.6 @@ -176,11 +184,12 @@ fn parse_def_notify(data: &[u8], fn parse_def_release(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } // TODO: Check ownership of the mutex pointed to @@ -198,11 +207,12 @@ fn parse_def_release(data: &[u8], fn parse_def_reset(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } // TODO: object (of type Event) is a semaphore. Reset the resource count to 0 @@ -218,11 +228,12 @@ fn parse_def_reset(data: &[u8], fn parse_def_signal(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } // TODO: Increment the resource count of the semaphore @@ -238,11 +249,12 @@ fn parse_def_signal(data: &[u8], fn parse_def_sleep(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } // TODO: Sleep the processor for the specified number of milliseconds (minimum) @@ -258,11 +270,12 @@ fn parse_def_sleep(data: &[u8], fn parse_def_stall(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } // TODO: Sleep the processor for the specified number of microseconds (minimum) @@ -278,11 +291,12 @@ fn parse_def_stall(data: &[u8], fn parse_def_unload(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } // TODO: remove from namespace all values added when `object` was loaded @@ -299,11 +313,12 @@ fn parse_def_unload(data: &[u8], fn parse_def_if_else(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode!(data, 0xA0); @@ -331,11 +346,12 @@ fn parse_def_if_else(data: &[u8], fn parse_def_while(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode!(data, 0xA2); @@ -343,13 +359,6 @@ fn parse_def_while(data: &[u8], let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; loop { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { - val: AmlValue::None, - len: 0 as usize - }); - } - let predicate = parse_term_arg(&data[1 + pkg_length_len..], ctx)?; if predicate.val.get_as_integer()? == 0 { break; @@ -357,11 +366,17 @@ fn parse_def_while(data: &[u8], parse_term_list(&data[1 + pkg_length_len + predicate.len .. 1 + pkg_length], ctx)?; - if ctx.state == ExecutionState::BREAK { - ctx.state = ExecutionState::EXECUTING; - break; - } else if ctx.state == ExecutionState::CONTINUE { - ctx.state = ExecutionState::EXECUTING; + match ctx.state { + ExecutionState::EXECUTING => (), + ExecutionState::BREAK => { + ctx.state = ExecutionState::EXECUTING; + break; + }, + ExecutionState::CONTINUE => ctx.state = ExecutionState::EXECUTING, + _ => return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }) } } @@ -373,18 +388,18 @@ fn parse_def_while(data: &[u8], fn parse_def_return(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } - // TODO: Return to the calling context - // TODO: We need contexts for that parser_opcode!(data, 0xA4); let arg_object = parse_term_arg(&data[1..], ctx)?; + ctx.state = ExecutionState::RETURN(arg_object.val); Ok(AmlParseType { val: AmlValue::None, diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index 2ef678e..52dcae0 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -25,11 +25,12 @@ pub enum MatchOpcode { pub fn parse_type2_opcode(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_selector! { @@ -91,11 +92,12 @@ pub fn parse_type2_opcode(data: &[u8], pub fn parse_type6_opcode(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_selector! { @@ -111,11 +113,12 @@ pub fn parse_type6_opcode(data: &[u8], pub fn parse_def_object_type(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode!(data, 0x8E); @@ -132,11 +135,12 @@ pub fn parse_def_object_type(data: &[u8], pub fn parse_def_package(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } // TODO: Handle deferred loads in here @@ -162,11 +166,12 @@ pub fn parse_def_package(data: &[u8], pub fn parse_def_var_package(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } // TODO: Handle deferred loads in here @@ -195,11 +200,12 @@ pub fn parse_def_var_package(data: &[u8], fn parse_package_elements_list(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } let mut current_offset: usize = 0; @@ -228,11 +234,12 @@ fn parse_package_elements_list(data: &[u8], pub fn parse_def_buffer(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } // TODO: Perform computation @@ -250,11 +257,12 @@ pub fn parse_def_buffer(data: &[u8], fn parse_def_ref_of(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } // TODO: Perform computation @@ -270,11 +278,12 @@ fn parse_def_ref_of(data: &[u8], fn parse_def_deref_of(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } // TODO: Perform computation @@ -290,11 +299,12 @@ fn parse_def_deref_of(data: &[u8], fn parse_def_acquire(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } // TODO: Store the result @@ -312,11 +322,12 @@ fn parse_def_acquire(data: &[u8], fn parse_def_increment(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode!(data, 0x75); @@ -334,11 +345,12 @@ fn parse_def_increment(data: &[u8], fn parse_def_index(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } // TODO: Store the result, if appropriate @@ -357,11 +369,12 @@ fn parse_def_index(data: &[u8], fn parse_def_land(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode!(data, 0x90); @@ -379,11 +392,12 @@ fn parse_def_land(data: &[u8], fn parse_def_lequal(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode!(data, 0x93); @@ -401,11 +415,12 @@ fn parse_def_lequal(data: &[u8], fn parse_def_lgreater(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode!(data, 0x94); @@ -423,11 +438,12 @@ fn parse_def_lgreater(data: &[u8], fn parse_def_lless(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode!(data, 0x95); @@ -445,11 +461,12 @@ fn parse_def_lless(data: &[u8], fn parse_def_lnot(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode!(data, 0x92); @@ -465,11 +482,12 @@ fn parse_def_lnot(data: &[u8], fn parse_def_lor(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode!(data, 0x91); @@ -487,11 +505,12 @@ fn parse_def_lor(data: &[u8], fn parse_def_to_hex_string(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } // TODO: Compute the result @@ -509,11 +528,12 @@ fn parse_def_to_hex_string(data: &[u8], fn parse_def_to_buffer(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } // TODO: Compute the result @@ -531,11 +551,12 @@ fn parse_def_to_buffer(data: &[u8], fn parse_def_to_bcd(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } // TODO: Compute the result @@ -553,11 +574,12 @@ fn parse_def_to_bcd(data: &[u8], fn parse_def_to_decimal_string(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } // TODO: Compute the result @@ -575,11 +597,12 @@ fn parse_def_to_decimal_string(data: &[u8], fn parse_def_to_integer(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } // TODO: Compute the result @@ -597,11 +620,12 @@ fn parse_def_to_integer(data: &[u8], fn parse_def_to_string(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } // TODO: Compute the result @@ -620,11 +644,12 @@ fn parse_def_to_string(data: &[u8], fn parse_def_subtract(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode!(data, 0x74); @@ -645,11 +670,12 @@ fn parse_def_subtract(data: &[u8], fn parse_def_size_of(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } // TODO: Perform the computation @@ -665,11 +691,12 @@ fn parse_def_size_of(data: &[u8], fn parse_def_store(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode!(data, 0x70); @@ -687,11 +714,12 @@ fn parse_def_store(data: &[u8], fn parse_def_or(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode!(data, 0x7D); @@ -712,11 +740,12 @@ fn parse_def_or(data: &[u8], fn parse_def_shift_left(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode!(data, 0x79); @@ -737,11 +766,12 @@ fn parse_def_shift_left(data: &[u8], fn parse_def_shift_right(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode!(data, 0x7A); @@ -762,11 +792,12 @@ fn parse_def_shift_right(data: &[u8], fn parse_def_add(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode!(data, 0x72); @@ -787,11 +818,12 @@ fn parse_def_add(data: &[u8], fn parse_def_and(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode!(data, 0x7B); @@ -812,11 +844,12 @@ fn parse_def_and(data: &[u8], fn parse_def_xor(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode!(data, 0x7F); @@ -837,11 +870,12 @@ fn parse_def_xor(data: &[u8], fn parse_def_concat_res(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } // TODO: Compute the result @@ -860,11 +894,12 @@ fn parse_def_concat_res(data: &[u8], fn parse_def_wait(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } // TODO: Compute the result @@ -881,11 +916,12 @@ fn parse_def_wait(data: &[u8], fn parse_def_cond_ref_of(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } // TODO: Compute the result @@ -903,11 +939,12 @@ fn parse_def_cond_ref_of(data: &[u8], fn parse_def_copy_object(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } // TODO: Compute the result @@ -925,11 +962,12 @@ fn parse_def_copy_object(data: &[u8], fn parse_def_concat(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } // TODO: Compute the result @@ -948,11 +986,12 @@ fn parse_def_concat(data: &[u8], fn parse_def_decrement(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode!(data, 0x76); @@ -970,11 +1009,12 @@ fn parse_def_decrement(data: &[u8], fn parse_def_divide(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode!(data, 0x78); @@ -1001,11 +1041,12 @@ fn parse_def_divide(data: &[u8], fn parse_def_find_set_left_bit(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode!(data, 0x81); @@ -1036,11 +1077,12 @@ fn parse_def_find_set_left_bit(data: &[u8], fn parse_def_find_set_right_bit(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode!(data, 0x82); @@ -1075,11 +1117,12 @@ fn parse_def_find_set_right_bit(data: &[u8], fn parse_def_load_table(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } // TODO: Compute the result @@ -1102,6 +1145,14 @@ fn parse_def_load_table(data: &[u8], fn parse_def_match(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }) + } + // TODO: Clean up parser_opcode!(data, 0x28); @@ -1163,7 +1214,7 @@ fn parse_def_match(data: &[u8], return Ok(AmlParseType { val: AmlValue::Integer(idx as u64), len: 3 + search_pkg.len + first_operand.len + second_operand.len + start_index.len - }); + }) } }, AmlValue::String(i) => { @@ -1194,7 +1245,7 @@ fn parse_def_match(data: &[u8], return Ok(AmlParseType { val: AmlValue::Integer(idx as u64), len: 3 + search_pkg.len + first_operand.len + second_operand.len + start_index.len - }); + }) } }, _ => { @@ -1226,7 +1277,7 @@ fn parse_def_match(data: &[u8], return Ok(AmlParseType { val: AmlValue::Integer(idx as u64), len: 3 + search_pkg.len + first_operand.len + second_operand.len + start_index.len - }); + }) } } } @@ -1239,11 +1290,12 @@ fn parse_def_match(data: &[u8], fn parse_def_from_bcd(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode_extended!(data, 0x28); @@ -1276,11 +1328,12 @@ fn parse_def_from_bcd(data: &[u8], fn parse_def_mid(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode!(data, 0x9E); @@ -1337,11 +1390,12 @@ fn parse_def_mid(data: &[u8], fn parse_def_mod(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode!(data, 0x85); @@ -1366,11 +1420,12 @@ fn parse_def_mod(data: &[u8], fn parse_def_multiply(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } // TODO: Handle overflow @@ -1392,11 +1447,12 @@ fn parse_def_multiply(data: &[u8], fn parse_def_nand(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode!(data, 0x7C); @@ -1417,11 +1473,12 @@ fn parse_def_nand(data: &[u8], fn parse_def_nor(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode!(data, 0x7E); @@ -1442,11 +1499,12 @@ fn parse_def_nor(data: &[u8], fn parse_def_not(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode!(data, 0x80); @@ -1466,11 +1524,12 @@ fn parse_def_not(data: &[u8], fn parse_def_timer(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { - if ctx.state != ExecutionState::EXECUTING { - return Ok(AmlParseType { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { val: AmlValue::None, len: 0 as usize - }); + }) } parser_opcode_extended!(data, 0x33); From 258cab878cc651c4d6ee0235b4107dd66a79f5f8 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Mon, 17 Jul 2017 13:22:06 +0100 Subject: [PATCH 057/113] Implemented index references --- src/acpi/aml/namespace.rs | 3 ++- src/acpi/aml/type2opcode.rs | 7 ++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index 0332b03..01ffdaf 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -28,7 +28,8 @@ pub enum ObjectReference { ArgObj(u8), LocalObj(u8), NamedObj(String), - Object(Box) + Object(Box), + Index(Box, Box) } #[derive(Debug, Clone)] diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index 52dcae0..c505201 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -353,16 +353,17 @@ fn parse_def_index(data: &[u8], }) } - // TODO: Store the result, if appropriate - // TODO: Perform computation parser_opcode!(data, 0x88); let obj = parse_term_arg(&data[1..], ctx)?; let idx = parse_term_arg(&data[1 + obj.len..], ctx)?; let target = parse_target(&data[1 + obj.len + idx.len..], ctx)?; + + let reference = AmlValue::ObjectReference(ObjectReference::Index(Box::new(obj.val), Box::new(idx.val))); + ctx.modify(target.val, reference.clone()); Ok(AmlParseType { - val: AmlValue::Uninitialized, + val: reference, len: 1 + obj.len + idx.len + target.len }) } From dba65f3128fffa752e057417809a624c0a1825ff Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Tue, 18 Jul 2017 10:16:26 +0100 Subject: [PATCH 058/113] Remove all namespace changes made within methods --- src/acpi/aml/namedobj.rs | 32 +++++++++++++++---------------- src/acpi/aml/namespace.rs | 1 + src/acpi/aml/namespacemodifier.rs | 7 +++---- src/acpi/aml/parser.rs | 23 ++++++++++++++++++++-- 4 files changed, 41 insertions(+), 22 deletions(-) diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index f9a308d..612d744 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -187,7 +187,7 @@ fn parse_def_create_bit_field(data: &[u8], let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); - ctx.namespace.insert(local_scope_string, AmlValue::BufferField { + ctx.add_to_namespace(local_scope_string, AmlValue::BufferField { source_buf: Box::new(source_buf.val), index: Box::new(bit_index.val), length: Box::new(AmlValue::IntegerConstant(1)) @@ -217,7 +217,7 @@ fn parse_def_create_byte_field(data: &[u8], let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); - ctx.namespace.insert(local_scope_string, AmlValue::BufferField { + ctx.add_to_namespace(local_scope_string, AmlValue::BufferField { source_buf: Box::new(source_buf.val), index: Box::new(bit_index.val), length: Box::new(AmlValue::IntegerConstant(8)) @@ -247,7 +247,7 @@ fn parse_def_create_word_field(data: &[u8], let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); - ctx.namespace.insert(local_scope_string, AmlValue::BufferField { + ctx.add_to_namespace(local_scope_string, AmlValue::BufferField { source_buf: Box::new(source_buf.val), index: Box::new(bit_index.val), length: Box::new(AmlValue::IntegerConstant(16)) @@ -277,7 +277,7 @@ fn parse_def_create_dword_field(data: &[u8], let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); - ctx.namespace.insert(local_scope_string, AmlValue::BufferField { + ctx.add_to_namespace(local_scope_string, AmlValue::BufferField { source_buf: Box::new(source_buf.val), index: Box::new(bit_index.val), length: Box::new(AmlValue::IntegerConstant(32)) @@ -307,7 +307,7 @@ fn parse_def_create_qword_field(data: &[u8], let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); - ctx.namespace.insert(local_scope_string, AmlValue::BufferField { + ctx.add_to_namespace(local_scope_string, AmlValue::BufferField { source_buf: Box::new(source_buf.val), index: Box::new(bit_index.val), length: Box::new(AmlValue::IntegerConstant(64)) @@ -338,7 +338,7 @@ fn parse_def_create_field(data: &[u8], let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); - ctx.namespace.insert(local_scope_string, AmlValue::BufferField { + ctx.add_to_namespace(local_scope_string, AmlValue::BufferField { source_buf: Box::new(source_buf.val), index: Box::new(bit_index.val), length: Box::new(num_bits.val) @@ -370,7 +370,7 @@ fn parse_def_data_region(data: &[u8], let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); - ctx.namespace.insert(local_scope_string, AmlValue::OperationRegion { + ctx.add_to_namespace(local_scope_string, AmlValue::OperationRegion { region: RegionSpace::SystemMemory, offset: Box::new(AmlValue::IntegerConstant(0)), len: Box::new(AmlValue::IntegerConstant(0)) @@ -397,7 +397,7 @@ fn parse_def_event(data: &[u8], let name = parse_name_string(&data[2..], ctx)?; let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); - ctx.namespace.insert(local_scope_string, AmlValue::Event); + ctx.add_to_namespace(local_scope_string, AmlValue::Event); Ok(AmlParseType { val: AmlValue::None, @@ -426,7 +426,7 @@ fn parse_def_device(data: &[u8], let obj_list = parse_object_list(&data[2 + pkg_length_len + name.len .. 2 + pkg_length], &mut local_ctx)?; let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); - ctx.namespace.insert(local_scope_string, AmlValue::Device(local_ctx.namespace.clone())); + ctx.add_to_namespace(local_scope_string, AmlValue::Device(local_ctx.namespace.clone())); Ok(AmlParseType { val: AmlValue::None, @@ -466,7 +466,7 @@ fn parse_def_op_region(data: &[u8], let len = parse_term_arg(&data[3 + name.len + offset.len..], ctx)?; let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); - ctx.namespace.insert(local_scope_string, AmlValue::OperationRegion { + ctx.add_to_namespace(local_scope_string, AmlValue::OperationRegion { region: region, offset: Box::new(offset.val), len: Box::new(len.val) @@ -626,7 +626,7 @@ fn parse_field_element(data: &[u8], let length = if let Ok(field) = parse_named_field(data, ctx) { let local_scope_string = get_namespace_string(ctx.scope.clone(), AmlValue::String(field.val.name.clone())); - ctx.namespace.insert(local_scope_string, AmlValue::FieldUnit { + ctx.add_to_namespace(local_scope_string, AmlValue::FieldUnit { selector: selector.clone(), connection: Box::new(connection.clone()), flags: flags.clone(), @@ -781,7 +781,7 @@ fn parse_def_method(data: &[u8], let term_list = &data[2 + pkg_len_len + name.len .. 1 + pkg_len]; let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); - ctx.namespace.insert(local_scope_string, AmlValue::Method(Method { + ctx.add_to_namespace(local_scope_string, AmlValue::Method(Method { arg_count, serialized, sync_level, @@ -811,7 +811,7 @@ fn parse_def_mutex(data: &[u8], let sync_level = flags & 0x0F; let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); - ctx.namespace.insert(local_scope_string, AmlValue::Mutex(sync_level)); + ctx.add_to_namespace(local_scope_string, AmlValue::Mutex(sync_level)); Ok(AmlParseType { val: AmlValue::None, @@ -845,7 +845,7 @@ fn parse_def_power_res(data: &[u8], let mut local_ctx = AmlExecutionContext::new(String::new()); parse_object_list(&data[5 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_ctx)?; - ctx.namespace.insert(local_scope_string, AmlValue::PowerResource { + ctx.add_to_namespace(local_scope_string, AmlValue::PowerResource { system_level, resource_order, obj_list: local_ctx.namespace.clone() @@ -884,7 +884,7 @@ fn parse_def_processor(data: &[u8], let mut local_ctx = AmlExecutionContext::new(String::new()); parse_object_list(&data[8 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_ctx)?; - ctx.namespace.insert(local_scope_string, AmlValue::Processor { + ctx.add_to_namespace(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_ctx.namespace.clone() @@ -916,7 +916,7 @@ fn parse_def_thermal_zone(data: &[u8], let mut local_ctx = AmlExecutionContext::new(String::new()); parse_object_list(&data[2 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_ctx)?; - ctx.namespace.insert(local_scope_string, AmlValue::ThermalZone(local_ctx.namespace.clone())); + ctx.add_to_namespace(local_scope_string, AmlValue::ThermalZone(local_ctx.namespace.clone())); Ok(AmlParseType { val: AmlValue::None, diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index 01ffdaf..6b8c598 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -130,6 +130,7 @@ impl Method { ctx.init_arg_vars(parameters); parse_term_list(&self.term_list[..], &mut ctx); + ctx.clean_namespace(); match ctx.state { ExecutionState::RETURN(v) => v, diff --git a/src/acpi/aml/namespacemodifier.rs b/src/acpi/aml/namespacemodifier.rs index 1c72e0a..7d08195 100644 --- a/src/acpi/aml/namespacemodifier.rs +++ b/src/acpi/aml/namespacemodifier.rs @@ -49,9 +49,8 @@ fn parse_alias_op(data: &[u8], let local_scope_string = get_namespace_string(ctx.scope.clone(), source_name.val); let local_alias_string = get_namespace_string(ctx.scope.clone(), alias_name.val); - ctx.namespace.insert(local_scope_string, AmlValue::ObjectReference( - ObjectReference::NamedObj(local_alias_string))); - + ctx.add_to_namespace(local_scope_string, AmlValue::ObjectReference(ObjectReference::NamedObj(local_alias_string)))?; + Ok(AmlParseType { val: AmlValue::None, len: 1 + source_name.len + alias_name.len @@ -75,7 +74,7 @@ fn parse_name_op(data: &[u8], let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); - ctx.namespace.insert(local_scope_string, data_ref_obj.val); + ctx.add_to_namespace(local_scope_string, data_ref_obj.val)?; Ok(AmlParseType { val: AmlValue::None, diff --git a/src/acpi/aml/parser.rs b/src/acpi/aml/parser.rs index 269bd6a..6c2468f 100644 --- a/src/acpi/aml/parser.rs +++ b/src/acpi/aml/parser.rs @@ -25,7 +25,8 @@ pub struct AmlExecutionContext { pub scope: String, pub local_vars: [AmlValue; 8], pub arg_vars: [AmlValue; 8], - pub state: ExecutionState + pub state: ExecutionState, + pub namespace_delta: Vec } impl AmlExecutionContext { @@ -49,7 +50,25 @@ impl AmlExecutionContext { AmlValue::Uninitialized, AmlValue::Uninitialized, AmlValue::Uninitialized], - state: ExecutionState::EXECUTING + state: ExecutionState::EXECUTING, + namespace_delta: vec!() + } + } + + pub fn add_to_namespace(&mut self, name: String, value: AmlValue) -> Result<(), AmlError> { + if self.namespace.contains_key(&name) { + return Err(AmlError::AmlValueError); + } + + self.namespace_delta.push(name.clone()); + self.namespace.insert(name, value); + + Ok(()) + } + + pub fn clean_namespace(&mut self) { + for k in &self.namespace_delta { + self.namespace.remove(k); } } From a14266fc828675242888759dc59e32bd89032b9a Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Fri, 21 Jul 2017 12:03:55 +0100 Subject: [PATCH 059/113] Parallelized ACPI subsystem --- src/acpi/aml/mod.rs | 4 ++-- src/acpi/aml/namedobj.rs | 25 ++++++++++++------------ src/acpi/aml/namespace.rs | 8 ++++---- src/acpi/aml/parser.rs | 30 +++++++++++++++++++---------- src/acpi/fs.rs | 19 +++++++++++++++++++ src/acpi/mod.rs | 40 +++++++++++++++++++++------------------ src/device/mod.rs | 2 +- src/stop.rs | 18 +++++++++++------- 8 files changed, 91 insertions(+), 55 deletions(-) create mode 100644 src/acpi/fs.rs diff --git a/src/acpi/aml/mod.rs b/src/acpi/aml/mod.rs index a6275db..1edab51 100644 --- a/src/acpi/aml/mod.rs +++ b/src/acpi/aml/mod.rs @@ -37,13 +37,13 @@ pub enum AmlError { AmlFatalError(u8, u16, AmlValue) } -pub fn parse_aml_table(sdt: &'static Sdt) -> Result, AmlError> { +pub fn parse_aml_table(sdt: &'static Sdt) -> Result<(), AmlError> { let data = sdt.data(); let mut ctx = AmlExecutionContext::new(String::from_str("\\").unwrap()); parse_term_list(data, &mut ctx)?; - Ok(ctx.namespace.clone()) + Ok(()) } pub fn is_aml_table(sdt: &'static Sdt) -> bool { diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index 612d744..a99c82f 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -416,17 +416,17 @@ fn parse_def_device(data: &[u8], } // TODO: How to handle local context deferreds - // TODO: How to also handle local context reference to calling context parser_opcode_extended!(data, 0x82); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[2..])?; let name = parse_name_string(&data[2 + pkg_length_len .. 2 + pkg_length], ctx)?; - - let mut local_ctx = AmlExecutionContext::new(String::new()); - let obj_list = parse_object_list(&data[2 + pkg_length_len + name.len .. 2 + pkg_length], &mut local_ctx)?; - + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); - ctx.add_to_namespace(local_scope_string, AmlValue::Device(local_ctx.namespace.clone())); + let mut local_ctx = AmlExecutionContext::new(local_scope_string.clone()); + + parse_object_list(&data[2 + pkg_length_len + name.len .. 2 + pkg_length], &mut local_ctx)?; + + ctx.add_to_namespace(local_scope_string, AmlValue::Device(local_ctx.namespace_delta.clone())); Ok(AmlParseType { val: AmlValue::None, @@ -830,7 +830,6 @@ fn parse_def_power_res(data: &[u8], } // TODO: How to handle local context deferreds - // TODO: How to also handle local context reference to calling context parser_opcode_extended!(data, 0x84); let (pkg_len, pkg_len_len) = parse_pkg_length(&data[2..])?; @@ -842,13 +841,13 @@ fn parse_def_power_res(data: &[u8], let resource_order: u16 = (data[3 + pkg_len_len + name.len] as u16) + ((data[4 + pkg_len_len + name.len] as u16) << 8); - let mut local_ctx = AmlExecutionContext::new(String::new()); + let mut local_ctx = AmlExecutionContext::new(local_scope_string.clone()); parse_object_list(&data[5 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_ctx)?; ctx.add_to_namespace(local_scope_string, AmlValue::PowerResource { system_level, resource_order, - obj_list: local_ctx.namespace.clone() + obj_list: local_ctx.namespace_delta.clone() }); Ok(AmlParseType { @@ -881,13 +880,13 @@ fn parse_def_processor(data: &[u8], ((data[6 + pkg_len_len + name.len] as u32) << 24); let p_blk_len = data[7 + pkg_len_len + name.len]; - let mut local_ctx = AmlExecutionContext::new(String::new()); + let mut local_ctx = AmlExecutionContext::new(local_scope_string.clone()); parse_object_list(&data[8 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_ctx)?; ctx.add_to_namespace(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_ctx.namespace.clone() + obj_list: local_ctx.namespace_delta.clone() }); Ok(AmlParseType { @@ -913,10 +912,10 @@ fn parse_def_thermal_zone(data: &[u8], let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); - let mut local_ctx = AmlExecutionContext::new(String::new()); + let mut local_ctx = AmlExecutionContext::new(local_scope_string.clone()); parse_object_list(&data[2 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_ctx)?; - ctx.add_to_namespace(local_scope_string, AmlValue::ThermalZone(local_ctx.namespace.clone())); + ctx.add_to_namespace(local_scope_string, AmlValue::ThermalZone(local_ctx.namespace_delta.clone())); Ok(AmlParseType { val: AmlValue::None, diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index 6b8c598..1c84f81 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -52,7 +52,7 @@ pub enum AmlValue { }, DDBHandle(u32), // Index into the XSDT DebugObject, - Device(BTreeMap), + Device(Vec), Event, FieldUnit { selector: FieldSelector, @@ -76,15 +76,15 @@ pub enum AmlValue { PowerResource { system_level: u8, resource_order: u16, - obj_list: BTreeMap + obj_list: Vec }, Processor { proc_id: u8, p_blk: Option, - obj_list: BTreeMap + obj_list: Vec }, RawDataBuffer(Vec), - ThermalZone(BTreeMap) + ThermalZone(Vec) } impl AmlValue { diff --git a/src/acpi/aml/parser.rs b/src/acpi/aml/parser.rs index 6c2468f..0b57f13 100644 --- a/src/acpi/aml/parser.rs +++ b/src/acpi/aml/parser.rs @@ -5,6 +5,8 @@ use collections::vec::Vec; use super::namespace::{ AmlValue, ObjectReference }; use super::AmlError; +use acpi::ACPI_TABLE; + pub type ParseResult = Result; pub type AmlParseType = AmlParseTypeGeneric; @@ -21,7 +23,6 @@ pub enum ExecutionState { } pub struct AmlExecutionContext { - pub namespace: BTreeMap, pub scope: String, pub local_vars: [AmlValue; 8], pub arg_vars: [AmlValue; 8], @@ -32,7 +33,6 @@ pub struct AmlExecutionContext { impl AmlExecutionContext { pub fn new(scope: String) -> AmlExecutionContext { AmlExecutionContext { - namespace: BTreeMap::new(), scope: scope, local_vars: [AmlValue::Uninitialized, AmlValue::Uninitialized, @@ -56,19 +56,29 @@ impl AmlExecutionContext { } pub fn add_to_namespace(&mut self, name: String, value: AmlValue) -> Result<(), AmlError> { - if self.namespace.contains_key(&name) { - return Err(AmlError::AmlValueError); - } + let mut namespace = ACPI_TABLE.namespace.write(); + + if let Some(ref mut namespace) = *namespace { + if namespace.contains_key(&name) { + return Err(AmlError::AmlValueError); + } - self.namespace_delta.push(name.clone()); - self.namespace.insert(name, value); + self.namespace_delta.push(name.clone()); + namespace.insert(name, value); - Ok(()) + Ok(()) + } else { + Err(AmlError::AmlValueError) + } } pub fn clean_namespace(&mut self) { - for k in &self.namespace_delta { - self.namespace.remove(k); + let mut namespace = ACPI_TABLE.namespace.write(); + + if let Some(ref mut namespace) = *namespace { + for k in &self.namespace_delta { + namespace.remove(k); + } } } diff --git a/src/acpi/fs.rs b/src/acpi/fs.rs new file mode 100644 index 0000000..2a6b608 --- /dev/null +++ b/src/acpi/fs.rs @@ -0,0 +1,19 @@ +pub fn init_fs() { + let schemes = schemes_mut().unwrap(); + schemes.insert(SchemeNamespace(0), Box::new(*b"acpi"), |_| Arc::new(Box::new(AcpiScheme::new()))).unwrap(); +} + +struct AcpiScheme { + +} + +impl AcpiScheme { + pub fn new() -> AcpiScheme { + AcpiScheme + } +} + +impl Scheme for AcpiScheme { + fn open(&self, url: &[u8], flags: usize, uid: u32, gid: u32) -> Result { + let path = str::from_utf8(url).unwrap_or("").trim_matches('/'); + diff --git a/src/acpi/mod.rs b/src/acpi/mod.rs index b9f7ba3..d246609 100644 --- a/src/acpi/mod.rs +++ b/src/acpi/mod.rs @@ -7,7 +7,7 @@ use collections::btree_map::BTreeMap; use collections::string::String; use alloc::boxed::Box; -use spin::Mutex; +use spin::{Mutex, RwLock}; use device::local_apic::LOCAL_APIC; use interrupt; @@ -73,9 +73,12 @@ fn parse_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) { if let Some(fadt) = Fadt::new(sdt) { println!(": {:X}", fadt.dsdt); + let dsdt = get_sdt(fadt.dsdt as usize, active_table); parse_sdt(dsdt, active_table); - ACPI_TABLE.lock().fadt = Some(fadt); + + let mut fadt_t = ACPI_TABLE.fadt.write(); + *fadt_t = Some(fadt); } else if let Some(madt) = Madt::new(sdt) { println!(": {:>08X}: {}", madt.local_address, madt.flags); @@ -202,20 +205,12 @@ fn parse_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) { } } else if let Some(hpet) = Hpet::new(sdt) { println!(": {}", hpet.hpet_number); - ACPI_TABLE.lock().hpet = Some(hpet); + + let mut hpet_t = ACPI_TABLE.hpet.write(); + *hpet_t = Some(hpet); } else if is_aml_table(sdt) { match parse_aml_table(sdt) { - Ok(res) => { - println!(": Parsed"); - let ref mut namespace = ACPI_TABLE.lock().namespace; - - if let Some(ref mut ns) = *namespace { - let mut res = res.clone(); - ns.append(&mut res); - } else { - *namespace = Some(res); - } - }, + Ok(()) => println!(": Parsed"), Err(AmlError::AmlParseError(e)) => println!(": {}", e), Err(AmlError::AmlInvalidOpCode) => println!(": Invalid opcode"), Err(AmlError::AmlValueError) => println!(": Type constraints or value bounds not met"), @@ -229,6 +224,11 @@ fn parse_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) { /// Parse the ACPI tables to gather CPU, interrupt, and timer information pub unsafe fn init(active_table: &mut ActivePageTable) { + { + let mut namespace = ACPI_TABLE.namespace.write(); + *namespace = Some(BTreeMap::new()); + } + let start_addr = 0xE0000; let end_addr = 0xFFFFF; @@ -283,12 +283,16 @@ pub unsafe fn init(active_table: &mut ActivePageTable) { } pub struct Acpi { - pub fadt: Option, - pub namespace: Option>, - pub hpet: Option + pub fadt: RwLock>, + pub namespace: RwLock>>, + pub hpet: RwLock> } -pub static ACPI_TABLE: Mutex = Mutex::new(Acpi { fadt: None, namespace: None, hpet: None }); +pub static ACPI_TABLE: Acpi = Acpi { + fadt: RwLock::new(None), + namespace: RwLock::new(None), + hpet: RwLock::new(None) +}; /// RSDP #[derive(Copy, Clone, Debug)] diff --git a/src/device/mod.rs b/src/device/mod.rs index 965e083..568f395 100644 --- a/src/device/mod.rs +++ b/src/device/mod.rs @@ -17,7 +17,7 @@ pub unsafe fn init(active_table: &mut ActivePageTable){ pub unsafe fn init_noncore(active_table: &mut ActivePageTable) { { - if let Some(ref hpet) = ACPI_TABLE.lock().hpet { + if let Some(ref hpet) = *ACPI_TABLE.hpet.read() { hpet::init(hpet, active_table); } else { pit::init(); diff --git a/src/stop.rs b/src/stop.rs index 7e53f10..acd0179 100644 --- a/src/stop.rs +++ b/src/stop.rs @@ -7,25 +7,29 @@ pub unsafe extern fn kstop() -> ! { // ACPI shutdown { - let acpi = acpi::ACPI_TABLE.lock(); - if let Some(ref fadt) = acpi.fadt { + let fadt = acpi::ACPI_TABLE.fadt.read(); + + if let Some(ref fadt) = *fadt { let port = fadt.pm1a_control_block as u16; let mut val = 1 << 13; - if let Some(ref namespace) = acpi.namespace { + + let namespace = acpi::ACPI_TABLE.namespace.read(); + + if let Some(ref namespace) = *namespace { if let Some(s) = namespace.get("\\_S5") { if let Ok(p) = s.get_as_package() { println!("{:?}", p); 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"); - + println!("Shutdown SLP_TYPa {:X}, SLP_TYPb {:X}", slp_typa, slp_typb); val |= slp_typa as u16; + + println!("Shutdown with ACPI outw(0x{:X}, 0x{:X})", port, val); + Pio::::new(port).write(val); } } } - - println!("Shutdown with ACPI outw(0x{:X}, 0x{:X})", port, val); - Pio::::new(port).write(val); } } From 2256e0288bae506d7b2b7c5e2ea9179b42986238 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Fri, 21 Jul 2017 12:04:36 +0100 Subject: [PATCH 060/113] Removed spurious file --- src/acpi/fs.rs | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 src/acpi/fs.rs diff --git a/src/acpi/fs.rs b/src/acpi/fs.rs deleted file mode 100644 index 2a6b608..0000000 --- a/src/acpi/fs.rs +++ /dev/null @@ -1,19 +0,0 @@ -pub fn init_fs() { - let schemes = schemes_mut().unwrap(); - schemes.insert(SchemeNamespace(0), Box::new(*b"acpi"), |_| Arc::new(Box::new(AcpiScheme::new()))).unwrap(); -} - -struct AcpiScheme { - -} - -impl AcpiScheme { - pub fn new() -> AcpiScheme { - AcpiScheme - } -} - -impl Scheme for AcpiScheme { - fn open(&self, url: &[u8], flags: usize, uid: u32, gid: u32) -> Result { - let path = str::from_utf8(url).unwrap_or("").trim_matches('/'); - From 5c05b489215fb93f178d4149eddb8e6675b76218 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Fri, 21 Jul 2017 12:42:11 +0100 Subject: [PATCH 061/113] GenericAddressStructure now handles reads and writes itself --- src/acpi/hpet.rs | 27 ++++++++++++-- src/acpi/mod.rs | 2 +- src/device/hpet.rs | 87 +++++++++++----------------------------------- src/device/mod.rs | 6 ++-- src/start.rs | 2 +- 5 files changed, 50 insertions(+), 74 deletions(-) diff --git a/src/acpi/hpet.rs b/src/acpi/hpet.rs index 664b6bb..74b14ea 100644 --- a/src/acpi/hpet.rs +++ b/src/acpi/hpet.rs @@ -1,6 +1,10 @@ use core::{mem, ptr}; use super::sdt::Sdt; +use core::intrinsics::{volatile_load, volatile_store}; + +use memory::Frame; +use paging::{entry, ActivePageTable, PhysicalAddress, Page, VirtualAddress}; #[repr(packed)] #[derive(Clone, Copy, Debug, Default)] @@ -29,11 +33,30 @@ pub struct Hpet { } impl Hpet { - pub fn new(sdt: &'static Sdt) -> Option { + pub fn new(sdt: &'static Sdt, active_table: &mut ActivePageTable) -> Option { if &sdt.signature == b"HPET" && sdt.length as usize >= mem::size_of::() { - Some(unsafe { ptr::read((sdt as *const Sdt) as *const Hpet) }) + let s = unsafe { ptr::read((sdt as *const Sdt) as *const Hpet) }; + unsafe { s.base_address.init(active_table) }; + Some(s) } else { None } } } + +impl GenericAddressStructure { + pub unsafe fn init(&self, active_table: &mut ActivePageTable) { + let page = Page::containing_address(VirtualAddress::new(self.address as usize)); + let frame = Frame::containing_address(PhysicalAddress::new(self.address as usize)); + let result = active_table.map_to(page, frame, entry::PRESENT | entry::WRITABLE | entry::NO_EXECUTE); + result.flush(active_table); + } + + pub unsafe fn read_u64(&self, offset: usize) -> u64{ + volatile_load((self.address as usize + offset) as *const u64) + } + + pub unsafe fn write_u64(&mut self, offset: usize, value: u64) { + volatile_store((self.address as usize + offset) as *mut u64, value); + } +} diff --git a/src/acpi/mod.rs b/src/acpi/mod.rs index d246609..ada10d1 100644 --- a/src/acpi/mod.rs +++ b/src/acpi/mod.rs @@ -203,7 +203,7 @@ fn parse_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) { _ => () } } - } else if let Some(hpet) = Hpet::new(sdt) { + } else if let Some(hpet) = Hpet::new(sdt, active_table) { println!(": {}", hpet.hpet_number); let mut hpet_t = ACPI_TABLE.hpet.write(); diff --git a/src/device/hpet.rs b/src/device/hpet.rs index 3f88f36..9307fc5 100644 --- a/src/device/hpet.rs +++ b/src/device/hpet.rs @@ -5,15 +5,6 @@ use paging::{entry, ActivePageTable, PhysicalAddress, Page, VirtualAddress}; use acpi::hpet::Hpet; -pub static mut HPET: HpetDevice = HpetDevice { - capability_addr: 0, - general_config_addr: 0, - general_interrupt_addr: 0, - main_counter_addr: 0, - t0_config_capability_addr: 0, - t0_comparator_addr: 0 -}; - static LEG_RT_CNF: u64 = 2; static ENABLE_CNF: u64 = 1; @@ -21,62 +12,24 @@ static TN_VAL_SET_CNF: u64 = 0x40; static TN_TYPE_CNF: u64 = 0x08; static TN_INT_ENB_CNF: u64 = 0x04; -pub struct HpetDevice { - capability_addr: usize, - general_config_addr: usize, - general_interrupt_addr: usize, - main_counter_addr: usize, - t0_config_capability_addr: usize, - t0_comparator_addr: usize -} - -pub unsafe fn init(hpet: &Hpet, active_table: &mut ActivePageTable) { - HPET.init(hpet, active_table); -} - -impl HpetDevice { - unsafe fn init(&mut self, hpet: &Hpet, active_table: &mut ActivePageTable) { - let base_address = hpet.base_address.address as usize; - - self.capability_addr = base_address; - self.general_config_addr = base_address + 0x10; - self.general_interrupt_addr = base_address + 0x20; - self.main_counter_addr = base_address + 0xF0; - - self.t0_config_capability_addr = base_address + 0x100; - self.t0_comparator_addr = base_address + 0x108; - - { - let page = Page::containing_address(VirtualAddress::new(base_address)); - let frame = Frame::containing_address(PhysicalAddress::new(base_address)); - let result = active_table.map_to(page, frame, entry::PRESENT | entry::WRITABLE | entry::NO_EXECUTE); - result.flush(active_table); - } - - println!("HPET mapped"); - - let counter_clk_period_fs = self.get_counter_clock_period(); - let desired_fs_period: u64 = 2250286 * 1000000; - - let clk_periods_per_kernel_tick: u64 = desired_fs_period / counter_clk_period_fs; - - let enable_word: u64 = volatile_load(self.general_config_addr as *const u64) - | LEG_RT_CNF | ENABLE_CNF; - - volatile_store(self.general_config_addr as *mut u64, enable_word); - // Enable interrupts from the HPET - - let t0_config_word: u64 = TN_VAL_SET_CNF | TN_TYPE_CNF | TN_INT_ENB_CNF; - volatile_store(self.t0_config_capability_addr as *mut u64, t0_config_word); - - volatile_store(self.t0_comparator_addr as *mut u64, clk_periods_per_kernel_tick); - } - - pub fn get_counter_clock_period(&self) -> u64 { - unsafe { volatile_load(self.capability_addr as *const u64) >> 32 } - } - - pub fn get_main_counter(&self) -> u64 { - unsafe { volatile_load(self.main_counter_addr as *const u64) } - } +static CAPABILITY_OFFSET: usize = 0x00; +static GENERAL_CONFIG_OFFSET: usize = 0x10; +static GENERAL_INTERRUPT_OFFSET: usize = 0x20; +static MAIN_COUNTER_OFFSET: usize = 0xF0; +static T0_CONFIG_CAPABILITY_OFFSET: usize = 0x100; +static T0_COMPARATOR_OFFSET: usize = 0x108; + +pub unsafe fn init(hpet: &mut Hpet) { + let counter_clk_period_fs = hpet.base_address.read_u64(CAPABILITY_OFFSET) >> 32; + let desired_fs_period: u64 = 2250286 * 1000000; + + let clk_periods_per_kernel_tick: u64 = desired_fs_period / counter_clk_period_fs; + + let enable_word: u64 = hpet.base_address.read_u64(GENERAL_CONFIG_OFFSET) | LEG_RT_CNF | ENABLE_CNF; + hpet.base_address.write_u64(GENERAL_CONFIG_OFFSET, enable_word); + // Enable interrupts from the HPET + + let t0_config_word: u64 = TN_VAL_SET_CNF | TN_TYPE_CNF | TN_INT_ENB_CNF; + hpet.base_address.write_u64(T0_CONFIG_CAPABILITY_OFFSET, t0_config_word); + hpet.base_address.write_u64(T0_COMPARATOR_OFFSET, clk_periods_per_kernel_tick); } diff --git a/src/device/mod.rs b/src/device/mod.rs index 568f395..18700d0 100644 --- a/src/device/mod.rs +++ b/src/device/mod.rs @@ -15,10 +15,10 @@ pub unsafe fn init(active_table: &mut ActivePageTable){ local_apic::init(active_table); } -pub unsafe fn init_noncore(active_table: &mut ActivePageTable) { +pub unsafe fn init_noncore() { { - if let Some(ref hpet) = *ACPI_TABLE.hpet.read() { - hpet::init(hpet, active_table); + if let Some(ref mut hpet) = *ACPI_TABLE.hpet.write() { + hpet::init(hpet); } else { pit::init(); } diff --git a/src/start.rs b/src/start.rs index 8f88204..d7b3663 100644 --- a/src/start.rs +++ b/src/start.rs @@ -109,7 +109,7 @@ pub unsafe extern fn kstart(kernel_base: usize, kernel_size: usize, stack_base: acpi::init(&mut active_table); // Initialize all of the non-core devices not otherwise needed to complete initialization - device::init_noncore(&mut active_table); + device::init_noncore(); // Initialize memory functions after core has loaded memory::init_noncore(); From 0365b6f2b79777bc54ae1988262188ccb4bb0888 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Fri, 21 Jul 2017 12:51:30 +0100 Subject: [PATCH 062/113] Created a function to control the global S state --- src/acpi/mod.rs | 30 ++++++++++++++++++++++++++++++ src/stop.rs | 31 ++----------------------------- 2 files changed, 32 insertions(+), 29 deletions(-) diff --git a/src/acpi/mod.rs b/src/acpi/mod.rs index ada10d1..d22140b 100644 --- a/src/acpi/mod.rs +++ b/src/acpi/mod.rs @@ -7,6 +7,8 @@ use collections::btree_map::BTreeMap; use collections::string::String; use alloc::boxed::Box; +use syscall::io::{Io, Pio}; + use spin::{Mutex, RwLock}; use device::local_apic::LOCAL_APIC; @@ -282,6 +284,34 @@ pub unsafe fn init(active_table: &mut ActivePageTable) { */ } +pub fn set_global_s_state(state: u8) { + if state == 5 { + let fadt = ACPI_TABLE.fadt.read(); + + if let Some(ref fadt) = *fadt { + let port = fadt.pm1a_control_block as u16; + let mut val = 1 << 13; + + let namespace = ACPI_TABLE.namespace.read(); + + if let Some(ref namespace) = *namespace { + if let Some(s) = namespace.get("\\_S5") { + if let Ok(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"); + + println!("Shutdown SLP_TYPa {:X}, SLP_TYPb {:X}", slp_typa, slp_typb); + val |= slp_typa as u16; + + println!("Shutdown with ACPI outw(0x{:X}, 0x{:X})", port, val); + Pio::::new(port).write(val); + } + } + } + } + } +} + pub struct Acpi { pub fadt: RwLock>, pub namespace: RwLock>>, diff --git a/src/stop.rs b/src/stop.rs index acd0179..bf01fde 100644 --- a/src/stop.rs +++ b/src/stop.rs @@ -4,35 +4,8 @@ use syscall::io::{Io, Pio}; #[no_mangle] pub unsafe extern fn kstop() -> ! { println!("kstop"); - - // ACPI shutdown - { - let fadt = acpi::ACPI_TABLE.fadt.read(); - - if let Some(ref fadt) = *fadt { - let port = fadt.pm1a_control_block as u16; - let mut val = 1 << 13; - - let namespace = acpi::ACPI_TABLE.namespace.read(); - - if let Some(ref namespace) = *namespace { - if let Some(s) = namespace.get("\\_S5") { - if let Ok(p) = s.get_as_package() { - println!("{:?}", p); - 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"); - - println!("Shutdown SLP_TYPa {:X}, SLP_TYPb {:X}", slp_typa, slp_typb); - val |= slp_typa as u16; - - println!("Shutdown with ACPI outw(0x{:X}, 0x{:X})", port, val); - Pio::::new(port).write(val); - } - } - } - } - } - + acpi::set_global_s_state(5); + // Magic shutdown code for bochs and qemu (older versions). for c in "Shutdown".bytes() { let port = 0x8900; From 1938ca043522bc9b5776edff624806fac8de2531 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Fri, 21 Jul 2017 14:11:29 +0100 Subject: [PATCH 063/113] Memory handler API --- src/acpi/aml/namedobj.rs | 14 +++++++++++--- src/acpi/aml/namespace.rs | 30 +++++++++++++++++++++++++----- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index a99c82f..1d16d2b 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -7,7 +7,7 @@ use collections::btree_map::BTreeMap; use super::AmlError; use super::parser::{ AmlParseType, ParseResult, AmlParseTypeGeneric, AmlExecutionContext, ExecutionState }; -use super::namespace::{ AmlValue, ObjectReference, FieldSelector, Method, get_namespace_string }; +use super::namespace::{ AmlValue, ObjectReference, FieldSelector, Method, get_namespace_string, Accessor }; use super::namestring::{parse_name_string, parse_name_seg}; use super::termlist::{parse_term_arg, parse_term_list, parse_object_list}; use super::pkglength::parse_pkg_length; @@ -373,7 +373,11 @@ fn parse_def_data_region(data: &[u8], ctx.add_to_namespace(local_scope_string, AmlValue::OperationRegion { region: RegionSpace::SystemMemory, offset: Box::new(AmlValue::IntegerConstant(0)), - len: Box::new(AmlValue::IntegerConstant(0)) + len: Box::new(AmlValue::IntegerConstant(0)), + accessor: Accessor { + read: |x| 0 as u64, + write: |x, y| () + } }); Ok(AmlParseType { @@ -469,7 +473,11 @@ fn parse_def_op_region(data: &[u8], ctx.add_to_namespace(local_scope_string, AmlValue::OperationRegion { region: region, offset: Box::new(offset.val), - len: Box::new(len.val) + len: Box::new(len.val), + accessor: Accessor { + read: |x| 0 as u64, + write: |x, y| () + } }); Ok(AmlParseType { diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index 1c84f81..ac3f585 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -4,13 +4,14 @@ use collections::vec::Vec; use collections::btree_map::BTreeMap; use core::str::FromStr; +use core::fmt::{Debug, Formatter, Error}; use super::termlist::parse_term_list; use super::namedobj::{ RegionSpace, FieldFlags }; use super::parser::{AmlExecutionContext, ExecutionState}; use super::AmlError; -#[derive(Debug, Clone)] +#[derive(Clone)] pub enum FieldSelector { Region(String), Bank { @@ -23,7 +24,7 @@ pub enum FieldSelector { } } -#[derive(Debug, Clone)] +#[derive(Clone)] pub enum ObjectReference { ArgObj(u8), LocalObj(u8), @@ -32,7 +33,7 @@ pub enum ObjectReference { Index(Box, Box) } -#[derive(Debug, Clone)] +#[derive(Clone)] pub struct Method { pub arg_count: u8, pub serialized: bool, @@ -40,7 +41,21 @@ pub struct Method { pub term_list: Vec } -#[derive(Debug, Clone)] +pub struct Accessor { + pub read: fn(usize) -> u64, + pub write: fn(usize, u64) +} + +impl Clone for Accessor { + fn clone(&self) -> Accessor { + Accessor { + read: (*self).read, + write: (*self).write + } + } +} + +#[derive(Clone)] pub enum AmlValue { None, Uninitialized, @@ -69,7 +84,8 @@ pub enum AmlValue { OperationRegion { region: RegionSpace, offset: Box, - len: Box + len: Box, + accessor: Accessor }, Package(Vec), String(String), @@ -87,6 +103,10 @@ pub enum AmlValue { ThermalZone(Vec) } +impl Debug for AmlValue { + fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { Ok(()) } +} + impl AmlValue { pub fn get_as_string(&self) -> Result { match *self { From 8412339ae927a8371cc4bc936fed2136eb6be5d5 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Sat, 22 Jul 2017 09:10:37 +0100 Subject: [PATCH 064/113] Every context has an ID --- src/acpi/aml/parser.rs | 11 +++++++++-- src/acpi/mod.rs | 6 ++++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/acpi/aml/parser.rs b/src/acpi/aml/parser.rs index 0b57f13..e31c6f7 100644 --- a/src/acpi/aml/parser.rs +++ b/src/acpi/aml/parser.rs @@ -27,11 +27,17 @@ pub struct AmlExecutionContext { pub local_vars: [AmlValue; 8], pub arg_vars: [AmlValue; 8], pub state: ExecutionState, - pub namespace_delta: Vec + pub namespace_delta: Vec, + pub ctx_id: u64 } impl AmlExecutionContext { pub fn new(scope: String) -> AmlExecutionContext { + let mut idptr = ACPI_TABLE.next_ctx.write(); + let id: u64 = *idptr; + + *idptr += 1; + AmlExecutionContext { scope: scope, local_vars: [AmlValue::Uninitialized, @@ -51,7 +57,8 @@ impl AmlExecutionContext { AmlValue::Uninitialized, AmlValue::Uninitialized], state: ExecutionState::EXECUTING, - namespace_delta: vec!() + namespace_delta: vec!(), + ctx_id: id } } diff --git a/src/acpi/mod.rs b/src/acpi/mod.rs index d22140b..04112f3 100644 --- a/src/acpi/mod.rs +++ b/src/acpi/mod.rs @@ -315,13 +315,15 @@ pub fn set_global_s_state(state: u8) { pub struct Acpi { pub fadt: RwLock>, pub namespace: RwLock>>, - pub hpet: RwLock> + pub hpet: RwLock>, + pub next_ctx: RwLock, } pub static ACPI_TABLE: Acpi = Acpi { fadt: RwLock::new(None), namespace: RwLock::new(None), - hpet: RwLock::new(None) + hpet: RwLock::new(None), + next_ctx: RwLock::new(0), }; /// RSDP From 8e98cdf9719e4bab41093466678a12dd35a23ed7 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Sat, 22 Jul 2017 09:57:44 +0100 Subject: [PATCH 065/113] Processed acquire mutex --- src/acpi/aml/namedobj.rs | 8 +++-- src/acpi/aml/namespace.rs | 5 ++-- src/acpi/aml/parser.rs | 6 ++++ src/acpi/aml/type2opcode.rs | 60 +++++++++++++++++++++++++++++++++++-- 4 files changed, 71 insertions(+), 8 deletions(-) diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index 1d16d2b..47a8e43 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -377,7 +377,8 @@ fn parse_def_data_region(data: &[u8], accessor: Accessor { read: |x| 0 as u64, write: |x, y| () - } + }, + accessed_by: None }); Ok(AmlParseType { @@ -477,7 +478,8 @@ fn parse_def_op_region(data: &[u8], accessor: Accessor { read: |x| 0 as u64, write: |x, y| () - } + }, + accessed_by: None }); Ok(AmlParseType { @@ -819,7 +821,7 @@ fn parse_def_mutex(data: &[u8], let sync_level = flags & 0x0F; let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); - ctx.add_to_namespace(local_scope_string, AmlValue::Mutex(sync_level)); + ctx.add_to_namespace(local_scope_string, AmlValue::Mutex((sync_level, None))); Ok(AmlParseType { val: AmlValue::None, diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index ac3f585..ddead79 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -79,13 +79,14 @@ pub enum AmlValue { Integer(u64), IntegerConstant(u64), Method(Method), - Mutex(u8), + Mutex((u8, Option)), ObjectReference(ObjectReference), OperationRegion { region: RegionSpace, offset: Box, len: Box, - accessor: Accessor + accessor: Accessor, + accessed_by: Option }, Package(Vec), String(String), diff --git a/src/acpi/aml/parser.rs b/src/acpi/aml/parser.rs index e31c6f7..a762eba 100644 --- a/src/acpi/aml/parser.rs +++ b/src/acpi/aml/parser.rs @@ -2,6 +2,8 @@ use collections::string::String; use collections::btree_map::BTreeMap; use collections::vec::Vec; +use spin::RwLockWriteGuard; + use super::namespace::{ AmlValue, ObjectReference }; use super::AmlError; @@ -101,6 +103,10 @@ impl AmlExecutionContext { } } + pub fn prelock(&mut self) -> RwLockWriteGuard<'static, Option>> { + ACPI_TABLE.namespace.write() + } + pub fn modify(&mut self, name: AmlValue, value: AmlValue) { // TODO: throw errors // TODO: return DRO diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index c505201..c91b3bd 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -307,17 +307,70 @@ fn parse_def_acquire(data: &[u8], }) } - // TODO: Store the result - // TODO: Perform computation parser_opcode_extended!(data, 0x23); let obj = parse_super_name(&data[1..], ctx)?; let timeout = (data[2 + obj.len] as u16) + ((data[3 + obj.len] as u16) << 8); + + let (seconds, nanoseconds) = monotonic(); + let starting_time_ns = nanoseconds + (seconds * 1000000000); + + let id = ctx.ctx_id; + + loop { + { + let mut namespace = ctx.prelock(); + let mutex = ctx.get(obj.val.clone()); + + match mutex { + AmlValue::Mutex((sync_level, owner)) => { + if owner == None { + ctx.modify(obj.val.clone(), AmlValue::Mutex((sync_level, Some(id)))); + return Ok(AmlParseType { + val: AmlValue::Integer(0), + len: 4 + obj.len + }); + } + }, + AmlValue::OperationRegion { region, offset, len, accessor, accessed_by } => { + if accessed_by == None { + ctx.modify(obj.val.clone(), AmlValue::OperationRegion { + region, + offset, + len, + accessor, + accessed_by: Some(id) + }); + return Ok(AmlParseType { + val: AmlValue::Integer(0), + len: 4 + obj.len + }); + } + }, + _ => return Err(AmlError::AmlValueError) + } + } + + if timeout == 0xFFFF { + // TODO: Brief sleep here + } else { + let (seconds, nanoseconds) = monotonic(); + let current_time_ns = nanoseconds + (seconds * 1000000000); + + if current_time_ns - starting_time_ns > timeout as u64 * 1000000 { + return Ok(AmlParseType { + val: AmlValue::Integer(1), + len: 4 + obj.len + }); + } + } + } Ok(AmlParseType { val: AmlValue::Uninitialized, len: 4 + obj.len }) + // This should never run } fn parse_def_increment(data: &[u8], @@ -333,8 +386,9 @@ fn parse_def_increment(data: &[u8], parser_opcode!(data, 0x75); let obj = parse_super_name(&data[1..], ctx)?; + + let mut namespace = ctx.prelock(); let value = AmlValue::Integer(ctx.get(obj.val.clone()).get_as_integer()? + 1); - ctx.modify(obj.val, value.clone()); Ok(AmlParseType { From b0b8a7e85d9e1eda9cdb5868b704f84c55c301ad Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Sat, 22 Jul 2017 10:06:20 +0100 Subject: [PATCH 066/113] Handled mutexes --- src/acpi/aml/mod.rs | 3 ++- src/acpi/aml/type1opcode.rs | 35 +++++++++++++++++++++++++++++++++-- src/acpi/aml/type2opcode.rs | 3 ++- src/acpi/mod.rs | 3 ++- 4 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/acpi/aml/mod.rs b/src/acpi/aml/mod.rs index 1edab51..7e37d08 100644 --- a/src/acpi/aml/mod.rs +++ b/src/acpi/aml/mod.rs @@ -34,7 +34,8 @@ pub enum AmlError { AmlInvalidOpCode, AmlValueError, AmlDeferredLoad, - AmlFatalError(u8, u16, AmlValue) + AmlFatalError(u8, u16, AmlValue), + AmlHardFatal } pub fn parse_aml_table(sdt: &'static Sdt) -> Result<(), AmlError> { diff --git a/src/acpi/aml/type1opcode.rs b/src/acpi/aml/type1opcode.rs index b09b868..adcb769 100644 --- a/src/acpi/aml/type1opcode.rs +++ b/src/acpi/aml/type1opcode.rs @@ -197,11 +197,42 @@ fn parse_def_release(data: &[u8], // TODO: Release if it is parser_opcode_extended!(data, 0x27); - let object = parse_super_name(&data[2..], ctx)?; + let obj = parse_super_name(&data[2..], ctx)?; + + let mut namespace = ctx.prelock(); + let mutex = ctx.get(obj.val.clone()); + + match mutex { + AmlValue::Mutex((sync_level, owner)) => { + if let Some(o) = owner { + if o == ctx.ctx_id { + ctx.modify(obj.val.clone(), AmlValue::Mutex((sync_level, None))); + } else { + return Err(AmlError::AmlHardFatal); + } + } + }, + AmlValue::OperationRegion { region, offset, len, accessor, accessed_by } => { + if let Some(o) = accessed_by { + if o == ctx.ctx_id { + ctx.modify(obj.val.clone(), AmlValue::OperationRegion { + region, + offset, + len, + accessor, + accessed_by: None + }); + } else { + return Err(AmlError::AmlHardFatal); + } + } + }, + _ => return Err(AmlError::AmlValueError) + } Ok(AmlParseType { val: AmlValue::None, - len: 2 + object.len + len: 2 + obj.len }) } diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index c91b3bd..7d889ec 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -1052,8 +1052,9 @@ fn parse_def_decrement(data: &[u8], parser_opcode!(data, 0x76); let obj = parse_super_name(&data[1..], ctx)?; + + let mut namespace = ctx.prelock(); let value = AmlValue::Integer(ctx.get(obj.val.clone()).get_as_integer()? - 1); - ctx.modify(obj.val, value.clone()); Ok(AmlParseType { diff --git a/src/acpi/mod.rs b/src/acpi/mod.rs index 04112f3..39e2799 100644 --- a/src/acpi/mod.rs +++ b/src/acpi/mod.rs @@ -217,7 +217,8 @@ fn parse_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) { Err(AmlError::AmlInvalidOpCode) => println!(": Invalid opcode"), Err(AmlError::AmlValueError) => println!(": Type constraints or value bounds not met"), Err(AmlError::AmlDeferredLoad) => println!(": Deferred load reached top level"), - Err(AmlError::AmlFatalError(_, _, _)) => println!(": Fatal error occurred") + Err(AmlError::AmlFatalError(_, _, _)) => println!(": Fatal error occurred"), + Err(AmlError::AmlHardFatal) => println!(": Fatal error occurred") }; } else { println!(": Unknown"); From b7d9ad60bb6286379c4dd9d1d5d8efa3900f4554 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Sat, 22 Jul 2017 10:55:09 +0100 Subject: [PATCH 067/113] Implemented Event synchronisation objects --- src/acpi/aml/namedobj.rs | 2 +- src/acpi/aml/namespace.rs | 9 +++++++- src/acpi/aml/type1opcode.rs | 14 ++++++----- src/acpi/aml/type2opcode.rs | 46 +++++++++++++++++++++++++++++++++---- 4 files changed, 59 insertions(+), 12 deletions(-) diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index 47a8e43..c7d2636 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -402,7 +402,7 @@ fn parse_def_event(data: &[u8], let name = parse_name_string(&data[2..], ctx)?; let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); - ctx.add_to_namespace(local_scope_string, AmlValue::Event); + ctx.add_to_namespace(local_scope_string, AmlValue::Event(0)); Ok(AmlParseType { val: AmlValue::None, diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index ddead79..0862e72 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -68,7 +68,7 @@ pub enum AmlValue { DDBHandle(u32), // Index into the XSDT DebugObject, Device(Vec), - Event, + Event(u64), FieldUnit { selector: FieldSelector, connection: Box, @@ -109,6 +109,13 @@ impl Debug for AmlValue { } impl AmlValue { + pub fn get_as_event(&self) -> Result { + match *self { + AmlValue::Event(ref e) => Ok(e.clone()), + _ => Err(AmlError::AmlValueError) + } + } + pub fn get_as_string(&self) -> Result { match *self { AmlValue::String(ref s) => Ok(s.clone()), diff --git a/src/acpi/aml/type1opcode.rs b/src/acpi/aml/type1opcode.rs index adcb769..e5f42ac 100644 --- a/src/acpi/aml/type1opcode.rs +++ b/src/acpi/aml/type1opcode.rs @@ -192,9 +192,6 @@ fn parse_def_release(data: &[u8], }) } - // TODO: Check ownership of the mutex pointed to - // TODO: FATAL if not owned - // TODO: Release if it is parser_opcode_extended!(data, 0x27); let obj = parse_super_name(&data[2..], ctx)?; @@ -246,10 +243,12 @@ fn parse_def_reset(data: &[u8], }) } - // TODO: object (of type Event) is a semaphore. Reset the resource count to 0 parser_opcode_extended!(data, 0x26); let object = parse_super_name(&data[2..], ctx)?; + let event = ctx.get(object.val.clone()).get_as_event()?; + + ctx.modify(object.val.clone(), AmlValue::Event(0)); Ok(AmlParseType { val: AmlValue::None, @@ -267,11 +266,14 @@ fn parse_def_signal(data: &[u8], }) } - // TODO: Increment the resource count of the semaphore parser_opcode_extended!(data, 0x24); - let object = parse_super_name(&data[2..], ctx)?; + let namespace = ctx.prelock(); + let event = ctx.get(object.val.clone()).get_as_event()?; + + ctx.modify(object.val.clone(), AmlValue::Event(event + 1)); + Ok(AmlParseType { val: AmlValue::None, len: 2 + object.len diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index 7d889ec..7ce6532 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -957,15 +957,53 @@ fn parse_def_wait(data: &[u8], }) } - // TODO: Compute the result parser_opcode_extended!(data, 0x25); - let event_object = parse_super_name(&data[2..], ctx)?; - let operand = parse_term_arg(&data[2 + event_object.len..], ctx)?; + let obj = parse_super_name(&data[2..], ctx)?; + let timeout_obj = parse_term_arg(&data[2 + obj.len..], ctx)?; + let timeout = timeout_obj.val.get_as_integer()?; + + let (seconds, nanoseconds) = monotonic(); + let starting_time_ns = nanoseconds + (seconds * 1000000000); + + loop { + { + let mut namespace = ctx.prelock(); + let mutex = ctx.get(obj.val.clone()); + + match mutex { + AmlValue::Event(count) => { + if count > 0 { + ctx.modify(obj.val.clone(), AmlValue::Event(count - 1)); + return Ok(AmlParseType { + val: AmlValue::Integer(0), + len: 2 + obj.len + timeout_obj.len + }); + } + }, + _ => return Err(AmlError::AmlValueError) + } + } + + if timeout >= 0xFFFF { + // TODO: Brief sleep here + } else { + let (seconds, nanoseconds) = monotonic(); + let current_time_ns = nanoseconds + (seconds * 1000000000); + + if current_time_ns - starting_time_ns > timeout as u64 * 1000000 { + return Ok(AmlParseType { + val: AmlValue::Integer(1), + len: 2 + obj.len + timeout_obj.len + }); + } + } + } + Ok(AmlParseType { val: AmlValue::Uninitialized, - len: 2 + event_object.len + operand.len + len: 2 + obj.len + timeout_obj.len }) } From ff23827155c88aea245d81b72057b782c5b1cd7f Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Sat, 22 Jul 2017 11:02:53 +0100 Subject: [PATCH 068/113] Implemented stall --- src/acpi/aml/type1opcode.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/acpi/aml/type1opcode.rs b/src/acpi/aml/type1opcode.rs index e5f42ac..73c2c6f 100644 --- a/src/acpi/aml/type1opcode.rs +++ b/src/acpi/aml/type1opcode.rs @@ -10,6 +10,8 @@ use super::pkglength::parse_pkg_length; use super::termlist::{parse_term_arg, parse_term_list}; use super::namestring::{parse_name_string, parse_super_name}; +use time::monotonic; + pub fn parse_type1_opcode(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { match ctx.state { @@ -311,10 +313,22 @@ fn parse_def_stall(data: &[u8], }) } - // TODO: Sleep the processor for the specified number of microseconds (minimum) parser_opcode_extended!(data, 0x21); let time = parse_term_arg(&data[2..], ctx)?; + let timeout = time.val.get_as_integer()?; + + let (seconds, nanoseconds) = monotonic(); + let starting_time_ns = nanoseconds + (seconds * 1000000000); + + loop { + let (seconds, nanoseconds) = monotonic(); + let current_time_ns = nanoseconds + (seconds * 1000000000); + + if current_time_ns - starting_time_ns > timeout as u64 * 1000 { + break; + } + } Ok(AmlParseType { val: AmlValue::None, From f8e433c4e75df442822b32646e14c731de5f583f Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Sat, 22 Jul 2017 11:13:30 +0100 Subject: [PATCH 069/113] Implemented sleep --- src/acpi/aml/type1opcode.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/acpi/aml/type1opcode.rs b/src/acpi/aml/type1opcode.rs index 73c2c6f..ee9d8cb 100644 --- a/src/acpi/aml/type1opcode.rs +++ b/src/acpi/aml/type1opcode.rs @@ -292,10 +292,22 @@ fn parse_def_sleep(data: &[u8], }) } - // TODO: Sleep the processor for the specified number of milliseconds (minimum) parser_opcode_extended!(data, 0x22); let time = parse_term_arg(&data[2..], ctx)?; + let timeout = time.val.get_as_integer()?; + + let (seconds, nanoseconds) = monotonic(); + let starting_time_ns = nanoseconds + (seconds * 1000000000); + + loop { + let (seconds, nanoseconds) = monotonic(); + let current_time_ns = nanoseconds + (seconds * 1000000000); + + if current_time_ns - starting_time_ns > timeout as u64 * 1000000 { + break; + } + } Ok(AmlParseType { val: AmlValue::None, From 79b6afd60869781d48a3cc0024235b692dbd036c Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Sat, 22 Jul 2017 12:12:31 +0100 Subject: [PATCH 070/113] Implemented to integer --- src/acpi/aml/type2opcode.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index 7ce6532..496f4da 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -660,15 +660,17 @@ fn parse_def_to_integer(data: &[u8], }) } - // TODO: Compute the result - // TODO: Store the result, if appropriate parser_opcode!(data, 0x99); let operand = parse_term_arg(&data[2..], ctx)?; let target = parse_target(&data[2 + operand.len..], ctx)?; + let res = AmlValue::Integer(operand.val.get_as_integer()?); + + ctx.modify(target.val, res.clone()); + Ok(AmlParseType { - val: AmlValue::Uninitialized, + val: res, len: 1 + operand.len + target.len }) } @@ -1247,7 +1249,6 @@ fn parse_def_match(data: &[u8], }) } - // TODO: Clean up parser_opcode!(data, 0x28); let search_pkg = parse_term_arg(&data[1..], ctx)?; From 797262df5cd5c3b1a2cc3cde7faef35cd6ebd8fe Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Sat, 22 Jul 2017 12:48:23 +0100 Subject: [PATCH 071/113] Several conversion operators --- src/acpi/aml/type2opcode.rs | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index 496f4da..b0eb793 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -614,15 +614,25 @@ fn parse_def_to_bcd(data: &[u8], }) } - // TODO: Compute the result - // TODO: Store the result, if appropriate parser_opcode_extended!(data, 0x29); let operand = parse_term_arg(&data[2..], ctx)?; let target = parse_target(&data[2 + operand.len..], ctx)?; + + let mut i = operand.val.get_as_integer()?; + let mut result = 0; + + while i != 0 { + result <<= 4; + result += i % 10; + i /= 10; + } + + let result = AmlValue::Integer(result); + ctx.modify(target.val, result.clone()); Ok(AmlParseType { - val: AmlValue::Uninitialized, + val: result, len: 1 + operand.len + target.len }) } @@ -685,16 +695,25 @@ fn parse_def_to_string(data: &[u8], }) } - // TODO: Compute the result - // TODO: Store the result, if appropriate parser_opcode!(data, 0x9C); let operand = parse_term_arg(&data[1..], ctx)?; let length = parse_term_arg(&data[1 + operand.len..], ctx)?; let target = parse_target(&data[1 + operand.len + length.len..], ctx)?; + let buf = operand.val.get_as_buffer()?; + let mut string = match String::from_utf8(buf) { + Ok(s) => s, + Err(_) => return Err(AmlError::AmlValueError) + }; + + string.truncate(length.val.get_as_integer()? as usize); + let res = AmlValue::String(string); + + ctx.modify(target.val, res.clone()); + Ok(AmlParseType { - val: AmlValue::Uninitialized, + val: res, len: 1 + operand.len + length.len + target.len }) } From 5873e553e908c986d2f94e2e9b4756ac70b95577 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Sat, 22 Jul 2017 12:56:53 +0100 Subject: [PATCH 072/113] Implemented toDecimalString --- src/acpi/aml/type2opcode.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index b0eb793..f4aa8bc 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -646,16 +646,19 @@ fn parse_def_to_decimal_string(data: &[u8], len: 0 as usize }) } - - // TODO: Compute the result - // TODO: Store the result, if appropriate + parser_opcode!(data, 0x97); let operand = parse_term_arg(&data[2..], ctx)?; let target = parse_target(&data[2 + operand.len..], ctx)?; + let result: String = format!("{}", operand.val.get_as_integer()?); + let res = AmlValue::String(result); + + ctx.modify(target.val, res.clone()); + Ok(AmlParseType { - val: AmlValue::Uninitialized, + val: res, len: 1 + operand.len + target.len }) } From 76316aa8d61cf68d072651fa98444a230fd81abb Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Sat, 22 Jul 2017 13:10:45 +0100 Subject: [PATCH 073/113] Implemented toHexString --- src/acpi/aml/type2opcode.rs | 42 ++++++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index f4aa8bc..49ded05 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -568,15 +568,33 @@ fn parse_def_to_hex_string(data: &[u8], }) } - // TODO: Compute the result - // TODO: Store the result, if appropriate parser_opcode!(data, 0x98); let operand = parse_term_arg(&data[2..], ctx)?; let target = parse_target(&data[2 + operand.len..], ctx)?; + let res = match operand.val { + AmlValue::Integer(_) => { + let result: String = format!("{:X}", operand.val.get_as_integer()?); + AmlValue::String(result) + }, + AmlValue::String(s) => AmlValue::String(s), + AmlValue::Buffer(_) => { + let mut string: String = String::new(); + + for b in operand.val.get_as_buffer()? { + string.push_str(&format!("{:X}", b)); + } + + AmlValue::String(string) + }, + _ => return Err(AmlError::AmlValueError) + }; + + ctx.modify(target.val, res.clone()); + Ok(AmlParseType { - val: AmlValue::Uninitialized, + val: res, len: 1 + operand.len + target.len }) } @@ -651,9 +669,23 @@ fn parse_def_to_decimal_string(data: &[u8], let operand = parse_term_arg(&data[2..], ctx)?; let target = parse_target(&data[2 + operand.len..], ctx)?; + let res = match operand.val { + AmlValue::Integer(_) => { + let result: String = format!("{}", operand.val.get_as_integer()?); + AmlValue::String(result) + }, + AmlValue::String(s) => AmlValue::String(s), + AmlValue::Buffer(_) => { + let mut string: String = String::new(); - let result: String = format!("{}", operand.val.get_as_integer()?); - let res = AmlValue::String(result); + for b in operand.val.get_as_buffer()? { + string.push_str(&format!("{}", b)); + } + + AmlValue::String(string) + }, + _ => return Err(AmlError::AmlValueError) + }; ctx.modify(target.val, res.clone()); From 3c2b3b3f5e362df0029e9bd169255c491437f9d5 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Sat, 22 Jul 2017 13:32:02 +0100 Subject: [PATCH 074/113] Fixed a bunch of warnings --- src/acpi/aml/dataobj.rs | 1 - src/acpi/aml/mod.rs | 6 +--- src/acpi/aml/namedobj.rs | 49 ++++++++++++++----------------- src/acpi/aml/namespace.rs | 2 -- src/acpi/aml/namespacemodifier.rs | 9 ++---- src/acpi/aml/namestring.rs | 5 ++-- src/acpi/aml/parser.rs | 2 +- src/acpi/aml/termlist.rs | 7 ++--- src/acpi/aml/type1opcode.rs | 9 ++---- src/acpi/aml/type2opcode.rs | 46 +++++++++++------------------ src/acpi/mod.rs | 3 +- src/device/hpet.rs | 9 ++---- src/device/mod.rs | 1 - src/start.rs | 2 -- 14 files changed, 52 insertions(+), 99 deletions(-) diff --git a/src/acpi/aml/dataobj.rs b/src/acpi/aml/dataobj.rs index 7bb50d3..fa9710d 100644 --- a/src/acpi/aml/dataobj.rs +++ b/src/acpi/aml/dataobj.rs @@ -1,6 +1,5 @@ use collections::vec::Vec; use collections::string::String; -use collections::btree_map::BTreeMap; use super::AmlError; use super::parser::{ AmlParseType, ParseResult, AmlExecutionContext, ExecutionState }; diff --git a/src/acpi/aml/mod.rs b/src/acpi/aml/mod.rs index 7e37d08..d161031 100644 --- a/src/acpi/aml/mod.rs +++ b/src/acpi/aml/mod.rs @@ -1,11 +1,7 @@ //! # AML //! Code to parse and execute AML tables -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; use super::sdt::Sdt; @@ -24,7 +20,7 @@ mod type1opcode; mod type2opcode; mod parser; -use self::parser::{ ParseResult, AmlExecutionContext }; +use self::parser::AmlExecutionContext; use self::termlist::parse_term_list; pub use self::namespace::AmlValue; diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index c7d2636..e483302 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -1,15 +1,11 @@ use alloc::boxed::Box; use collections::string::String; -use collections::vec::Vec; -use core::str::FromStr; - -use collections::btree_map::BTreeMap; use super::AmlError; use super::parser::{ AmlParseType, ParseResult, AmlParseTypeGeneric, AmlExecutionContext, ExecutionState }; use super::namespace::{ AmlValue, ObjectReference, FieldSelector, Method, get_namespace_string, Accessor }; use super::namestring::{parse_name_string, parse_name_seg}; -use super::termlist::{parse_term_arg, parse_term_list, parse_object_list}; +use super::termlist::{parse_term_arg, parse_object_list}; use super::pkglength::parse_pkg_length; use super::type2opcode::parse_def_buffer; @@ -159,9 +155,8 @@ fn parse_def_bank_field(data: &[u8], bank_selector: Box::new(bank_value.val) }; - let field_list = parse_field_list( - &data[3 + pkg_length_len + region_name.len + bank_name.len + bank_value.len .. - 2 + pkg_length], ctx, selector, &mut flags)?; + parse_field_list(&data[3 + pkg_length_len + region_name.len + bank_name.len + bank_value.len .. + 2 + pkg_length], ctx, selector, &mut flags)?; Ok(AmlParseType { val: AmlValue::None, @@ -191,7 +186,7 @@ fn parse_def_create_bit_field(data: &[u8], source_buf: Box::new(source_buf.val), index: Box::new(bit_index.val), length: Box::new(AmlValue::IntegerConstant(1)) - }); + })?; Ok(AmlParseType { val: AmlValue::None, @@ -221,7 +216,7 @@ fn parse_def_create_byte_field(data: &[u8], source_buf: Box::new(source_buf.val), index: Box::new(bit_index.val), length: Box::new(AmlValue::IntegerConstant(8)) - }); + })?; Ok(AmlParseType { val: AmlValue::None, @@ -251,7 +246,7 @@ fn parse_def_create_word_field(data: &[u8], source_buf: Box::new(source_buf.val), index: Box::new(bit_index.val), length: Box::new(AmlValue::IntegerConstant(16)) - }); + })?; Ok(AmlParseType { val: AmlValue::None, @@ -311,7 +306,7 @@ fn parse_def_create_qword_field(data: &[u8], source_buf: Box::new(source_buf.val), index: Box::new(bit_index.val), length: Box::new(AmlValue::IntegerConstant(64)) - }); + })?; Ok(AmlParseType { val: AmlValue::None, @@ -342,7 +337,7 @@ fn parse_def_create_field(data: &[u8], source_buf: Box::new(source_buf.val), index: Box::new(bit_index.val), length: Box::new(num_bits.val) - }); + })?; Ok(AmlParseType { val: AmlValue::None, @@ -379,7 +374,7 @@ fn parse_def_data_region(data: &[u8], write: |x, y| () }, accessed_by: None - }); + })?; Ok(AmlParseType { val: AmlValue::None, @@ -402,7 +397,7 @@ fn parse_def_event(data: &[u8], let name = parse_name_string(&data[2..], ctx)?; let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); - ctx.add_to_namespace(local_scope_string, AmlValue::Event(0)); + ctx.add_to_namespace(local_scope_string, AmlValue::Event(0))?; Ok(AmlParseType { val: AmlValue::None, @@ -431,7 +426,7 @@ fn parse_def_device(data: &[u8], parse_object_list(&data[2 + pkg_length_len + name.len .. 2 + pkg_length], &mut local_ctx)?; - ctx.add_to_namespace(local_scope_string, AmlValue::Device(local_ctx.namespace_delta.clone())); + ctx.add_to_namespace(local_scope_string, AmlValue::Device(local_ctx.namespace_delta.clone()))?; Ok(AmlParseType { val: AmlValue::None, @@ -480,7 +475,7 @@ fn parse_def_op_region(data: &[u8], write: |x, y| () }, accessed_by: None - }); + })?; Ok(AmlParseType { val: AmlValue::None, @@ -525,7 +520,7 @@ fn parse_def_field(data: &[u8], let selector = FieldSelector::Region(name.val.get_as_string()?); - let field_list = parse_field_list(&data[3 + pkg_length_len + name.len .. 2 + pkg_length], ctx, selector, &mut flags)?; + parse_field_list(&data[3 + pkg_length_len + name.len .. 2 + pkg_length], ctx, selector, &mut flags)?; Ok(AmlParseType { val: AmlValue::None, @@ -574,8 +569,8 @@ fn parse_def_index_field(data: &[u8], data_selector: data_name.val.get_as_string()? }; - let field_list = parse_field_list( - &data[3 + pkg_length_len + idx_name.len + data_name.len .. 2 + pkg_length], ctx, selector, &mut flags)?; + parse_field_list(&data[3 + pkg_length_len + idx_name.len + data_name.len .. 2 + pkg_length], + ctx, selector, &mut flags)?; Ok(AmlParseType { val: AmlValue::None, @@ -642,7 +637,7 @@ fn parse_field_element(data: &[u8], flags: flags.clone(), offset: offset.clone(), length: field.val.length - }); + })?; *offset += field.val.length; field.len @@ -681,7 +676,7 @@ fn parse_named_field(data: &[u8], Ok(AmlParseTypeGeneric { val: NamedField { name, length }, - len: 4 + length_len + len: name_seg_len + length_len }) } @@ -796,7 +791,7 @@ fn parse_def_method(data: &[u8], serialized, sync_level, term_list: term_list.to_vec() - })); + }))?; Ok(AmlParseType { val: AmlValue::None, @@ -821,7 +816,7 @@ fn parse_def_mutex(data: &[u8], let sync_level = flags & 0x0F; let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); - ctx.add_to_namespace(local_scope_string, AmlValue::Mutex((sync_level, None))); + ctx.add_to_namespace(local_scope_string, AmlValue::Mutex((sync_level, None)))?; Ok(AmlParseType { val: AmlValue::None, @@ -858,7 +853,7 @@ fn parse_def_power_res(data: &[u8], system_level, resource_order, obj_list: local_ctx.namespace_delta.clone() - }); + })?; Ok(AmlParseType { val: AmlValue::None, @@ -897,7 +892,7 @@ fn parse_def_processor(data: &[u8], proc_id: proc_id, p_blk: if p_blk_len > 0 { Some(p_blk_addr) } else { None }, obj_list: local_ctx.namespace_delta.clone() - }); + })?; Ok(AmlParseType { val: AmlValue::None, @@ -925,7 +920,7 @@ fn parse_def_thermal_zone(data: &[u8], let mut local_ctx = AmlExecutionContext::new(local_scope_string.clone()); parse_object_list(&data[2 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_ctx)?; - ctx.add_to_namespace(local_scope_string, AmlValue::ThermalZone(local_ctx.namespace_delta.clone())); + ctx.add_to_namespace(local_scope_string, AmlValue::ThermalZone(local_ctx.namespace_delta.clone()))?; Ok(AmlParseType { val: AmlValue::None, diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index 0862e72..8e9e61b 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -1,9 +1,7 @@ use alloc::boxed::Box; use collections::string::String; use collections::vec::Vec; -use collections::btree_map::BTreeMap; -use core::str::FromStr; use core::fmt::{Debug, Formatter, Error}; use super::termlist::parse_term_list; diff --git a/src/acpi/aml/namespacemodifier.rs b/src/acpi/aml/namespacemodifier.rs index 7d08195..059a93c 100644 --- a/src/acpi/aml/namespacemodifier.rs +++ b/src/acpi/aml/namespacemodifier.rs @@ -1,11 +1,6 @@ -use alloc::boxed::Box; -use collections::string::String; -use collections::vec::Vec; -use collections::btree_map::BTreeMap; - use super::AmlError; -use super::parser::{AmlParseType, ParseResult, AmlParseTypeGeneric, AmlExecutionContext, ExecutionState}; -use super::namespace::{AmlValue, ObjectReference, FieldSelector, get_namespace_string}; +use super::parser::{AmlParseType, ParseResult, AmlExecutionContext, ExecutionState}; +use super::namespace::{AmlValue, ObjectReference, get_namespace_string}; use super::pkglength::parse_pkg_length; use super::namestring::parse_name_string; use super::termlist::parse_term_list; diff --git a/src/acpi/aml/namestring.rs b/src/acpi/aml/namestring.rs index 389e650..8464b6c 100644 --- a/src/acpi/aml/namestring.rs +++ b/src/acpi/aml/namestring.rs @@ -1,10 +1,9 @@ use collections::vec::Vec; use collections::string::String; -use collections::btree_map::BTreeMap; use super::AmlError; -use super::parser::{AmlParseType, ParseResult, AmlParseTypeGeneric, AmlExecutionContext, ExecutionState}; -use super::namespace::{AmlValue, ObjectReference, FieldSelector, get_namespace_string}; +use super::parser::{AmlParseType, ParseResult, AmlExecutionContext, ExecutionState}; +use super::namespace::AmlValue; use super::dataobj::{parse_arg_obj, parse_local_obj}; use super::type2opcode::parse_type6_opcode; diff --git a/src/acpi/aml/parser.rs b/src/acpi/aml/parser.rs index a762eba..758dd17 100644 --- a/src/acpi/aml/parser.rs +++ b/src/acpi/aml/parser.rs @@ -113,7 +113,7 @@ impl AmlExecutionContext { match name { AmlValue::None => (), AmlValue::ObjectReference(r) => match r { - ObjectReference::ArgObj(i) => (), + ObjectReference::ArgObj(_) => (), ObjectReference::LocalObj(i) => self.local_vars[i as usize] = value, _ => () }, diff --git a/src/acpi/aml/termlist.rs b/src/acpi/aml/termlist.rs index 9152f56..700fa00 100644 --- a/src/acpi/aml/termlist.rs +++ b/src/acpi/aml/termlist.rs @@ -1,11 +1,8 @@ -use alloc::boxed::Box; -use collections::string::String; use collections::vec::Vec; -use collections::btree_map::BTreeMap; use super::AmlError; -use super::parser::{ AmlParseType, ParseResult, AmlParseTypeGeneric, AmlExecutionContext, ExecutionState }; -use super::namespace::{AmlValue, ObjectReference, FieldSelector, get_namespace_string}; +use super::parser::{ AmlParseType, ParseResult, AmlExecutionContext, ExecutionState }; +use super::namespace::{AmlValue, get_namespace_string}; use super::namespacemodifier::parse_namespace_modifier; use super::namedobj::parse_named_obj; use super::dataobj::{parse_data_obj, parse_arg_obj, parse_local_obj}; diff --git a/src/acpi/aml/type1opcode.rs b/src/acpi/aml/type1opcode.rs index ee9d8cb..3493935 100644 --- a/src/acpi/aml/type1opcode.rs +++ b/src/acpi/aml/type1opcode.rs @@ -1,11 +1,6 @@ -use alloc::boxed::Box; -use collections::string::String; -use collections::vec::Vec; -use collections::btree_map::BTreeMap; - use super::AmlError; use super::parser::{AmlParseType, ParseResult, AmlExecutionContext, ExecutionState}; -use super::namespace::{AmlValue, ObjectReference}; +use super::namespace::AmlValue; use super::pkglength::parse_pkg_length; use super::termlist::{parse_term_arg, parse_term_list}; use super::namestring::{parse_name_string, parse_super_name}; @@ -248,7 +243,7 @@ fn parse_def_reset(data: &[u8], parser_opcode_extended!(data, 0x26); let object = parse_super_name(&data[2..], ctx)?; - let event = ctx.get(object.val.clone()).get_as_event()?; + ctx.get(object.val.clone()).get_as_event()?; ctx.modify(object.val.clone(), AmlValue::Event(0)); diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index 49ded05..00924de 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -1,7 +1,6 @@ use alloc::boxed::Box; use collections::string::String; use collections::vec::Vec; -use collections::btree_map::BTreeMap; use super::AmlError; use super::parser::{AmlParseType, ParseResult, AmlExecutionContext, ExecutionState}; @@ -153,7 +152,7 @@ pub fn parse_def_package(data: &[u8], if elements.len() > numelements { elements = elements[0 .. numelements].to_vec(); } else if numelements > elements.len() { - for i in 0..numelements - elements.len() { + for _ in 0..numelements - elements.len() { elements.push(AmlValue::Uninitialized); } } @@ -187,7 +186,7 @@ pub fn parse_def_var_package(data: &[u8], if elements.len() > numelements { elements = elements[0 .. numelements].to_vec(); } else if numelements > elements.len() { - for i in 0..numelements - elements.len() { + for _ in 0..numelements - elements.len() { elements.push(AmlValue::Uninitialized); } } @@ -365,12 +364,6 @@ fn parse_def_acquire(data: &[u8], } } } - - Ok(AmlParseType { - val: AmlValue::Uninitialized, - len: 4 + obj.len - }) - // This should never run } fn parse_def_increment(data: &[u8], @@ -1056,11 +1049,6 @@ fn parse_def_wait(data: &[u8], } } } - - Ok(AmlParseType { - val: AmlValue::Uninitialized, - len: 2 + obj.len + timeout_obj.len - }) } fn parse_def_cond_ref_of(data: &[u8], @@ -1353,11 +1341,11 @@ fn parse_def_match(data: &[u8], match second_operation { MatchOpcode::MTR => (), - MatchOpcode::MEQ => if val != i { continue }, - MatchOpcode::MLE => if val > i { continue }, - MatchOpcode::MLT => if val >= i { continue }, - MatchOpcode::MGE => if val < i { continue }, - MatchOpcode::MGT => if val <= i { continue } + MatchOpcode::MEQ => if val != j { continue }, + MatchOpcode::MLE => if val > j { continue }, + MatchOpcode::MLT => if val >= j { continue }, + MatchOpcode::MGE => if val < j { continue }, + MatchOpcode::MGT => if val <= j { continue } } return Ok(AmlParseType { @@ -1384,11 +1372,11 @@ fn parse_def_match(data: &[u8], match second_operation { MatchOpcode::MTR => (), - MatchOpcode::MEQ => if val != i { continue }, - MatchOpcode::MLE => if val > i { continue }, - MatchOpcode::MLT => if val >= i { continue }, - MatchOpcode::MGE => if val < i { continue }, - MatchOpcode::MGT => if val <= i { continue } + MatchOpcode::MEQ => if val != j { continue }, + MatchOpcode::MLE => if val > j { continue }, + MatchOpcode::MLT => if val >= j { continue }, + MatchOpcode::MGE => if val < j { continue }, + MatchOpcode::MGT => if val <= j { continue } } return Ok(AmlParseType { @@ -1416,11 +1404,11 @@ fn parse_def_match(data: &[u8], match second_operation { MatchOpcode::MTR => (), - MatchOpcode::MEQ => if val != i { continue }, - MatchOpcode::MLE => if val > i { continue }, - MatchOpcode::MLT => if val >= i { continue }, - MatchOpcode::MGE => if val < i { continue }, - MatchOpcode::MGT => if val <= i { continue } + MatchOpcode::MEQ => if val != j { continue }, + MatchOpcode::MLE => if val > j { continue }, + MatchOpcode::MLT => if val >= j { continue }, + MatchOpcode::MGE => if val < j { continue }, + MatchOpcode::MGT => if val <= j { continue } } return Ok(AmlParseType { diff --git a/src/acpi/mod.rs b/src/acpi/mod.rs index 39e2799..6adae4c 100644 --- a/src/acpi/mod.rs +++ b/src/acpi/mod.rs @@ -5,11 +5,10 @@ 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}; -use spin::{Mutex, RwLock}; +use spin::RwLock; use device::local_apic::LOCAL_APIC; use interrupt; diff --git a/src/device/hpet.rs b/src/device/hpet.rs index 9307fc5..3490dee 100644 --- a/src/device/hpet.rs +++ b/src/device/hpet.rs @@ -1,8 +1,3 @@ -use core::intrinsics::{volatile_load, volatile_store}; - -use memory::Frame; -use paging::{entry, ActivePageTable, PhysicalAddress, Page, VirtualAddress}; - use acpi::hpet::Hpet; static LEG_RT_CNF: u64 = 2; @@ -14,8 +9,8 @@ static TN_INT_ENB_CNF: u64 = 0x04; static CAPABILITY_OFFSET: usize = 0x00; static GENERAL_CONFIG_OFFSET: usize = 0x10; -static GENERAL_INTERRUPT_OFFSET: usize = 0x20; -static MAIN_COUNTER_OFFSET: usize = 0xF0; +// static GENERAL_INTERRUPT_OFFSET: usize = 0x20; +// static MAIN_COUNTER_OFFSET: usize = 0xF0; static T0_CONFIG_CAPABILITY_OFFSET: usize = 0x100; static T0_COMPARATOR_OFFSET: usize = 0x108; diff --git a/src/device/mod.rs b/src/device/mod.rs index 18700d0..b7b9cea 100644 --- a/src/device/mod.rs +++ b/src/device/mod.rs @@ -1,6 +1,5 @@ use paging::ActivePageTable; use acpi::ACPI_TABLE; -use syscall::io::{Pio, Io}; pub mod cpu; pub mod local_apic; diff --git a/src/start.rs b/src/start.rs index d7b3663..faac4b4 100644 --- a/src/start.rs +++ b/src/start.rs @@ -15,8 +15,6 @@ use memory; use paging::{self, entry, Page, VirtualAddress}; use paging::mapper::MapperFlushAll; -use stop; - /// Test of zero values in BSS. static BSS_TEST_ZERO: usize = 0; /// Test of non-zero values in data. From 82e814469cc2d57203bf2c82e5b8ff13a7faf7de Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Sat, 22 Jul 2017 13:52:48 +0100 Subject: [PATCH 075/113] Shutdown on fatal error --- src/acpi/mod.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/acpi/mod.rs b/src/acpi/mod.rs index 6adae4c..0961d3c 100644 --- a/src/acpi/mod.rs +++ b/src/acpi/mod.rs @@ -10,6 +10,8 @@ use syscall::io::{Io, Pio}; use spin::RwLock; +use stop::kstop; + use device::local_apic::LOCAL_APIC; use interrupt; use memory::{allocate_frames, Frame}; @@ -216,8 +218,14 @@ fn parse_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) { Err(AmlError::AmlInvalidOpCode) => println!(": Invalid opcode"), Err(AmlError::AmlValueError) => println!(": Type constraints or value bounds not met"), Err(AmlError::AmlDeferredLoad) => println!(": Deferred load reached top level"), - Err(AmlError::AmlFatalError(_, _, _)) => println!(": Fatal error occurred"), - Err(AmlError::AmlHardFatal) => println!(": Fatal error occurred") + Err(AmlError::AmlFatalError(_, _, _)) => { + println!(": Fatal error occurred"); + unsafe { kstop(); } + }, + Err(AmlError::AmlHardFatal) => { + println!(": Fatal error occurred"); + unsafe { kstop(); } + } }; } else { println!(": Unknown"); From 42881821069bb3795692e63b1b4cc371783451d3 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Sun, 23 Jul 2017 10:34:50 +0100 Subject: [PATCH 076/113] Implemented Load --- src/acpi/aml/mod.rs | 7 ++++--- src/acpi/aml/namespace.rs | 2 +- src/acpi/aml/type1opcode.rs | 28 +++++++++++++++++++--------- src/acpi/mod.rs | 2 +- src/acpi/sdt.rs | 6 +++--- 5 files changed, 28 insertions(+), 17 deletions(-) diff --git a/src/acpi/aml/mod.rs b/src/acpi/aml/mod.rs index d161031..f943b54 100644 --- a/src/acpi/aml/mod.rs +++ b/src/acpi/aml/mod.rs @@ -2,6 +2,7 @@ //! Code to parse and execute AML tables use collections::string::String; +use collections::vec::Vec; use core::str::FromStr; use super::sdt::Sdt; @@ -34,16 +35,16 @@ pub enum AmlError { AmlHardFatal } -pub fn parse_aml_table(sdt: &'static Sdt) -> Result<(), AmlError> { +pub fn parse_aml_table(sdt: &Sdt) -> Result, AmlError> { let data = sdt.data(); let mut ctx = AmlExecutionContext::new(String::from_str("\\").unwrap()); parse_term_list(data, &mut ctx)?; - Ok(()) + Ok(ctx.namespace_delta) } -pub fn is_aml_table(sdt: &'static Sdt) -> bool { +pub fn is_aml_table(sdt: &Sdt) -> bool { if &sdt.signature == b"DSDT" || &sdt.signature == b"SSDT" { true } else { diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index 8e9e61b..641ddb5 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -63,7 +63,7 @@ pub enum AmlValue { index: Box, length: Box }, - DDBHandle(u32), // Index into the XSDT + DDBHandle(Vec), DebugObject, Device(Vec), Event(u64), diff --git a/src/acpi/aml/type1opcode.rs b/src/acpi/aml/type1opcode.rs index 3493935..eb57bc0 100644 --- a/src/acpi/aml/type1opcode.rs +++ b/src/acpi/aml/type1opcode.rs @@ -1,12 +1,15 @@ use super::AmlError; use super::parser::{AmlParseType, ParseResult, AmlExecutionContext, ExecutionState}; -use super::namespace::AmlValue; +use super::namespace::{AmlValue, ObjectReference}; use super::pkglength::parse_pkg_length; use super::termlist::{parse_term_arg, parse_term_list}; use super::namestring::{parse_name_string, parse_super_name}; use time::monotonic; +use acpi::Sdt; +use super::{parse_aml_table, is_aml_table}; + pub fn parse_type1_opcode(data: &[u8], ctx: &mut AmlExecutionContext) -> ParseResult { match ctx.state { @@ -143,18 +146,25 @@ fn parse_def_load(data: &[u8], }) } - // TODO: Load in the table pointed to by `name` - // TODO: Set DDB_Handle to the handle returned by loading in the table - // TODO: Run the AML parser on the table, in a secondary namespace parser_opcode_extended!(data, 0x20); let name = parse_name_string(&data[2..], ctx)?; let ddb_handle_object = parse_super_name(&data[2 + name.len..], ctx)?; - - Ok(AmlParseType { - val: AmlValue::None, - len: 2 + name.len + ddb_handle_object.len - }) + + let tbl = ctx.get(AmlValue::ObjectReference(ObjectReference::NamedObj(name.val.get_as_string()?))).get_as_buffer()?; + let sdt = unsafe { &*(tbl.as_ptr() as *const Sdt) }; + + if is_aml_table(sdt) { + let delta = parse_aml_table(sdt)?; + ctx.modify(ddb_handle_object.val, AmlValue::DDBHandle(delta)); + + Ok(AmlParseType { + val: AmlValue::None, + len: 2 + name.len + ddb_handle_object.len + }) + } else { + Err(AmlError::AmlValueError) + } } fn parse_def_notify(data: &[u8], diff --git a/src/acpi/mod.rs b/src/acpi/mod.rs index 0961d3c..ac19b5c 100644 --- a/src/acpi/mod.rs +++ b/src/acpi/mod.rs @@ -213,7 +213,7 @@ fn parse_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) { *hpet_t = Some(hpet); } else if is_aml_table(sdt) { match parse_aml_table(sdt) { - Ok(()) => println!(": Parsed"), + Ok(_) => println!(": Parsed"), Err(AmlError::AmlParseError(e)) => println!(": {}", e), Err(AmlError::AmlInvalidOpCode) => println!(": Invalid opcode"), Err(AmlError::AmlValueError) => println!(": Type constraints or value bounds not met"), diff --git a/src/acpi/sdt.rs b/src/acpi/sdt.rs index 62d55cf..1a7a4fa 100644 --- a/src/acpi/sdt.rs +++ b/src/acpi/sdt.rs @@ -17,12 +17,12 @@ pub struct Sdt { impl Sdt { /// Get the address of this tables data - pub fn data_address(&'static self) -> usize { + pub fn data_address(&self) -> usize { self as *const _ as usize + mem::size_of::() } /// Get the length of this tables data - pub fn data_len(&'static self) -> usize { + pub fn data_len(&self) -> usize { let total_size = self.length as usize; let header_size = mem::size_of::(); if total_size >= header_size { @@ -32,7 +32,7 @@ impl Sdt { } } - pub fn data(&'static self) -> &[u8] { + pub fn data(&self) -> &[u8] { unsafe { slice::from_raw_parts(self.data_address() as *const u8, self.data_len()) } } } From c79eb0eeabd434b82bbf3084babe393625910e45 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Sun, 23 Jul 2017 13:42:30 +0100 Subject: [PATCH 077/113] Implemented table API in full --- src/acpi/aml/mod.rs | 6 +++++- src/acpi/aml/namespace.rs | 7 +++++++ src/acpi/aml/type1opcode.rs | 11 +++++++++-- src/acpi/aml/type2opcode.rs | 33 +++++++++++++++++++++++++++++---- src/acpi/mod.rs | 37 ++++++++++++++++++++++++++++--------- src/acpi/rsdt.rs | 10 +++++++--- src/acpi/rxsdt.rs | 28 ++++++++++++++++++++++++++++ src/acpi/sdt.rs | 4 ++++ src/acpi/xsdt.rs | 10 +++++++--- src/lib.rs | 1 + 10 files changed, 125 insertions(+), 22 deletions(-) create mode 100644 src/acpi/rxsdt.rs diff --git a/src/acpi/aml/mod.rs b/src/acpi/aml/mod.rs index f943b54..9ec105c 100644 --- a/src/acpi/aml/mod.rs +++ b/src/acpi/aml/mod.rs @@ -36,8 +36,12 @@ pub enum AmlError { } pub fn parse_aml_table(sdt: &Sdt) -> Result, AmlError> { + parse_aml_with_scope(sdt, String::from_str("\\").unwrap()) +} + +pub fn parse_aml_with_scope(sdt: &Sdt, scope: String) -> Result, 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)?; diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index 641ddb5..9c7f564 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -113,6 +113,13 @@ impl AmlValue { _ => Err(AmlError::AmlValueError) } } + + pub fn get_as_ddb_handle(&self) -> Result, AmlError> { + match *self { + AmlValue::DDBHandle(ref v) => Ok(v.clone()), + _ => Err(AmlError::AmlValueError) + } + } pub fn get_as_string(&self) -> Result { match *self { diff --git a/src/acpi/aml/type1opcode.rs b/src/acpi/aml/type1opcode.rs index eb57bc0..638de9e 100644 --- a/src/acpi/aml/type1opcode.rs +++ b/src/acpi/aml/type1opcode.rs @@ -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 diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index 00924de..e445119 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -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 }) } diff --git a/src/acpi/mod.rs b/src/acpi/mod.rs index ac19b5c..cdd7e0a 100644 --- a/src/acpi/mod.rs +++ b/src/acpi/mod.rs @@ -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 = 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>>, pub fadt: RwLock>, pub namespace: RwLock>>, pub hpet: RwLock>, @@ -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), diff --git a/src/acpi/rsdt.rs b/src/acpi/rsdt.rs index fa391c0..7877a06 100644 --- a/src/acpi/rsdt.rs +++ b/src/acpi/rsdt.rs @@ -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> { + Box::new(RsdtIter { sdt: self.0, i: 0 - } + }) } } diff --git a/src/acpi/rxsdt.rs b/src/acpi/rxsdt.rs new file mode 100644 index 0000000..8c7278b --- /dev/null +++ b/src/acpi/rxsdt.rs @@ -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>; + + 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; + } +} diff --git a/src/acpi/sdt.rs b/src/acpi/sdt.rs index 1a7a4fa..67dee89 100644 --- a/src/acpi/sdt.rs +++ b/src/acpi/sdt.rs @@ -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 + } } diff --git a/src/acpi/xsdt.rs b/src/acpi/xsdt.rs index 5ec6036..7339ce0 100644 --- a/src/acpi/xsdt.rs +++ b/src/acpi/xsdt.rs @@ -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> { + Box::new(XsdtIter { sdt: self.0, i: 0 - } + }) } } diff --git a/src/lib.rs b/src/lib.rs index 533b9e4..4dc0c3f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,6 +19,7 @@ #![feature(never_type)] #![feature(thread_local)] #![feature(unique)] +#![feature(conservative_impl_trait)] #![no_std] extern crate alloc_kernel as allocator; From 59b176c24ed2ed18e7dcc2a9d27d4ca4edd4eaf1 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Mon, 24 Jul 2017 09:09:07 +0100 Subject: [PATCH 078/113] Implemented path parent character "^" when calculating scope paths --- src/acpi/aml/namespace.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index 9c7f564..8c18f1a 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -1,5 +1,6 @@ use alloc::boxed::Box; use collections::string::String; +use collections::string::ToString; use collections::vec::Vec; use core::fmt::{Debug, Formatter, Error}; @@ -174,7 +175,7 @@ impl Method { pub fn get_namespace_string(current: String, modifier_v: AmlValue) -> String { // TODO: Type error if modifier not string - let modifier = if let Ok(s) = modifier_v.get_as_string() { + let mut modifier = if let Ok(s) = modifier_v.get_as_string() { s } else { return current; @@ -192,12 +193,15 @@ pub fn get_namespace_string(current: String, modifier_v: AmlValue) -> String { return modifier; } - if modifier.starts_with("^") { - // TODO - } - let mut namespace = current.clone(); + if modifier.starts_with("^") { + while modifier.starts_with("^") { + modifier = modifier[1..].to_string(); + while namespace.pop() != Some('.') { } + } + } + if !namespace.ends_with("\\") { namespace.push('.'); } From a70b26555ede9ded73ec399a9cd5e612e9fc806b Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Mon, 24 Jul 2017 09:21:53 +0100 Subject: [PATCH 079/113] Error handling in namespace path assembly --- src/acpi/aml/namedobj.rs | 32 +++++++++++++++---------------- src/acpi/aml/namespace.rs | 32 ++++++++++++++++++++----------- src/acpi/aml/namespacemodifier.rs | 8 ++++---- src/acpi/aml/termlist.rs | 2 +- 4 files changed, 42 insertions(+), 32 deletions(-) diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index e483302..b836ea6 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -180,7 +180,7 @@ fn parse_def_create_bit_field(data: &[u8], let bit_index = parse_term_arg(&data[2 + source_buf.len..], ctx)?; let name = parse_name_string(&data[1 + source_buf.len + bit_index.len..], ctx)?; - let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val)?; ctx.add_to_namespace(local_scope_string, AmlValue::BufferField { source_buf: Box::new(source_buf.val), @@ -210,7 +210,7 @@ fn parse_def_create_byte_field(data: &[u8], let bit_index = parse_term_arg(&data[2 + source_buf.len..], ctx)?; let name = parse_name_string(&data[1 + source_buf.len + bit_index.len..], ctx)?; - let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val)?; ctx.add_to_namespace(local_scope_string, AmlValue::BufferField { source_buf: Box::new(source_buf.val), @@ -240,7 +240,7 @@ fn parse_def_create_word_field(data: &[u8], let bit_index = parse_term_arg(&data[2 + source_buf.len..], ctx)?; let name = parse_name_string(&data[1 + source_buf.len + bit_index.len..], ctx)?; - let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val)?; ctx.add_to_namespace(local_scope_string, AmlValue::BufferField { source_buf: Box::new(source_buf.val), @@ -270,7 +270,7 @@ fn parse_def_create_dword_field(data: &[u8], let bit_index = parse_term_arg(&data[2 + source_buf.len..], ctx)?; let name = parse_name_string(&data[1 + source_buf.len + bit_index.len..], ctx)?; - let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val)?; ctx.add_to_namespace(local_scope_string, AmlValue::BufferField { source_buf: Box::new(source_buf.val), @@ -300,7 +300,7 @@ fn parse_def_create_qword_field(data: &[u8], let bit_index = parse_term_arg(&data[2 + source_buf.len..], ctx)?; let name = parse_name_string(&data[1 + source_buf.len + bit_index.len..], ctx)?; - let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val)?; ctx.add_to_namespace(local_scope_string, AmlValue::BufferField { source_buf: Box::new(source_buf.val), @@ -331,7 +331,7 @@ fn parse_def_create_field(data: &[u8], let num_bits = parse_term_arg(&data[2 + source_buf.len + bit_index.len..], ctx)?; let name = parse_name_string(&data[2 + source_buf.len + bit_index.len + num_bits.len..], ctx)?; - let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val)?; ctx.add_to_namespace(local_scope_string, AmlValue::BufferField { source_buf: Box::new(source_buf.val), @@ -363,7 +363,7 @@ fn parse_def_data_region(data: &[u8], let oem_id = parse_term_arg(&data[2 + name.len + signature.len..], ctx)?; let oem_table_id = parse_term_arg(&data[2 + name.len + signature.len + oem_id.len..], ctx)?; - let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val)?; ctx.add_to_namespace(local_scope_string, AmlValue::OperationRegion { region: RegionSpace::SystemMemory, @@ -396,7 +396,7 @@ fn parse_def_event(data: &[u8], let name = parse_name_string(&data[2..], ctx)?; - let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val)?; ctx.add_to_namespace(local_scope_string, AmlValue::Event(0))?; Ok(AmlParseType { @@ -421,7 +421,7 @@ fn parse_def_device(data: &[u8], let (pkg_length, pkg_length_len) = parse_pkg_length(&data[2..])?; let name = parse_name_string(&data[2 + pkg_length_len .. 2 + pkg_length], ctx)?; - let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val)?; let mut local_ctx = AmlExecutionContext::new(local_scope_string.clone()); parse_object_list(&data[2 + pkg_length_len + name.len .. 2 + pkg_length], &mut local_ctx)?; @@ -465,7 +465,7 @@ fn parse_def_op_region(data: &[u8], let offset = parse_term_arg(&data[3 + name.len..], ctx)?; let len = parse_term_arg(&data[3 + name.len + offset.len..], ctx)?; - let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val)?; ctx.add_to_namespace(local_scope_string, AmlValue::OperationRegion { region: region, offset: Box::new(offset.val), @@ -629,7 +629,7 @@ fn parse_field_element(data: &[u8], } let length = if let Ok(field) = parse_named_field(data, ctx) { - let local_scope_string = get_namespace_string(ctx.scope.clone(), AmlValue::String(field.val.name.clone())); + let local_scope_string = get_namespace_string(ctx.scope.clone(), AmlValue::String(field.val.name.clone()))?; ctx.add_to_namespace(local_scope_string, AmlValue::FieldUnit { selector: selector.clone(), @@ -785,7 +785,7 @@ fn parse_def_method(data: &[u8], let term_list = &data[2 + pkg_len_len + name.len .. 1 + pkg_len]; - let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val)?; ctx.add_to_namespace(local_scope_string, AmlValue::Method(Method { arg_count, serialized, @@ -815,7 +815,7 @@ fn parse_def_mutex(data: &[u8], let flags = data[2 + name.len]; let sync_level = flags & 0x0F; - let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val)?; ctx.add_to_namespace(local_scope_string, AmlValue::Mutex((sync_level, None)))?; Ok(AmlParseType { @@ -840,7 +840,7 @@ fn parse_def_power_res(data: &[u8], let (pkg_len, pkg_len_len) = parse_pkg_length(&data[2..])?; let name = parse_name_string(&data[2 + pkg_len_len..], ctx)?; - let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val)?; let system_level = data[2 + pkg_len_len + name.len]; let resource_order: u16 = (data[3 + pkg_len_len + name.len] as u16) + @@ -876,7 +876,7 @@ fn parse_def_processor(data: &[u8], let (pkg_len, pkg_len_len) = parse_pkg_length(&data[2..])?; let name = parse_name_string(&data[2 + pkg_len_len..], ctx)?; - let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val)?; let proc_id = data[2 + pkg_len_len + name.len]; let p_blk_addr: u32 = (data[3 + pkg_len_len + name.len] as u32) + @@ -915,7 +915,7 @@ fn parse_def_thermal_zone(data: &[u8], let (pkg_len, pkg_len_len) = parse_pkg_length(&data[2..])?; let name = parse_name_string(&data[2 + pkg_len_len .. 2 + pkg_len], ctx)?; - let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val)?; let mut local_ctx = AmlExecutionContext::new(local_scope_string.clone()); parse_object_list(&data[2 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_ctx)?; diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index 8c18f1a..4abeeda 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -173,24 +173,20 @@ impl Method { } } -pub fn get_namespace_string(current: String, modifier_v: AmlValue) -> String { +pub fn get_namespace_string(current: String, modifier_v: AmlValue) -> Result { // TODO: Type error if modifier not string - let mut modifier = if let Ok(s) = modifier_v.get_as_string() { - s - } else { - return current; - }; + let mut modifier = modifier_v.get_as_string()?; if current.len() == 0 { - return modifier; + return Ok(modifier); } if modifier.len() == 0 { - return current; + return Ok(current); } if modifier.starts_with("\\") { - return modifier; + return Ok(modifier); } let mut namespace = current.clone(); @@ -198,7 +194,21 @@ pub fn get_namespace_string(current: String, modifier_v: AmlValue) -> String { if modifier.starts_with("^") { while modifier.starts_with("^") { modifier = modifier[1..].to_string(); - while namespace.pop() != Some('.') { } + + if namespace.ends_with("\\") { + return Err(AmlError::AmlValueError); + } + + loop { + if namespace.ends_with(".") { + namespace.pop(); + break; + } + + if namespace.pop() == None { + return Err(AmlError::AmlValueError); + } + } } } @@ -206,5 +216,5 @@ pub fn get_namespace_string(current: String, modifier_v: AmlValue) -> String { namespace.push('.'); } - namespace + &modifier + Ok(namespace + &modifier) } diff --git a/src/acpi/aml/namespacemodifier.rs b/src/acpi/aml/namespacemodifier.rs index 059a93c..57d1b1a 100644 --- a/src/acpi/aml/namespacemodifier.rs +++ b/src/acpi/aml/namespacemodifier.rs @@ -41,8 +41,8 @@ fn parse_alias_op(data: &[u8], let source_name = parse_name_string(&data[1..], ctx)?; let alias_name = parse_name_string(&data[1 + source_name.len..], ctx)?; - let local_scope_string = get_namespace_string(ctx.scope.clone(), source_name.val); - let local_alias_string = get_namespace_string(ctx.scope.clone(), alias_name.val); + let local_scope_string = get_namespace_string(ctx.scope.clone(), source_name.val)?; + let local_alias_string = get_namespace_string(ctx.scope.clone(), alias_name.val)?; ctx.add_to_namespace(local_scope_string, AmlValue::ObjectReference(ObjectReference::NamedObj(local_alias_string)))?; @@ -67,7 +67,7 @@ fn parse_name_op(data: &[u8], let name = parse_name_string(&data[1..], ctx)?; let data_ref_obj = parse_data_ref_obj(&data[1 + name.len..], ctx)?; - let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val)?; ctx.add_to_namespace(local_scope_string, data_ref_obj.val)?; @@ -92,7 +92,7 @@ fn parse_scope_op(data: &[u8], let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; let name = parse_name_string(&data[1 + pkg_length_len..], ctx)?; - let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val.clone()); + let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val.clone())?; let containing_scope_string = ctx.scope.clone(); ctx.scope = local_scope_string; diff --git a/src/acpi/aml/termlist.rs b/src/acpi/aml/termlist.rs index 700fa00..8087c44 100644 --- a/src/acpi/aml/termlist.rs +++ b/src/acpi/aml/termlist.rs @@ -147,7 +147,7 @@ pub fn parse_method_invocation(data: &[u8], } Ok(AmlParseType { - val: method.execute(get_namespace_string(ctx.scope.clone(), name.val), params), + val: method.execute(get_namespace_string(ctx.scope.clone(), name.val)?, params), len: current_offset }) } From c6ecf105ad10fd7e2ec905ecb38519cd775a474f Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Mon, 24 Jul 2017 09:48:27 +0100 Subject: [PATCH 080/113] Converted Integer to Buffer --- src/acpi/aml/namespace.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index 4abeeda..620ea71 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -132,6 +132,21 @@ impl AmlValue { pub fn get_as_buffer(&self) -> Result, AmlError> { match *self { AmlValue::Buffer(ref b) => Ok(b.clone()), + AmlValue::Integer(ref i) => { + let mut v: Vec = vec!(); + let mut i = i.clone(); + + while i != 0 { + v.push((i & 0xFF) as u8); + i >>= 8; + } + + while v.len() < 8 { + v.push(0); + } + + Ok(v) + }, _ => Err(AmlError::AmlValueError) } } @@ -174,7 +189,6 @@ impl Method { } pub fn get_namespace_string(current: String, modifier_v: AmlValue) -> Result { - // TODO: Type error if modifier not string let mut modifier = modifier_v.get_as_string()?; if current.len() == 0 { From 82762863df023d6f45b39ec888d69f3d567a20f8 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Mon, 24 Jul 2017 09:56:54 +0100 Subject: [PATCH 081/113] Converted string to buffer --- src/acpi/aml/namespace.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index 620ea71..935c565 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -147,6 +147,9 @@ impl AmlValue { Ok(v) }, + AmlValue::String(ref s) => { + Ok(s.clone().into_bytes()) + }, _ => Err(AmlError::AmlValueError) } } From 9408e71dcd7c794f27faed71bfeb8b879edd731a Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Mon, 24 Jul 2017 16:02:19 +0100 Subject: [PATCH 082/113] Converted BufferField into Buffer --- src/acpi/aml/namespace.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index 935c565..2fa363a 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -150,6 +150,17 @@ impl AmlValue { AmlValue::String(ref s) => { Ok(s.clone().into_bytes()) }, + AmlValue::BufferField { ref source_buf, ref index, ref length } => { + let buf = source_buf.get_as_buffer()?; + let idx = index.get_as_integer()? as usize; + let len = length.get_as_integer()? as usize; + + if idx + len > buf.len() { + return Err(AmlError::AmlValueError); + } + + Ok(buf[idx .. idx + len].to_vec()) + }, _ => Err(AmlError::AmlValueError) } } From e7edaceec0de23171a78bc02edc32ab0457ea9b2 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Mon, 24 Jul 2017 16:15:18 +0100 Subject: [PATCH 083/113] All conversions to BufferField, dependent on the conversion to Buffer --- src/acpi/aml/namedobj.rs | 27 ++++++++++++++------------- src/acpi/aml/namespace.rs | 39 ++++++++++++++++++++++++++++++--------- 2 files changed, 44 insertions(+), 22 deletions(-) diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index b836ea6..c92e345 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -3,7 +3,8 @@ use collections::string::String; use super::AmlError; use super::parser::{ AmlParseType, ParseResult, AmlParseTypeGeneric, AmlExecutionContext, ExecutionState }; -use super::namespace::{ AmlValue, ObjectReference, FieldSelector, Method, get_namespace_string, Accessor }; +use super::namespace::{AmlValue, ObjectReference, FieldSelector, Method, get_namespace_string, + Accessor, BufferField}; use super::namestring::{parse_name_string, parse_name_seg}; use super::termlist::{parse_term_arg, parse_object_list}; use super::pkglength::parse_pkg_length; @@ -182,11 +183,11 @@ fn parse_def_create_bit_field(data: &[u8], let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val)?; - ctx.add_to_namespace(local_scope_string, AmlValue::BufferField { + ctx.add_to_namespace(local_scope_string, AmlValue::BufferField(BufferField { source_buf: Box::new(source_buf.val), index: Box::new(bit_index.val), length: Box::new(AmlValue::IntegerConstant(1)) - })?; + }))?; Ok(AmlParseType { val: AmlValue::None, @@ -212,11 +213,11 @@ fn parse_def_create_byte_field(data: &[u8], let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val)?; - ctx.add_to_namespace(local_scope_string, AmlValue::BufferField { + ctx.add_to_namespace(local_scope_string, AmlValue::BufferField(BufferField { source_buf: Box::new(source_buf.val), index: Box::new(bit_index.val), length: Box::new(AmlValue::IntegerConstant(8)) - })?; + }))?; Ok(AmlParseType { val: AmlValue::None, @@ -242,11 +243,11 @@ fn parse_def_create_word_field(data: &[u8], let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val)?; - ctx.add_to_namespace(local_scope_string, AmlValue::BufferField { + ctx.add_to_namespace(local_scope_string, AmlValue::BufferField(BufferField { source_buf: Box::new(source_buf.val), index: Box::new(bit_index.val), length: Box::new(AmlValue::IntegerConstant(16)) - })?; + }))?; Ok(AmlParseType { val: AmlValue::None, @@ -272,11 +273,11 @@ fn parse_def_create_dword_field(data: &[u8], let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val)?; - ctx.add_to_namespace(local_scope_string, AmlValue::BufferField { + ctx.add_to_namespace(local_scope_string, AmlValue::BufferField(BufferField { source_buf: Box::new(source_buf.val), index: Box::new(bit_index.val), length: Box::new(AmlValue::IntegerConstant(32)) - }); + })); Ok(AmlParseType { val: AmlValue::None, @@ -302,11 +303,11 @@ fn parse_def_create_qword_field(data: &[u8], let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val)?; - ctx.add_to_namespace(local_scope_string, AmlValue::BufferField { + ctx.add_to_namespace(local_scope_string, AmlValue::BufferField(BufferField { source_buf: Box::new(source_buf.val), index: Box::new(bit_index.val), length: Box::new(AmlValue::IntegerConstant(64)) - })?; + }))?; Ok(AmlParseType { val: AmlValue::None, @@ -333,11 +334,11 @@ fn parse_def_create_field(data: &[u8], let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val)?; - ctx.add_to_namespace(local_scope_string, AmlValue::BufferField { + ctx.add_to_namespace(local_scope_string, AmlValue::BufferField(BufferField { source_buf: Box::new(source_buf.val), index: Box::new(bit_index.val), length: Box::new(num_bits.val) - })?; + }))?; Ok(AmlParseType { val: AmlValue::None, diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index 2fa363a..ba9ebf4 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -40,6 +40,13 @@ pub struct Method { pub term_list: Vec } +#[derive(Clone)] +pub struct BufferField { + pub source_buf: Box, + pub index: Box, + pub length: Box +} + pub struct Accessor { pub read: fn(usize) -> u64, pub write: fn(usize, u64) @@ -59,11 +66,7 @@ pub enum AmlValue { None, Uninitialized, Buffer(Vec), - BufferField { - source_buf: Box, - index: Box, - length: Box - }, + BufferField(BufferField), DDBHandle(Vec), DebugObject, Device(Vec), @@ -129,6 +132,24 @@ impl AmlValue { } } + pub fn get_as_buffer_field(&self) -> Result { + match *self { + AmlValue::BufferField(ref b) => Ok(b.clone()), + _ => { + let raw_buf = self.get_as_buffer()?; + let buf = Box::new(AmlValue::Buffer(raw_buf.clone())); + let idx = Box::new(AmlValue::IntegerConstant(0)); + let len = Box::new(AmlValue::Integer(raw_buf.len() as u64)); + + Ok(BufferField { + source_buf: buf, + index: idx, + length: len + }) + } + } + } + pub fn get_as_buffer(&self) -> Result, AmlError> { match *self { AmlValue::Buffer(ref b) => Ok(b.clone()), @@ -150,10 +171,10 @@ impl AmlValue { AmlValue::String(ref s) => { Ok(s.clone().into_bytes()) }, - AmlValue::BufferField { ref source_buf, ref index, ref length } => { - let buf = source_buf.get_as_buffer()?; - let idx = index.get_as_integer()? as usize; - let len = length.get_as_integer()? as usize; + AmlValue::BufferField(ref b) => { + let buf = b.source_buf.get_as_buffer()?; + let idx = b.index.get_as_integer()? as usize; + let len = b.length.get_as_integer()? as usize; if idx + len > buf.len() { return Err(AmlError::AmlValueError); From fdcacd7d18aa8cafac4abdab8f15e6a002296921 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Mon, 24 Jul 2017 17:27:01 +0100 Subject: [PATCH 084/113] Implemented numerous "simple" type conversions --- src/acpi/aml/namedobj.rs | 6 +- src/acpi/aml/namespace.rs | 118 ++++++++++++++++++++++---------------- 2 files changed, 71 insertions(+), 53 deletions(-) diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index c92e345..7ca72c2 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -4,7 +4,7 @@ use collections::string::String; use super::AmlError; use super::parser::{ AmlParseType, ParseResult, AmlParseTypeGeneric, AmlExecutionContext, ExecutionState }; use super::namespace::{AmlValue, ObjectReference, FieldSelector, Method, get_namespace_string, - Accessor, BufferField}; + Accessor, BufferField, FieldUnit}; use super::namestring::{parse_name_string, parse_name_seg}; use super::termlist::{parse_term_arg, parse_object_list}; use super::pkglength::parse_pkg_length; @@ -632,13 +632,13 @@ fn parse_field_element(data: &[u8], let length = if let Ok(field) = parse_named_field(data, ctx) { let local_scope_string = get_namespace_string(ctx.scope.clone(), AmlValue::String(field.val.name.clone()))?; - ctx.add_to_namespace(local_scope_string, AmlValue::FieldUnit { + ctx.add_to_namespace(local_scope_string, AmlValue::FieldUnit(FieldUnit { selector: selector.clone(), connection: Box::new(connection.clone()), flags: flags.clone(), offset: offset.clone(), length: field.val.length - })?; + }))?; *offset += field.val.length; field.len diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index ba9ebf4..a8b3336 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -47,6 +47,15 @@ pub struct BufferField { pub length: Box } +#[derive(Clone)] +pub struct FieldUnit { + pub selector: FieldSelector, + pub connection: Box, + pub flags: FieldFlags, + pub offset: usize, + pub length: usize +} + pub struct Accessor { pub read: fn(usize) -> u64, pub write: fn(usize, u64) @@ -71,13 +80,7 @@ pub enum AmlValue { DebugObject, Device(Vec), Event(u64), - FieldUnit { - selector: FieldSelector, - connection: Box, - flags: FieldFlags, - offset: usize, - length: usize - }, + FieldUnit(FieldUnit), Integer(u64), IntegerConstant(u64), Method(Method), @@ -110,46 +113,7 @@ impl Debug for AmlValue { fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { Ok(()) } } -impl AmlValue { - pub fn get_as_event(&self) -> Result { - match *self { - AmlValue::Event(ref e) => Ok(e.clone()), - _ => Err(AmlError::AmlValueError) - } - } - - pub fn get_as_ddb_handle(&self) -> Result, AmlError> { - match *self { - AmlValue::DDBHandle(ref v) => Ok(v.clone()), - _ => Err(AmlError::AmlValueError) - } - } - - pub fn get_as_string(&self) -> Result { - match *self { - AmlValue::String(ref s) => Ok(s.clone()), - _ => Err(AmlError::AmlValueError) - } - } - - pub fn get_as_buffer_field(&self) -> Result { - match *self { - AmlValue::BufferField(ref b) => Ok(b.clone()), - _ => { - let raw_buf = self.get_as_buffer()?; - let buf = Box::new(AmlValue::Buffer(raw_buf.clone())); - let idx = Box::new(AmlValue::IntegerConstant(0)); - let len = Box::new(AmlValue::Integer(raw_buf.len() as u64)); - - Ok(BufferField { - source_buf: buf, - index: idx, - length: len - }) - } - } - } - +impl AmlValue { pub fn get_as_buffer(&self) -> Result, AmlError> { match *self { AmlValue::Buffer(ref b) => Ok(b.clone()), @@ -185,10 +149,50 @@ impl AmlValue { _ => Err(AmlError::AmlValueError) } } - - pub fn get_as_package(&self) -> Result, AmlError> { + + pub fn get_as_buffer_field(&self) -> Result { match *self { - AmlValue::Package(ref p) => Ok(p.clone()), + AmlValue::BufferField(ref b) => Ok(b.clone()), + _ => { + let raw_buf = self.get_as_buffer()?; + let buf = Box::new(AmlValue::Buffer(raw_buf.clone())); + let idx = Box::new(AmlValue::IntegerConstant(0)); + let len = Box::new(AmlValue::Integer(raw_buf.len() as u64)); + + Ok(BufferField { + source_buf: buf, + index: idx, + length: len + }) + } + } + } + + pub fn get_as_ddb_handle(&self) -> Result, AmlError> { + // TODO: Integer conversion + match *self { + AmlValue::DDBHandle(ref v) => Ok(v.clone()), + _ => Err(AmlError::AmlValueError) + } + } + + pub fn get_as_device(&self) -> Result, AmlError> { + match *self { + AmlValue::Device(ref s) => Ok(s.clone()), + _ => Err(AmlError::AmlValueError) + } + } + + pub fn get_as_event(&self) -> Result { + match *self { + AmlValue::Event(ref e) => Ok(e.clone()), + _ => Err(AmlError::AmlValueError) + } + } + + pub fn get_as_field_unit(&self) -> Result { + match *self { + AmlValue::FieldUnit(ref e) => Ok(e.clone()), _ => Err(AmlError::AmlValueError) } } @@ -206,6 +210,20 @@ impl AmlValue { _ => Err(AmlError::AmlValueError) } } + + pub fn get_as_package(&self) -> Result, AmlError> { + match *self { + AmlValue::Package(ref p) => Ok(p.clone()), + _ => Err(AmlError::AmlValueError) + } + } + + pub fn get_as_string(&self) -> Result { + match *self { + AmlValue::String(ref s) => Ok(s.clone()), + _ => Err(AmlError::AmlValueError) + } + } } impl Method { From d7229d71329fb7ccf4e347b4df085c5a8c007c85 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Mon, 24 Jul 2017 17:50:41 +0100 Subject: [PATCH 085/113] Completed simple type conversions --- src/acpi/aml/namedobj.rs | 18 +++---- src/acpi/aml/namespace.rs | 100 ++++++++++++++++++++++++++++++------ src/acpi/aml/type1opcode.rs | 17 +++--- src/acpi/aml/type2opcode.rs | 17 +++--- 4 files changed, 106 insertions(+), 46 deletions(-) diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index 7ca72c2..9135932 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -4,7 +4,7 @@ use collections::string::String; use super::AmlError; use super::parser::{ AmlParseType, ParseResult, AmlParseTypeGeneric, AmlExecutionContext, ExecutionState }; use super::namespace::{AmlValue, ObjectReference, FieldSelector, Method, get_namespace_string, - Accessor, BufferField, FieldUnit}; + Accessor, BufferField, FieldUnit, Processor, PowerResource, OperationRegion}; use super::namestring::{parse_name_string, parse_name_seg}; use super::termlist::{parse_term_arg, parse_object_list}; use super::pkglength::parse_pkg_length; @@ -366,7 +366,7 @@ fn parse_def_data_region(data: &[u8], let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val)?; - ctx.add_to_namespace(local_scope_string, AmlValue::OperationRegion { + ctx.add_to_namespace(local_scope_string, AmlValue::OperationRegion(OperationRegion { region: RegionSpace::SystemMemory, offset: Box::new(AmlValue::IntegerConstant(0)), len: Box::new(AmlValue::IntegerConstant(0)), @@ -375,7 +375,7 @@ fn parse_def_data_region(data: &[u8], write: |x, y| () }, accessed_by: None - })?; + }))?; Ok(AmlParseType { val: AmlValue::None, @@ -467,7 +467,7 @@ fn parse_def_op_region(data: &[u8], let len = parse_term_arg(&data[3 + name.len + offset.len..], ctx)?; let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val)?; - ctx.add_to_namespace(local_scope_string, AmlValue::OperationRegion { + ctx.add_to_namespace(local_scope_string, AmlValue::OperationRegion(OperationRegion { region: region, offset: Box::new(offset.val), len: Box::new(len.val), @@ -476,7 +476,7 @@ fn parse_def_op_region(data: &[u8], write: |x, y| () }, accessed_by: None - })?; + }))?; Ok(AmlParseType { val: AmlValue::None, @@ -850,11 +850,11 @@ fn parse_def_power_res(data: &[u8], let mut local_ctx = AmlExecutionContext::new(local_scope_string.clone()); parse_object_list(&data[5 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_ctx)?; - ctx.add_to_namespace(local_scope_string, AmlValue::PowerResource { + ctx.add_to_namespace(local_scope_string, AmlValue::PowerResource(PowerResource { system_level, resource_order, obj_list: local_ctx.namespace_delta.clone() - })?; + }))?; Ok(AmlParseType { val: AmlValue::None, @@ -889,11 +889,11 @@ fn parse_def_processor(data: &[u8], let mut local_ctx = AmlExecutionContext::new(local_scope_string.clone()); parse_object_list(&data[8 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_ctx)?; - ctx.add_to_namespace(local_scope_string, AmlValue::Processor { + ctx.add_to_namespace(local_scope_string, AmlValue::Processor(Processor { proc_id: proc_id, p_blk: if p_blk_len > 0 { Some(p_blk_addr) } else { None }, obj_list: local_ctx.namespace_delta.clone() - })?; + }))?; Ok(AmlParseType { val: AmlValue::None, diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index a8b3336..c818ef7 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -56,6 +56,29 @@ pub struct FieldUnit { pub length: usize } +#[derive(Clone)] +pub struct Processor { + pub proc_id: u8, + pub p_blk: Option, + pub obj_list: Vec +} + +#[derive(Clone)] +pub struct OperationRegion { + pub region: RegionSpace, + pub offset: Box, + pub len: Box, + pub accessor: Accessor, + pub accessed_by: Option +} + +#[derive(Clone)] +pub struct PowerResource { + pub system_level: u8, + pub resource_order: u16, + pub obj_list: Vec +} + pub struct Accessor { pub read: fn(usize) -> u64, pub write: fn(usize, u64) @@ -86,25 +109,11 @@ pub enum AmlValue { Method(Method), Mutex((u8, Option)), ObjectReference(ObjectReference), - OperationRegion { - region: RegionSpace, - offset: Box, - len: Box, - accessor: Accessor, - accessed_by: Option - }, + OperationRegion(OperationRegion), Package(Vec), String(String), - PowerResource { - system_level: u8, - resource_order: u16, - obj_list: Vec - }, - Processor { - proc_id: u8, - p_blk: Option, - obj_list: Vec - }, + PowerResource(PowerResource), + Processor(Processor), RawDataBuffer(Vec), ThermalZone(Vec) } @@ -198,6 +207,14 @@ impl AmlValue { } pub fn get_as_integer(&self) -> Result { + match *self { + AmlValue::IntegerConstant(ref i) => Ok(i.clone()), + AmlValue::Integer(ref i) => Ok(i.clone()), + _ => Err(AmlError::AmlValueError) + } + } + + pub fn get_as_integer_constant(&self) -> Result { match *self { AmlValue::IntegerConstant(ref i) => Ok(i.clone()), _ => Err(AmlError::AmlValueError) @@ -210,6 +227,27 @@ impl AmlValue { _ => Err(AmlError::AmlValueError) } } + + pub fn get_as_mutex(&self) -> Result<(u8, Option), AmlError> { + match *self { + AmlValue::Mutex(ref m) => Ok(m.clone()), + _ => Err(AmlError::AmlValueError) + } + } + + pub fn get_as_object_reference(&self) -> Result { + match *self { + AmlValue::ObjectReference(ref m) => Ok(m.clone()), + _ => Err(AmlError::AmlValueError) + } + } + + pub fn get_as_operation_region(&self) -> Result { + match *self { + AmlValue::OperationRegion(ref p) => Ok(p.clone()), + _ => Err(AmlError::AmlValueError) + } + } pub fn get_as_package(&self) -> Result, AmlError> { match *self { @@ -224,6 +262,34 @@ impl AmlValue { _ => Err(AmlError::AmlValueError) } } + + pub fn get_as_power_resource(&self) -> Result { + match *self { + AmlValue::PowerResource(ref p) => Ok(p.clone()), + _ => Err(AmlError::AmlValueError) + } + } + + pub fn get_as_processor(&self) -> Result { + match *self { + AmlValue::Processor(ref p) => Ok(p.clone()), + _ => Err(AmlError::AmlValueError) + } + } + + pub fn get_as_raw_data_buffer(&self) -> Result, AmlError> { + match *self { + AmlValue::RawDataBuffer(ref p) => Ok(p.clone()), + _ => Err(AmlError::AmlValueError) + } + } + + pub fn get_as_thermal_zone(&self) -> Result, AmlError> { + match *self { + AmlValue::ThermalZone(ref p) => Ok(p.clone()), + _ => Err(AmlError::AmlValueError) + } + } } impl Method { diff --git a/src/acpi/aml/type1opcode.rs b/src/acpi/aml/type1opcode.rs index 638de9e..d5c0f52 100644 --- a/src/acpi/aml/type1opcode.rs +++ b/src/acpi/aml/type1opcode.rs @@ -1,6 +1,6 @@ use super::AmlError; use super::parser::{AmlParseType, ParseResult, AmlExecutionContext, ExecutionState}; -use super::namespace::{AmlValue, ObjectReference}; +use super::namespace::{AmlValue, ObjectReference, OperationRegion}; use super::pkglength::parse_pkg_length; use super::termlist::{parse_term_arg, parse_term_list}; use super::namestring::{parse_name_string, parse_super_name}; @@ -216,16 +216,13 @@ fn parse_def_release(data: &[u8], } } }, - AmlValue::OperationRegion { region, offset, len, accessor, accessed_by } => { - if let Some(o) = accessed_by { + AmlValue::OperationRegion(ref region) => { + if let Some(o) = region.accessed_by { if o == ctx.ctx_id { - ctx.modify(obj.val.clone(), AmlValue::OperationRegion { - region, - offset, - len, - accessor, - accessed_by: None - }); + let mut new_region = region.clone(); + new_region.accessed_by = None; + + ctx.modify(obj.val.clone(), AmlValue::OperationRegion(new_region)); } else { return Err(AmlError::AmlHardFatal); } diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index e445119..13149cf 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -4,7 +4,7 @@ use collections::vec::Vec; use super::{AmlError, parse_aml_with_scope}; use super::parser::{AmlParseType, ParseResult, AmlExecutionContext, ExecutionState}; -use super::namespace::{AmlValue, ObjectReference}; +use super::namespace::{AmlValue, ObjectReference, OperationRegion}; use super::pkglength::parse_pkg_length; use super::termlist::{parse_term_arg, parse_method_invocation}; use super::namestring::{parse_super_name, parse_target, parse_name_string, parse_simple_name}; @@ -332,15 +332,12 @@ fn parse_def_acquire(data: &[u8], }); } }, - AmlValue::OperationRegion { region, offset, len, accessor, accessed_by } => { - if accessed_by == None { - ctx.modify(obj.val.clone(), AmlValue::OperationRegion { - region, - offset, - len, - accessor, - accessed_by: Some(id) - }); + AmlValue::OperationRegion(ref o) => { + if o.accessed_by == None { + let mut new_region = o.clone(); + new_region.accessed_by = Some(id); + + ctx.modify(obj.val.clone(), AmlValue::OperationRegion(new_region)); return Ok(AmlParseType { val: AmlValue::Integer(0), len: 4 + obj.len From a5382534e605db6d9774eb3bcd940089227d6ca3 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Mon, 24 Jul 2017 18:53:21 +0100 Subject: [PATCH 086/113] Converted to integer fully --- src/acpi/aml/namespace.rs | 45 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index c818ef7..78beb9c 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -210,6 +210,51 @@ impl AmlValue { match *self { AmlValue::IntegerConstant(ref i) => Ok(i.clone()), AmlValue::Integer(ref i) => Ok(i.clone()), + AmlValue::Buffer(ref b) => { + let mut b = b.clone(); + if b.len() > 8 { + return Err(AmlError::AmlValueError); + } + + let mut i: u64 = 0; + + while b.len() > 0 { + i <<= 8; + i += b.pop().expect("Won't happen") as u64; + } + + Ok(i) + }, + AmlValue::BufferField(_) => { + let mut b = self.get_as_buffer()?; + if b.len() > 8 { + return Err(AmlError::AmlValueError); + } + + let mut i: u64 = 0; + + while b.len() > 0 { + i <<= 8; + i += b.pop().expect("Won't happen") as u64; + } + + Ok(i) + }, + AmlValue::String(ref s) => { + let mut s = s.clone()[0..8].to_string().to_uppercase(); + let mut i: u64 = 0; + + for c in s.chars() { + if !c.is_digit(16) { + break; + } + + i <<= 8; + i += c.to_digit(16).unwrap() as u64; + } + + Ok(i) + }, _ => Err(AmlError::AmlValueError) } } From a115d214955fc27b317b8749bade24dee7aa39ca Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Mon, 24 Jul 2017 19:02:09 +0100 Subject: [PATCH 087/113] Converted all types to string --- src/acpi/aml/namespace.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index 78beb9c..7dbf2d4 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -304,6 +304,13 @@ impl AmlValue { pub fn get_as_string(&self) -> Result { match *self { AmlValue::String(ref s) => Ok(s.clone()), + AmlValue::Integer(ref i) => Ok(format!("{:X}", i)), + AmlValue::IntegerConstant(ref i) => Ok(format!("{:X}", i)), + AmlValue::Buffer(ref b) => Ok(String::from_utf8(b.clone()).expect("Invalid UTF-8")), + AmlValue::BufferField(_) => { + let b = self.get_as_buffer()?; + Ok(String::from_utf8(b).expect("Invalid UTF-8")) + }, _ => Err(AmlError::AmlValueError) } } From 1cd124a8525bbdd5f6cead124fac7bb7b72a9d16 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Tue, 25 Jul 2017 10:36:56 +0100 Subject: [PATCH 088/113] Fixed bank name issue --- src/acpi/aml/namedobj.rs | 1 + src/acpi/aml/namespace.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index 9135932..c7b4954 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -153,6 +153,7 @@ fn parse_def_bank_field(data: &[u8], let selector = FieldSelector::Bank { region: region_name.val.get_as_string()?, + bank_register: bank_name.val.get_as_string()?, bank_selector: Box::new(bank_value.val) }; diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index 7dbf2d4..f364347 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -15,6 +15,7 @@ pub enum FieldSelector { Region(String), Bank { region: String, + bank_register: String, bank_selector: Box }, Index { From 6df99953dc39c56be743d86f1e45980a9676f847 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Tue, 25 Jul 2017 11:25:29 +0100 Subject: [PATCH 089/113] Implemented defBuffer --- src/acpi/aml/namedobj.rs | 1 - src/acpi/aml/type2opcode.rs | 7 ++++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index c7b4954..c5431ca 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -120,7 +120,6 @@ fn parse_def_bank_field(data: &[u8], }) } - // TODO: Why isn't bank name used? parser_opcode_extended!(data, 0x87); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[2..])?; diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index 13149cf..2d7946b 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -242,15 +242,16 @@ pub fn parse_def_buffer(data: &[u8], }) } - // TODO: Perform computation parser_opcode!(data, 0x11); let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?; let buffer_size = parse_term_arg(&data[1 + pkg_length_len..], ctx)?; - let byte_list = data[1 + pkg_length_len + buffer_size.len .. 1 + pkg_length].to_vec(); + let mut byte_list = data[1 + pkg_length_len + buffer_size.len .. 1 + pkg_length].to_vec().clone(); + + byte_list.truncate(buffer_size.val.get_as_integer()? as usize); Ok(AmlParseType { - val: AmlValue::Uninitialized, + val: AmlValue::Buffer(byte_list), len: 1 + pkg_length }) } From 0652bc8099d941ef83e8066a0735bfd43db345b9 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Tue, 25 Jul 2017 11:29:32 +0100 Subject: [PATCH 090/113] Implemented ToBuffer --- src/acpi/aml/type2opcode.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index 2d7946b..1d235d4 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -601,15 +601,16 @@ fn parse_def_to_buffer(data: &[u8], }) } - // TODO: Compute the result - // TODO: Store the result, if appropriate parser_opcode!(data, 0x96); let operand = parse_term_arg(&data[2..], ctx)?; let target = parse_target(&data[2 + operand.len..], ctx)?; + let res = AmlValue::Buffer(operand.val.get_as_buffer()?); + ctx.modify(target.val, res.clone()); + Ok(AmlParseType { - val: AmlValue::Uninitialized, + val: res, len: 1 + operand.len + target.len }) } From 8a5ec3a26bcabe80761acd7311ecdf8ba1f3a72a Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Tue, 25 Jul 2017 11:37:49 +0100 Subject: [PATCH 091/113] Implemented SizeOf --- src/acpi/aml/type2opcode.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index 1d235d4..665f1b8 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -782,13 +782,20 @@ fn parse_def_size_of(data: &[u8], }) } - // TODO: Perform the computation parser_opcode!(data, 0x87); let name = parse_super_name(&data[1..], ctx)?; + let obj = ctx.get(name.val); + + let res = match obj { + AmlValue::Buffer(ref v) => v.len(), + AmlValue::String(ref s) => s.len(), + AmlValue::Package(ref p) => p.len(), + _ => return Err(AmlError::AmlValueError) + }; Ok(AmlParseType { - val: AmlValue::Uninitialized, + val: AmlValue::Integer(res as u64), len: 1 + name.len }) } From 968fd30b0a8099d626e7b3c751043c84631f1da5 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Tue, 25 Jul 2017 11:51:43 +0100 Subject: [PATCH 092/113] Fixed object references --- src/acpi/aml/dataobj.rs | 2 +- src/acpi/aml/namedobj.rs | 2 +- src/acpi/aml/namespace.rs | 4 ++-- src/acpi/aml/namespacemodifier.rs | 2 +- src/acpi/aml/type1opcode.rs | 2 +- src/acpi/aml/type2opcode.rs | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/acpi/aml/dataobj.rs b/src/acpi/aml/dataobj.rs index fa9710d..ba6e0f0 100644 --- a/src/acpi/aml/dataobj.rs +++ b/src/acpi/aml/dataobj.rs @@ -48,7 +48,7 @@ pub fn parse_data_ref_obj(data: &[u8], match parse_super_name(data, ctx) { Ok(res) => match res.val { AmlValue::String(s) => Ok(AmlParseType { - val: AmlValue::ObjectReference(ObjectReference::NamedObj(s)), + val: AmlValue::ObjectReference(ObjectReference::Object(s)), len: res.len }), _ => Ok(res) diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index c5431ca..ecd761e 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -758,7 +758,7 @@ fn parse_connect_field(data: &[u8], } else { let name = parse_name_string(&data[1..], ctx)?; Ok(AmlParseType { - val: AmlValue::ObjectReference(ObjectReference::NamedObj(name.val.get_as_string()?)), + val: AmlValue::Alias(name.val.get_as_string()?), len: name.len + 1 }) } diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index f364347..3dcdb25 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -28,8 +28,7 @@ pub enum FieldSelector { pub enum ObjectReference { ArgObj(u8), LocalObj(u8), - NamedObj(String), - Object(Box), + Object(String), Index(Box, Box) } @@ -98,6 +97,7 @@ impl Clone for Accessor { pub enum AmlValue { None, Uninitialized, + Alias(String), Buffer(Vec), BufferField(BufferField), DDBHandle(Vec), diff --git a/src/acpi/aml/namespacemodifier.rs b/src/acpi/aml/namespacemodifier.rs index 57d1b1a..a223f5c 100644 --- a/src/acpi/aml/namespacemodifier.rs +++ b/src/acpi/aml/namespacemodifier.rs @@ -44,7 +44,7 @@ fn parse_alias_op(data: &[u8], let local_scope_string = get_namespace_string(ctx.scope.clone(), source_name.val)?; let local_alias_string = get_namespace_string(ctx.scope.clone(), alias_name.val)?; - ctx.add_to_namespace(local_scope_string, AmlValue::ObjectReference(ObjectReference::NamedObj(local_alias_string)))?; + ctx.add_to_namespace(local_scope_string, AmlValue::Alias(local_alias_string))?; Ok(AmlParseType { val: AmlValue::None, diff --git a/src/acpi/aml/type1opcode.rs b/src/acpi/aml/type1opcode.rs index d5c0f52..9d74a5f 100644 --- a/src/acpi/aml/type1opcode.rs +++ b/src/acpi/aml/type1opcode.rs @@ -151,7 +151,7 @@ fn parse_def_load(data: &[u8], let name = parse_name_string(&data[2..], ctx)?; let ddb_handle_object = parse_super_name(&data[2 + name.len..], ctx)?; - let tbl = ctx.get(AmlValue::ObjectReference(ObjectReference::NamedObj(name.val.get_as_string()?))).get_as_buffer()?; + let tbl = ctx.get(name.val).get_as_buffer()?; let sdt = unsafe { &*(tbl.as_ptr() as *const Sdt) }; if is_aml_table(sdt) { diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index 665f1b8..c0b1bc8 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -217,7 +217,7 @@ fn parse_package_elements_list(data: &[u8], } else { let d = parse_name_string(&data[current_offset..], ctx)?; AmlParseType { - val: AmlValue::ObjectReference(ObjectReference::NamedObj(d.val.get_as_string()?)), + val: AmlValue::ObjectReference(ObjectReference::Object(d.val.get_as_string()?)), len: d.len } }; From afc93f82a90108f9bc38267d615bc9a01582e3c1 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Tue, 25 Jul 2017 13:06:10 +0100 Subject: [PATCH 093/113] Implemented RefOf --- src/acpi/aml/type2opcode.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index c0b1bc8..d4591ce 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -266,13 +266,22 @@ fn parse_def_ref_of(data: &[u8], }) } - // TODO: Perform computation parser_opcode!(data, 0x71); let obj = parse_super_name(&data[1..], ctx)?; + let res = match obj.val { + AmlValue::String(ref s) => { + match ctx.get(AmlValue::String(s.clone())) { + AmlValue::None => return Err(AmlError::AmlValueError), + _ => ObjectReference::Object(s.clone()) + } + }, + AmlValue::ObjectReference(ref o) => o.clone(), + _ => return Err(AmlError::AmlValueError) + }; Ok(AmlParseType { - val: AmlValue::Uninitialized, + val: AmlValue::ObjectReference(res), len: 1 + obj.len }) } From ada5ba6dbc8c60e68f527bff761c912e91f4fc84 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Tue, 25 Jul 2017 13:12:42 +0100 Subject: [PATCH 094/113] Implemented condrefof --- src/acpi/aml/type2opcode.rs | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index d4591ce..35f3faf 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -1077,16 +1077,30 @@ fn parse_def_cond_ref_of(data: &[u8], }) } - // TODO: Compute the result - // TODO: Store the result parser_opcode_extended!(data, 0x12); - let operand = parse_super_name(&data[2..], ctx)?; - let target = parse_target(&data[2 + operand.len..], ctx)?; + let obj = parse_super_name(&data[2..], ctx)?; + let target = parse_target(&data[2 + obj.len..], ctx)?; + let res = match obj.val { + AmlValue::String(ref s) => { + match ctx.get(AmlValue::String(s.clone())) { + AmlValue::None => return Ok(AmlParseType { + val: AmlValue::Integer(0), + len: 1 + obj.len + target.len + }), + _ => ObjectReference::Object(s.clone()) + } + }, + AmlValue::ObjectReference(ref o) => o.clone(), + _ => return Err(AmlError::AmlValueError) + }; + + ctx.modify(target.val, AmlValue::ObjectReference(res)); + Ok(AmlParseType { - val: AmlValue::Uninitialized, - len: 2 + operand.len + target.len + val: AmlValue::Integer(1), + len: 1 + obj.len + target.len }) } From f25df99a411f8820a01b02f60d347763a2c7ca7a Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Tue, 25 Jul 2017 14:48:07 +0100 Subject: [PATCH 095/113] Implemented derefof --- src/acpi/aml/type2opcode.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index 35f3faf..e2880dd 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -296,15 +296,18 @@ fn parse_def_deref_of(data: &[u8], }) } - // TODO: Perform computation parser_opcode!(data, 0x83); let obj = parse_term_arg(&data[1..], ctx)?; - - Ok(AmlParseType { - val: AmlValue::Uninitialized, - len: 1 + obj.len - }) + let res = ctx.get(obj.val); + + match res { + AmlValue::None => Err(AmlError::AmlValueError), + _ => Ok(AmlParseType { + val: res, + len: 1 + obj.len + }) + } } fn parse_def_acquire(data: &[u8], From ab9874687996a14973f175a1fc714ee2ba37dacd Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Sat, 29 Jul 2017 12:39:08 +0300 Subject: [PATCH 096/113] Moved lock manipulation into context --- src/acpi/aml/parser.rs | 114 +++++++++++++++++++++++++++++++++++- src/acpi/aml/type1opcode.rs | 31 +--------- src/acpi/aml/type2opcode.rs | 56 +++++------------- 3 files changed, 130 insertions(+), 71 deletions(-) diff --git a/src/acpi/aml/parser.rs b/src/acpi/aml/parser.rs index 758dd17..e8a1865 100644 --- a/src/acpi/aml/parser.rs +++ b/src/acpi/aml/parser.rs @@ -30,7 +30,8 @@ pub struct AmlExecutionContext { pub arg_vars: [AmlValue; 8], pub state: ExecutionState, pub namespace_delta: Vec, - pub ctx_id: u64 + pub ctx_id: u64, + pub sync_level: u8 } impl AmlExecutionContext { @@ -60,9 +61,118 @@ impl AmlExecutionContext { AmlValue::Uninitialized], state: ExecutionState::EXECUTING, namespace_delta: vec!(), - ctx_id: id + ctx_id: id, + sync_level: 0 } } + + pub fn release_mutex(&mut self, mutex_ptr: AmlValue) -> Result<(), AmlError> { + let id = self.ctx_id; + + let mut namespace_ptr = self.prelock(); + let mut namespace = match *namespace_ptr { + Some(ref mut n) => n, + None => return Err(AmlError::AmlHardFatal) + }; + + let mutex_idx = match mutex_ptr { + AmlValue::String(ref s) => s.clone(), + AmlValue::ObjectReference(ref o) => match *o { + ObjectReference::Object(ref s) => s.clone(), + _ => return Err(AmlError::AmlValueError) + }, + _ => return Err(AmlError::AmlValueError) + }; + + let mutex = match namespace.get(&mutex_idx) { + Some(s) => s.clone(), + None => return Err(AmlError::AmlValueError) + }; + + match mutex { + AmlValue::Mutex((sync_level, owner)) => { + if let Some(o) = owner { + if o == id { + if sync_level == self.sync_level { + namespace.insert(mutex_idx, AmlValue::Mutex((sync_level, None))); + return Ok(()); + } else { + return Err(AmlError::AmlValueError); + } + } else { + return Err(AmlError::AmlHardFatal); + } + } + }, + AmlValue::OperationRegion(ref region) => { + if let Some(o) = region.accessed_by { + if o == id { + let mut new_region = region.clone(); + new_region.accessed_by = None; + + namespace.insert(mutex_idx, AmlValue::OperationRegion(new_region)); + return Ok(()); + } else { + return Err(AmlError::AmlHardFatal); + } + } + }, + _ => return Err(AmlError::AmlValueError) + } + + Ok(()) + } + + pub fn acquire_mutex(&mut self, mutex_ptr: AmlValue, timeout: u16) -> Result { + let id = self.ctx_id; + + + let mut namespace_ptr = self.prelock(); + let mut namespace = match *namespace_ptr { + Some(ref mut n) => n, + None => return Err(AmlError::AmlHardFatal) + }; + let mutex_idx = match mutex_ptr { + AmlValue::String(ref s) => s.clone(), + AmlValue::ObjectReference(ref o) => match *o { + ObjectReference::Object(ref s) => s.clone(), + _ => return Err(AmlError::AmlValueError) + }, + _ => return Err(AmlError::AmlValueError) + }; + + let mutex = match namespace.get(&mutex_idx) { + Some(s) => s.clone(), + None => return Err(AmlError::AmlValueError) + }; + + match mutex { + AmlValue::Mutex((sync_level, owner)) => { + if owner == None { + if sync_level < self.sync_level { + return Err(AmlError::AmlValueError); + } + + namespace.insert(mutex_idx, AmlValue::Mutex((sync_level, Some(id)))); + self.sync_level = sync_level; + + return Ok(true); + } + }, + AmlValue::OperationRegion(ref o) => { + if o.accessed_by == None { + let mut new_region = o.clone(); + new_region.accessed_by = Some(id); + + namespace.insert(mutex_idx, AmlValue::OperationRegion(new_region)); + return Ok(true); + } + }, + _ => return Err(AmlError::AmlValueError) + } + + Ok(false) + } pub fn add_to_namespace(&mut self, name: String, value: AmlValue) -> Result<(), AmlError> { let mut namespace = ACPI_TABLE.namespace.write(); diff --git a/src/acpi/aml/type1opcode.rs b/src/acpi/aml/type1opcode.rs index 9d74a5f..c277b32 100644 --- a/src/acpi/aml/type1opcode.rs +++ b/src/acpi/aml/type1opcode.rs @@ -202,35 +202,8 @@ fn parse_def_release(data: &[u8], parser_opcode_extended!(data, 0x27); let obj = parse_super_name(&data[2..], ctx)?; - - let mut namespace = ctx.prelock(); - let mutex = ctx.get(obj.val.clone()); - - match mutex { - AmlValue::Mutex((sync_level, owner)) => { - if let Some(o) = owner { - if o == ctx.ctx_id { - ctx.modify(obj.val.clone(), AmlValue::Mutex((sync_level, None))); - } else { - return Err(AmlError::AmlHardFatal); - } - } - }, - AmlValue::OperationRegion(ref region) => { - if let Some(o) = region.accessed_by { - if o == ctx.ctx_id { - let mut new_region = region.clone(); - new_region.accessed_by = None; - - ctx.modify(obj.val.clone(), AmlValue::OperationRegion(new_region)); - } else { - return Err(AmlError::AmlHardFatal); - } - } - }, - _ => return Err(AmlError::AmlValueError) - } - + ctx.release_mutex(obj.val); + Ok(AmlParseType { val: AmlValue::None, len: 2 + obj.len diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index e2880dd..2ff6017 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -328,50 +328,26 @@ fn parse_def_acquire(data: &[u8], let (seconds, nanoseconds) = monotonic(); let starting_time_ns = nanoseconds + (seconds * 1000000000); - let id = ctx.ctx_id; - loop { - { - let mut namespace = ctx.prelock(); - let mutex = ctx.get(obj.val.clone()); - - match mutex { - AmlValue::Mutex((sync_level, owner)) => { - if owner == None { - ctx.modify(obj.val.clone(), AmlValue::Mutex((sync_level, Some(id)))); - return Ok(AmlParseType { - val: AmlValue::Integer(0), - len: 4 + obj.len - }); - } - }, - AmlValue::OperationRegion(ref o) => { - if o.accessed_by == None { - let mut new_region = o.clone(); - new_region.accessed_by = Some(id); - - ctx.modify(obj.val.clone(), AmlValue::OperationRegion(new_region)); - return Ok(AmlParseType { - val: AmlValue::Integer(0), - len: 4 + obj.len - }); - } - }, - _ => return Err(AmlError::AmlValueError) - } - } - - if timeout == 0xFFFF { - // TODO: Brief sleep here - } else { - let (seconds, nanoseconds) = monotonic(); - let current_time_ns = nanoseconds + (seconds * 1000000000); - - if current_time_ns - starting_time_ns > timeout as u64 * 1000000 { + match ctx.acquire_mutex(obj.val.clone(), timeout) { + Err(e) => return Err(e), + Ok(b) => if b { return Ok(AmlParseType { - val: AmlValue::Integer(1), + val: AmlValue::Integer(0), len: 4 + obj.len }); + } else if timeout == 0xFFFF { + // TODO: Brief sleep here + } else { + let (seconds, nanoseconds) = monotonic(); + let current_time_ns = nanoseconds + (seconds * 1000000000); + + if current_time_ns - starting_time_ns > timeout as u64 * 1000000 { + return Ok(AmlParseType { + val: AmlValue::Integer(1), + len: 4 + obj.len + }); + } } } } From 6122b2199766e41983a0c7edac9ee49b488af8fd Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Sat, 29 Jul 2017 12:57:53 +0300 Subject: [PATCH 097/113] Moved event signal/wait code into context --- src/acpi/aml/parser.rs | 72 +++++++++++++++++++++++++++++++++++-- src/acpi/aml/type1opcode.rs | 6 +--- src/acpi/aml/type2opcode.rs | 46 ++++++++++-------------- 3 files changed, 88 insertions(+), 36 deletions(-) diff --git a/src/acpi/aml/parser.rs b/src/acpi/aml/parser.rs index e8a1865..1cfc6e0 100644 --- a/src/acpi/aml/parser.rs +++ b/src/acpi/aml/parser.rs @@ -65,6 +65,73 @@ impl AmlExecutionContext { sync_level: 0 } } + + pub fn wait_for_event(&mut self, event_ptr: AmlValue) -> Result { + let mut namespace_ptr = self.prelock(); + let mut namespace = match *namespace_ptr { + Some(ref mut n) => n, + None => return Err(AmlError::AmlHardFatal) + }; + + let mutex_idx = match event_ptr { + AmlValue::String(ref s) => s.clone(), + AmlValue::ObjectReference(ref o) => match *o { + ObjectReference::Object(ref s) => s.clone(), + _ => return Err(AmlError::AmlValueError) + }, + _ => return Err(AmlError::AmlValueError) + }; + + let mutex = match namespace.get(&mutex_idx) { + Some(s) => s.clone(), + None => return Err(AmlError::AmlValueError) + }; + + match mutex { + AmlValue::Event(count) => { + if count > 0 { + namespace.insert(mutex_idx, AmlValue::Event(count - 1)); + return Ok(true); + } + }, + _ => return Err(AmlError::AmlValueError) + } + + Ok(false) + } + + pub fn signal_event(&mut self, event_ptr: AmlValue) -> Result<(), AmlError> { + let mut namespace_ptr = self.prelock(); + let mut namespace = match *namespace_ptr { + Some(ref mut n) => n, + None => return Err(AmlError::AmlHardFatal) + }; + + + let mutex_idx = match event_ptr { + AmlValue::String(ref s) => s.clone(), + AmlValue::ObjectReference(ref o) => match *o { + ObjectReference::Object(ref s) => s.clone(), + _ => return Err(AmlError::AmlValueError) + }, + _ => return Err(AmlError::AmlValueError) + }; + + let mutex = match namespace.get(&mutex_idx) { + Some(s) => s.clone(), + None => return Err(AmlError::AmlValueError) + }; + + match mutex { + AmlValue::Event(count) => { + namespace.insert(mutex_idx, AmlValue::Event(count + 1)); + return Ok(()); + }, + _ => return Err(AmlError::AmlValueError) + } + + Ok(()) + } pub fn release_mutex(&mut self, mutex_ptr: AmlValue) -> Result<(), AmlError> { let id = self.ctx_id; @@ -123,9 +190,8 @@ impl AmlExecutionContext { Ok(()) } - pub fn acquire_mutex(&mut self, mutex_ptr: AmlValue, timeout: u16) -> Result { - let id = self.ctx_id; - + pub fn acquire_mutex(&mut self, mutex_ptr: AmlValue) -> Result { + let id = self.ctx_id; let mut namespace_ptr = self.prelock(); let mut namespace = match *namespace_ptr { diff --git a/src/acpi/aml/type1opcode.rs b/src/acpi/aml/type1opcode.rs index c277b32..bf6f7d6 100644 --- a/src/acpi/aml/type1opcode.rs +++ b/src/acpi/aml/type1opcode.rs @@ -246,11 +246,7 @@ fn parse_def_signal(data: &[u8], parser_opcode_extended!(data, 0x24); let object = parse_super_name(&data[2..], ctx)?; - let namespace = ctx.prelock(); - let event = ctx.get(object.val.clone()).get_as_event()?; - - ctx.modify(object.val.clone(), AmlValue::Event(event + 1)); - + ctx.signal_event(object.val)?; Ok(AmlParseType { val: AmlValue::None, len: 2 + object.len diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index 2ff6017..d0a6c32 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -329,7 +329,7 @@ fn parse_def_acquire(data: &[u8], let starting_time_ns = nanoseconds + (seconds * 1000000000); loop { - match ctx.acquire_mutex(obj.val.clone(), timeout) { + match ctx.acquire_mutex(obj.val.clone()) { Err(e) => return Err(e), Ok(b) => if b { return Ok(AmlParseType { @@ -1012,35 +1012,25 @@ fn parse_def_wait(data: &[u8], let starting_time_ns = nanoseconds + (seconds * 1000000000); loop { - { - let mut namespace = ctx.prelock(); - let mutex = ctx.get(obj.val.clone()); - - match mutex { - AmlValue::Event(count) => { - if count > 0 { - ctx.modify(obj.val.clone(), AmlValue::Event(count - 1)); - return Ok(AmlParseType { - val: AmlValue::Integer(0), - len: 2 + obj.len + timeout_obj.len - }); - } - }, - _ => return Err(AmlError::AmlValueError) - } - } - - if timeout >= 0xFFFF { - // TODO: Brief sleep here - } else { - let (seconds, nanoseconds) = monotonic(); - let current_time_ns = nanoseconds + (seconds * 1000000000); - - if current_time_ns - starting_time_ns > timeout as u64 * 1000000 { + match ctx.wait_for_event(obj.val.clone()) { + Err(e) => return Err(e), + Ok(b) => if b { return Ok(AmlParseType { - val: AmlValue::Integer(1), + val: AmlValue::Integer(0), len: 2 + obj.len + timeout_obj.len - }); + }) + } else if timeout >= 0xFFFF { + // TODO: Brief sleep here + } else { + let (seconds, nanoseconds) = monotonic(); + let current_time_ns = nanoseconds + (seconds * 1000000000); + + if current_time_ns - starting_time_ns > timeout as u64 * 1000000 { + return Ok(AmlParseType { + val: AmlValue::Integer(1), + len: 2 + obj.len + timeout_obj.len + }); + } } } } From 41ce7fdf1f96cf8cfe254981976ddf20f6cf61b4 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Sun, 30 Jul 2017 11:23:32 +0300 Subject: [PATCH 098/113] Implemented much of ctx::modify and ctx::get --- src/acpi/aml/parser.rs | 90 ++++++++++++++++++++++++++++++++----- src/acpi/aml/termlist.rs | 2 +- src/acpi/aml/type1opcode.rs | 6 +-- src/acpi/aml/type2opcode.rs | 12 ++--- 4 files changed, 88 insertions(+), 22 deletions(-) diff --git a/src/acpi/aml/parser.rs b/src/acpi/aml/parser.rs index 1cfc6e0..2cc907c 100644 --- a/src/acpi/aml/parser.rs +++ b/src/acpi/aml/parser.rs @@ -283,29 +283,95 @@ impl AmlExecutionContext { ACPI_TABLE.namespace.write() } - pub fn modify(&mut self, name: AmlValue, value: AmlValue) { - // TODO: throw errors - // TODO: return DRO + pub fn modify(&mut self, name: AmlValue, value: AmlValue) -> Result<(), AmlError> { match name { - AmlValue::None => (), AmlValue::ObjectReference(r) => match r { - ObjectReference::ArgObj(_) => (), + ObjectReference::ArgObj(_) => return Err(AmlError::AmlValueError), ObjectReference::LocalObj(i) => self.local_vars[i as usize] = value, - _ => () + ObjectReference::Object(s) => if let Some(ref mut namespace) = *ACPI_TABLE.namespace.write() { + namespace.insert(s, value); + }, + ObjectReference::Index(c, v) => { + let idx = v.get_as_integer()? as usize; + match *c { + AmlValue::ObjectReference(r) => match r { + ObjectReference::Object(s) => { + if let Some(ref mut namespace) = *ACPI_TABLE.namespace.write() { + let obj = if let Some(s) = namespace.get(&s) { + s.clone() + } else { + return Err(AmlError::AmlValueError); + }; + + match obj { + AmlValue::String(ref string) => { + let mut bytes = string.clone().into_bytes(); + bytes[idx] = value.get_as_integer()? as u8; + + let string = String::from_utf8(bytes).unwrap(); + namespace.insert(s, AmlValue::String(string)); + }, + AmlValue::Buffer(ref b) => { + let mut b = b.clone(); + b[idx] = value.get_as_integer()? as u8; + + namespace.insert(s, AmlValue::Buffer(b)); + }, + AmlValue::Package(ref p) => { + let mut p = p.clone(); + p[idx] = value; + + namespace.insert(s, AmlValue::Package(p)); + }, + _ => return Err(AmlError::AmlValueError) + } + } + }, + _ => return Err(AmlError::AmlValueError) + }, + _ => return Err(AmlError::AmlValueError) + } + } }, - _ => () + AmlValue::String(s) => if let Some(ref mut namespace) = *ACPI_TABLE.namespace.write() { + namespace.insert(s, value); + }, + _ => return Err(AmlError::AmlValueError) } + + Ok(()) } - pub fn get(&self, name: AmlValue) -> AmlValue { - match name { - AmlValue::None => AmlValue::None, + pub fn get(&self, name: AmlValue) -> Result { + Ok(match name { AmlValue::ObjectReference(r) => match r { ObjectReference::ArgObj(i) => self.arg_vars[i as usize].clone(), ObjectReference::LocalObj(i) => self.local_vars[i as usize].clone(), - _ => AmlValue::None + ObjectReference::Object(ref s) => if let Some(ref namespace) = *ACPI_TABLE.namespace.read() { + if let Some(o) = namespace.get(s) { + o.clone() + } else { + AmlValue::None + } + } else { AmlValue::None }, + ObjectReference::Index(c, v) => if let Some(ref mut namespace) = *ACPI_TABLE.namespace.write() { + let idx = v.get_as_integer()? as usize; + match *c { + AmlValue::Package(p) => p[idx].clone(), + _ => AmlValue::None + } + } else { + AmlValue::None + } }, + AmlValue::String(ref s) => if let Some(ref namespace) = *ACPI_TABLE.namespace.read() { + if let Some(o) = namespace.get(s) { + o.clone() + } else { + AmlValue::None + } + } else { AmlValue::None }, _ => AmlValue::None - } + }) } } diff --git a/src/acpi/aml/termlist.rs b/src/acpi/aml/termlist.rs index 8087c44..262f731 100644 --- a/src/acpi/aml/termlist.rs +++ b/src/acpi/aml/termlist.rs @@ -125,7 +125,7 @@ pub fn parse_method_invocation(data: &[u8], } let name = parse_name_string(data, ctx)?; - let method = ctx.get(name.val.clone()); + let method = ctx.get(name.val.clone())?; let method = match method { AmlValue::None => return Err(AmlError::AmlDeferredLoad), diff --git a/src/acpi/aml/type1opcode.rs b/src/acpi/aml/type1opcode.rs index bf6f7d6..2ea0482 100644 --- a/src/acpi/aml/type1opcode.rs +++ b/src/acpi/aml/type1opcode.rs @@ -151,7 +151,7 @@ fn parse_def_load(data: &[u8], let name = parse_name_string(&data[2..], ctx)?; let ddb_handle_object = parse_super_name(&data[2 + name.len..], ctx)?; - let tbl = ctx.get(name.val).get_as_buffer()?; + let tbl = ctx.get(name.val)?.get_as_buffer()?; let sdt = unsafe { &*(tbl.as_ptr() as *const Sdt) }; if is_aml_table(sdt) { @@ -223,7 +223,7 @@ fn parse_def_reset(data: &[u8], parser_opcode_extended!(data, 0x26); let object = parse_super_name(&data[2..], ctx)?; - ctx.get(object.val.clone()).get_as_event()?; + ctx.get(object.val.clone())?.get_as_event()?; ctx.modify(object.val.clone(), AmlValue::Event(0)); @@ -333,7 +333,7 @@ fn parse_def_unload(data: &[u8], let object = parse_super_name(&data[2..], ctx)?; - let delta = ctx.get(object.val).get_as_ddb_handle()?; + let delta = ctx.get(object.val)?.get_as_ddb_handle()?; let mut namespace = ctx.prelock(); if let Some(ref mut ns) = *namespace { diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index d0a6c32..20dc756 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -271,7 +271,7 @@ fn parse_def_ref_of(data: &[u8], let obj = parse_super_name(&data[1..], ctx)?; let res = match obj.val { AmlValue::String(ref s) => { - match ctx.get(AmlValue::String(s.clone())) { + match ctx.get(AmlValue::String(s.clone()))? { AmlValue::None => return Err(AmlError::AmlValueError), _ => ObjectReference::Object(s.clone()) } @@ -299,7 +299,7 @@ fn parse_def_deref_of(data: &[u8], parser_opcode!(data, 0x83); let obj = parse_term_arg(&data[1..], ctx)?; - let res = ctx.get(obj.val); + let res = ctx.get(obj.val)?; match res { AmlValue::None => Err(AmlError::AmlValueError), @@ -368,7 +368,7 @@ fn parse_def_increment(data: &[u8], let obj = parse_super_name(&data[1..], ctx)?; let mut namespace = ctx.prelock(); - let value = AmlValue::Integer(ctx.get(obj.val.clone()).get_as_integer()? + 1); + let value = AmlValue::Integer(ctx.get(obj.val.clone())?.get_as_integer()? + 1); ctx.modify(obj.val, value.clone()); Ok(AmlParseType { @@ -773,7 +773,7 @@ fn parse_def_size_of(data: &[u8], parser_opcode!(data, 0x87); let name = parse_super_name(&data[1..], ctx)?; - let obj = ctx.get(name.val); + let obj = ctx.get(name.val)?; let res = match obj { AmlValue::Buffer(ref v) => v.len(), @@ -1053,7 +1053,7 @@ fn parse_def_cond_ref_of(data: &[u8], let res = match obj.val { AmlValue::String(ref s) => { - match ctx.get(AmlValue::String(s.clone())) { + match ctx.get(AmlValue::String(s.clone()))? { AmlValue::None => return Ok(AmlParseType { val: AmlValue::Integer(0), len: 1 + obj.len + target.len @@ -1135,7 +1135,7 @@ fn parse_def_decrement(data: &[u8], let obj = parse_super_name(&data[1..], ctx)?; let mut namespace = ctx.prelock(); - let value = AmlValue::Integer(ctx.get(obj.val.clone()).get_as_integer()? - 1); + let value = AmlValue::Integer(ctx.get(obj.val.clone())?.get_as_integer()? - 1); ctx.modify(obj.val, value.clone()); Ok(AmlParseType { From 328a89c224fb74c6494e31fae48e62ec80313228 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Thu, 10 Aug 2017 14:28:30 +0200 Subject: [PATCH 099/113] Completed context modify, aside from BufferFields and nested Indexes --- src/acpi/aml/parser.rs | 129 +++++++++++++++++++++++++---------------- 1 file changed, 78 insertions(+), 51 deletions(-) diff --git a/src/acpi/aml/parser.rs b/src/acpi/aml/parser.rs index 2cc907c..b5251d5 100644 --- a/src/acpi/aml/parser.rs +++ b/src/acpi/aml/parser.rs @@ -283,65 +283,92 @@ impl AmlExecutionContext { ACPI_TABLE.namespace.write() } - pub fn modify(&mut self, name: AmlValue, value: AmlValue) -> Result<(), AmlError> { - match name { - AmlValue::ObjectReference(r) => match r { - ObjectReference::ArgObj(_) => return Err(AmlError::AmlValueError), - ObjectReference::LocalObj(i) => self.local_vars[i as usize] = value, - ObjectReference::Object(s) => if let Some(ref mut namespace) = *ACPI_TABLE.namespace.write() { - namespace.insert(s, value); - }, - ObjectReference::Index(c, v) => { - let idx = v.get_as_integer()? as usize; - match *c { - AmlValue::ObjectReference(r) => match r { - ObjectReference::Object(s) => { - if let Some(ref mut namespace) = *ACPI_TABLE.namespace.write() { - let obj = if let Some(s) = namespace.get(&s) { - s.clone() - } else { - return Err(AmlError::AmlValueError); - }; - - match obj { - AmlValue::String(ref string) => { - let mut bytes = string.clone().into_bytes(); - bytes[idx] = value.get_as_integer()? as u8; - - let string = String::from_utf8(bytes).unwrap(); - namespace.insert(s, AmlValue::String(string)); - }, - AmlValue::Buffer(ref b) => { - let mut b = b.clone(); - b[idx] = value.get_as_integer()? as u8; + fn modify_local_obj(&mut self, local: usize, value: AmlValue) -> Result<(), AmlError> { + self.local_vars[local] = value; + Ok(()) + } - namespace.insert(s, AmlValue::Buffer(b)); - }, - AmlValue::Package(ref p) => { - let mut p = p.clone(); - p[idx] = value; + fn modify_object(&mut self, name: String, value: AmlValue) -> Result<(), AmlError> { + if let Some(ref mut namespace) = *ACPI_TABLE.namespace.write() { + namespace.insert(name, value); + Ok(()) + } else { + Err(AmlError::AmlHardFatal) + } + } - namespace.insert(s, AmlValue::Package(p)); - }, - _ => return Err(AmlError::AmlValueError) - } - } - }, - _ => return Err(AmlError::AmlValueError) - }, - _ => return Err(AmlError::AmlValueError) + fn modify_index_final(&mut self, name: String, value: AmlValue, indices: Vec) -> Result<(), AmlError> { + if let Some(ref mut namespace) = *ACPI_TABLE.namespace.write() { + let obj = if let Some(s) = namespace.get(&name) { + s.clone() + } else { + return Err(AmlError::AmlValueError); + }; + + match obj { + AmlValue::String(ref string) => { + if indices.len() != 1 { + return Err(AmlError::AmlValueError); } - } - }, - AmlValue::String(s) => if let Some(ref mut namespace) = *ACPI_TABLE.namespace.write() { - namespace.insert(s, value); - }, - _ => return Err(AmlError::AmlValueError) + + let mut bytes = string.clone().into_bytes(); + bytes[indices[0] as usize] = value.get_as_integer()? as u8; + + let string = String::from_utf8(bytes).unwrap(); + namespace.insert(name, AmlValue::String(string)); + }, + AmlValue::Buffer(ref b) => { + if indices.len() != 1 { + return Err(AmlError::AmlValueError); + } + + let mut b = b.clone(); + b[indices[0] as usize] = value.get_as_integer()? as u8; + + namespace.insert(name, AmlValue::Buffer(b)); + }, + AmlValue::Package(ref p) => { + // TODO: Nested references need to be handled here + if indices.len() < 0 { + return Err(AmlError::AmlValueError); + } + + let mut p = p.clone(); +// let ref mut current = p; + + p[indices[0] as usize] = value; + + namespace.insert(name, AmlValue::Package(p)); + }, + _ => return Err(AmlError::AmlValueError) + } } Ok(()) } + pub fn modify(&mut self, name: AmlValue, value: AmlValue) -> Result<(), AmlError> { + match name { + AmlValue::ObjectReference(r) => match r { + ObjectReference::ArgObj(_) => Err(AmlError::AmlValueError), + ObjectReference::LocalObj(i) => self.modify_local_obj(i as usize, value), + ObjectReference::Object(s) => self.modify_object(s, value), + ObjectReference::Index(c, v) => { + let idx = v.get_as_integer()?; + match *c { + AmlValue::ObjectReference(r) => match r { + ObjectReference::Object(s) => self.modify_index_final(s, value, vec!(idx)), + _ => Err(AmlError::AmlValueError) + }, + _ => Err(AmlError::AmlValueError) + } + } + }, + AmlValue::String(s) => self.modify_object(s, value), + _ => Err(AmlError::AmlValueError) + } + } + pub fn get(&self, name: AmlValue) -> Result { Ok(match name { AmlValue::ObjectReference(r) => match r { From f0a185741a216557f16dedd165efc2e1aca67f9d Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Sun, 13 Aug 2017 16:13:57 +0200 Subject: [PATCH 100/113] Implemented recursive index modifications --- src/acpi/aml/parser.rs | 92 +++++++++++++++++++++++------------------- 1 file changed, 51 insertions(+), 41 deletions(-) diff --git a/src/acpi/aml/parser.rs b/src/acpi/aml/parser.rs index b5251d5..f592d7c 100644 --- a/src/acpi/aml/parser.rs +++ b/src/acpi/aml/parser.rs @@ -299,52 +299,62 @@ impl AmlExecutionContext { fn modify_index_final(&mut self, name: String, value: AmlValue, indices: Vec) -> Result<(), AmlError> { if let Some(ref mut namespace) = *ACPI_TABLE.namespace.write() { - let obj = if let Some(s) = namespace.get(&name) { + let mut obj = if let Some(s) = namespace.get(&name) { s.clone() } else { return Err(AmlError::AmlValueError); }; - - match obj { - AmlValue::String(ref string) => { - if indices.len() != 1 { - return Err(AmlError::AmlValueError); - } - - let mut bytes = string.clone().into_bytes(); - bytes[indices[0] as usize] = value.get_as_integer()? as u8; - - let string = String::from_utf8(bytes).unwrap(); - namespace.insert(name, AmlValue::String(string)); - }, - AmlValue::Buffer(ref b) => { - if indices.len() != 1 { - return Err(AmlError::AmlValueError); - } - - let mut b = b.clone(); - b[indices[0] as usize] = value.get_as_integer()? as u8; - - namespace.insert(name, AmlValue::Buffer(b)); - }, - AmlValue::Package(ref p) => { - // TODO: Nested references need to be handled here - if indices.len() < 0 { - return Err(AmlError::AmlValueError); - } - - let mut p = p.clone(); -// let ref mut current = p; - - p[indices[0] as usize] = value; - - namespace.insert(name, AmlValue::Package(p)); - }, - _ => return Err(AmlError::AmlValueError) - } - } - Ok(()) + obj = self.modify_index_core(obj, value, indices)?; + + namespace.insert(name, obj); + Ok(()) + } else { + Err(AmlError::AmlValueError) + } + } + + fn modify_index_core(&self, obj: AmlValue, value: AmlValue, indices: Vec) -> Result { + match obj { + AmlValue::String(ref string) => { + if indices.len() != 1 { + return Err(AmlError::AmlValueError); + } + + let mut bytes = string.clone().into_bytes(); + bytes[indices[0] as usize] = value.get_as_integer()? as u8; + + let string = String::from_utf8(bytes).unwrap(); + + Ok(AmlValue::String(string)) + }, + AmlValue::Buffer(ref b) => { + if indices.len() != 1 { + return Err(AmlError::AmlValueError); + } + + let mut b = b.clone(); + b[indices[0] as usize] = value.get_as_integer()? as u8; + + Ok(AmlValue::Buffer(b)) + }, + AmlValue::Package(ref p) => { + if indices.len() < 0 { + return Err(AmlError::AmlValueError); + } + + let mut p = p.clone(); + + if indices.len() == 1 { + p[indices[0] as usize] = value; + } else { + p[indices[0] as usize] = self.modify_index_core(p[indices[0] as usize].clone(), value, indices[1..].to_vec())?; + } + + Ok(AmlValue::Package(p)) + }, + _ => return Err(AmlError::AmlValueError) + } } pub fn modify(&mut self, name: AmlValue, value: AmlValue) -> Result<(), AmlError> { From aa35967f72fd930d8754751122615d8f06764dc6 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Sun, 13 Aug 2017 19:02:25 +0200 Subject: [PATCH 101/113] Made index modification recursion resolve --- src/acpi/aml/parser.rs | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/src/acpi/aml/parser.rs b/src/acpi/aml/parser.rs index f592d7c..d40b02f 100644 --- a/src/acpi/aml/parser.rs +++ b/src/acpi/aml/parser.rs @@ -357,22 +357,29 @@ impl AmlExecutionContext { } } + pub fn modify_index(&mut self, name: AmlValue, value: AmlValue, indices: Vec) -> Result<(), AmlError>{ + match name { + AmlValue::ObjectReference(r) => match r { + ObjectReference::Object(s) => self.modify_index_final(s, value, indices), + ObjectReference::Index(c, v) => { + let mut indices = indices.clone(); + indices.push(v.get_as_integer()?); + + self.modify_index(*c, value, indices) + }, + _ => Err(AmlError::AmlValueError) + }, + _ => Err(AmlError::AmlValueError) + } + } + pub fn modify(&mut self, name: AmlValue, value: AmlValue) -> Result<(), AmlError> { match name { AmlValue::ObjectReference(r) => match r { ObjectReference::ArgObj(_) => Err(AmlError::AmlValueError), ObjectReference::LocalObj(i) => self.modify_local_obj(i as usize, value), ObjectReference::Object(s) => self.modify_object(s, value), - ObjectReference::Index(c, v) => { - let idx = v.get_as_integer()?; - match *c { - AmlValue::ObjectReference(r) => match r { - ObjectReference::Object(s) => self.modify_index_final(s, value, vec!(idx)), - _ => Err(AmlError::AmlValueError) - }, - _ => Err(AmlError::AmlValueError) - } - } + ObjectReference::Index(c, v) => self.modify_index(*c, value, vec!(v.get_as_integer()?)) }, AmlValue::String(s) => self.modify_object(s, value), _ => Err(AmlError::AmlValueError) From d5d156a3d21377f80686010fa2188ebd89e9d33f Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Sat, 19 Aug 2017 15:10:47 +0100 Subject: [PATCH 102/113] Implemented buffer field index modify --- src/acpi/aml/parser.rs | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/acpi/aml/parser.rs b/src/acpi/aml/parser.rs index d40b02f..3470c75 100644 --- a/src/acpi/aml/parser.rs +++ b/src/acpi/aml/parser.rs @@ -1,6 +1,7 @@ use collections::string::String; use collections::btree_map::BTreeMap; use collections::vec::Vec; +use alloc::boxed::Box; use spin::RwLockWriteGuard; @@ -314,7 +315,7 @@ impl AmlExecutionContext { } } - fn modify_index_core(&self, obj: AmlValue, value: AmlValue, indices: Vec) -> Result { + fn modify_index_core(&mut self, obj: AmlValue, value: AmlValue, indices: Vec) -> Result { match obj { AmlValue::String(ref string) => { if indices.len() != 1 { @@ -338,6 +339,18 @@ impl AmlExecutionContext { Ok(AmlValue::Buffer(b)) }, + AmlValue::BufferField(ref b) => { + if indices.len() != 1 { + return Err(AmlError::AmlValueError); + } + + let mut idx = indices[0]; + idx += b.index.get_as_integer()?; + + self.modify(AmlValue::ObjectReference(ObjectReference::Index(b.source_buf.clone(), Box::new(AmlValue::Integer(idx.clone())))), value); + + Ok(AmlValue::BufferField(b.clone())) + }, AmlValue::Package(ref p) => { if indices.len() < 0 { return Err(AmlError::AmlValueError); @@ -367,7 +380,13 @@ impl AmlExecutionContext { self.modify_index(*c, value, indices) }, - _ => Err(AmlError::AmlValueError) + ObjectReference::ArgObj(_) => Err(AmlError::AmlValueError), + ObjectReference::LocalObj(i) => { + let v = self.local_vars[i as usize].clone(); + self.local_vars[i as usize] = self.modify_index_core(v, value, indices)?; + + Ok(()) + } }, _ => Err(AmlError::AmlValueError) } From b78f7139b9b64ff04f34b4bfdc4a0ad161ba03e3 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Tue, 29 Aug 2017 09:38:36 +0100 Subject: [PATCH 103/113] Completed Get method --- src/acpi/aml/parser.rs | 86 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 77 insertions(+), 9 deletions(-) diff --git a/src/acpi/aml/parser.rs b/src/acpi/aml/parser.rs index 3470c75..7ef78e7 100644 --- a/src/acpi/aml/parser.rs +++ b/src/acpi/aml/parser.rs @@ -405,6 +405,82 @@ impl AmlExecutionContext { } } + fn get_index_final(&self, name: String, indices: Vec) -> Result { + if let Some(ref namespace) = *ACPI_TABLE.namespace.read() { + let obj = if let Some(s) = namespace.get(&name) { + s.clone() + } else { + return Err(AmlError::AmlValueError); + }; + + self.get_index_core(obj, indices) + } else { + Err(AmlError::AmlValueError) + } + } + + fn get_index_core(&self, obj: AmlValue, indices: Vec) -> Result { + match obj { + AmlValue::String(ref string) => { + if indices.len() != 1 { + return Err(AmlError::AmlValueError); + } + + let mut bytes = string.clone().into_bytes(); + Ok(AmlValue::Integer(bytes[indices[0] as usize] as u64)) + }, + AmlValue::Buffer(ref b) => { + if indices.len() != 1 { + return Err(AmlError::AmlValueError); + } + + Ok(AmlValue::Integer(b[indices[0] as usize] as u64)) + }, + AmlValue::BufferField(ref b) => { + if indices.len() != 1 { + return Err(AmlError::AmlValueError); + } + + let mut idx = indices[0]; + idx += b.index.get_as_integer()?; + + Ok(AmlValue::Integer(b.source_buf.get_as_buffer()?[idx as usize] as u64)) + }, + AmlValue::Package(ref p) => { + if indices.len() < 0 { + return Err(AmlError::AmlValueError); + } + + if indices.len() == 1 { + Ok(p[indices[0] as usize].clone()) + } else { + self.get_index_core(p[indices[0] as usize].clone(), indices[1..].to_vec()) + } + }, + _ => Err(AmlError::AmlValueError) + } + } + + pub fn get_index(&self, name: AmlValue, indices: Vec) -> Result{ + match name { + AmlValue::ObjectReference(r) => match r { + ObjectReference::Object(s) => self.get_index_final(s, indices), + ObjectReference::Index(c, v) => { + let mut indices = indices.clone(); + indices.push(v.get_as_integer()?); + + self.get_index(*c, indices) + }, + ObjectReference::ArgObj(_) => Err(AmlError::AmlValueError), + ObjectReference::LocalObj(i) => { + let v = self.local_vars[i as usize].clone(); + self.get_index_core(v, indices) + } + }, + _ => Err(AmlError::AmlValueError) + } + } + pub fn get(&self, name: AmlValue) -> Result { Ok(match name { AmlValue::ObjectReference(r) => match r { @@ -417,15 +493,7 @@ impl AmlExecutionContext { AmlValue::None } } else { AmlValue::None }, - ObjectReference::Index(c, v) => if let Some(ref mut namespace) = *ACPI_TABLE.namespace.write() { - let idx = v.get_as_integer()? as usize; - match *c { - AmlValue::Package(p) => p[idx].clone(), - _ => AmlValue::None - } - } else { - AmlValue::None - } + ObjectReference::Index(c, v) => self.get_index(*c, vec!(v.get_as_integer()?))?, }, AmlValue::String(ref s) => if let Some(ref namespace) = *ACPI_TABLE.namespace.read() { if let Some(o) = namespace.get(s) { From 60edb9da68a16ea947ee1fb07a58da8c7669fe6a Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Tue, 29 Aug 2017 10:11:01 +0100 Subject: [PATCH 104/113] Implemented type checking and coersion upon store --- src/acpi/aml/namespace.rs | 38 +++++++++++++++++++++++++++++++++++++- src/acpi/aml/parser.rs | 14 ++++++++++++-- 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index 3dcdb25..64ebb05 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -123,7 +123,43 @@ impl Debug for AmlValue { fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { Ok(()) } } -impl AmlValue { +impl AmlValue { + pub fn get_as_type(&self, t: AmlValue) -> Result { + match t { + AmlValue::None => Ok(AmlValue::None), + AmlValue::Uninitialized => Ok(self.clone()), + AmlValue::Alias(_) => match *self { + AmlValue::Alias(_) => Ok(self.clone()), + _ => Err(AmlError::AmlValueError) + }, + AmlValue::Buffer(_) => Ok(AmlValue::Buffer(self.get_as_buffer()?)), + AmlValue::BufferField(_) => Ok(AmlValue::BufferField(self.get_as_buffer_field()?)), + AmlValue::DDBHandle(_) => Ok(AmlValue::DDBHandle(self.get_as_ddb_handle()?)), + AmlValue::DebugObject => match *self { + AmlValue::DebugObject => Ok(self.clone()), + _ => Err(AmlError::AmlValueError) + }, + AmlValue::Device(_) => Ok(AmlValue::Device(self.get_as_device()?)), + AmlValue::Event(_) => Ok(AmlValue::Event(self.get_as_event()?)), + AmlValue::FieldUnit(_) => Ok(AmlValue::FieldUnit(self.get_as_field_unit()?)), + AmlValue::Integer(_) => Ok(AmlValue::Integer(self.get_as_integer()?)), + AmlValue::IntegerConstant(_) => Ok(AmlValue::IntegerConstant(self.get_as_integer_constant()?)), + AmlValue::Method(_) => Ok(AmlValue::Method(self.get_as_method()?)), + AmlValue::Mutex(_) => Ok(AmlValue::Mutex(self.get_as_mutex()?)), + AmlValue::ObjectReference(_) => Ok(AmlValue::ObjectReference(self.get_as_object_reference()?)), + AmlValue::OperationRegion(_) => match *self { + AmlValue::OperationRegion(_) => Ok(self.clone()), + _ => Err(AmlError::AmlValueError) + }, + AmlValue::Package(_) => Ok(AmlValue::Package(self.get_as_package()?)), + AmlValue::String(_) => Ok(AmlValue::String(self.get_as_string()?)), + AmlValue::PowerResource(_) => Ok(AmlValue::PowerResource(self.get_as_power_resource()?)), + AmlValue::Processor(_) => Ok(AmlValue::Processor(self.get_as_processor()?)), + AmlValue::RawDataBuffer(_) => Ok(AmlValue::RawDataBuffer(self.get_as_raw_data_buffer()?)), + AmlValue::ThermalZone(_) => Ok(AmlValue::ThermalZone(self.get_as_thermal_zone()?)) + } + } + pub fn get_as_buffer(&self) -> Result, AmlError> { match *self { AmlValue::Buffer(ref b) => Ok(b.clone()), diff --git a/src/acpi/aml/parser.rs b/src/acpi/aml/parser.rs index 7ef78e7..3b382d4 100644 --- a/src/acpi/aml/parser.rs +++ b/src/acpi/aml/parser.rs @@ -285,13 +285,23 @@ impl AmlExecutionContext { } fn modify_local_obj(&mut self, local: usize, value: AmlValue) -> Result<(), AmlError> { - self.local_vars[local] = value; + self.local_vars[local] = value.get_as_type(self.local_vars[local].clone())?; Ok(()) } fn modify_object(&mut self, name: String, value: AmlValue) -> Result<(), AmlError> { if let Some(ref mut namespace) = *ACPI_TABLE.namespace.write() { - namespace.insert(name, value); + let coercion_obj = { + let obj = namespace.get(&name); + + if let Some(o) = obj { + o.clone() + } else { + AmlValue::Uninitialized + } + }; + + namespace.insert(name, value.get_as_type(coercion_obj)?); Ok(()) } else { Err(AmlError::AmlHardFatal) From 71c53014482ac9dbfa7947b0b531972f2876ffe5 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Tue, 29 Aug 2017 11:32:48 +0100 Subject: [PATCH 105/113] Implemented concat --- src/acpi/aml/namespace.rs | 24 ++++++++++++++++++ src/acpi/aml/type2opcode.rs | 50 ++++++++++++++++++++++++++++++++++--- 2 files changed, 71 insertions(+), 3 deletions(-) diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index 64ebb05..64f02ab 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -4,6 +4,7 @@ use collections::string::ToString; use collections::vec::Vec; use core::fmt::{Debug, Formatter, Error}; +use core::str::FromStr; use super::termlist::parse_term_list; use super::namedobj::{ RegionSpace, FieldFlags }; @@ -124,6 +125,29 @@ impl Debug for AmlValue { } impl AmlValue { + pub fn get_type_string(&self) -> String { + match *self { + AmlValue::Uninitialized => String::from_str("[Uninitialized Object]").unwrap(), + AmlValue::Integer(_) => String::from_str("[Integer]").unwrap(), + AmlValue::String(_) => String::from_str("[String]").unwrap(), + AmlValue::Buffer(_) => String::from_str("[Buffer]").unwrap(), + AmlValue::Package(_) => String::from_str("[Package]").unwrap(), + AmlValue::FieldUnit(_) => String::from_str("[Field]").unwrap(), + AmlValue::Device(_) => String::from_str("[Device]").unwrap(), + AmlValue::Event(_) => String::from_str("[Event]").unwrap(), + AmlValue::Method(_) => String::from_str("[Control Method]").unwrap(), + AmlValue::Mutex(_) => String::from_str("[Mutex]").unwrap(), + AmlValue::OperationRegion(_) => String::from_str("[Operation Region]").unwrap(), + AmlValue::PowerResource(_) => String::from_str("[Power Resource]").unwrap(), + AmlValue::Processor(_) => String::from_str("[Processor]").unwrap(), + AmlValue::ThermalZone(_) => String::from_str("[Thermal Zone]").unwrap(), + AmlValue::BufferField(_) => String::from_str("[Buffer Field]").unwrap(), + AmlValue::DDBHandle(_) => String::from_str("[DDB Handle]").unwrap(), + AmlValue::DebugObject => String::from_str("[Debug Object]").unwrap(), + _ => String::new() + } + } + pub fn get_as_type(&self, t: AmlValue) -> Result { match t { AmlValue::None => Ok(AmlValue::None), diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index 20dc756..5802584 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -1106,16 +1106,60 @@ fn parse_def_concat(data: &[u8], }) } - // TODO: Compute the result - // TODO: Store the result parser_opcode!(data, 0x73); let lhs = parse_term_arg(&data[1..], ctx)?; let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; + let result = match lhs.val { + AmlValue::Integer(i) => { + let j = AmlValue::Integer(rhs.val.get_as_integer()?); + + let mut first = lhs.val.get_as_buffer()?.clone(); + let mut second = j.get_as_buffer()?.clone(); + + first.append(&mut second); + + AmlValue::Buffer(first) + }, + AmlValue::String(s) => { + let t = if let Ok(t) = rhs.val.get_as_string() { + t + } else { + rhs.val.get_type_string() + }; + + AmlValue::String(format!("{}{}", s, t)) + }, + AmlValue::Buffer(b) => { + let mut b = b.clone(); + let mut c = if let Ok(c) = rhs.val.get_as_buffer() { + c.clone() + } else { + AmlValue::String(rhs.val.get_type_string()).get_as_buffer()?.clone() + }; + + b.append(&mut c); + + AmlValue::Buffer(b) + }, + _ => { + let first = lhs.val.get_type_string(); + let second = if let Ok(second) = rhs.val.get_as_string() { + second + } else { + rhs.val.get_type_string() + }; + + AmlValue::String(format!("{}{}", first, second)) + } + }; + + ctx.modify(target.val, result.clone())?; + Ok(AmlParseType { - val: AmlValue::Uninitialized, + val: result, len: 1 + lhs.len + rhs.len + target.len }) } From d75dfd3c20eeb3a54afed3428a5cc41a84d31209 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Tue, 29 Aug 2017 12:02:03 +0100 Subject: [PATCH 106/113] Implemented externam --- src/acpi/aml/namedobj.rs | 37 +++++++++++++++++++++++++++++++++++++ src/acpi/aml/parser.rs | 12 ++++++++++-- src/acpi/aml/type2opcode.rs | 34 +++++++++++++++++++++++++++++++--- 3 files changed, 78 insertions(+), 5 deletions(-) diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index ecd761e..1d2a8e5 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -96,6 +96,7 @@ pub fn parse_named_obj(data: &[u8], parse_def_create_field, parse_def_data_region, parse_def_event, + parse_def_external, parse_def_device, parse_def_op_region, parse_def_field, @@ -928,3 +929,39 @@ fn parse_def_thermal_zone(data: &[u8], len: 2 + pkg_len }) } + +fn parse_def_external(data: &[u8], + ctx: &mut AmlExecutionContext) -> ParseResult { + match ctx.state { + ExecutionState::EXECUTING => (), + _ => return Ok(AmlParseType { + val: AmlValue::None, + len: 0 as usize + }) + } + + parser_opcode_extended!(data, 0x15); + + let object_name = parse_name_string(&data[1..], ctx)?; + let object_type = data[1 + object_name.len]; + let argument_count = data[2 + object_name.len]; + + let local_scope_string = get_namespace_string(ctx.scope.clone(), object_name.val)?; + + let obj = match object_type { + 8 => AmlValue::Method(Method { + arg_count: argument_count, + serialized: false, + sync_level: 0, + term_list: vec!() + }), + _ => AmlValue::Uninitialized + }; + + ctx.add_to_namespace(local_scope_string, obj)?; + + Ok(AmlParseType { + val: AmlValue::None, + len: 3 + object_name.len + }) +} diff --git a/src/acpi/aml/parser.rs b/src/acpi/aml/parser.rs index 3b382d4..e956c02 100644 --- a/src/acpi/aml/parser.rs +++ b/src/acpi/aml/parser.rs @@ -245,8 +245,16 @@ impl AmlExecutionContext { let mut namespace = ACPI_TABLE.namespace.write(); if let Some(ref mut namespace) = *namespace { - if namespace.contains_key(&name) { - return Err(AmlError::AmlValueError); + if let Some(obj) = namespace.get(&name) { + match *obj { + AmlValue::Uninitialized => (), + AmlValue::Method(ref m) => { + if m.term_list.len() != 0 { + return Err(AmlError::AmlValueError); + } + }, + _ => return Err(AmlError::AmlValueError) + } } self.namespace_delta.push(name.clone()); diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index 5802584..09c3b93 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -977,16 +977,44 @@ fn parse_def_concat_res(data: &[u8], }) } - // TODO: Compute the result - // TODO: Store the result, if appropriate parser_opcode!(data, 0x84); let lhs = parse_term_arg(&data[1..], ctx)?; let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?; let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?; + + let mut buf1 = lhs.val.get_as_buffer()?.clone(); + let mut buf2 = rhs.val.get_as_buffer()?.clone(); + + if buf1.len() == 1 || buf2.len() == 1 { + return Err(AmlError::AmlValueError); + } + + if buf1.len() >= 2 && buf1[buf1.len() - 2] == 0x79 { + buf1 = buf1[0..buf1.len() - 2].to_vec(); + } + + if buf2.len() >= 2 && buf2[buf2.len() - 2] == 0x79 { + buf2 = buf2[0..buf2.len() - 2].to_vec(); + } + + buf1.append(&mut buf2); + buf1.push(0x79); + + let mut checksum: u8 = 0; + let loopbuf = buf1.clone(); + for b in loopbuf { + checksum += b; + } + + checksum = (!checksum) + 1; + buf1.push(checksum); + + let res = AmlValue::Buffer(buf1); + ctx.modify(target.val, res.clone())?; Ok(AmlParseType { - val: AmlValue::Uninitialized, + val: res, len: 1 + lhs.len + rhs.len + target.len }) } From d23241d8007f4571d67dc6b2255a8a92621d51f3 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Tue, 29 Aug 2017 12:25:41 +0100 Subject: [PATCH 107/113] Implemented copy --- src/acpi/aml/parser.rs | 27 +++++++++++++++++++++++++++ src/acpi/aml/type2opcode.rs | 4 +++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/acpi/aml/parser.rs b/src/acpi/aml/parser.rs index e956c02..13c51a9 100644 --- a/src/acpi/aml/parser.rs +++ b/src/acpi/aml/parser.rs @@ -423,6 +423,33 @@ impl AmlExecutionContext { } } + fn copy_local_obj(&mut self, local: usize, value: AmlValue) -> Result<(), AmlError> { + self.local_vars[local] = value; + Ok(()) + } + + fn copy_object(&mut self, name: String, value: AmlValue) -> Result<(), AmlError> { + if let Some(ref mut namespace) = *ACPI_TABLE.namespace.write() { + namespace.insert(name, value); + Ok(()) + } else { + Err(AmlError::AmlHardFatal) + } + } + + pub fn copy(&mut self, name: AmlValue, value: AmlValue) -> Result<(), AmlError> { + match name { + AmlValue::ObjectReference(r) => match r { + ObjectReference::ArgObj(_) => Err(AmlError::AmlValueError), + ObjectReference::LocalObj(i) => self.copy_local_obj(i as usize, value), + ObjectReference::Object(s) => self.copy_object(s, value), + ObjectReference::Index(c, v) => self.modify_index(*c, value, vec!(v.get_as_integer()?)) + }, + AmlValue::String(s) => self.copy_object(s, value), + _ => Err(AmlError::AmlValueError) + } + } + fn get_index_final(&self, name: String, indices: Vec) -> Result { if let Some(ref namespace) = *ACPI_TABLE.namespace.read() { let obj = if let Some(s) = namespace.get(&name) { diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index 09c3b93..f193575 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -1118,8 +1118,10 @@ fn parse_def_copy_object(data: &[u8], let source = parse_term_arg(&data[1..], ctx)?; let destination = parse_simple_name(&data[1 + source.len..], ctx)?; + ctx.copy(destination.val, source.val.clone())?; + Ok(AmlParseType { - val: AmlValue::Uninitialized, + val: source.val, len: 1 + source.len + destination.len }) } From 9f55367906dbf13492f4b05a5e678d70de14b0a9 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Tue, 29 Aug 2017 17:29:07 +0100 Subject: [PATCH 108/113] Implemented notification API --- src/acpi/aml/namedobj.rs | 17 +++++++++++++---- src/acpi/aml/namespace.rs | 24 +++++++++++++++++++----- src/acpi/aml/type1opcode.rs | 28 +++++++++++++++++++++++++++- 3 files changed, 59 insertions(+), 10 deletions(-) diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index 1d2a8e5..bd813a8 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -1,10 +1,12 @@ use alloc::boxed::Box; use collections::string::String; +use collections::btree_map::BTreeMap; use super::AmlError; use super::parser::{ AmlParseType, ParseResult, AmlParseTypeGeneric, AmlExecutionContext, ExecutionState }; use super::namespace::{AmlValue, ObjectReference, FieldSelector, Method, get_namespace_string, - Accessor, BufferField, FieldUnit, Processor, PowerResource, OperationRegion}; + Accessor, BufferField, FieldUnit, Processor, PowerResource, OperationRegion, + Device, ThermalZone}; use super::namestring::{parse_name_string, parse_name_seg}; use super::termlist::{parse_term_arg, parse_object_list}; use super::pkglength::parse_pkg_length; @@ -428,7 +430,10 @@ fn parse_def_device(data: &[u8], parse_object_list(&data[2 + pkg_length_len + name.len .. 2 + pkg_length], &mut local_ctx)?; - ctx.add_to_namespace(local_scope_string, AmlValue::Device(local_ctx.namespace_delta.clone()))?; + ctx.add_to_namespace(local_scope_string, AmlValue::Device(Device { + obj_list: local_ctx.namespace_delta.clone(), + notify_methods: BTreeMap::new() + }))?; Ok(AmlParseType { val: AmlValue::None, @@ -893,7 +898,8 @@ fn parse_def_processor(data: &[u8], ctx.add_to_namespace(local_scope_string, AmlValue::Processor(Processor { proc_id: proc_id, p_blk: if p_blk_len > 0 { Some(p_blk_addr) } else { None }, - obj_list: local_ctx.namespace_delta.clone() + obj_list: local_ctx.namespace_delta.clone(), + notify_methods: BTreeMap::new() }))?; Ok(AmlParseType { @@ -922,7 +928,10 @@ fn parse_def_thermal_zone(data: &[u8], let mut local_ctx = AmlExecutionContext::new(local_scope_string.clone()); parse_object_list(&data[2 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_ctx)?; - ctx.add_to_namespace(local_scope_string, AmlValue::ThermalZone(local_ctx.namespace_delta.clone()))?; + ctx.add_to_namespace(local_scope_string, AmlValue::ThermalZone(ThermalZone { + obj_list: local_ctx.namespace_delta.clone(), + notify_methods: BTreeMap::new() + }))?; Ok(AmlParseType { val: AmlValue::None, diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index 64f02ab..ca51fe5 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -2,6 +2,7 @@ use alloc::boxed::Box; use collections::string::String; use collections::string::ToString; use collections::vec::Vec; +use collections::btree_map::BTreeMap; use core::fmt::{Debug, Formatter, Error}; use core::str::FromStr; @@ -57,11 +58,24 @@ pub struct FieldUnit { pub length: usize } +#[derive(Clone)] +pub struct Device { + pub obj_list: Vec, + pub notify_methods: BTreeMap> +} + +#[derive(Clone)] +pub struct ThermalZone { + pub obj_list: Vec, + pub notify_methods: BTreeMap> +} + #[derive(Clone)] pub struct Processor { pub proc_id: u8, pub p_blk: Option, - pub obj_list: Vec + pub obj_list: Vec, + pub notify_methods: BTreeMap> } #[derive(Clone)] @@ -103,7 +117,7 @@ pub enum AmlValue { BufferField(BufferField), DDBHandle(Vec), DebugObject, - Device(Vec), + Device(Device), Event(u64), FieldUnit(FieldUnit), Integer(u64), @@ -117,7 +131,7 @@ pub enum AmlValue { PowerResource(PowerResource), Processor(Processor), RawDataBuffer(Vec), - ThermalZone(Vec) + ThermalZone(ThermalZone) } impl Debug for AmlValue { @@ -246,7 +260,7 @@ impl AmlValue { } } - pub fn get_as_device(&self) -> Result, AmlError> { + pub fn get_as_device(&self) -> Result { match *self { AmlValue::Device(ref s) => Ok(s.clone()), _ => Err(AmlError::AmlValueError) @@ -397,7 +411,7 @@ impl AmlValue { } } - pub fn get_as_thermal_zone(&self) -> Result, AmlError> { + pub fn get_as_thermal_zone(&self) -> Result { match *self { AmlValue::ThermalZone(ref p) => Ok(p.clone()), _ => Err(AmlError::AmlValueError) diff --git a/src/acpi/aml/type1opcode.rs b/src/acpi/aml/type1opcode.rs index 2ea0482..18e43bd 100644 --- a/src/acpi/aml/type1opcode.rs +++ b/src/acpi/aml/type1opcode.rs @@ -177,12 +177,38 @@ fn parse_def_notify(data: &[u8], }) } - // TODO: This requires significantly more infrastructure from the OS itself, see 5.6.6 parser_opcode!(data, 0x86); let object = parse_super_name(&data[1..], ctx)?; let value = parse_term_arg(&data[1 + object.len..], ctx)?; + let number = value.val.get_as_integer()? as u8; + + match ctx.get(object.val)? { + AmlValue::Device(d) => { + if let Some(methods) = d.notify_methods.get(&number) { + for method in methods { + method(); + } + } + }, + AmlValue::Processor(d) => { + if let Some(methods) = d.notify_methods.get(&number) { + for method in methods { + method(); + } + } + }, + AmlValue::ThermalZone(d) => { + if let Some(methods) = d.notify_methods.get(&number) { + for method in methods { + method(); + } + } + }, + _ => return Err(AmlError::AmlValueError) + } + Ok(AmlParseType { val: AmlValue::None, len: 1 + object.len + value.len From c3d07e4caa991b7ea5d22557326ff8a0d44d03cb Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Wed, 30 Aug 2017 19:03:39 +0100 Subject: [PATCH 109/113] Refactored ACPI initialisation code to be better conducive to DDB Handle stuff --- src/acpi/dmar/mod.rs | 34 ++++++++++ src/acpi/fadt.rs | 26 ++++++++ src/acpi/hpet.rs | 22 +++++- src/acpi/madt.rs | 138 ++++++++++++++++++++++++++++++++++++++ src/acpi/mod.rs | 155 +++++++++++++++++++++---------------------- 5 files changed, 294 insertions(+), 81 deletions(-) diff --git a/src/acpi/dmar/mod.rs b/src/acpi/dmar/mod.rs index 02aac83..e2cf184 100644 --- a/src/acpi/dmar/mod.rs +++ b/src/acpi/dmar/mod.rs @@ -5,6 +5,8 @@ use self::drhd::Drhd; use memory::Frame; use paging::{entry, ActivePageTable, PhysicalAddress}; +use super::{ACPI_TABLE, SDT_POINTERS, get_sdt}; + pub mod drhd; /// The DMA Remapping Table @@ -17,6 +19,38 @@ pub struct Dmar { } impl Dmar { + pub fn init(active_table: &mut ActivePageTable) { + if let Some(ref ptrs) = *(SDT_POINTERS.read()) { + let dmar = if let Some(dmar_sdt) = ptrs.get("DMAR") { + Dmar::new(dmar_sdt) + } else { + println!("Unable to find DMAR"); + return; + }; + + if let Some(dmar) = dmar { + println!(" DMAR: {}: {}", dmar.addr_width, dmar.flags); + + for dmar_entry in dmar.iter() { + println!(" {:?}", dmar_entry); + match dmar_entry { + DmarEntry::Drhd(dmar_drhd) => { + let drhd = dmar_drhd.get(active_table); + + println!("VER: {:X}", drhd.version); + println!("CAP: {:X}", drhd.cap); + println!("EXT_CAP: {:X}", drhd.ext_cap); + println!("GCMD: {:X}", drhd.gl_cmd); + println!("GSTS: {:X}", drhd.gl_sts); + println!("RT: {:X}", drhd.root_table); + }, + _ => () + } + } + } + } + } + pub fn new(sdt: &'static Sdt) -> Option { if &sdt.signature == b"DMAR" && sdt.data_len() >= 12 { //Not valid if no local address and flags let addr_width = unsafe { *(sdt.data_address() as *const u8) }; diff --git a/src/acpi/fadt.rs b/src/acpi/fadt.rs index d40d5a1..c6ff36c 100644 --- a/src/acpi/fadt.rs +++ b/src/acpi/fadt.rs @@ -1,6 +1,10 @@ use core::{mem, ptr}; +use collections::string::String; use super::sdt::Sdt; +use super::{ACPI_TABLE, SDT_POINTERS, get_sdt}; + +use paging::ActivePageTable; #[repr(packed)] #[derive(Debug)] @@ -93,4 +97,26 @@ impl Fadt { None } } + + pub fn init(active_table: &mut ActivePageTable) { + if let Some(ref mut ptrs) = *(SDT_POINTERS.write()) { + let fadt = if let Some(fadt_sdt) = ptrs.get("FACP") { + Fadt::new(fadt_sdt) + } else { + println!("Unable to find FADT"); + return; + }; + + if let Some(fadt) = fadt { + println!(" FACP: {:X}", fadt.dsdt); + + let dsdt_sdt = get_sdt(fadt.dsdt as usize, active_table); + let signature = String::from_utf8(dsdt_sdt.signature.to_vec()).expect("Error converting signature to string"); + ptrs.insert(signature, dsdt_sdt); + + let mut fadt_t = ACPI_TABLE.fadt.write(); + *fadt_t = Some(fadt); + } + } + } } diff --git a/src/acpi/hpet.rs b/src/acpi/hpet.rs index 74b14ea..7b92648 100644 --- a/src/acpi/hpet.rs +++ b/src/acpi/hpet.rs @@ -1,11 +1,13 @@ use core::{mem, ptr}; -use super::sdt::Sdt; use core::intrinsics::{volatile_load, volatile_store}; use memory::Frame; use paging::{entry, ActivePageTable, PhysicalAddress, Page, VirtualAddress}; +use super::sdt::Sdt; +use super::{ACPI_TABLE, SDT_POINTERS, get_sdt}; + #[repr(packed)] #[derive(Clone, Copy, Debug, Default)] pub struct GenericAddressStructure { @@ -33,6 +35,24 @@ pub struct Hpet { } impl Hpet { + pub fn init(active_table: &mut ActivePageTable) { + if let Some(ref ptrs) = *(SDT_POINTERS.read()) { + let hpet = if let Some(hpet_sdt) = ptrs.get("HPET") { + Hpet::new(hpet_sdt, active_table) + } else { + println!("Unable to find HPET"); + return; + }; + + if let Some(hpet) = hpet { + println!(" HPET: {:X}", hpet.hpet_number); + + let mut hpet_t = ACPI_TABLE.hpet.write(); + *hpet_t = Some(hpet); + } + } + } + pub fn new(sdt: &'static Sdt, active_table: &mut ActivePageTable) -> Option { if &sdt.signature == b"HPET" && sdt.length as usize >= mem::size_of::() { let s = unsafe { ptr::read((sdt as *const Sdt) as *const Hpet) }; diff --git a/src/acpi/madt.rs b/src/acpi/madt.rs index dac16dc..501bba5 100644 --- a/src/acpi/madt.rs +++ b/src/acpi/madt.rs @@ -1,6 +1,27 @@ use core::mem; +use memory::{allocate_frames, Frame}; +use paging::{entry, ActivePageTable, Page, PhysicalAddress, VirtualAddress}; + use super::sdt::Sdt; +use super::{ACPI_TABLE, SDT_POINTERS, AP_STARTUP, TRAMPOLINE}; + +use core::intrinsics::{atomic_load, atomic_store}; +use core::sync::atomic::Ordering; +use collections::btree_map::BTreeMap; +use collections::string::String; +use collections::vec::Vec; +use alloc::boxed::Box; + +use syscall::io::{Io, Pio}; + +use spin::RwLock; + +use stop::kstop; + +use device::local_apic::LOCAL_APIC; +use interrupt; +use start::{kstart_ap, CPU_COUNT, AP_READY}; /// The Multiple APIC Descriptor Table #[derive(Debug)] @@ -11,6 +32,123 @@ pub struct Madt { } impl Madt { + pub fn init(active_table: &mut ActivePageTable) { + if let Some(ref ptrs) = *(SDT_POINTERS.read()) { + let madt = if let Some(madt_sdt) = ptrs.get("APIC") { + Madt::new(madt_sdt) + } else { + println!("Unable to find MADT"); + return; + }; + + if let Some(madt) = madt { + println!(" APIC: {:>08X}: {}", madt.local_address, madt.flags); + + let local_apic = unsafe { &mut LOCAL_APIC }; + let me = local_apic.id() as u8; + + if local_apic.x2 { + println!(" X2APIC {}", me); + } else { + println!(" XAPIC {}: {:>08X}", me, local_apic.address); + } + + if cfg!(feature = "multi_core"){ + let trampoline_frame = Frame::containing_address(PhysicalAddress::new(TRAMPOLINE)); + let trampoline_page = Page::containing_address(VirtualAddress::new(TRAMPOLINE)); + + // Map trampoline + let result = active_table.map_to(trampoline_page, trampoline_frame, entry::PRESENT | entry::WRITABLE); + result.flush(active_table); + + for madt_entry in madt.iter() { + println!(" {:?}", madt_entry); + match madt_entry { + MadtEntry::LocalApic(ap_local_apic) => if ap_local_apic.id == me { + println!(" This is my local APIC"); + } else { + if ap_local_apic.flags & 1 == 1 { + // Increase CPU ID + CPU_COUNT.fetch_add(1, Ordering::SeqCst); + + // Allocate a stack + let stack_start = allocate_frames(64).expect("no more frames in acpi stack_start").start_address().get() + ::KERNEL_OFFSET; + let stack_end = stack_start + 64 * 4096; + + let ap_ready = TRAMPOLINE as *mut u64; + let ap_cpu_id = unsafe { ap_ready.offset(1) }; + let ap_page_table = unsafe { ap_ready.offset(2) }; + let ap_stack_start = unsafe { ap_ready.offset(3) }; + let ap_stack_end = unsafe { ap_ready.offset(4) }; + let ap_code = unsafe { ap_ready.offset(5) }; + + // Set the ap_ready to 0, volatile + unsafe { atomic_store(ap_ready, 0) }; + unsafe { atomic_store(ap_cpu_id, ap_local_apic.id as u64) }; + unsafe { atomic_store(ap_page_table, active_table.address() as u64) }; + unsafe { atomic_store(ap_stack_start, stack_start as u64) }; + unsafe { atomic_store(ap_stack_end, stack_end as u64) }; + unsafe { atomic_store(ap_code, kstart_ap as u64) }; + AP_READY.store(false, Ordering::SeqCst); + + print!(" AP {}:", ap_local_apic.id); + + // Send INIT IPI + { + let mut icr = 0x4500; + if local_apic.x2 { + icr |= (ap_local_apic.id as u64) << 32; + } else { + icr |= (ap_local_apic.id as u64) << 56; + } + print!(" IPI..."); + local_apic.set_icr(icr); + } + + // Send START IPI + { + //Start at 0x0800:0000 => 0x8000. Hopefully the bootloader code is still there + let ap_segment = (AP_STARTUP >> 12) & 0xFF; + let mut icr = 0x4600 | ap_segment as u64; + + if local_apic.x2 { + icr |= (ap_local_apic.id as u64) << 32; + } else { + icr |= (ap_local_apic.id as u64) << 56; + } + + print!(" SIPI..."); + local_apic.set_icr(icr); + } + + // Wait for trampoline ready + print!(" Wait..."); + while unsafe { atomic_load(ap_ready) } == 0 { + interrupt::pause(); + } + print!(" Trampoline..."); + while ! AP_READY.load(Ordering::SeqCst) { + interrupt::pause(); + } + println!(" Ready"); + + active_table.flush_all(); + } else { + println!(" CPU Disabled"); + } + }, + _ => () + } + } + + // Unmap trampoline + let (result, _frame) = active_table.unmap_return(trampoline_page, false); + result.flush(active_table); + } + } + } + } + pub fn new(sdt: &'static Sdt) -> Option { if &sdt.signature == b"APIC" && sdt.data_len() >= 8 { //Not valid if no local address and flags let local_address = unsafe { *(sdt.data_address() as *const u32) }; diff --git a/src/acpi/mod.rs b/src/acpi/mod.rs index cdd7e0a..96447ff 100644 --- a/src/acpi/mod.rs +++ b/src/acpi/mod.rs @@ -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 collections::vec::Vec; use alloc::boxed::Box; use syscall::io::{Io, Pio}; @@ -27,6 +28,7 @@ use self::sdt::Sdt; use self::xsdt::Xsdt; use self::hpet::Hpet; use self::rxsdt::Rxsdt; +use self::rsdp::RSDP; use self::aml::{is_aml_table, parse_aml_table, AmlError, AmlValue}; @@ -39,6 +41,7 @@ mod sdt; mod xsdt; mod aml; mod rxsdt; +mod rsdp; const TRAMPOLINE: usize = 0x7E00; const AP_STARTUP: usize = TRAMPOLINE + 512; @@ -235,29 +238,68 @@ fn parse_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) { } } -/// Parse the ACPI tables to gather CPU, interrupt, and timer information -pub unsafe fn init(active_table: &mut ActivePageTable) { +fn init_aml_table(sdt: &'static Sdt) { + match parse_aml_table(sdt) { + Ok(_) => println!(": Parsed"), + Err(AmlError::AmlParseError(e)) => println!(": {}", e), + Err(AmlError::AmlInvalidOpCode) => println!(": Invalid opcode"), + Err(AmlError::AmlValueError) => println!(": Type constraints or value bounds not met"), + Err(AmlError::AmlDeferredLoad) => println!(": Deferred load reached top level"), + Err(AmlError::AmlFatalError(_, _, _)) => { + println!(": Fatal error occurred"); + unsafe { kstop(); } + }, + Err(AmlError::AmlHardFatal) => { + println!(": Fatal error occurred"); + unsafe { kstop(); } + } + } +} + +fn init_namespace() { { let mut namespace = ACPI_TABLE.namespace.write(); *namespace = Some(BTreeMap::new()); } - - let start_addr = 0xE0000; - let end_addr = 0xFFFFF; - // Map all of the ACPI RSDP space - { - 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) { - let page = Page::containing_address(VirtualAddress::new(frame.start_address().get())); - let result = active_table.map_to(page, frame, entry::PRESENT | entry::NO_EXECUTE); - result.flush(active_table); + let dsdt: &'static Sdt = if let Some(ref ptrs) = *(SDT_POINTERS.read()) { + if let Some(dsdt_sdt) = ptrs.get("DSDT") { + print!(" DSDT"); + dsdt_sdt + } else { + println!("No DSDT found"); + return; } - } + } else { + return; + }; + init_aml_table(dsdt); + + let ssdt: &'static Sdt = if let Some(ref ptrs) = *(SDT_POINTERS.read()) { + if let Some(ssdt_sdt) = ptrs.get("SSDT") { + print!(" SSDT"); + ssdt_sdt + } else { + println!("No SSDT found"); + return; + } + } else { + return; + }; + + init_aml_table(ssdt); +} + +/// Parse the ACPI tables to gather CPU, interrupt, and timer information +pub unsafe fn init(active_table: &mut ActivePageTable) { + { + let mut sdt_ptrs = SDT_POINTERS.write(); + *sdt_ptrs = Some(BTreeMap::new()); + } + // Search for RSDP - if let Some(rsdp) = RSDP::search(start_addr, end_addr) { + if let Some(rsdp) = RSDP::get_rsdp(active_table) { let rxsdt = get_sdt(rsdp.sdt_address(), active_table); for &c in rxsdt.signature.iter() { @@ -273,40 +315,28 @@ pub unsafe fn init(active_table: &mut ActivePageTable) { 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); + + rxsdt.map_all(active_table); + + for sdt_address in rxsdt.iter() { + let sdt = unsafe { &*(sdt_address as *const Sdt) }; + + let signature = String::from_utf8(sdt.signature.to_vec()).expect("Error converting signature to string"); + { + if let Some(ref mut ptrs) = *(SDT_POINTERS.write()) { + ptrs.insert(signature, sdt); } } } + + Fadt::init(active_table); + Madt::init(active_table); + Dmar::init(active_table); + Hpet::init(active_table); + init_namespace(); } else { println!("NO RSDP FOUND"); } - - /* TODO: Cleanup mapping when looking for RSDP - // Unmap all of the ACPI RSDP space - { - 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) { - let page = Page::containing_address(VirtualAddress::new(frame.start_address().get())); - let result = active_table.unmap(page); - result.flush(active_table); - } - } - */ } pub fn set_global_s_state(state: u8) { @@ -337,6 +367,8 @@ pub fn set_global_s_state(state: u8) { } } +pub static SDT_POINTERS: RwLock>> = RwLock::new(None); + pub struct Acpi { pub rxsdt: RwLock>>, pub fadt: RwLock>, @@ -352,40 +384,3 @@ pub static ACPI_TABLE: Acpi = Acpi { hpet: RwLock::new(None), next_ctx: RwLock::new(0), }; - -/// RSDP -#[derive(Copy, Clone, Debug)] -#[repr(packed)] -pub struct RSDP { - signature: [u8; 8], - checksum: u8, - oemid: [u8; 6], - revision: u8, - rsdt_address: u32, - length: 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 { - for i in 0 .. (end_addr + 1 - start_addr)/16 { - let 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 - } - } -} From 5592484d0714e6b94abbe6ae6fc982800b646b08 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Wed, 30 Aug 2017 19:09:08 +0100 Subject: [PATCH 110/113] Eliminated dead code --- src/acpi/mod.rs | 164 ----------------------------------------------- src/acpi/rsdp.rs | 57 ++++++++++++++++ 2 files changed, 57 insertions(+), 164 deletions(-) create mode 100644 src/acpi/rsdp.rs diff --git a/src/acpi/mod.rs b/src/acpi/mod.rs index 96447ff..a1d5ecc 100644 --- a/src/acpi/mod.rs +++ b/src/acpi/mod.rs @@ -74,170 +74,6 @@ fn get_sdt(sdt_address: usize, active_table: &mut ActivePageTable) -> &'static S sdt } -fn parse_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) { - print!(" "); - for &c in sdt.signature.iter() { - print!("{}", c as char); - } - - if let Some(fadt) = Fadt::new(sdt) { - println!(": {:X}", fadt.dsdt); - - let dsdt = get_sdt(fadt.dsdt as usize, active_table); - parse_sdt(dsdt, active_table); - - let mut fadt_t = ACPI_TABLE.fadt.write(); - *fadt_t = Some(fadt); - } else if let Some(madt) = Madt::new(sdt) { - println!(": {:>08X}: {}", madt.local_address, madt.flags); - - let local_apic = unsafe { &mut LOCAL_APIC }; - - let me = local_apic.id() as u8; - - if local_apic.x2 { - println!(" X2APIC {}", me); - } else { - println!(" XAPIC {}: {:>08X}", me, local_apic.address); - } - - if cfg!(feature = "multi_core"){ - let trampoline_frame = Frame::containing_address(PhysicalAddress::new(TRAMPOLINE)); - let trampoline_page = Page::containing_address(VirtualAddress::new(TRAMPOLINE)); - - // Map trampoline - let result = active_table.map_to(trampoline_page, trampoline_frame, entry::PRESENT | entry::WRITABLE); - result.flush(active_table); - - for madt_entry in madt.iter() { - println!(" {:?}", madt_entry); - match madt_entry { - MadtEntry::LocalApic(ap_local_apic) => if ap_local_apic.id == me { - println!(" This is my local APIC"); - } else { - if ap_local_apic.flags & 1 == 1 { - // Increase CPU ID - CPU_COUNT.fetch_add(1, Ordering::SeqCst); - - // Allocate a stack - let stack_start = allocate_frames(64).expect("no more frames in acpi stack_start").start_address().get() + ::KERNEL_OFFSET; - let stack_end = stack_start + 64 * 4096; - - let ap_ready = TRAMPOLINE as *mut u64; - let ap_cpu_id = unsafe { ap_ready.offset(1) }; - let ap_page_table = unsafe { ap_ready.offset(2) }; - let ap_stack_start = unsafe { ap_ready.offset(3) }; - let ap_stack_end = unsafe { ap_ready.offset(4) }; - let ap_code = unsafe { ap_ready.offset(5) }; - - // Set the ap_ready to 0, volatile - unsafe { atomic_store(ap_ready, 0) }; - unsafe { atomic_store(ap_cpu_id, ap_local_apic.id as u64) }; - unsafe { atomic_store(ap_page_table, active_table.address() as u64) }; - unsafe { atomic_store(ap_stack_start, stack_start as u64) }; - unsafe { atomic_store(ap_stack_end, stack_end as u64) }; - unsafe { atomic_store(ap_code, kstart_ap as u64) }; - AP_READY.store(false, Ordering::SeqCst); - - print!(" AP {}:", ap_local_apic.id); - - // Send INIT IPI - { - let mut icr = 0x4500; - if local_apic.x2 { - icr |= (ap_local_apic.id as u64) << 32; - } else { - icr |= (ap_local_apic.id as u64) << 56; - } - print!(" IPI..."); - local_apic.set_icr(icr); - } - - // Send START IPI - { - //Start at 0x0800:0000 => 0x8000. Hopefully the bootloader code is still there - let ap_segment = (AP_STARTUP >> 12) & 0xFF; - let mut icr = 0x4600 | ap_segment as u64; - - if local_apic.x2 { - icr |= (ap_local_apic.id as u64) << 32; - } else { - icr |= (ap_local_apic.id as u64) << 56; - } - - print!(" SIPI..."); - local_apic.set_icr(icr); - } - - // Wait for trampoline ready - print!(" Wait..."); - while unsafe { atomic_load(ap_ready) } == 0 { - interrupt::pause(); - } - print!(" Trampoline..."); - while ! AP_READY.load(Ordering::SeqCst) { - interrupt::pause(); - } - println!(" Ready"); - - active_table.flush_all(); - } else { - println!(" CPU Disabled"); - } - }, - _ => () - } - } - - // Unmap trampoline - let (result, _frame) = active_table.unmap_return(trampoline_page, false); - result.flush(active_table); - } - } else if let Some(dmar) = Dmar::new(sdt) { - println!(": {}: {}", dmar.addr_width, dmar.flags); - - for dmar_entry in dmar.iter() { - println!(" {:?}", dmar_entry); - match dmar_entry { - DmarEntry::Drhd(dmar_drhd) => { - let drhd = dmar_drhd.get(active_table); - - println!("VER: {:X}", drhd.version); - println!("CAP: {:X}", drhd.cap); - println!("EXT_CAP: {:X}", drhd.ext_cap); - println!("GCMD: {:X}", drhd.gl_cmd); - println!("GSTS: {:X}", drhd.gl_sts); - println!("RT: {:X}", drhd.root_table); - }, - _ => () - } - } - } else if let Some(hpet) = Hpet::new(sdt, active_table) { - println!(": {}", hpet.hpet_number); - - let mut hpet_t = ACPI_TABLE.hpet.write(); - *hpet_t = Some(hpet); - } else if is_aml_table(sdt) { - match parse_aml_table(sdt) { - Ok(_) => println!(": Parsed"), - Err(AmlError::AmlParseError(e)) => println!(": {}", e), - Err(AmlError::AmlInvalidOpCode) => println!(": Invalid opcode"), - Err(AmlError::AmlValueError) => println!(": Type constraints or value bounds not met"), - Err(AmlError::AmlDeferredLoad) => println!(": Deferred load reached top level"), - Err(AmlError::AmlFatalError(_, _, _)) => { - println!(": Fatal error occurred"); - unsafe { kstop(); } - }, - Err(AmlError::AmlHardFatal) => { - println!(": Fatal error occurred"); - unsafe { kstop(); } - } - }; - } else { - println!(": Unknown"); - } -} - fn init_aml_table(sdt: &'static Sdt) { match parse_aml_table(sdt) { Ok(_) => println!(": Parsed"), diff --git a/src/acpi/rsdp.rs b/src/acpi/rsdp.rs new file mode 100644 index 0000000..3e25ec0 --- /dev/null +++ b/src/acpi/rsdp.rs @@ -0,0 +1,57 @@ +use memory::{allocate_frames, Frame}; +use paging::{entry, ActivePageTable, Page, PhysicalAddress, VirtualAddress}; + +/// RSDP +#[derive(Copy, Clone, Debug)] +#[repr(packed)] +pub struct RSDP { + signature: [u8; 8], + checksum: u8, + oemid: [u8; 6], + revision: u8, + rsdt_address: u32, + length: u32, + xsdt_address: u64, + extended_checksum: u8, + reserved: [u8; 3] +} + +impl RSDP { + /// Search for the RSDP + pub fn get_rsdp(active_table: &mut ActivePageTable) -> Option { + let start_addr = 0xE0000; + let end_addr = 0xFFFFF; + + // Map all of the ACPI RSDP space + { + 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) { + let page = Page::containing_address(VirtualAddress::new(frame.start_address().get())); + let result = active_table.map_to(page, frame, entry::PRESENT | entry::NO_EXECUTE); + result.flush(active_table); + } + } + + RSDP::search(start_addr, end_addr) + } + + fn search(start_addr: usize, end_addr: usize) -> Option { + for i in 0 .. (end_addr + 1 - start_addr)/16 { + let 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 + } + } +} From 1bcd8530d254dbb5c2f76bcb376241424c01ee51 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Thu, 31 Aug 2017 10:52:59 +0100 Subject: [PATCH 111/113] Stored signature to include OEM signature and OEM table ID --- src/acpi/aml/type2opcode.rs | 13 +-- src/acpi/dmar/mod.rs | 50 ++++----- src/acpi/fadt.rs | 37 ++++--- src/acpi/hpet.rs | 28 ++--- src/acpi/madt.rs | 200 ++++++++++++++++++------------------ src/acpi/mod.rs | 82 +++++++++------ 6 files changed, 217 insertions(+), 193 deletions(-) diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index f193575..cd94e70 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -11,7 +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; +use acpi::{ACPI_TABLE, SDT_POINTERS}; #[derive(Debug, Clone)] pub enum MatchOpcode { @@ -1346,11 +1346,10 @@ 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 { + if let Some(ref ptrs) = *(SDT_POINTERS.read()) { let sig_str = unsafe { - *(signature.val.get_as_string()?.as_bytes().as_ptr() as *const [u8; 4]) + let sig = *(signature.val.get_as_string()?.as_bytes().as_ptr() as *const [u8; 4]); + String::from_utf8(sig.to_vec()).expect("Error converting signature to string") }; let oem_str = unsafe { *(oem_id.val.get_as_string()?.as_bytes().as_ptr() as *const [u8; 6]) @@ -1358,8 +1357,10 @@ fn parse_def_load_table(data: &[u8], let oem_table_str = unsafe { *(oem_table_id.val.get_as_string()?.as_bytes().as_ptr() as *const [u8; 8]) }; + + let sdt_signature = (sig_str, oem_str, oem_table_str); - let sdt = rxsdt.find(sig_str, oem_str, oem_table_str); + let sdt = ptrs.get(&sdt_signature); if let Some(sdt) = sdt { let hdl = parse_aml_with_scope(sdt, root_path.val.get_as_string()?)?; diff --git a/src/acpi/dmar/mod.rs b/src/acpi/dmar/mod.rs index e2cf184..549f686 100644 --- a/src/acpi/dmar/mod.rs +++ b/src/acpi/dmar/mod.rs @@ -5,7 +5,7 @@ use self::drhd::Drhd; use memory::Frame; use paging::{entry, ActivePageTable, PhysicalAddress}; -use super::{ACPI_TABLE, SDT_POINTERS, get_sdt}; +use super::{ACPI_TABLE, SDT_POINTERS, get_sdt, find_sdt, load_table, get_sdt_signature}; pub mod drhd; @@ -20,32 +20,32 @@ pub struct Dmar { impl Dmar { pub fn init(active_table: &mut ActivePageTable) { - if let Some(ref ptrs) = *(SDT_POINTERS.read()) { - let dmar = if let Some(dmar_sdt) = ptrs.get("DMAR") { - Dmar::new(dmar_sdt) - } else { - println!("Unable to find DMAR"); - return; - }; - - if let Some(dmar) = dmar { - println!(" DMAR: {}: {}", dmar.addr_width, dmar.flags); + let dmar_sdt = find_sdt("DMAR"); + let dmar = if dmar_sdt.len() == 1 { + load_table(get_sdt_signature(dmar_sdt[0])); + Dmar::new(dmar_sdt[0]) + } else { + println!("Unable to find DMAR"); + return; + }; + + if let Some(dmar) = dmar { + println!(" DMAR: {}: {}", dmar.addr_width, dmar.flags); - for dmar_entry in dmar.iter() { - println!(" {:?}", dmar_entry); - match dmar_entry { - DmarEntry::Drhd(dmar_drhd) => { - let drhd = dmar_drhd.get(active_table); + for dmar_entry in dmar.iter() { + println!(" {:?}", dmar_entry); + match dmar_entry { + DmarEntry::Drhd(dmar_drhd) => { + let drhd = dmar_drhd.get(active_table); - println!("VER: {:X}", drhd.version); - println!("CAP: {:X}", drhd.cap); - println!("EXT_CAP: {:X}", drhd.ext_cap); - println!("GCMD: {:X}", drhd.gl_cmd); - println!("GSTS: {:X}", drhd.gl_sts); - println!("RT: {:X}", drhd.root_table); - }, - _ => () - } + println!("VER: {:X}", drhd.version); + println!("CAP: {:X}", drhd.cap); + println!("EXT_CAP: {:X}", drhd.ext_cap); + println!("GCMD: {:X}", drhd.gl_cmd); + println!("GSTS: {:X}", drhd.gl_sts); + println!("RT: {:X}", drhd.root_table); + }, + _ => () } } } diff --git a/src/acpi/fadt.rs b/src/acpi/fadt.rs index c6ff36c..6dd82d8 100644 --- a/src/acpi/fadt.rs +++ b/src/acpi/fadt.rs @@ -2,7 +2,7 @@ use core::{mem, ptr}; use collections::string::String; use super::sdt::Sdt; -use super::{ACPI_TABLE, SDT_POINTERS, get_sdt}; +use super::{ACPI_TABLE, SDT_POINTERS, get_sdt, find_sdt, get_sdt_signature, load_table}; use paging::ActivePageTable; @@ -99,24 +99,27 @@ impl Fadt { } pub fn init(active_table: &mut ActivePageTable) { - if let Some(ref mut ptrs) = *(SDT_POINTERS.write()) { - let fadt = if let Some(fadt_sdt) = ptrs.get("FACP") { - Fadt::new(fadt_sdt) - } else { - println!("Unable to find FADT"); - return; - }; - - if let Some(fadt) = fadt { - println!(" FACP: {:X}", fadt.dsdt); - - let dsdt_sdt = get_sdt(fadt.dsdt as usize, active_table); - let signature = String::from_utf8(dsdt_sdt.signature.to_vec()).expect("Error converting signature to string"); - ptrs.insert(signature, dsdt_sdt); + let fadt_sdt = find_sdt("FACP"); + let fadt = if fadt_sdt.len() == 1 { + load_table(get_sdt_signature(fadt_sdt[0])); + Fadt::new(fadt_sdt[0]) + } else { + println!("Unable to find FADT"); + return; + }; - let mut fadt_t = ACPI_TABLE.fadt.write(); - *fadt_t = Some(fadt); + if let Some(fadt) = fadt { + println!(" FACP: {:X}", fadt.dsdt); + + let dsdt_sdt = get_sdt(fadt.dsdt as usize, active_table); + + let signature = get_sdt_signature(dsdt_sdt); + if let Some(ref mut ptrs) = *(SDT_POINTERS.write()) { + ptrs.insert(signature, dsdt_sdt); } + + let mut fadt_t = ACPI_TABLE.fadt.write(); + *fadt_t = Some(fadt); } } } diff --git a/src/acpi/hpet.rs b/src/acpi/hpet.rs index 7b92648..d2e5ecf 100644 --- a/src/acpi/hpet.rs +++ b/src/acpi/hpet.rs @@ -6,7 +6,7 @@ use memory::Frame; use paging::{entry, ActivePageTable, PhysicalAddress, Page, VirtualAddress}; use super::sdt::Sdt; -use super::{ACPI_TABLE, SDT_POINTERS, get_sdt}; +use super::{ACPI_TABLE, SDT_POINTERS, get_sdt, find_sdt, load_table, get_sdt_signature}; #[repr(packed)] #[derive(Clone, Copy, Debug, Default)] @@ -36,20 +36,20 @@ pub struct Hpet { impl Hpet { pub fn init(active_table: &mut ActivePageTable) { - if let Some(ref ptrs) = *(SDT_POINTERS.read()) { - let hpet = if let Some(hpet_sdt) = ptrs.get("HPET") { - Hpet::new(hpet_sdt, active_table) - } else { - println!("Unable to find HPET"); - return; - }; + let hpet_sdt = find_sdt("HPET"); + let hpet = if hpet_sdt.len() == 1 { + load_table(get_sdt_signature(hpet_sdt[0])); + Hpet::new(hpet_sdt[0], active_table) + } else { + println!("Unable to find HPET"); + return; + }; + + if let Some(hpet) = hpet { + println!(" HPET: {:X}", hpet.hpet_number); - if let Some(hpet) = hpet { - println!(" HPET: {:X}", hpet.hpet_number); - - let mut hpet_t = ACPI_TABLE.hpet.write(); - *hpet_t = Some(hpet); - } + let mut hpet_t = ACPI_TABLE.hpet.write(); + *hpet_t = Some(hpet); } } diff --git a/src/acpi/madt.rs b/src/acpi/madt.rs index 501bba5..c4f922a 100644 --- a/src/acpi/madt.rs +++ b/src/acpi/madt.rs @@ -4,7 +4,7 @@ use memory::{allocate_frames, Frame}; use paging::{entry, ActivePageTable, Page, PhysicalAddress, VirtualAddress}; use super::sdt::Sdt; -use super::{ACPI_TABLE, SDT_POINTERS, AP_STARTUP, TRAMPOLINE}; +use super::{ACPI_TABLE, SDT_POINTERS, AP_STARTUP, TRAMPOLINE, find_sdt, load_table, get_sdt_signature}; use core::intrinsics::{atomic_load, atomic_store}; use core::sync::atomic::Ordering; @@ -33,118 +33,118 @@ pub struct Madt { impl Madt { pub fn init(active_table: &mut ActivePageTable) { - if let Some(ref ptrs) = *(SDT_POINTERS.read()) { - let madt = if let Some(madt_sdt) = ptrs.get("APIC") { - Madt::new(madt_sdt) + let madt_sdt = find_sdt("APIC"); + let madt = if madt_sdt.len() == 1 { + load_table(get_sdt_signature(madt_sdt[0])); + Madt::new(madt_sdt[0]) + } else { + println!("Unable to find MADT"); + return; + }; + + if let Some(madt) = madt { + println!(" APIC: {:>08X}: {}", madt.local_address, madt.flags); + + let local_apic = unsafe { &mut LOCAL_APIC }; + let me = local_apic.id() as u8; + + if local_apic.x2 { + println!(" X2APIC {}", me); } else { - println!("Unable to find MADT"); - return; - }; - - if let Some(madt) = madt { - println!(" APIC: {:>08X}: {}", madt.local_address, madt.flags); + println!(" XAPIC {}: {:>08X}", me, local_apic.address); + } - let local_apic = unsafe { &mut LOCAL_APIC }; - let me = local_apic.id() as u8; + if cfg!(feature = "multi_core"){ + let trampoline_frame = Frame::containing_address(PhysicalAddress::new(TRAMPOLINE)); + let trampoline_page = Page::containing_address(VirtualAddress::new(TRAMPOLINE)); - if local_apic.x2 { - println!(" X2APIC {}", me); - } else { - println!(" XAPIC {}: {:>08X}", me, local_apic.address); - } + // Map trampoline + let result = active_table.map_to(trampoline_page, trampoline_frame, entry::PRESENT | entry::WRITABLE); + result.flush(active_table); - if cfg!(feature = "multi_core"){ - let trampoline_frame = Frame::containing_address(PhysicalAddress::new(TRAMPOLINE)); - let trampoline_page = Page::containing_address(VirtualAddress::new(TRAMPOLINE)); + for madt_entry in madt.iter() { + println!(" {:?}", madt_entry); + match madt_entry { + MadtEntry::LocalApic(ap_local_apic) => if ap_local_apic.id == me { + println!(" This is my local APIC"); + } else { + if ap_local_apic.flags & 1 == 1 { + // Increase CPU ID + CPU_COUNT.fetch_add(1, Ordering::SeqCst); - // Map trampoline - let result = active_table.map_to(trampoline_page, trampoline_frame, entry::PRESENT | entry::WRITABLE); - result.flush(active_table); + // Allocate a stack + let stack_start = allocate_frames(64).expect("no more frames in acpi stack_start").start_address().get() + ::KERNEL_OFFSET; + let stack_end = stack_start + 64 * 4096; - for madt_entry in madt.iter() { - println!(" {:?}", madt_entry); - match madt_entry { - MadtEntry::LocalApic(ap_local_apic) => if ap_local_apic.id == me { - println!(" This is my local APIC"); - } else { - if ap_local_apic.flags & 1 == 1 { - // Increase CPU ID - CPU_COUNT.fetch_add(1, Ordering::SeqCst); + let ap_ready = TRAMPOLINE as *mut u64; + let ap_cpu_id = unsafe { ap_ready.offset(1) }; + let ap_page_table = unsafe { ap_ready.offset(2) }; + let ap_stack_start = unsafe { ap_ready.offset(3) }; + let ap_stack_end = unsafe { ap_ready.offset(4) }; + let ap_code = unsafe { ap_ready.offset(5) }; - // Allocate a stack - let stack_start = allocate_frames(64).expect("no more frames in acpi stack_start").start_address().get() + ::KERNEL_OFFSET; - let stack_end = stack_start + 64 * 4096; + // Set the ap_ready to 0, volatile + unsafe { atomic_store(ap_ready, 0) }; + unsafe { atomic_store(ap_cpu_id, ap_local_apic.id as u64) }; + unsafe { atomic_store(ap_page_table, active_table.address() as u64) }; + unsafe { atomic_store(ap_stack_start, stack_start as u64) }; + unsafe { atomic_store(ap_stack_end, stack_end as u64) }; + unsafe { atomic_store(ap_code, kstart_ap as u64) }; + AP_READY.store(false, Ordering::SeqCst); - let ap_ready = TRAMPOLINE as *mut u64; - let ap_cpu_id = unsafe { ap_ready.offset(1) }; - let ap_page_table = unsafe { ap_ready.offset(2) }; - let ap_stack_start = unsafe { ap_ready.offset(3) }; - let ap_stack_end = unsafe { ap_ready.offset(4) }; - let ap_code = unsafe { ap_ready.offset(5) }; + print!(" AP {}:", ap_local_apic.id); - // Set the ap_ready to 0, volatile - unsafe { atomic_store(ap_ready, 0) }; - unsafe { atomic_store(ap_cpu_id, ap_local_apic.id as u64) }; - unsafe { atomic_store(ap_page_table, active_table.address() as u64) }; - unsafe { atomic_store(ap_stack_start, stack_start as u64) }; - unsafe { atomic_store(ap_stack_end, stack_end as u64) }; - unsafe { atomic_store(ap_code, kstart_ap as u64) }; - AP_READY.store(false, Ordering::SeqCst); - - print!(" AP {}:", ap_local_apic.id); - - // Send INIT IPI - { - let mut icr = 0x4500; - if local_apic.x2 { - icr |= (ap_local_apic.id as u64) << 32; - } else { - icr |= (ap_local_apic.id as u64) << 56; - } - print!(" IPI..."); - local_apic.set_icr(icr); + // Send INIT IPI + { + let mut icr = 0x4500; + if local_apic.x2 { + icr |= (ap_local_apic.id as u64) << 32; + } else { + icr |= (ap_local_apic.id as u64) << 56; } - - // Send START IPI - { - //Start at 0x0800:0000 => 0x8000. Hopefully the bootloader code is still there - let ap_segment = (AP_STARTUP >> 12) & 0xFF; - let mut icr = 0x4600 | ap_segment as u64; - - if local_apic.x2 { - icr |= (ap_local_apic.id as u64) << 32; - } else { - icr |= (ap_local_apic.id as u64) << 56; - } - - print!(" SIPI..."); - local_apic.set_icr(icr); - } - - // Wait for trampoline ready - print!(" Wait..."); - while unsafe { atomic_load(ap_ready) } == 0 { - interrupt::pause(); - } - print!(" Trampoline..."); - while ! AP_READY.load(Ordering::SeqCst) { - interrupt::pause(); - } - println!(" Ready"); - - active_table.flush_all(); - } else { - println!(" CPU Disabled"); + print!(" IPI..."); + local_apic.set_icr(icr); } - }, - _ => () - } - } - // Unmap trampoline - let (result, _frame) = active_table.unmap_return(trampoline_page, false); - result.flush(active_table); + // Send START IPI + { + //Start at 0x0800:0000 => 0x8000. Hopefully the bootloader code is still there + let ap_segment = (AP_STARTUP >> 12) & 0xFF; + let mut icr = 0x4600 | ap_segment as u64; + + if local_apic.x2 { + icr |= (ap_local_apic.id as u64) << 32; + } else { + icr |= (ap_local_apic.id as u64) << 56; + } + + print!(" SIPI..."); + local_apic.set_icr(icr); + } + + // Wait for trampoline ready + print!(" Wait..."); + while unsafe { atomic_load(ap_ready) } == 0 { + interrupt::pause(); + } + print!(" Trampoline..."); + while ! AP_READY.load(Ordering::SeqCst) { + interrupt::pause(); + } + println!(" Ready"); + + active_table.flush_all(); + } else { + println!(" CPU Disabled"); + } + }, + _ => () + } } + + // Unmap trampoline + let (result, _frame) = active_table.unmap_return(trampoline_page, false); + result.flush(active_table); } } } diff --git a/src/acpi/mod.rs b/src/acpi/mod.rs index a1d5ecc..5902ebc 100644 --- a/src/acpi/mod.rs +++ b/src/acpi/mod.rs @@ -97,34 +97,24 @@ fn init_namespace() { let mut namespace = ACPI_TABLE.namespace.write(); *namespace = Some(BTreeMap::new()); } - - let dsdt: &'static Sdt = if let Some(ref ptrs) = *(SDT_POINTERS.read()) { - if let Some(dsdt_sdt) = ptrs.get("DSDT") { - print!(" DSDT"); - dsdt_sdt - } else { - println!("No DSDT found"); - return; - } - } else { - return; - }; - - init_aml_table(dsdt); - let ssdt: &'static Sdt = if let Some(ref ptrs) = *(SDT_POINTERS.read()) { - if let Some(ssdt_sdt) = ptrs.get("SSDT") { - print!(" SSDT"); - ssdt_sdt - } else { - println!("No SSDT found"); - return; - } + let dsdt = find_sdt("DSDT"); + if dsdt.len() == 1 { + print!(" DSDT"); + load_table(get_sdt_signature(dsdt[0])); + init_aml_table(dsdt[0]); } else { + println!("Unable to find DSDT"); return; }; + + let ssdts = find_sdt("SSDT"); - init_aml_table(ssdt); + for ssdt in ssdts { + print!(" SSDT"); + load_table(get_sdt_signature(ssdt)); + init_aml_table(ssdt); + } } /// Parse the ACPI tables to gather CPU, interrupt, and timer information @@ -133,6 +123,11 @@ pub unsafe fn init(active_table: &mut ActivePageTable) { let mut sdt_ptrs = SDT_POINTERS.write(); *sdt_ptrs = Some(BTreeMap::new()); } + + { + let mut order = SDT_ORDER.write(); + *order = Some(vec!()); + } // Search for RSDP if let Some(rsdp) = RSDP::get_rsdp(active_table) { @@ -157,11 +152,9 @@ pub unsafe fn init(active_table: &mut ActivePageTable) { for sdt_address in rxsdt.iter() { let sdt = unsafe { &*(sdt_address as *const Sdt) }; - let signature = String::from_utf8(sdt.signature.to_vec()).expect("Error converting signature to string"); - { - if let Some(ref mut ptrs) = *(SDT_POINTERS.write()) { - ptrs.insert(signature, sdt); - } + let signature = get_sdt_signature(sdt); + if let Some(ref mut ptrs) = *(SDT_POINTERS.write()) { + ptrs.insert(signature, sdt); } } @@ -203,10 +196,38 @@ pub fn set_global_s_state(state: u8) { } } -pub static SDT_POINTERS: RwLock>> = RwLock::new(None); +type SdtSignature = (String, [u8; 6], [u8; 8]); +pub static SDT_POINTERS: RwLock>> = RwLock::new(None); +pub static SDT_ORDER: RwLock>> = RwLock::new(None); + +pub fn find_sdt(name: &str) -> Vec<&'static Sdt> { + let mut sdts: Vec<&'static Sdt> = vec!(); + + if let Some(ref ptrs) = *(SDT_POINTERS.read()) { + for (signature, sdt) in ptrs { + if signature.0 == name { + sdts.push(sdt); + } + } + } + + sdts +} + +pub fn get_sdt_signature(sdt: &'static Sdt) -> SdtSignature { + let signature = String::from_utf8(sdt.signature.to_vec()).expect("Error converting signature to string"); + (signature, sdt.oem_id, sdt.oem_table_id) +} + +pub fn load_table(signature: SdtSignature) { + let mut order = SDT_ORDER.write(); + + if let Some(ref mut o) = *order { + o.push(signature); + } +} pub struct Acpi { - pub rxsdt: RwLock>>, pub fadt: RwLock>, pub namespace: RwLock>>, pub hpet: RwLock>, @@ -214,7 +235,6 @@ 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), From 1cce42b69133f14886da261c1485a5a11b7cff0e Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Thu, 31 Aug 2017 11:07:01 +0100 Subject: [PATCH 112/113] Moved DDB handles over to using signature scheme --- src/acpi/aml/namespace.rs | 6 ++++-- src/acpi/aml/type1opcode.rs | 7 ++++--- src/acpi/aml/type2opcode.rs | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index ca51fe5..6e6dfa9 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -12,6 +12,8 @@ use super::namedobj::{ RegionSpace, FieldFlags }; use super::parser::{AmlExecutionContext, ExecutionState}; use super::AmlError; +use acpi::SdtSignature; + #[derive(Clone)] pub enum FieldSelector { Region(String), @@ -115,7 +117,7 @@ pub enum AmlValue { Alias(String), Buffer(Vec), BufferField(BufferField), - DDBHandle(Vec), + DDBHandle((Vec, SdtSignature)), DebugObject, Device(Device), Event(u64), @@ -252,7 +254,7 @@ impl AmlValue { } } - pub fn get_as_ddb_handle(&self) -> Result, AmlError> { + pub fn get_as_ddb_handle(&self) -> Result<(Vec, SdtSignature), AmlError> { // TODO: Integer conversion match *self { AmlValue::DDBHandle(ref v) => Ok(v.clone()), diff --git a/src/acpi/aml/type1opcode.rs b/src/acpi/aml/type1opcode.rs index 18e43bd..e5c7023 100644 --- a/src/acpi/aml/type1opcode.rs +++ b/src/acpi/aml/type1opcode.rs @@ -7,7 +7,7 @@ use super::namestring::{parse_name_string, parse_super_name}; use time::monotonic; -use acpi::Sdt; +use acpi::{Sdt, load_table, get_sdt_signature}; use super::{parse_aml_table, is_aml_table}; pub fn parse_type1_opcode(data: &[u8], @@ -155,8 +155,9 @@ fn parse_def_load(data: &[u8], let sdt = unsafe { &*(tbl.as_ptr() as *const Sdt) }; if is_aml_table(sdt) { + load_table(get_sdt_signature(sdt)); let delta = parse_aml_table(sdt)?; - ctx.modify(ddb_handle_object.val, AmlValue::DDBHandle(delta)); + ctx.modify(ddb_handle_object.val, AmlValue::DDBHandle((delta, get_sdt_signature(sdt)))); Ok(AmlParseType { val: AmlValue::None, @@ -363,7 +364,7 @@ fn parse_def_unload(data: &[u8], let mut namespace = ctx.prelock(); if let Some(ref mut ns) = *namespace { - for o in delta { + for o in delta.0 { ns.remove(&o); } } diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index cd94e70..37b3001 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -1367,7 +1367,7 @@ fn parse_def_load_table(data: &[u8], ctx.modify(parameter_path.val, parameter_data.val); return Ok(AmlParseType { - val: AmlValue::DDBHandle(hdl), + val: AmlValue::DDBHandle((hdl, sdt_signature)), len: 2 + signature.len + oem_id.len + oem_table_id.len + root_path.len + parameter_path.len + parameter_data.len }); } From 7145e2390c8c9f34b37143adcb6eaf9e0b97dec3 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Thu, 31 Aug 2017 11:25:08 +0100 Subject: [PATCH 113/113] Converted DDB handle to integer and vice versa --- src/acpi/aml/namespace.rs | 13 +++++++++++-- src/acpi/mod.rs | 27 +++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index 6e6dfa9..18eb7a3 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -12,7 +12,7 @@ use super::namedobj::{ RegionSpace, FieldFlags }; use super::parser::{AmlExecutionContext, ExecutionState}; use super::AmlError; -use acpi::SdtSignature; +use acpi::{SdtSignature, get_signature_from_index, get_index_from_signature}; #[derive(Clone)] pub enum FieldSelector { @@ -255,9 +255,13 @@ impl AmlValue { } pub fn get_as_ddb_handle(&self) -> Result<(Vec, SdtSignature), AmlError> { - // TODO: Integer conversion match *self { AmlValue::DDBHandle(ref v) => Ok(v.clone()), + AmlValue::Integer(i) => if let Some(sig) = get_signature_from_index(i as usize) { + Ok((vec!(), sig)) + } else { + Err(AmlError::AmlValueError) + }, _ => Err(AmlError::AmlValueError) } } @@ -317,6 +321,11 @@ impl AmlValue { Ok(i) }, + AmlValue::DDBHandle(ref v) => if let Some(idx) = get_index_from_signature(v.1.clone()) { + Ok(idx as u64) + } else { + Err(AmlError::AmlValueError) + }, AmlValue::String(ref s) => { let mut s = s.clone()[0..8].to_string().to_uppercase(); let mut i: u64 = 0; diff --git a/src/acpi/mod.rs b/src/acpi/mod.rs index 5902ebc..8324f8e 100644 --- a/src/acpi/mod.rs +++ b/src/acpi/mod.rs @@ -227,6 +227,33 @@ pub fn load_table(signature: SdtSignature) { } } +pub fn get_signature_from_index(index: usize) -> Option { + if let Some(ref order) = *(SDT_ORDER.read()) { + if index < order.len() { + Some(order[index].clone()) + } else { + None + } + } else { + None + } +} + +pub fn get_index_from_signature(signature: SdtSignature) -> Option { + if let Some(ref order) = *(SDT_ORDER.read()) { + let mut i = order.len(); + while i > 0 { + i -= 1; + + if order[i] == signature { + return Some(i); + } + } + } + + None +} + pub struct Acpi { pub fadt: RwLock>, pub namespace: RwLock>>,