Skip to content

Commit df5778a

Browse files
committed
aml: implement DefConcat and DefConcatRes
1 parent 77d446e commit df5778a

File tree

2 files changed

+123
-2
lines changed

2 files changed

+123
-2
lines changed

aml/src/lib.rs

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,27 @@ where
191191
self.do_logical_op(&mut context, op)?;
192192
}
193193
Opcode::Mid => self.do_mid(&mut context, op)?,
194+
Opcode::Concat => self.do_concat(&mut context, op)?,
195+
Opcode::ConcatRes => {
196+
let [Argument::Object(source1), Argument::Object(source2), target] = &op.arguments[..]
197+
else {
198+
panic!()
199+
};
200+
let source1 = source1.as_buffer()?;
201+
let source2 = source2.as_buffer()?;
202+
let result = {
203+
let mut buffer = Vec::from(source1);
204+
buffer.extend_from_slice(source2);
205+
// Add a new end-tag
206+
buffer.push(0x78);
207+
// Don't calculate the new real checksum - just use 0
208+
buffer.push(0x00);
209+
Arc::new(Object::Buffer(buffer))
210+
};
211+
// TODO: use potentially-updated result for return value here
212+
self.do_store(&mut context, target, result.clone())?;
213+
context.contribute_arg(Argument::Object(result));
214+
}
194215
Opcode::FromBCD => self.do_from_bcd(&mut context, op)?,
195216
Opcode::ToBCD => self.do_to_bcd(&mut context, op)?,
196217
Opcode::Name => {
@@ -914,8 +935,8 @@ where
914935
context.start_in_flight_op(OpInFlight::new(opcode, 2))
915936
}
916937
Opcode::DerefOf => todo!(),
917-
Opcode::ConcatRes => todo!(),
918938
Opcode::Notify => todo!(),
939+
Opcode::ConcatRes => context.start_in_flight_op(OpInFlight::new(opcode, 3)),
919940
Opcode::SizeOf => context.start_in_flight_op(OpInFlight::new(opcode, 1)),
920941
Opcode::Index => context.start_in_flight_op(OpInFlight::new(opcode, 3)),
921942
Opcode::Match => todo!(),
@@ -1263,6 +1284,62 @@ where
12631284
Ok(())
12641285
}
12651286

