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)