kernel/acpi/aml/
execution.rs

1use alloc::{
2    string::{String, ToString},
3    vec::Vec,
4};
5
6use crate::{
7    acpi::aml::{parser::PackageElement, structured::ElementType},
8    testing,
9};
10
11use super::{
12    parser::{resource_template::ResourceTemplate, IntegerData, TermArg, UnresolvedDataObject},
13    structured::{StructuredAml, StructuredAmlError},
14};
15
16#[derive(Debug, Clone)]
17pub struct Package {
18    size: IntegerData,
19    elements: Vec<PackageElement<DataObject>>,
20}
21
22#[allow(dead_code)]
23impl Package {
24    pub fn size(&self) -> usize {
25        self.size.as_u64() as usize
26    }
27
28    pub fn get(&self, index: usize) -> Option<&PackageElement<DataObject>> {
29        self.elements.get(index)
30    }
31
32    pub fn iter(&self) -> impl Iterator<Item = &PackageElement<DataObject>> {
33        self.elements.iter()
34    }
35}
36
37/// A version of [UnresolvedDataObject] that is after execution
38/// so it doesn't have dynamic contents, references, or expressions
39#[derive(Debug, Clone)]
40#[allow(dead_code)]
41pub enum DataObject {
42    Integer(IntegerData),
43    ResourceTemplate(ResourceTemplate),
44    Buffer(IntegerData, Vec<u8>),
45    Package(Package),
46    String(String),
47    EisaId(String),
48}
49
50#[allow(dead_code)]
51impl DataObject {
52    pub fn as_integer(&self) -> Option<&IntegerData> {
53        match self {
54            Self::Integer(data) => Some(data),
55            _ => None,
56        }
57    }
58
59    pub fn as_package(&self) -> Option<&Package> {
60        match self {
61            Self::Package(package) => Some(package),
62            _ => None,
63        }
64    }
65}
66
67#[derive(Debug, Clone)]
68#[allow(dead_code)]
69pub enum AmlExecutionError {
70    LableNotFound(String),
71    StructuredAmlError(StructuredAmlError),
72    ElementNotExecutable(String),
73    UnexpectedTermResultType(TermArg, String),
74}
75
76impl From<StructuredAmlError> for AmlExecutionError {
77    fn from(err: StructuredAmlError) -> Self {
78        Self::StructuredAmlError(err)
79    }
80}
81
82#[derive(Debug, Default, Clone)]
83pub struct ExecutionContext {}
84impl ExecutionContext {
85    pub fn execute(
86        &self,
87        structured: &StructuredAml,
88        label: &str,
89        _args: &[UnresolvedDataObject],
90    ) -> Result<DataObject, AmlExecutionError> {
91        let element_to_execute = structured
92            .find_object(label)?
93            .ok_or(AmlExecutionError::LableNotFound(label.to_string()))?;
94
95        let data = match element_to_execute {
96            ElementType::Method(_) => todo!("Execute method"),
97            ElementType::Name(data) => data,
98            ElementType::UnknownElements(_) => {
99                // This label is internal and should never be reached
100                return Err(AmlExecutionError::LableNotFound(label.to_string()));
101            }
102            ElementType::PowerResource(_)
103            | ElementType::RegionFields(_, _)
104            | ElementType::IndexField(_)
105            | ElementType::ScopeOrDevice(_)
106            | ElementType::Processor(_) => {
107                return Err(AmlExecutionError::ElementNotExecutable(label.to_string()))
108            }
109        };
110
111        self.evaluate_data_object(data.clone(), label)
112    }
113
114    fn execute_term_arg(
115        &self,
116        term: &TermArg,
117        _reference_path: &str,
118    ) -> Result<DataObject, AmlExecutionError> {
119        todo!("Execute term: {:?}", term)
120    }
121
122    fn convert_package_elements(
123        &self,
124        elements: Vec<PackageElement<UnresolvedDataObject>>,
125        reference_path: &str,
126    ) -> Result<Vec<PackageElement<DataObject>>, AmlExecutionError> {
127        elements
128            .into_iter()
129            .map(|e| {
130                Ok(match e {
131                    PackageElement::DataObject(data) => {
132                        PackageElement::DataObject(self.evaluate_data_object(data, reference_path)?)
133                    }
134                    PackageElement::Name(name) => PackageElement::Name(name),
135                })
136            })
137            .collect::<Result<Vec<_>, _>>()
138    }
139
140    fn evaluate_data_object(
141        &self,
142        data: UnresolvedDataObject,
143        reference_path: &str,
144    ) -> Result<DataObject, AmlExecutionError> {
145        match data {
146            UnresolvedDataObject::Buffer(buffer) => {
147                let size_term = self.execute_term_arg(buffer.size.as_ref(), reference_path)?;
148
149                let size_term = match size_term {
150                    DataObject::Integer(i) => i,
151                    _ => {
152                        return Err(AmlExecutionError::UnexpectedTermResultType(
153                            buffer.size.as_ref().clone(),
154                            "Integer".to_string(),
155                        ))
156                    }
157                };
158
159                Ok(DataObject::Buffer(
160                    size_term,
161                    buffer.data.into_iter().collect(),
162                ))
163            }
164            UnresolvedDataObject::ResourceTemplate(template) => {
165                Ok(DataObject::ResourceTemplate(template))
166            }
167            UnresolvedDataObject::Package(size, elements) => Ok(DataObject::Package(Package {
168                size: IntegerData::ByteConst(size),
169                elements: self.convert_package_elements(elements, reference_path)?,
170            })),
171            UnresolvedDataObject::VarPackage(term, elements) => {
172                let size_term = self.execute_term_arg(term.as_ref(), reference_path)?;
173
174                let size_term = match size_term {
175                    DataObject::Integer(i) => i,
176                    _ => {
177                        return Err(AmlExecutionError::UnexpectedTermResultType(
178                            term.as_ref().clone(),
179                            "Integer".to_string(),
180                        ))
181                    }
182                };
183
184                Ok(DataObject::Package(Package {
185                    size: size_term,
186                    elements: self.convert_package_elements(elements, reference_path)?,
187                }))
188            }
189            UnresolvedDataObject::Integer(i) => Ok(DataObject::Integer(i)),
190            UnresolvedDataObject::String(s) => Ok(DataObject::String(s)),
191            UnresolvedDataObject::EisaId(s) => Ok(DataObject::EisaId(s)),
192        }
193    }
194}
195
196/// Test executing and getting data from
197/// ```
198/// Name("_S5_", Package(4) {0x5, 0x5, Zero, Zero}
199/// Name("_S4_", Package(4) {0x4, 0x4, Zero, Zero}
200/// ```
201/// ```
202#[macro_rules_attribute::apply(testing::test)]
203fn test_execute_normal_sleep_package() {
204    use super::parser::{AmlCode, AmlTerm};
205    use alloc::vec;
206
207    fn return_package_of_name(
208        ctx: &mut ExecutionContext,
209        structured_code: &StructuredAml,
210        name: &str,
211    ) -> Vec<u8> {
212        ctx.execute(structured_code, name, &[])
213            .expect("label")
214            .as_package()
215            .expect("package")
216            .iter()
217            .map(|d| {
218                d.as_data()
219                    .expect("data")
220                    .as_integer()
221                    .expect("integer")
222                    .as_u8()
223                    .unwrap()
224            })
225            .collect::<Vec<_>>()
226    }
227
228    let code = AmlCode {
229        term_list: vec![
230            AmlTerm::NameObj(
231                "_S5_".to_string(),
232                UnresolvedDataObject::Package(
233                    4,
234                    vec![
235                        PackageElement::DataObject(UnresolvedDataObject::Integer(
236                            IntegerData::ByteConst(5),
237                        )),
238                        PackageElement::DataObject(UnresolvedDataObject::Integer(
239                            IntegerData::ByteConst(5),
240                        )),
241                        PackageElement::DataObject(UnresolvedDataObject::Integer(
242                            IntegerData::ConstZero,
243                        )),
244                        PackageElement::DataObject(UnresolvedDataObject::Integer(
245                            IntegerData::ConstZero,
246                        )),
247                    ],
248                ),
249            ),
250            AmlTerm::NameObj(
251                "_S4_".to_string(),
252                UnresolvedDataObject::Package(
253                    4,
254                    vec![
255                        PackageElement::DataObject(UnresolvedDataObject::Integer(
256                            IntegerData::ByteConst(4),
257                        )),
258                        PackageElement::DataObject(UnresolvedDataObject::Integer(
259                            IntegerData::ByteConst(4),
260                        )),
261                        PackageElement::DataObject(UnresolvedDataObject::Integer(
262                            IntegerData::ConstZero,
263                        )),
264                        PackageElement::DataObject(UnresolvedDataObject::Integer(
265                            IntegerData::ConstZero,
266                        )),
267                    ],
268                ),
269            ),
270        ],
271    };
272
273    let structured_code = StructuredAml::parse(&code);
274
275    let mut execution_ctx = ExecutionContext::default();
276
277    assert_eq!(
278        return_package_of_name(&mut execution_ctx, &structured_code, "\\_S5_"),
279        vec![5, 5, 0, 0]
280    );
281    assert_eq!(
282        return_package_of_name(&mut execution_ctx, &structured_code, "\\_S4_"),
283        vec![4, 4, 0, 0]
284    );
285}