1287+
fn do_concat(&self, context: &mut MethodContext, op: OpInFlight) -> Result<(), AmlError> {
1288+
let [Argument::Object(source1), Argument::Object(source2), target] = &op.arguments[..] else { panic!() };
1289+
fn resolve_as_string(obj: &Object) -> String {
1290+
match obj {
1291+
Object::Uninitialized => "[Uninitialized Object]".to_string(),
1292+
Object::Buffer(bytes) => String::from_utf8_lossy(&bytes).into_owned(),
1293+
Object::BufferField { .. } => "[Buffer Field]".to_string(),
1294+
Object::Device => "[Device]".to_string(),
1295+
Object::Event => "[Event]".to_string(),
1296+
Object::FieldUnit(_) => "[Field]".to_string(),
1297+
Object::Integer(value) => value.to_string(),
1298+
Object::Method { .. } => "[Control Method]".to_string(),
1299+
Object::Mutex { .. } => "[Mutex]".to_string(),
1300+
Object::Reference { inner, .. } => resolve_as_string(&*(inner.clone().unwrap_reference())),
1301+
Object::OpRegion(_) => "[Operation Region]".to_string(),
1302+
Object::Package(_) => "[Package]".to_string(),
1303+
Object::PowerResource { .. } => "[Power Resource]".to_string(),
1304+
Object::Processor { .. } => "[Processor]".to_string(),
1305+
// TODO: what even is one of these??
1306+
Object::RawDataBuffer => todo!(),
1307+
Object::String(value) => value.clone(),
1308+
Object::ThermalZone => "[Thermal Zone]".to_string(),
1309+
Object::Debug => "[Debug Object]".to_string(),
1310+
}
1311+
}
1312+
let result = match source1.typ() {
1313+
ObjectType::Integer => {
1314+
let source1 = source1.as_integer()?;
1315+
let source2 = source2.to_integer(if self.dsdt_revision >= 2 { 8 } else { 4 })?;
1316+
let mut buffer = Vec::new();
1317+
if self.dsdt_revision >= 2 {
1318+
buffer.extend_from_slice(&source1.to_le_bytes());
1319+
buffer.extend_from_slice(&source2.to_le_bytes());
1320+
} else {
1321+
buffer.extend_from_slice(&(source1 as u32).to_le_bytes());
1322+
buffer.extend_from_slice(&(source2 as u32).to_le_bytes());
1323+
}
1324+
Arc::new(Object::Buffer(buffer))
1325+
}
1326+
ObjectType::Buffer => {
1327+
let mut buffer = source1.as_buffer()?.to_vec();
1328+
buffer.extend(source2.to_buffer(if self.dsdt_revision >= 2 { 8 } else { 4 })?);
1329+
Arc::new(Object::Buffer(buffer))
1330+
}
1331+
ObjectType::String | _ => {
1332+
let source1 = resolve_as_string(&source1);
1333+
let source2 = resolve_as_string(&source2);
1334+
Arc::new(Object::String(source1 + &source2))
1335+
}
1336+
};
1337+
// TODO: use result of store
1338+
self.do_store(context, target, result.clone())?;
1339+
context.contribute_arg(Argument::Object(result));
1340+
Ok(())
1341+
}
1342+
12661343
fn do_from_bcd(&self, context: &mut MethodContext, op: OpInFlight) -> Result<(), AmlError> {
12671344
let [Argument::Object(value)] = &op.arguments[..] else { Err(AmlError::InvalidOperationOnObject)? };
12681345
let mut value = value.clone().unwrap_transparent_reference().as_integer()?;

aml/src/object.rs

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::{AmlError, op_region::OpRegion};
2-
use alloc::{string::String, sync::Arc, vec::Vec};
2+
use alloc::{borrow::Cow, string::String, sync::Arc, vec::Vec};
33
use bit_field::BitField;
44

55
#[derive(Debug)]
@@ -52,6 +52,50 @@ impl Object {
5252
}
5353
}
5454

55+
pub fn as_string(&self) -> Result<Cow<str>, AmlError> {
56+
if let Object::String(value) = self {
57+
Ok(Cow::from(value))
58+
} else {
59+
Err(AmlError::ObjectNotOfExpectedType { expected: ObjectType::String, got: self.typ() })
60+
}
61+
}
62+
63+
pub fn as_buffer(&self) -> Result<&[u8], AmlError> {
64+
if let Object::Buffer(bytes) = self {
65+
Ok(bytes)
66+
} else {
67+
Err(AmlError::ObjectNotOfExpectedType { expected: ObjectType::Buffer, got: self.typ() })
68+
}
69+
}
70+
71+
pub fn to_integer(&self, allowed_bytes: usize) -> Result<u64, AmlError> {
72+
match self {
73+
Object::Integer(value) => Ok(*value),
74+
Object::Buffer(value) => {
75+
let length = usize::min(value.len(), allowed_bytes);
76+
let mut bytes = [0u8; 8];
77+
bytes[0..length].copy_from_slice(&value[0..length]);
78+
Ok(u64::from_le_bytes(bytes))
79+
}
80+
// TODO: how should we handle invalid inputs? What does NT do here?
81+
Object::String(value) => Ok(value.parse::<u64>().unwrap_or(0)),
82+
_ => Ok(0),
83+
}
84+
}
85+
86+
pub fn to_buffer(&self, allowed_bytes: usize) -> Result<Vec<u8>, AmlError> {
87+
match self {
88+
Object::Buffer(bytes) => Ok(bytes.clone()),
89+
Object::Integer(value) => match allowed_bytes {
90+
4 => Ok((*value as u32).to_le_bytes().to_vec()),
91+
8 => Ok(value.to_le_bytes().to_vec()),
92+
_ => panic!(),
93+
},
94+
Object::String(value) => Ok(value.as_bytes().to_vec()),
95+
_ => Err(AmlError::InvalidOperationOnObject),
96+
}
97+
}
98+
5599
pub fn read_buffer_field(&self, dst: &mut [u8]) -> Result<(), AmlError> {
56100
if let Self::BufferField { buffer, offset, length } = self {
57101
let buffer = match **buffer {

0 commit comments

Comments
 (0)