Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Implement DefConcat
  • Loading branch information
IsaacWoods committed Jul 29, 2021
1 parent b303da9 commit 6f92f67
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 2 deletions.
1 change: 1 addition & 0 deletions aml/src/opcode.rs
Expand Up @@ -49,6 +49,7 @@ pub const DEF_BREAKPOINT_OP: u8 = 0xcc;
*/
pub const DEF_STORE_OP: u8 = 0x70;
pub const DEF_ADD_OP: u8 = 0x72;
pub const DEF_CONCAT_OP: u8 = 0x73;
pub const DEF_SHIFT_LEFT: u8 = 0x79;
pub const DEF_SHIFT_RIGHT: u8 = 0x7a;
pub const DEF_AND_OP: u8 = 0x7b;
Expand Down
49 changes: 48 additions & 1 deletion aml/src/type2.rs
Expand Up @@ -19,7 +19,7 @@ use crate::{
DebugVerbosity,
};
use alloc::{vec, vec::Vec};
use core::{cmp::Ordering, convert::TryInto};
use core::{cmp::Ordering, convert::TryInto, mem};

/// Type 2 opcodes return a value and so can be used in expressions.
pub fn type2_opcode<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
Expand All @@ -44,6 +44,7 @@ where
def_add(),
def_and(),
def_buffer(),
def_concat(),
def_l_equal(),
def_l_greater(),
def_l_greater_equal(),
Expand Down Expand Up @@ -147,6 +148,52 @@ where
.map(|((), buffer)| Ok(AmlValue::Buffer(buffer)))
}

pub fn def_concat<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
where
'c: 'a,
{
/*
* DefConcat := 0x73 Data Data Target
* Data := TermArg => ComputationalData
*/
opcode(opcode::DEF_CONCAT_OP)
.then(comment_scope(
DebugVerbosity::AllScopes,
"DefConcat",
term_arg().then(term_arg()).then(target()).map_with_context(|((left, right), target), context| {
let result = match left.as_concat_type() {
AmlValue::Integer(left) => {
let right = try_with_context!(context, right.as_integer(context));

let mut buffer = Vec::with_capacity(mem::size_of::<u64>() * 2);
buffer.extend_from_slice(&left.to_le_bytes());
buffer.extend_from_slice(&right.to_le_bytes());

AmlValue::Buffer(buffer)
}
AmlValue::Buffer(mut left) => {
left.extend(try_with_context!(context, right.as_buffer(context)));
AmlValue::Buffer(left)
}
AmlValue::String(left) => {
let right = match right.as_concat_type() {
AmlValue::String(right) => right,
AmlValue::Integer(_) => try_with_context!(context, right.as_string(context)),
AmlValue::Buffer(_) => try_with_context!(context, right.as_string(context)),
_ => panic!("Invalid type returned from `as_concat_type`"),
};
AmlValue::String(left + &right)
}
_ => panic!("Invalid type returned from `as_concat_type`"),
};

try_with_context!(context, context.store(target, result.clone()));
(Ok(result), context)
}),
))
.map(|((), result)| Ok(result))
}

fn def_l_or<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
where
'c: 'a,
Expand Down
34 changes: 33 additions & 1 deletion aml/src/value.rs
@@ -1,5 +1,9 @@
use crate::{misc::ArgNum, AmlContext, AmlError, AmlHandle, AmlName};
use alloc::{string::String, sync::Arc, vec::Vec};
use alloc::{
string::{String, ToString},
sync::Arc,
vec::Vec,
};
use bit_field::BitField;
use core::{cmp, fmt, fmt::Debug};

Expand Down Expand Up @@ -307,6 +311,34 @@ impl AmlValue {
}
}

/// Converts an `AmlValue` to the representation that should be used when concatenating it with other values,
/// primarily by the `DefConcat` opcode. This will always produce a `AmlValue::Integer`, `AmlValue::String`, or
/// `AmlValue::Buffer`, with other types being converted to strings containing the name of their type.
pub fn as_concat_type(&self) -> AmlValue {
match self.type_of() {
AmlType::Integer => self.clone(),
AmlType::String => self.clone(),
AmlType::Buffer => self.clone(),

AmlType::Uninitialized => AmlValue::String("[Uninitialized]".to_string()),
AmlType::BufferField => AmlValue::String("[Buffer Field]".to_string()),
AmlType::DdbHandle => AmlValue::String("[Ddb Handle]".to_string()),
AmlType::DebugObject => AmlValue::String("[Debug Object]".to_string()),
AmlType::Event => AmlValue::String("[Event]".to_string()),
AmlType::FieldUnit => AmlValue::String("[Field]".to_string()),
AmlType::Device => AmlValue::String("[Device]".to_string()),
AmlType::Method => AmlValue::String("[Control Method]".to_string()),
AmlType::Mutex => AmlValue::String("[Mutex]".to_string()),
AmlType::ObjReference => AmlValue::String("[Obj Reference]".to_string()),
AmlType::OpRegion => AmlValue::String("[Operation Region]".to_string()),
AmlType::Package => AmlValue::String("[Package]".to_string()),
AmlType::Processor => AmlValue::String("[Processor]".to_string()),
AmlType::PowerResource => AmlValue::String("[Power Resource]".to_string()),
AmlType::RawDataBuffer => AmlValue::String("[Raw Data Buffer]".to_string()),
AmlType::ThermalZone => AmlValue::String("[Thermal Zone]".to_string()),
}
}

/// Turns an `AmlValue` returned from a `_STA` method into a `StatusObject`. Should only be called for values
/// returned from `_STA`. If you need a `StatusObject`, but the device does not have a `_STA` method, use
/// `StatusObject::default()`.
Expand Down

0 comments on commit 6f92f67

Please sign in to comment.