Skip to content

Commit 4c24b08

Browse files
committed
aml: implement DefIndex
1 parent fe877bd commit 4c24b08

File tree

2 files changed

+70
-6
lines changed

2 files changed

+70
-6
lines changed

aml/src/lib.rs

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,7 @@ where
384384
context.contribute_arg(Argument::Object(Arc::new(Object::Integer(typ))));
385385
}
386386
Opcode::SizeOf => self.do_size_of(&mut context, op)?,
387+
Opcode::Index => self.do_index(&mut context, op)?,
387388
Opcode::BankField => {
388389
let [
389390
Argument::TrackedPc(start_pc),
@@ -826,7 +827,7 @@ where
826827
Opcode::ConcatRes => todo!(),
827828
Opcode::Notify => todo!(),
828829
Opcode::SizeOf => context.start_in_flight_op(OpInFlight::new(opcode, 1)),
829-
Opcode::Index => todo!(),
830+
Opcode::Index => context.start_in_flight_op(OpInFlight::new(opcode, 3)),
830831
Opcode::Match => todo!(),
831832

832833
Opcode::CreateBitField
@@ -1104,6 +1105,55 @@ where
11041105
context.contribute_arg(Argument::Object(Arc::new(Object::Integer(result as u64))));
11051106
Ok(())
11061107
}
1108+
1109+
fn do_index(&self, context: &mut MethodContext, op: OpInFlight) -> Result<(), AmlError> {
1110+
let [Argument::Object(object), Argument::Object(index_value), target] = &op.arguments[..] else {
1111+
panic!()
1112+
};
1113+
let Object::Integer(index_value) = **index_value else {
1114+
Err(AmlError::ObjectNotOfExpectedType { expected: ObjectType::Integer, got: index_value.typ() })?
1115+
};
1116+
1117+
let result = Arc::new(match **object {
1118+
Object::Buffer(ref buffer) => {
1119+
if index_value as usize >= buffer.len() {
1120+
Err(AmlError::IndexOutOfBounds)?
1121+
}
1122+
1123+
Object::Reference {
1124+
kind: ReferenceKind::RefOf,
1125+
inner: Arc::new(Object::BufferField {
1126+
buffer: object.clone(),
1127+
offset: index_value as usize * 8,
1128+
length: 8,
1129+
}),
1130+
}
1131+
}
1132+
Object::String(ref string) => {
1133+
if index_value as usize >= string.len() {
1134+
Err(AmlError::IndexOutOfBounds)?
1135+
}
1136+
1137+
Object::Reference {
1138+
kind: ReferenceKind::RefOf,
1139+
inner: Arc::new(Object::BufferField {
1140+
buffer: object.clone(),
1141+
offset: index_value as usize * 8,
1142+
length: 8,
1143+
}),
1144+
}
1145+
}
1146+
Object::Package(ref package) => {
1147+
let Some(element) = package.get(index_value as usize) else { Err(AmlError::IndexOutOfBounds)? };
1148+
Object::Reference { kind: ReferenceKind::RefOf, inner: element.clone() }
1149+
}
1150+
_ => Err(AmlError::IndexOutOfBounds)?,
1151+
});
1152+
1153+
self.do_store(context, target, result.clone())?;
1154+
context.contribute_arg(Argument::Object(result));
1155+
Ok(())
1156+
}
11071157
fn do_store(
11081158
&self,
11091159
context: &mut MethodContext,
@@ -1703,6 +1753,8 @@ pub enum AmlError {
17031753
MethodArgCountIncorrect,
17041754

17051755
InvalidOperationOnObject,
1756+
IndexOutOfBounds,
1757+
ObjectNotOfExpectedType { expected: ObjectType, got: ObjectType },
17061758

17071759
InvalidResourceDescriptor,
17081760
UnexpectedResourceType,

aml/src/object.rs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,19 +46,30 @@ impl Object {
4646

4747
pub fn read_buffer_field(&self, dst: &mut [u8]) -> Result<(), AmlError> {
4848
if let Self::BufferField { buffer, offset, length } = self {
49-
let Object::Buffer(ref buffer) = **buffer else { panic!() };
50-
// TODO: assert length of buffer is sufficient
51-
copy_bits(buffer.as_slice(), *offset, dst, 0, *length);
49+
let buffer = match **buffer {
50+
Object::Buffer(ref buffer) => buffer.as_slice(),
51+
Object::String(ref string) => string.as_bytes(),
52+
_ => panic!(),
53+
};
54+
// TODO: bounds check the buffer first to avoid panicking
55+
copy_bits(buffer, *offset, dst, 0, *length);
5256
Ok(())
5357
} else {
5458
Err(AmlError::InvalidOperationOnObject)
5559
}
5660
}
5761

5862
pub fn write_buffer_field(&mut self, value: &[u8]) -> Result<(), AmlError> {
63+
// TODO: bounds check the buffer first to avoid panicking
5964
if let Self::BufferField { buffer, offset, length } = self {
60-
let Object::Buffer(buffer) = buffer.gain_mut() else { panic!() };
61-
copy_bits(value, 0, buffer.as_mut_slice(), *offset, *length);
65+
let buffer = match buffer.gain_mut() {
66+
Object::Buffer(buffer) => buffer.as_mut_slice(),
67+
// XXX: this unfortunately requires us to trust AML to keep the string as valid
68+
// UTF8... maybe there is a better way?
69+
Object::String(string) => unsafe { string.as_bytes_mut() },
70+
_ => panic!(),
71+
};
72+
copy_bits(value, 0, buffer, *offset, *length);
6273
Ok(())
6374
} else {
6475
Err(AmlError::InvalidOperationOnObject)
@@ -157,6 +168,7 @@ impl MethodFlags {
157168

158169
#[derive(Clone, Copy, PartialEq, Debug)]
159170
pub enum ReferenceKind {
171+
RefOf,
160172
LocalOrArg,
161173
Unresolved,
162174
}

0 commit comments

Comments
 (0)