Refactored parser to execute in the parse step for efficiency and simplicity

This commit is contained in:
Connor Wood
2017-07-02 13:07:43 +01:00
parent f72f97ef36
commit 590610f4a5
14 changed files with 1622 additions and 1918 deletions

View File

@@ -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())
}
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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
})
}

View File

@@ -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())
}
}

View File

@@ -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
}

View File

@@ -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)
}
};
}

View File

@@ -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;

View File

@@ -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)
}

View File

@@ -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

View File

@@ -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");

View File

@@ -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");