Implemented further opcodes in full, added get to context

This commit is contained in:
Connor Wood
2017-07-07 10:37:09 +01:00
parent 38263bf700
commit e0bd497bb8
4 changed files with 159 additions and 59 deletions

View File

@@ -34,10 +34,7 @@ pub enum ObjectReference {
pub enum AmlValue {
None,
Uninitialized,
Buffer {
length: Box<AmlValue>,
byte_list: Vec<u8>
},
Buffer(Vec<u8>),
BufferField {
source_buf: Box<AmlValue>,
index: Box<AmlValue>,
@@ -81,13 +78,19 @@ pub enum AmlValue {
}
impl AmlValue {
// TODO: These should be able to throw errors rather than returning options
pub fn get_as_string(&self) -> Result<String, AmlError> {
match *self {
AmlValue::String(ref s) => Ok(s.clone()),
_ => Err(AmlError::AmlValueError)
}
}
pub fn get_as_buffer(&self) -> Result<Vec<u8>, AmlError> {
match *self {
AmlValue::Buffer(ref b) => Ok(b.clone()),
_ => Err(AmlError::AmlValueError)
}
}
pub fn get_as_package(&self) -> Result<Vec<AmlValue>, AmlError> {
match *self {

View File

@@ -56,4 +56,16 @@ impl AmlExecutionContext {
_ => ()
}
}
pub fn get(&self, name: AmlValue) -> AmlValue {
match name {
AmlValue::None => AmlValue::None,
AmlValue::ObjectReference(r) => match r {
ObjectReference::ArgObj(i) => self.arg_vars[i as usize].clone(),
ObjectReference::LocalObj(i) => self.local_vars[i as usize].clone(),
_ => AmlValue::None
},
_ => AmlValue::None
}
}
}

View File

@@ -4,10 +4,7 @@ macro_rules! parser_selector {
match $func($data, $ctx) {
Ok(res) => return Ok(res),
Err(AmlError::AmlInvalidOpCode) => (),
Err(e) => {
// println!("This doesn't work for some reason");
return Err(e);
}
Err(e) => return Err(e)
}
};
{$data:expr, $ctx:expr, $func:expr, $($funcs:expr),+} => {

View File

@@ -110,15 +110,22 @@ pub fn parse_def_object_type(data: &[u8],
pub fn parse_def_package(data: &[u8],
ctx: &mut AmlExecutionContext) -> ParseResult {
// TODO: Handle deferred loads in here
// TODO: Truncate/extend array if necessary
parser_opcode!(data, 0x12);
let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?;
let num_elements = data[1 + pkg_length_len];
let elements = parse_package_elements_list(&data[2 + pkg_length_len .. 1 + pkg_length], ctx)?;
let numelements = data[1 + pkg_length_len] as usize;
let mut elements = parse_package_elements_list(&data[2 + pkg_length_len .. 1 + pkg_length], ctx)?.val.get_as_package()?;
if elements.len() > numelements {
elements = elements[0 .. numelements].to_vec();
} else if numelements > elements.len() {
for i in 0..numelements - elements.len() {
elements.push(AmlValue::Uninitialized);
}
}
Ok(AmlParseType {
val: elements.val,
val: AmlValue::Package(elements),
len: 1 + pkg_length
})
}
@@ -126,16 +133,25 @@ pub fn parse_def_package(data: &[u8],
pub fn parse_def_var_package(data: &[u8],
ctx: &mut AmlExecutionContext) -> ParseResult {
// TODO: Handle deferred loads in here
// TODO: Truncate/extend array if necessary
parser_opcode!(data, 0x13);
let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?;
let num_elements = parse_term_arg(&data[1 + pkg_length_len .. 1 + pkg_length], ctx)?;
let elements = parse_package_elements_list(&data[1 + pkg_length_len + num_elements.len ..
1 + pkg_length], ctx)?;
let mut elements = parse_package_elements_list(&data[1 + pkg_length_len + num_elements.len ..
1 + pkg_length], ctx)?.val.get_as_package()?;
let numelements = num_elements.val.get_as_integer()? as usize;
if elements.len() > numelements {
elements = elements[0 .. numelements].to_vec();
} else if numelements > elements.len() {
for i in 0..numelements - elements.len() {
elements.push(AmlValue::Uninitialized);
}
}
Ok(AmlParseType {
val: elements.val,
val: AmlValue::Package(elements),
len: 1 + pkg_length
})
}
@@ -224,14 +240,15 @@ fn parse_def_acquire(data: &[u8],
fn parse_def_increment(data: &[u8],
ctx: &mut AmlExecutionContext) -> ParseResult {
// TODO: Store the result
// TODO: Perform computation
parser_opcode!(data, 0x75);
let obj = parse_super_name(&data[1..], ctx)?;
let value = AmlValue::Integer(ctx.get(obj.val.clone()).get_as_integer()? + 1);
ctx.modify(obj.val, value.clone());
Ok(AmlParseType {
val: AmlValue::Uninitialized,
val: value,
len: 1 + obj.len
})
}
@@ -464,16 +481,15 @@ fn parse_def_size_of(data: &[u8],
fn parse_def_store(data: &[u8],
ctx: &mut AmlExecutionContext) -> ParseResult {
// TODO: Return the DRO
parser_opcode!(data, 0x70);
let operand = parse_term_arg(&data[1..], ctx)?;
let target = parse_super_name(&data[1 + operand.len..], ctx)?;
ctx.modify(target.val, operand.val);
ctx.modify(target.val.clone(), operand.val);
Ok(AmlParseType {
val: AmlValue::Uninitialized,
val: target.val,
len: 1 + operand.len + target.len
})
}
@@ -664,61 +680,99 @@ fn parse_def_concat(data: &[u8],
fn parse_def_decrement(data: &[u8],
ctx: &mut AmlExecutionContext) -> ParseResult {
// TODO: Compute the result
// TODO: Store the result
parser_opcode!(data, 0x76);
let target = parse_super_name(&data[1..], ctx)?;
let obj = parse_super_name(&data[1..], ctx)?;
let value = AmlValue::Integer(ctx.get(obj.val.clone()).get_as_integer()? - 1);
ctx.modify(obj.val, value.clone());
Ok(AmlParseType {
val: AmlValue::Uninitialized,
len: 1 + target.len
val: value,
len: 1 + obj.len
})
}
fn parse_def_divide(data: &[u8],
ctx: &mut AmlExecutionContext) -> ParseResult {
// TODO: Compute the result
// TODO: Store the result, if appropriate
parser_opcode!(data, 0x78);
let lhs = parse_term_arg(&data[1..], ctx)?;
let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?;
let target_remainder = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?;
let target_quotient = parse_target(&data[1 + lhs.len + rhs.len + target_remainder.len..], ctx)?;
let numerator = lhs.val.get_as_integer()?;
let denominator = rhs.val.get_as_integer()?;
let remainder = numerator % denominator;
let quotient = (numerator - remainder) / denominator;
ctx.modify(target_remainder.val, AmlValue::Integer(remainder));
ctx.modify(target_quotient.val, AmlValue::Integer(quotient));
Ok(AmlParseType {
val: AmlValue::Uninitialized,
val: AmlValue::Integer(quotient),
len: 1 + lhs.len + rhs.len + target_remainder.len + target_quotient.len
})
}
fn parse_def_find_set_left_bit(data: &[u8],
ctx: &mut AmlExecutionContext) -> ParseResult {
// TODO: Compute the result
// TODO: Store the result, if appropriate
parser_opcode!(data, 0x81);
let operand = parse_term_arg(&data[2..], ctx)?;
let target = parse_target(&data[2 + operand.len..], ctx)?;
let mut first_bit = 32;
let mut test = operand.val.get_as_integer()?;
while first_bit > 0{
if test & 0x8000000000000000 > 0 {
break;
}
test <<= 1;
first_bit -= 1;
}
let result = AmlValue::Integer(first_bit);
ctx.modify(target.val, result.clone());
Ok(AmlParseType {
val: AmlValue::Uninitialized,
val: result,
len: 1 + operand.len + target.len
})
}
fn parse_def_find_set_right_bit(data: &[u8],
ctx: &mut AmlExecutionContext) -> ParseResult {
// TODO: Compute the result
// TODO: Store the result, if appropriate
parser_opcode!(data, 0x82);
let operand = parse_term_arg(&data[2..], ctx)?;
let target = parse_target(&data[2 + operand.len..], ctx)?;
let mut first_bit = 1;
let mut test = operand.val.get_as_integer()?;
while first_bit <= 32 {
if test & 1 > 0 {
break;
}
test >>= 1;
first_bit += 1;
}
if first_bit == 33 {
first_bit = 0;
}
let result = AmlValue::Integer(first_bit);
ctx.modify(target.val, result.clone());
Ok(AmlParseType {
val: AmlValue::Uninitialized,
val: result,
len: 1 + operand.len + target.len
})
}
@@ -784,31 +838,25 @@ fn parse_def_match(data: &[u8],
fn parse_def_from_bcd(data: &[u8],
ctx: &mut AmlExecutionContext) -> ParseResult {
// TODO: Clean up match block
parser_opcode_extended!(data, 0x28);
let operand = parse_term_arg(&data[2..], ctx)?;
let target = parse_target(&data[2 + operand.len..], ctx)?;
let result = AmlValue::Integer(match target.val.get_as_integer() {
Ok(i) => {
let mut i = i;
let mut ires = 0;
while i != 0 {
if i & 0x0F > 10 {
return Err(AmlError::AmlValueError);
}
let mut i = operand.val.get_as_integer()?;
let mut result = 0;
ires *= 10;
ires += i & 0x0F;
i >>= 4;
}
while i != 0 {
if i & 0x0F > 10 {
return Err(AmlError::AmlValueError);
}
result *= 10;
result += i & 0x0F;
i >>= 4;
}
ires
},
Err(e) => return Err(e)
});
let result = AmlValue::Integer(result);
ctx.modify(target.val, result.clone());
@@ -820,8 +868,6 @@ fn parse_def_from_bcd(data: &[u8],
fn parse_def_mid(data: &[u8],
ctx: &mut AmlExecutionContext) -> ParseResult {
// TODO: Compute the result
// TODO: Store the result, if appropriate
parser_opcode!(data, 0x9E);
let source = parse_term_arg(&data[1..], ctx)?;
@@ -829,21 +875,63 @@ fn parse_def_mid(data: &[u8],
let length = parse_term_arg(&data[1 + source.len + index.len..], ctx)?;
let target = parse_target(&data[1 + source.len + index.len + length.len..], ctx)?;
let idx = index.val.get_as_integer()? as usize;
let mut len = length.val.get_as_integer()? as usize;
let result = match source.val {
AmlValue::String(s) => {
if idx > s.len() {
AmlValue::String(String::new())
} else {
let mut res = s.clone().split_off(idx);
if len < res.len() {
res.split_off(len);
}
AmlValue::String(res)
}
},
_ => {
// If it isn't a string already, treat it as a buffer. Must perform that check first,
// as Mid can operate on both strings and buffers, but a string can be cast as a buffer
// implicitly.
// Additionally, any type that can be converted to a buffer can also be converted to a
// string, so no information is lost
let b = source.val.get_as_buffer()?;
if idx > b.len() {
AmlValue::Buffer(vec!())
} else {
if idx + len > b.len() {
len = b.len() - idx;
}
AmlValue::Buffer(b[idx .. idx + len].to_vec())
}
}
};
ctx.modify(target.val, result.clone());
Ok(AmlParseType {
val: AmlValue::Uninitialized,
val: result,
len: 1 + source.len + index.len + length.len + target.len
})
}
fn parse_def_mod(data: &[u8],
ctx: &mut AmlExecutionContext) -> ParseResult {
// TODO: Fatal exception on rhs == 0
parser_opcode!(data, 0x85);
let lhs = parse_term_arg(&data[1..], ctx)?;
let rhs = parse_term_arg(&data[1 + lhs.len..], ctx)?;
let target = parse_target(&data[1 + lhs.len + rhs.len..], ctx)?;
if rhs.val.get_as_integer()? == 0 {
return Err(AmlError::AmlValueError);
}
let result = AmlValue::Integer(lhs.val.get_as_integer()? % rhs.val.get_as_integer()?);
ctx.modify(target.val, result.clone());