acpi/aml/
objects.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Utilities for encoding various objects into ACPI Machine Language (AML).
5
6use super::helpers::*;
7
8/// A trait indicating that a particular type can be serialized
9/// into a byte stream of ACPI Machine Language (AML).
10pub trait AmlObject {
11    fn append_to_vec(&self, byte_stream: &mut Vec<u8>);
12
13    fn to_bytes(&self) -> Vec<u8> {
14        let mut byte_stream = Vec::new();
15        self.append_to_vec(&mut byte_stream);
16        byte_stream
17    }
18}
19
20/// A named AML object.
21pub struct NamedObject {
22    name: Vec<u8>,
23    object: Vec<u8>,
24}
25
26impl NamedObject {
27    /// Construct a new [`NamedObject`]
28    pub fn new(name: &[u8], object: &impl AmlObject) -> Self {
29        let encoded_name = encode_name(name);
30        assert!(!encoded_name.is_empty());
31        NamedObject {
32            name: encoded_name,
33            object: object.to_bytes(),
34        }
35    }
36}
37
38impl AmlObject for NamedObject {
39    // A named object consists of the identifier (0x8) followed by the 4-byte name
40    fn append_to_vec(&self, byte_stream: &mut Vec<u8>) {
41        byte_stream.push(8);
42        byte_stream.extend_from_slice(&self.name);
43        byte_stream.extend_from_slice(&self.object);
44    }
45}
46
47pub struct GenericObject<T: AsRef<[u8]>>(pub T);
48
49impl<T> AmlObject for GenericObject<T>
50where
51    T: AsRef<[u8]>,
52{
53    fn append_to_vec(&self, byte_stream: &mut Vec<u8>) {
54        let buffer = self.0.as_ref();
55        byte_stream.extend_from_slice(buffer);
56    }
57}
58
59/// A named AML integer.
60pub struct NamedInteger {
61    data: NamedObject,
62}
63
64impl NamedInteger {
65    /// Construct a new [`NamedInteger`]
66    pub fn new(name: &[u8], value: u64) -> Self {
67        Self {
68            data: NamedObject::new(name, &GenericObject(encode_integer(value))),
69        }
70    }
71}
72
73impl AmlObject for NamedInteger {
74    fn append_to_vec(&self, byte_stream: &mut Vec<u8>) {
75        self.data.append_to_vec(byte_stream);
76    }
77}
78
79/// A named AML string.
80pub struct NamedString {
81    data: NamedObject,
82}
83
84impl NamedString {
85    /// Construct a new [`NamedString`]
86    pub fn new(name: &[u8], value: &[u8]) -> Self {
87        Self {
88            data: NamedObject::new(name, &GenericObject(encode_string(value))),
89        }
90    }
91}
92
93impl AmlObject for NamedString {
94    fn append_to_vec(&self, byte_stream: &mut Vec<u8>) {
95        self.data.append_to_vec(byte_stream);
96    }
97}
98
99/// A structured AML package.
100pub struct StructuredPackage<T: AsRef<[u8]>> {
101    pub elem_count: u8,
102    pub elem_data: T,
103}
104
105impl<T> AmlObject for StructuredPackage<T>
106where
107    T: AsRef<[u8]>,
108{
109    // A package consists of the identifier (0x12), followed by the length (including itself),
110    // the number of elements (depends on what package contents represent) and the content.
111    fn append_to_vec(&self, byte_stream: &mut Vec<u8>) {
112        let buffer = self.elem_data.as_ref();
113        byte_stream.push(0x12);
114        byte_stream.extend_from_slice(&encode_package_len(buffer.len() + 1));
115        byte_stream.push(self.elem_count);
116        byte_stream.extend_from_slice(buffer);
117    }
118}
119
120pub struct Package<T: AsRef<[u8]>>(pub T);
121
122impl<T> AmlObject for Package<T>
123where
124    T: AsRef<[u8]>,
125{
126    fn append_to_vec(&self, byte_stream: &mut Vec<u8>) {
127        let buffer = self.0.as_ref();
128        StructuredPackage {
129            elem_count: buffer.len() as u8,
130            elem_data: buffer,
131        }
132        .append_to_vec(byte_stream);
133    }
134}
135
136pub struct Buffer<T: AsRef<[u8]>>(pub T);
137
138impl<T> AmlObject for Buffer<T>
139where
140    T: AsRef<[u8]>,
141{
142    // A buffer consists of the identifier (0x11), followed by the length (including itself), followed by the size of
143    // the buffer in bytes and then the content.
144    fn append_to_vec(&self, byte_stream: &mut Vec<u8>) {
145        let buffer = self.0.as_ref();
146        let encoded_len = encode_integer(buffer.len().try_into().unwrap());
147        byte_stream.push(0x11);
148        byte_stream.extend_from_slice(&encode_package_len(buffer.len() + encoded_len.len()));
149        byte_stream.extend_from_slice(&encoded_len);
150        byte_stream.extend_from_slice(buffer);
151    }
152}
153
154#[cfg(test)]
155mod tests {
156    use super::*;
157    use crate::aml::test_helpers::verify_expected_bytes;
158
159    #[test]
160    fn verify_package() {
161        let package = Package(vec![1, 2, 3, 4]);
162        let bytes = package.to_bytes();
163        verify_expected_bytes(&bytes, &[0x12, 6, 4, 1, 2, 3, 4]);
164    }
165
166    #[test]
167    fn verify_large_package() {
168        let package = Package(vec![0; 0xff]);
169        let bytes = package.to_bytes();
170        assert_eq!(bytes.len(), 0xff + 4);
171        verify_expected_bytes(&bytes[..5], &[0x12, (1 << 6) | 2, 0x10, 0xff, 0]);
172        assert_eq!(bytes[0xff + 3], 0);
173    }
174
175    #[test]
176    fn verify_named_object() {
177        let package = Package(vec![0]);
178        let nobj = NamedObject::new(b"FOO", &package);
179        let bytes = nobj.to_bytes();
180        verify_expected_bytes(&bytes, &[8, b'F', b'O', b'O', b'_', 0x12, 3, 1, 0]);
181    }
182
183    #[test]
184    fn verify_named_integers() {
185        let nobj = NamedInteger::new(b"FOO", 0);
186        let bytes = nobj.to_bytes();
187        verify_expected_bytes(&bytes, &[8, b'F', b'O', b'O', b'_', 0]);
188
189        let nobj = NamedInteger::new(b"FOO", 1);
190        let bytes = nobj.to_bytes();
191        verify_expected_bytes(&bytes, &[8, b'F', b'O', b'O', b'_', 1]);
192
193        let nobj = NamedInteger::new(b"FOO", 2);
194        let bytes = nobj.to_bytes();
195        verify_expected_bytes(&bytes, &[8, b'F', b'O', b'O', b'_', 0xa, 2]);
196
197        let nobj = NamedInteger::new(b"FOO", 0x100);
198        let bytes = nobj.to_bytes();
199        verify_expected_bytes(&bytes, &[8, b'F', b'O', b'O', b'_', 0xb, 0x00, 0x01]);
200
201        let nobj = NamedInteger::new(b"FOO", 0x10000);
202        let bytes = nobj.to_bytes();
203        verify_expected_bytes(
204            &bytes,
205            &[8, b'F', b'O', b'O', b'_', 0xc, 0x00, 0x00, 0x01, 0x00],
206        );
207
208        let nobj = NamedInteger::new(b"FOO", 0x100000000);
209        let bytes = nobj.to_bytes();
210        verify_expected_bytes(
211            &bytes,
212            &[
213                8, b'F', b'O', b'O', b'_', 0xe, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
214            ],
215        );
216    }
217
218    #[test]
219    fn verify_named_string() {
220        let nobj = NamedString::new(b"FOO", b"hello");
221        let bytes = nobj.to_bytes();
222        verify_expected_bytes(
223            &bytes,
224            &[
225                8, b'F', b'O', b'O', b'_', 0xd, b'h', b'e', b'l', b'l', b'o', 0,
226            ],
227        );
228    }
229}