Refactored parser to execute in the parse step for efficiency and simplicity
This commit is contained in:
@@ -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<String, AmlValue>, scope: String) -> Option<AmlValue> {
|
||||
match *self {
|
||||
DataRefObj::DataObj(ref cd) => cd.execute(namespace, scope),
|
||||
_ => Some(AmlValue::Uninitialized)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AmlExecutable for DataObj {
|
||||
fn execute(&self, namespace: &mut BTreeMap<String, AmlValue>, scope: String) -> Option<AmlValue> {
|
||||
match *self {
|
||||
DataObj::ComputationalData(ref cd) => cd.execute(namespace, scope),
|
||||
DataObj::DefPackage(ref pkg) => pkg.execute(namespace, scope),
|
||||
_ => Some(AmlValue::Uninitialized)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AmlExecutable for ComputationalData {
|
||||
fn execute(&self, namespace: &mut BTreeMap<String, AmlValue>, scope: String) -> Option<AmlValue> {
|
||||
match *self {
|
||||
ComputationalData::Byte(b) => Some(AmlValue::IntegerConstant(b as u64)),
|
||||
ComputationalData::Word(w) => Some(AmlValue::IntegerConstant(w as u64)),
|
||||
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<String, AmlValue>,
|
||||
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<String, AmlValue>,
|
||||
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<String, AmlValue>,
|
||||
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<String, AmlValue>,
|
||||
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<String, AmlValue>,
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<String, AmlValue>, scope: String) -> Option<AmlValue>;
|
||||
}
|
||||
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<BTreeMap<String, AmlValue>, 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)
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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<AmlValue>)
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum AmlValue {
|
||||
None,
|
||||
Uninitialized,
|
||||
Buffer {
|
||||
length: Box<AmlValue>,
|
||||
@@ -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<AmlValue>,
|
||||
@@ -73,22 +80,37 @@ pub enum AmlValue {
|
||||
}
|
||||
|
||||
impl AmlValue {
|
||||
pub fn get_as_package(&self) -> Option<Vec<AmlValue>> {
|
||||
// TODO: These should be able to throw errors rather than returning options
|
||||
pub fn get_as_string(&self) -> Result<String, AmlError> {
|
||||
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<Vec<AmlValue>, AmlError> {
|
||||
match *self {
|
||||
AmlValue::Package(ref p) => Ok(p.clone()),
|
||||
_ => Err(AmlError::AmlValueError)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_as_integer(&self) -> Option<u64> {
|
||||
pub fn get_as_integer(&self) -> Result<u64, AmlError> {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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<String, AmlValue>,
|
||||
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
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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<String, AmlValue>,
|
||||
scope: String) -> ParseResult {
|
||||
let mut characters: Vec<u8> = 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<u8>, usize), AmlInternalError> {
|
||||
fn parse_null_name(data: &[u8]) -> Result<(Vec<u8>, usize), AmlError> {
|
||||
parser_opcode!(data, 0x00);
|
||||
Ok((vec!(), 1 as usize))
|
||||
}
|
||||
|
||||
pub fn parse_name_seg(data: &[u8]) -> Result<(Vec<u8>, usize), AmlInternalError> {
|
||||
pub fn parse_name_seg(data: &[u8]) -> Result<(Vec<u8>, 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<u8>, usize), AmlInternalError>
|
||||
Ok((name_seg, 4 as usize))
|
||||
}
|
||||
|
||||
fn parse_dual_name_path(data: &[u8]) -> Result<(Vec<u8>, usize), AmlInternalError> {
|
||||
fn parse_dual_name_path(data: &[u8]) -> Result<(Vec<u8>, usize), AmlError> {
|
||||
parser_opcode!(data, 0x2E);
|
||||
|
||||
let mut characters: Vec<u8> = vec!();
|
||||
@@ -118,12 +110,12 @@ fn parse_dual_name_path(data: &[u8]) -> Result<(Vec<u8>, usize), AmlInternalErro
|
||||
Ok((characters, dual_len))
|
||||
}
|
||||
|
||||
fn parse_multi_name_path(data: &[u8]) -> Result<(Vec<u8>, usize), AmlInternalError> {
|
||||
fn parse_multi_name_path(data: &[u8]) -> Result<(Vec<u8>, 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<u8>, 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<String, AmlValue>,
|
||||
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<String, AmlValue>,
|
||||
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<String, AmlValue>,
|
||||
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<String, AmlValue>,
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,10 @@
|
||||
use super::AmlValue;
|
||||
use super::namespace::AmlValue;
|
||||
use super::AmlError;
|
||||
|
||||
pub type ParseResult = Result<AmlParseType, AmlInternalError>;
|
||||
pub type ParseResult = Result<AmlParseType, AmlError>;
|
||||
pub type AmlParseType = AmlParseTypeGeneric<AmlValue>;
|
||||
|
||||
pub struct AmlParseType {
|
||||
val: Option<AmlValue>,
|
||||
len: usize
|
||||
}
|
||||
|
||||
// TODO: make private
|
||||
pub enum AmlInternalError {
|
||||
AmlParseError(&'static str),
|
||||
AmlInvalidOpCode,
|
||||
AmlValueError,
|
||||
AmlDeferredLoad
|
||||
pub struct AmlParseTypeGeneric<T> {
|
||||
pub val: T,
|
||||
pub len: usize
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<LocalObj>),
|
||||
DataObj(Box<DataObj>),
|
||||
ArgObj(Box<ArgObj>),
|
||||
Type2Opcode(Box<Type2OpCode>)
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum TermObj {
|
||||
NamespaceModifier(Box<NamespaceModifier>),
|
||||
NamedObj(Box<NamedObj>),
|
||||
Type1Opcode(Box<Type1OpCode>),
|
||||
Type2Opcode(Box<Type2OpCode>)
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Object {
|
||||
NamespaceModifier(Box<NamespaceModifier>),
|
||||
NamedObj(Box<NamedObj>)
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MethodInvocation {
|
||||
|
||||
}
|
||||
|
||||
impl AmlExecutable for Vec<Object> {
|
||||
fn execute(&self, namespace: &mut BTreeMap<String, AmlValue>, scope: String) -> Option<AmlValue> {
|
||||
for term in self {
|
||||
term.execute(namespace, scope.clone());
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl AmlExecutable for Object {
|
||||
fn execute(&self, namespace: &mut BTreeMap<String, AmlValue>, scope: String) -> Option<AmlValue> {
|
||||
match *self {
|
||||
Object::NamespaceModifier(ref d) => d.execute(namespace, scope),
|
||||
Object::NamedObj(ref d) => d.execute(namespace, scope)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AmlExecutable for Vec<TermObj> {
|
||||
fn execute(&self, namespace: &mut BTreeMap<String, AmlValue>, scope: String) -> Option<AmlValue> {
|
||||
for term in self {
|
||||
term.execute(namespace, scope.clone());
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl AmlExecutable for TermArg {
|
||||
fn execute(&self, namespace: &mut BTreeMap<String, AmlValue>, scope: String) -> Option<AmlValue> {
|
||||
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<String, AmlValue>, scope: String) -> Option<AmlValue> {
|
||||
match *self {
|
||||
TermObj::NamespaceModifier(ref res) => res.execute(namespace, scope.clone()),
|
||||
TermObj::NamedObj(ref res) => res.execute(namespace, scope.clone()),
|
||||
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<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..], 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<String, AmlValue>,
|
||||
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<Vec<Object>, AmlInternalError> {
|
||||
let mut terms: Vec<Object> = vec!();
|
||||
pub fn parse_object_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_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<String, AmlValue>,
|
||||
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<String, AmlValue>,
|
||||
scope: String) -> ParseResult {
|
||||
let name = parse_name_string(data, namespace, scope)?;
|
||||
Err(AmlError::AmlDeferredLoad)
|
||||
}
|
||||
|
||||
fn parse_term_obj(data: &[u8],
|
||||
namespace: &mut BTreeMap<String, AmlValue>,
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -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<TermObj>
|
||||
},
|
||||
DefReturn(TermArg),
|
||||
DeferredLoad(Vec<u8>)
|
||||
}
|
||||
|
||||
impl AmlExecutable for Type1OpCode {
|
||||
fn execute(&self, namespace: &mut BTreeMap<String, AmlValue>, scope: String) -> Option<AmlValue> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum IfBlock {
|
||||
If {
|
||||
predicate: TermArg,
|
||||
if_block: Vec<TermObj>
|
||||
},
|
||||
Else(Vec<TermObj>),
|
||||
NoBlock,
|
||||
DeferredLoad(Vec<u8>)
|
||||
}
|
||||
|
||||
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<String, AmlValue>,
|
||||
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<String, AmlValue>,
|
||||
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<String, AmlValue>,
|
||||
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<String, AmlValue>,
|
||||
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<String, AmlValue>,
|
||||
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<String, AmlValue>,
|
||||
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<String, AmlValue>,
|
||||
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<String, AmlValue>,
|
||||
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<String, AmlValue>,
|
||||
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<String, AmlValue>,
|
||||
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<String, AmlValue>,
|
||||
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<String, AmlValue>,
|
||||
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<String, AmlValue>,
|
||||
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<String, AmlValue>,
|
||||
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<String, AmlValue>,
|
||||
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<String, AmlValue>,
|
||||
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<String, AmlValue>,
|
||||
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
|
||||
})
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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");
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user