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#[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 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#[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}