Rolled parsing and execution steps into one for namespace modifiers
This commit is contained in:
@@ -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<String, AmlValue>, scope: String) -> Option<AmlValue>;
|
||||
}
|
||||
|
||||
// TODO: make private
|
||||
pub enum AmlInternalError {
|
||||
AmlParseError(&'static str),
|
||||
AmlInvalidOpCode,
|
||||
AmlDeferredLoad
|
||||
}
|
||||
|
||||
pub enum AmlError {
|
||||
AmlParseError(&'static str)
|
||||
}
|
||||
|
||||
@@ -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<TermObj>
|
||||
},
|
||||
Alias {
|
||||
source_name: String,
|
||||
alias_name: String
|
||||
},
|
||||
DeferredLoad(Vec<u8>)
|
||||
}
|
||||
|
||||
impl AmlExecutable for NamespaceModifier {
|
||||
fn execute(&self, namespace: &mut BTreeMap<String, AmlValue>, scope: String) -> Option<AmlValue> {
|
||||
match *self {
|
||||
NamespaceModifier::Scope { name: ref name, terms: ref terms } => {
|
||||
let local_scope_string = get_namespace_string(scope, name.clone());
|
||||
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<String, AmlValue>,
|
||||
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<String, AmlValue>,
|
||||
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<String, AmlValue>,
|
||||
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<String, AmlValue>,
|
||||
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
|
||||
})
|
||||
}
|
||||
|
||||
16
src/acpi/aml/parser.rs
Normal file
16
src/acpi/aml/parser.rs
Normal file
@@ -0,0 +1,16 @@
|
||||
use super::AmlValue;
|
||||
|
||||
pub type ParseResult = Result<AmlParseType, AmlInternalError>;
|
||||
|
||||
pub struct AmlParseType {
|
||||
val: Option<AmlValue>,
|
||||
len: usize
|
||||
}
|
||||
|
||||
// TODO: make private
|
||||
pub enum AmlInternalError {
|
||||
AmlParseError(&'static str),
|
||||
AmlInvalidOpCode,
|
||||
AmlValueError,
|
||||
AmlDeferredLoad
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -89,17 +89,20 @@ impl AmlExecutable for TermObj {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_term_list(data: &[u8]) -> Result<Vec<TermObj>, AmlInternalError> {
|
||||
let mut terms: Vec<TermObj> = vec!();
|
||||
pub fn parse_term_list(data: &[u8],
|
||||
namespace: &mut BTreeMap<String, AmlValue>,
|
||||
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<String, AmlValue>,
|
||||
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)
|
||||
|
||||
Reference in New Issue
Block a user