1 // Copyright 2020 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 /// The trait Aml can be implemented by the ACPI objects to translate itself
6 /// into the AML raw data. So that these AML raw data can be added into the
7 /// ACPI DSDT for guest.
8 pub trait Aml {
9     /// Translate an ACPI object into AML code and append to the vector
10     /// buffer.
11     /// * `bytes` - The vector used to append the AML code.
to_aml_bytes(&self, bytes: &mut Vec<u8>)12     fn to_aml_bytes(&self, bytes: &mut Vec<u8>);
13 }
14 
15 // AML byte stream defines
16 const ZEROOP: u8 = 0x00;
17 const ONEOP: u8 = 0x01;
18 const NAMEOP: u8 = 0x08;
19 const BYTEPREFIX: u8 = 0x0a;
20 const WORDPREFIX: u8 = 0x0b;
21 const DWORDPREFIX: u8 = 0x0c;
22 const STRINGOP: u8 = 0x0d;
23 const QWORDPREFIX: u8 = 0x0e;
24 const SCOPEOP: u8 = 0x10;
25 const BUFFEROP: u8 = 0x11;
26 const PACKAGEOP: u8 = 0x12;
27 const METHODOP: u8 = 0x14;
28 const DUALNAMEPREFIX: u8 = 0x2e;
29 const MULTINAMEPREFIX: u8 = 0x2f;
30 const NAMECHARBASE: u8 = 0x40;
31 
32 const EXTOPPREFIX: u8 = 0x5b;
33 const MUTEXOP: u8 = 0x01;
34 const ACQUIREOP: u8 = 0x23;
35 const RELEASEOP: u8 = 0x27;
36 const OPREGIONOP: u8 = 0x80;
37 const FIELDOP: u8 = 0x81;
38 const DEVICEOP: u8 = 0x82;
39 
40 const LOCAL0OP: u8 = 0x60;
41 const ARG0OP: u8 = 0x68;
42 const STOREOP: u8 = 0x70;
43 const ADDOP: u8 = 0x72;
44 const CONCATOP: u8 = 0x73;
45 const SUBTRACTOP: u8 = 0x74;
46 const MULTIPLYOP: u8 = 0x77;
47 const SHIFTLEFTOP: u8 = 0x79;
48 const SHIFTRIGHTOP: u8 = 0x7a;
49 const ANDOP: u8 = 0x7b;
50 const NANDOP: u8 = 0x7c;
51 const OROP: u8 = 0x7d;
52 const NOROP: u8 = 0x7e;
53 const XOROP: u8 = 0x7f;
54 const CONCATRESOP: u8 = 0x84;
55 const MODOP: u8 = 0x85;
56 const NOTIFYOP: u8 = 0x86;
57 const INDEXOP: u8 = 0x88;
58 const LEQUALOP: u8 = 0x93;
59 const LLESSOP: u8 = 0x95;
60 const TOSTRINGOP: u8 = 0x9c;
61 const IFOP: u8 = 0xa0;
62 const WHILEOP: u8 = 0xa2;
63 const RETURNOP: u8 = 0xa4;
64 const ONESOP: u8 = 0xff;
65 
66 // AML resouce data fields
67 const IOPORTDESC: u8 = 0x47;
68 const ENDTAG: u8 = 0x79;
69 const MEMORY32FIXEDDESC: u8 = 0x86;
70 const DWORDADDRSPACEDESC: u8 = 0x87;
71 const WORDADDRSPACEDESC: u8 = 0x88;
72 const EXTIRQDESC: u8 = 0x89;
73 const QWORDADDRSPACEDESC: u8 = 0x8A;
74 
75 /// Zero object in ASL.
76 pub const ZERO: Zero = Zero {};
77 pub struct Zero {}
78 
79 impl Aml for Zero {
to_aml_bytes(&self, bytes: &mut Vec<u8>)80     fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
81         bytes.append(&mut vec![ZEROOP]);
82     }
83 }
84 
85 /// One object in ASL.
86 pub const ONE: One = One {};
87 pub struct One {}
88 
89 impl Aml for One {
to_aml_bytes(&self, bytes: &mut Vec<u8>)90     fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
91         bytes.append(&mut vec![ONEOP]);
92     }
93 }
94 
95 /// Ones object represents all bits 1.
96 pub const ONES: Ones = Ones {};
97 pub struct Ones {}
98 
99 impl Aml for Ones {
to_aml_bytes(&self, bytes: &mut Vec<u8>)100     fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
101         bytes.append(&mut vec![ONESOP]);
102     }
103 }
104 
105 /// Represents Namestring to construct ACPI objects like
106 /// Name/Device/Method/Scope and so on...
107 pub struct Path {
108     root: bool,
109     name_parts: Vec<[u8; 4]>,
110 }
111 
112 impl Aml for Path {
to_aml_bytes(&self, bytes: &mut Vec<u8>)113     fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
114         if self.root {
115             bytes.push(b'\\');
116         }
117 
118         match self.name_parts.len() {
119             0 => panic!("Name cannot be empty"),
120             1 => {}
121             2 => {
122                 bytes.push(DUALNAMEPREFIX);
123             }
124             n => {
125                 bytes.push(MULTINAMEPREFIX);
126                 bytes.push(n as u8);
127             }
128         };
129 
130         for part in self.name_parts.clone().iter_mut() {
131             bytes.append(&mut part.to_vec());
132         }
133     }
134 }
135 
136 impl Path {
137     /// Per ACPI Spec, the Namestring split by "." has 4 bytes long. So any name
138     /// not has 4 bytes will not be accepted.
new(name: &str) -> Self139     pub fn new(name: &str) -> Self {
140         let root = name.starts_with('\\');
141         let offset = root as usize;
142         let mut name_parts = Vec::new();
143         for part in name[offset..].split('.') {
144             assert_eq!(part.len(), 4);
145             let mut name_part = [0u8; 4];
146             name_part.copy_from_slice(part.as_bytes());
147             name_parts.push(name_part);
148         }
149 
150         Path { root, name_parts }
151     }
152 }
153 
154 impl From<&str> for Path {
from(s: &str) -> Self155     fn from(s: &str) -> Self {
156         Path::new(s)
157     }
158 }
159 
160 pub type Byte = u8;
161 
162 impl Aml for Byte {
to_aml_bytes(&self, bytes: &mut Vec<u8>)163     fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
164         bytes.push(BYTEPREFIX);
165         bytes.push(*self);
166     }
167 }
168 
169 pub type Word = u16;
170 
171 impl Aml for Word {
to_aml_bytes(&self, bytes: &mut Vec<u8>)172     fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
173         bytes.push(WORDPREFIX);
174         bytes.append(&mut self.to_le_bytes().to_vec());
175     }
176 }
177 
178 pub type DWord = u32;
179 
180 impl Aml for DWord {
to_aml_bytes(&self, bytes: &mut Vec<u8>)181     fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
182         bytes.push(DWORDPREFIX);
183         bytes.append(&mut self.to_le_bytes().to_vec());
184     }
185 }
186 
187 pub type QWord = u64;
188 
189 impl Aml for QWord {
to_aml_bytes(&self, bytes: &mut Vec<u8>)190     fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
191         bytes.push(QWORDPREFIX);
192         bytes.append(&mut self.to_le_bytes().to_vec());
193     }
194 }
195 
196 /// Name object. bytes represents the raw AML data for it.
197 pub struct Name {
198     bytes: Vec<u8>,
199 }
200 
201 impl Aml for Name {
to_aml_bytes(&self, bytes: &mut Vec<u8>)202     fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
203         bytes.append(&mut self.bytes.clone());
204     }
205 }
206 
207 impl Name {
208     /// Create Name object:
209     ///
210     /// * `path` - The namestring.
211     /// * `inner` - AML objects contained in this namespace.
new(path: Path, inner: &dyn Aml) -> Self212     pub fn new(path: Path, inner: &dyn Aml) -> Self {
213         let mut bytes = Vec::new();
214         bytes.push(NAMEOP);
215         path.to_aml_bytes(&mut bytes);
216         inner.to_aml_bytes(&mut bytes);
217         Name { bytes }
218     }
219 }
220 
221 /// Package object. 'children' represents the ACPI objects contained in this package.
222 pub struct Package<'a> {
223     children: Vec<&'a dyn Aml>,
224 }
225 
226 impl<'a> Aml for Package<'a> {
to_aml_bytes(&self, aml: &mut Vec<u8>)227     fn to_aml_bytes(&self, aml: &mut Vec<u8>) {
228         let mut bytes = Vec::new();
229         bytes.push(self.children.len() as u8);
230         for child in &self.children {
231             child.to_aml_bytes(&mut bytes);
232         }
233 
234         let mut pkg_length = create_pkg_length(&bytes, true);
235         pkg_length.reverse();
236         for byte in pkg_length {
237             bytes.insert(0, byte);
238         }
239 
240         bytes.insert(0, PACKAGEOP);
241 
242         aml.append(&mut bytes);
243     }
244 }
245 
246 impl<'a> Package<'a> {
247     /// Create Package object:
new(children: Vec<&'a dyn Aml>) -> Self248     pub fn new(children: Vec<&'a dyn Aml>) -> Self {
249         Package { children }
250     }
251 }
252 
253 /*
254 
255 From the ACPI spec for PkgLength:
256 
257 "The high 2 bits of the first byte reveal how many follow bytes are in the PkgLength. If the
258 PkgLength has only one byte, bit 0 through 5 are used to encode the package length (in other
259 words, values 0-63). If the package length value is more than 63, more than one byte must be
260 used for the encoding in which case bit 4 and 5 of the PkgLeadByte are reserved and must be zero.
261 If the multiple bytes encoding is used, bits 0-3 of the PkgLeadByte become the least significant 4
262 bits of the resulting package length value. The next ByteData will become the next least
263 significant 8 bits of the resulting value and so on, up to 3 ByteData bytes. Thus, the maximum
264 package length is 2**28."
265 
266 */
267 
268 /* Also used for NamedField but in that case the length is not included in itself */
create_pkg_length(data: &[u8], include_self: bool) -> Vec<u8>269 fn create_pkg_length(data: &[u8], include_self: bool) -> Vec<u8> {
270     let mut result = Vec::new();
271 
272     /* PkgLength is inclusive and includes the length bytes */
273     let length_length = if data.len() < (2usize.pow(6) - 1) {
274         1
275     } else if data.len() < (2usize.pow(12) - 2) {
276         2
277     } else if data.len() < (2usize.pow(20) - 3) {
278         3
279     } else {
280         4
281     };
282 
283     let length = data.len() + if include_self { length_length } else { 0 };
284 
285     match length_length {
286         1 => result.push(length as u8),
287         2 => {
288             result.push((1u8 << 6) | (length & 0xf) as u8);
289             result.push((length >> 4) as u8)
290         }
291         3 => {
292             result.push((2u8 << 6) | (length & 0xf) as u8);
293             result.push((length >> 4) as u8);
294             result.push((length >> 12) as u8);
295         }
296         _ => {
297             result.push((3u8 << 6) | (length & 0xf) as u8);
298             result.push((length >> 4) as u8);
299             result.push((length >> 12) as u8);
300             result.push((length >> 20) as u8);
301         }
302     }
303 
304     result
305 }
306 
307 /// EISAName object. 'value' means the encoded u32 EisaIdString.
308 pub struct EISAName {
309     value: DWord,
310 }
311 
312 impl EISAName {
313     /// Per ACPI Spec, the EisaIdString must be a String
314     /// object of the form UUUNNNN, where U is an uppercase letter
315     /// and N is a hexadecimal digit. No asterisks or other characters
316     /// are allowed in the string.
new(name: &str) -> Self317     pub fn new(name: &str) -> Self {
318         assert_eq!(name.len(), 7);
319 
320         let data = name.as_bytes();
321 
322         let value: u32 = (u32::from(data[0].checked_sub(NAMECHARBASE).unwrap()) << 26
323             | u32::from(data[1].checked_sub(NAMECHARBASE).unwrap()) << 21
324             | u32::from(data[2].checked_sub(NAMECHARBASE).unwrap()) << 16
325             | name.chars().nth(3).unwrap().to_digit(16).unwrap() << 12
326             | name.chars().nth(4).unwrap().to_digit(16).unwrap() << 8
327             | name.chars().nth(5).unwrap().to_digit(16).unwrap() << 4
328             | name.chars().nth(6).unwrap().to_digit(16).unwrap())
329         .swap_bytes();
330 
331         EISAName { value }
332     }
333 }
334 
335 impl Aml for EISAName {
to_aml_bytes(&self, bytes: &mut Vec<u8>)336     fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
337         self.value.to_aml_bytes(bytes);
338     }
339 }
340 
create_integer(v: usize, bytes: &mut Vec<u8>)341 fn create_integer(v: usize, bytes: &mut Vec<u8>) {
342     if v <= u8::max_value().into() {
343         (v as u8).to_aml_bytes(bytes);
344     } else if v <= u16::max_value().into() {
345         (v as u16).to_aml_bytes(bytes);
346     } else if v <= u32::max_value() as usize {
347         (v as u32).to_aml_bytes(bytes);
348     } else {
349         (v as u64).to_aml_bytes(bytes);
350     }
351 }
352 
353 pub type Usize = usize;
354 
355 impl Aml for Usize {
to_aml_bytes(&self, bytes: &mut Vec<u8>)356     fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
357         create_integer(*self, bytes);
358     }
359 }
360 
create_aml_string(v: &str) -> Vec<u8>361 fn create_aml_string(v: &str) -> Vec<u8> {
362     let mut data = Vec::new();
363     data.push(STRINGOP);
364     data.extend_from_slice(v.as_bytes());
365     data.push(0x0); /* NullChar */
366     data
367 }
368 
369 /// implement Aml trait for 'str' so that 'str' can be directly append to the aml vector
370 pub type AmlStr = &'static str;
371 
372 impl Aml for AmlStr {
to_aml_bytes(&self, bytes: &mut Vec<u8>)373     fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
374         bytes.append(&mut create_aml_string(self));
375     }
376 }
377 
378 /// implement Aml trait for 'String'. So purpose with str.
379 pub type AmlString = String;
380 
381 impl Aml for AmlString {
to_aml_bytes(&self, bytes: &mut Vec<u8>)382     fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
383         bytes.append(&mut create_aml_string(self));
384     }
385 }
386 
387 /// ResouceTemplate object. 'children' represents the ACPI objects in it.
388 pub struct ResourceTemplate<'a> {
389     children: Vec<&'a dyn Aml>,
390 }
391 
392 impl<'a> Aml for ResourceTemplate<'a> {
to_aml_bytes(&self, aml: &mut Vec<u8>)393     fn to_aml_bytes(&self, aml: &mut Vec<u8>) {
394         let mut bytes = Vec::new();
395 
396         // Add buffer data
397         for child in &self.children {
398             child.to_aml_bytes(&mut bytes);
399         }
400 
401         // Mark with end and mark checksum as as always valid
402         bytes.push(ENDTAG);
403         bytes.push(0); /* zero checksum byte */
404 
405         // Buffer length is an encoded integer including buffer data
406         // and EndTag and checksum byte
407         let mut buffer_length = Vec::new();
408         bytes.len().to_aml_bytes(&mut buffer_length);
409         buffer_length.reverse();
410         for byte in buffer_length {
411             bytes.insert(0, byte);
412         }
413 
414         // PkgLength is everything else
415         let mut pkg_length = create_pkg_length(&bytes, true);
416         pkg_length.reverse();
417         for byte in pkg_length {
418             bytes.insert(0, byte);
419         }
420 
421         bytes.insert(0, BUFFEROP);
422 
423         aml.append(&mut bytes);
424     }
425 }
426 
427 impl<'a> ResourceTemplate<'a> {
428     /// Create ResouceTemplate object
new(children: Vec<&'a dyn Aml>) -> Self429     pub fn new(children: Vec<&'a dyn Aml>) -> Self {
430         ResourceTemplate { children }
431     }
432 }
433 
434 /// Memory32Fixed object with read_write accessing type, and the base address/length.
435 pub struct Memory32Fixed {
436     read_write: bool, /* true for read & write, false for read only */
437     base: u32,
438     length: u32,
439 }
440 
441 impl Memory32Fixed {
442     /// Create Memory32Fixed object.
new(read_write: bool, base: u32, length: u32) -> Self443     pub fn new(read_write: bool, base: u32, length: u32) -> Self {
444         Memory32Fixed {
445             read_write,
446             base,
447             length,
448         }
449     }
450 }
451 
452 impl Aml for Memory32Fixed {
to_aml_bytes(&self, bytes: &mut Vec<u8>)453     fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
454         bytes.push(MEMORY32FIXEDDESC); /* 32bit Fixed Memory Range Descriptor */
455         bytes.append(&mut 9u16.to_le_bytes().to_vec());
456 
457         // 9 bytes of payload
458         bytes.push(self.read_write as u8);
459         bytes.append(&mut self.base.to_le_bytes().to_vec());
460         bytes.append(&mut self.length.to_le_bytes().to_vec());
461     }
462 }
463 
464 #[derive(Copy, Clone)]
465 enum AddressSpaceType {
466     Memory,
467     IO,
468     BusNumber,
469 }
470 
471 /// AddressSpaceCachable represent cache types for AddressSpace object
472 #[derive(Copy, Clone)]
473 pub enum AddressSpaceCachable {
474     NotCacheable,
475     Cacheable,
476     WriteCombining,
477     PreFetchable,
478 }
479 
480 /// AddressSpace structure with type, resouce range and flags to
481 /// construct Memory/IO/BusNumber objects
482 pub struct AddressSpace<T> {
483     type_: AddressSpaceType,
484     min: T,
485     max: T,
486     type_flags: u8,
487 }
488 
489 impl<T> AddressSpace<T> {
490     /// Create DWordMemory/QWordMemory object
new_memory(cacheable: AddressSpaceCachable, read_write: bool, min: T, max: T) -> Self491     pub fn new_memory(cacheable: AddressSpaceCachable, read_write: bool, min: T, max: T) -> Self {
492         AddressSpace {
493             type_: AddressSpaceType::Memory,
494             min,
495             max,
496             type_flags: (cacheable as u8) << 1 | read_write as u8,
497         }
498     }
499 
500     /// Create WordIO/DWordIO/QWordIO object
new_io(min: T, max: T) -> Self501     pub fn new_io(min: T, max: T) -> Self {
502         AddressSpace {
503             type_: AddressSpaceType::IO,
504             min,
505             max,
506             type_flags: 3, /* EntireRange */
507         }
508     }
509 
510     /// Create WordBusNumber object
new_bus_number(min: T, max: T) -> Self511     pub fn new_bus_number(min: T, max: T) -> Self {
512         AddressSpace {
513             type_: AddressSpaceType::BusNumber,
514             min,
515             max,
516             type_flags: 0,
517         }
518     }
519 
push_header(&self, bytes: &mut Vec<u8>, descriptor: u8, length: usize)520     fn push_header(&self, bytes: &mut Vec<u8>, descriptor: u8, length: usize) {
521         bytes.push(descriptor); /* Word Address Space Descriptor */
522         bytes.append(&mut (length as u16).to_le_bytes().to_vec());
523         bytes.push(self.type_ as u8); /* type */
524         let generic_flags = 1 << 2 /* Min Fixed */ | 1 << 3; /* Max Fixed */
525         bytes.push(generic_flags);
526         bytes.push(self.type_flags);
527     }
528 }
529 
530 impl Aml for AddressSpace<u16> {
to_aml_bytes(&self, bytes: &mut Vec<u8>)531     fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
532         self.push_header(
533             bytes,
534             WORDADDRSPACEDESC,                  /* Word Address Space Descriptor */
535             3 + 5 * std::mem::size_of::<u16>(), /* 3 bytes of header + 5 u16 fields */
536         );
537 
538         bytes.append(&mut 0u16.to_le_bytes().to_vec()); /* Granularity */
539         bytes.append(&mut self.min.to_le_bytes().to_vec()); /* Min */
540         bytes.append(&mut self.max.to_le_bytes().to_vec()); /* Max */
541         bytes.append(&mut 0u16.to_le_bytes().to_vec()); /* Translation */
542         let len = self.max - self.min + 1;
543         bytes.append(&mut len.to_le_bytes().to_vec()); /* Length */
544     }
545 }
546 
547 impl Aml for AddressSpace<u32> {
to_aml_bytes(&self, bytes: &mut Vec<u8>)548     fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
549         self.push_header(
550             bytes,
551             DWORDADDRSPACEDESC, /* DWord Address Space Descriptor */
552             3 + 5 * std::mem::size_of::<u32>(), /* 3 bytes of header + 5 u32 fields */
553         );
554 
555         bytes.append(&mut 0u32.to_le_bytes().to_vec()); /* Granularity */
556         bytes.append(&mut self.min.to_le_bytes().to_vec()); /* Min */
557         bytes.append(&mut self.max.to_le_bytes().to_vec()); /* Max */
558         bytes.append(&mut 0u32.to_le_bytes().to_vec()); /* Translation */
559         let len = self.max - self.min + 1;
560         bytes.append(&mut len.to_le_bytes().to_vec()); /* Length */
561     }
562 }
563 
564 impl Aml for AddressSpace<u64> {
to_aml_bytes(&self, bytes: &mut Vec<u8>)565     fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
566         self.push_header(
567             bytes,
568             QWORDADDRSPACEDESC, /* QWord Address Space Descriptor */
569             3 + 5 * std::mem::size_of::<u64>(), /* 3 bytes of header + 5 u64 fields */
570         );
571 
572         bytes.append(&mut 0u64.to_le_bytes().to_vec()); /* Granularity */
573         bytes.append(&mut self.min.to_le_bytes().to_vec()); /* Min */
574         bytes.append(&mut self.max.to_le_bytes().to_vec()); /* Max */
575         bytes.append(&mut 0u64.to_le_bytes().to_vec()); /* Translation */
576         let len = self.max - self.min + 1;
577         bytes.append(&mut len.to_le_bytes().to_vec()); /* Length */
578     }
579 }
580 
581 /// IO resouce object with the IO range, alignment and length
582 pub struct IO {
583     min: u16,
584     max: u16,
585     alignment: u8,
586     length: u8,
587 }
588 
589 impl IO {
590     /// Create IO object
new(min: u16, max: u16, alignment: u8, length: u8) -> Self591     pub fn new(min: u16, max: u16, alignment: u8, length: u8) -> Self {
592         IO {
593             min,
594             max,
595             alignment,
596             length,
597         }
598     }
599 }
600 
601 impl Aml for IO {
to_aml_bytes(&self, bytes: &mut Vec<u8>)602     fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
603         bytes.push(IOPORTDESC); /* IO Port Descriptor */
604         bytes.push(1); /* IODecode16 */
605         bytes.append(&mut self.min.to_le_bytes().to_vec());
606         bytes.append(&mut self.max.to_le_bytes().to_vec());
607         bytes.push(self.alignment);
608         bytes.push(self.length);
609     }
610 }
611 
612 /// Interrupt resouce object with the interrupt characters.
613 pub struct Interrupt {
614     consumer: bool,
615     edge_triggered: bool,
616     active_low: bool,
617     shared: bool,
618     number: u32,
619 }
620 
621 impl Interrupt {
622     /// Create Interrupt object
new( consumer: bool, edge_triggered: bool, active_low: bool, shared: bool, number: u32, ) -> Self623     pub fn new(
624         consumer: bool,
625         edge_triggered: bool,
626         active_low: bool,
627         shared: bool,
628         number: u32,
629     ) -> Self {
630         Interrupt {
631             consumer,
632             edge_triggered,
633             active_low,
634             shared,
635             number,
636         }
637     }
638 }
639 
640 impl Aml for Interrupt {
to_aml_bytes(&self, bytes: &mut Vec<u8>)641     fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
642         bytes.push(EXTIRQDESC); /* Extended IRQ Descriptor */
643         bytes.append(&mut 6u16.to_le_bytes().to_vec());
644         let flags = (self.shared as u8) << 3
645             | (self.active_low as u8) << 2
646             | (self.edge_triggered as u8) << 1
647             | self.consumer as u8;
648         bytes.push(flags);
649         bytes.push(1u8); /* count */
650         bytes.append(&mut self.number.to_le_bytes().to_vec());
651     }
652 }
653 
654 /// Device object with its device name and children objects in it.
655 pub struct Device<'a> {
656     path: Path,
657     children: Vec<&'a dyn Aml>,
658 }
659 
660 impl<'a> Aml for Device<'a> {
to_aml_bytes(&self, aml: &mut Vec<u8>)661     fn to_aml_bytes(&self, aml: &mut Vec<u8>) {
662         let mut bytes = Vec::new();
663         self.path.to_aml_bytes(&mut bytes);
664         for child in &self.children {
665             child.to_aml_bytes(&mut bytes);
666         }
667 
668         let mut pkg_length = create_pkg_length(&bytes, true);
669         pkg_length.reverse();
670         for byte in pkg_length {
671             bytes.insert(0, byte);
672         }
673 
674         bytes.insert(0, DEVICEOP); /* DeviceOp */
675         bytes.insert(0, EXTOPPREFIX); /* ExtOpPrefix */
676         aml.append(&mut bytes)
677     }
678 }
679 
680 impl<'a> Device<'a> {
681     /// Create Device object
new(path: Path, children: Vec<&'a dyn Aml>) -> Self682     pub fn new(path: Path, children: Vec<&'a dyn Aml>) -> Self {
683         Device { path, children }
684     }
685 }
686 
687 /// Scope object with its name and children objects in it.
688 pub struct Scope<'a> {
689     path: Path,
690     children: Vec<&'a dyn Aml>,
691 }
692 
693 impl<'a> Aml for Scope<'a> {
to_aml_bytes(&self, aml: &mut Vec<u8>)694     fn to_aml_bytes(&self, aml: &mut Vec<u8>) {
695         let mut bytes = Vec::new();
696         self.path.to_aml_bytes(&mut bytes);
697         for child in &self.children {
698             child.to_aml_bytes(&mut bytes);
699         }
700 
701         let mut pkg_length = create_pkg_length(&bytes, true);
702         pkg_length.reverse();
703         for byte in pkg_length {
704             bytes.insert(0, byte);
705         }
706 
707         bytes.insert(0, SCOPEOP);
708         aml.append(&mut bytes)
709     }
710 }
711 
712 impl<'a> Scope<'a> {
713     /// Create Scope object
new(path: Path, children: Vec<&'a dyn Aml>) -> Self714     pub fn new(path: Path, children: Vec<&'a dyn Aml>) -> Self {
715         Scope { path, children }
716     }
717 }
718 
719 /// Method object with its name, children objects, arguments and serialized character.
720 pub struct Method<'a> {
721     path: Path,
722     children: Vec<&'a dyn Aml>,
723     args: u8,
724     serialized: bool,
725 }
726 
727 impl<'a> Method<'a> {
728     /// Create Method object.
new(path: Path, args: u8, serialized: bool, children: Vec<&'a dyn Aml>) -> Self729     pub fn new(path: Path, args: u8, serialized: bool, children: Vec<&'a dyn Aml>) -> Self {
730         Method {
731             path,
732             children,
733             args,
734             serialized,
735         }
736     }
737 }
738 
739 impl<'a> Aml for Method<'a> {
to_aml_bytes(&self, aml: &mut Vec<u8>)740     fn to_aml_bytes(&self, aml: &mut Vec<u8>) {
741         let mut bytes = Vec::new();
742         self.path.to_aml_bytes(&mut bytes);
743         let flags: u8 = (self.args & 0x7) | (self.serialized as u8) << 3;
744         bytes.push(flags);
745         for child in &self.children {
746             child.to_aml_bytes(&mut bytes);
747         }
748 
749         let mut pkg_length = create_pkg_length(&bytes, true);
750         pkg_length.reverse();
751         for byte in pkg_length {
752             bytes.insert(0, byte);
753         }
754 
755         bytes.insert(0, METHODOP);
756         aml.append(&mut bytes)
757     }
758 }
759 
760 /// Return object with its return value.
761 pub struct Return<'a> {
762     value: &'a dyn Aml,
763 }
764 
765 impl<'a> Return<'a> {
766     /// Create Return object
new(value: &'a dyn Aml) -> Self767     pub fn new(value: &'a dyn Aml) -> Self {
768         Return { value }
769     }
770 }
771 
772 impl<'a> Aml for Return<'a> {
to_aml_bytes(&self, bytes: &mut Vec<u8>)773     fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
774         bytes.push(RETURNOP);
775         self.value.to_aml_bytes(bytes);
776     }
777 }
778 
779 /// FiledAccessType defines the filed accessing types.
780 #[derive(Clone, Copy)]
781 pub enum FieldAccessType {
782     Any,
783     Byte,
784     Word,
785     DWord,
786     QWord,
787     Buffer,
788 }
789 
790 /// FiledUpdateRule defines the rules to update the filed.
791 #[derive(Clone, Copy)]
792 pub enum FieldUpdateRule {
793     Preserve = 0,
794     WriteAsOnes = 1,
795     WriteAsZeroes = 2,
796 }
797 
798 /// FiledEntry defines the filed entry.
799 pub enum FieldEntry {
800     Named([u8; 4], usize),
801     Reserved(usize),
802 }
803 
804 /// Field object with the region name, filed entries, access type and update rules.
805 pub struct Field {
806     path: Path,
807 
808     fields: Vec<FieldEntry>,
809     access_type: FieldAccessType,
810     update_rule: FieldUpdateRule,
811 }
812 
813 impl Field {
814     /// Create Field object
new( path: Path, access_type: FieldAccessType, update_rule: FieldUpdateRule, fields: Vec<FieldEntry>, ) -> Self815     pub fn new(
816         path: Path,
817         access_type: FieldAccessType,
818         update_rule: FieldUpdateRule,
819         fields: Vec<FieldEntry>,
820     ) -> Self {
821         Field {
822             path,
823             access_type,
824             update_rule,
825             fields,
826         }
827     }
828 }
829 
830 impl Aml for Field {
to_aml_bytes(&self, aml: &mut Vec<u8>)831     fn to_aml_bytes(&self, aml: &mut Vec<u8>) {
832         let mut bytes = Vec::new();
833         self.path.to_aml_bytes(&mut bytes);
834 
835         let flags: u8 = self.access_type as u8 | (self.update_rule as u8) << 5;
836         bytes.push(flags);
837 
838         for field in self.fields.iter() {
839             match field {
840                 FieldEntry::Named(name, length) => {
841                     bytes.extend_from_slice(name);
842                     bytes.append(&mut create_pkg_length(&vec![0; *length], false));
843                 }
844                 FieldEntry::Reserved(length) => {
845                     bytes.push(0x0);
846                     bytes.append(&mut create_pkg_length(&vec![0; *length], false));
847                 }
848             }
849         }
850 
851         let mut pkg_length = create_pkg_length(&bytes, true);
852         pkg_length.reverse();
853         for byte in pkg_length {
854             bytes.insert(0, byte);
855         }
856 
857         bytes.insert(0, FIELDOP);
858         bytes.insert(0, EXTOPPREFIX);
859         aml.append(&mut bytes)
860     }
861 }
862 
863 /// The space type for OperationRegion object
864 #[derive(Clone, Copy)]
865 pub enum OpRegionSpace {
866     SystemMemory,
867     SystemIO,
868     PCIConfig,
869     EmbeddedControl,
870     SMBus,
871     SystemCMOS,
872     PciBarTarget,
873     IPMI,
874     GeneralPurposeIO,
875     GenericSerialBus,
876 }
877 
878 /// OperationRegion object with region name, region space type, its offset and length.
879 pub struct OpRegion {
880     path: Path,
881     space: OpRegionSpace,
882     offset: usize,
883     length: usize,
884 }
885 
886 impl OpRegion {
887     /// Create OperationRegion object.
new(path: Path, space: OpRegionSpace, offset: usize, length: usize) -> Self888     pub fn new(path: Path, space: OpRegionSpace, offset: usize, length: usize) -> Self {
889         OpRegion {
890             path,
891             space,
892             offset,
893             length,
894         }
895     }
896 }
897 
898 impl Aml for OpRegion {
to_aml_bytes(&self, aml: &mut Vec<u8>)899     fn to_aml_bytes(&self, aml: &mut Vec<u8>) {
900         let mut bytes = Vec::new();
901         self.path.to_aml_bytes(&mut bytes);
902         bytes.push(self.space as u8);
903         self.offset.to_aml_bytes(&mut bytes); /* RegionOffset */
904         self.length.to_aml_bytes(&mut bytes); /* RegionLen */
905         bytes.insert(0, OPREGIONOP);
906         bytes.insert(0, EXTOPPREFIX);
907         aml.append(&mut bytes)
908     }
909 }
910 
911 /// If object with the if condition(predicate) and the body presented by the if_children objects.
912 pub struct If<'a> {
913     predicate: &'a dyn Aml,
914     if_children: Vec<&'a dyn Aml>,
915 }
916 
917 impl<'a> If<'a> {
918     /// Create If object.
new(predicate: &'a dyn Aml, if_children: Vec<&'a dyn Aml>) -> Self919     pub fn new(predicate: &'a dyn Aml, if_children: Vec<&'a dyn Aml>) -> Self {
920         If {
921             predicate,
922             if_children,
923         }
924     }
925 }
926 
927 impl<'a> Aml for If<'a> {
to_aml_bytes(&self, aml: &mut Vec<u8>)928     fn to_aml_bytes(&self, aml: &mut Vec<u8>) {
929         let mut bytes = Vec::new();
930         self.predicate.to_aml_bytes(&mut bytes);
931         for child in self.if_children.iter() {
932             child.to_aml_bytes(&mut bytes);
933         }
934 
935         let mut pkg_length = create_pkg_length(&bytes, true);
936         pkg_length.reverse();
937         for byte in pkg_length {
938             bytes.insert(0, byte);
939         }
940 
941         bytes.insert(0, IFOP);
942         aml.append(&mut bytes)
943     }
944 }
945 
946 /// Equal object with its right part and left part, which are both ACPI objects.
947 pub struct Equal<'a> {
948     right: &'a dyn Aml,
949     left: &'a dyn Aml,
950 }
951 
952 impl<'a> Equal<'a> {
953     /// Create Equal object.
new(left: &'a dyn Aml, right: &'a dyn Aml) -> Self954     pub fn new(left: &'a dyn Aml, right: &'a dyn Aml) -> Self {
955         Equal { left, right }
956     }
957 }
958 
959 impl<'a> Aml for Equal<'a> {
to_aml_bytes(&self, bytes: &mut Vec<u8>)960     fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
961         bytes.push(LEQUALOP);
962         self.left.to_aml_bytes(bytes);
963         self.right.to_aml_bytes(bytes);
964     }
965 }
966 
967 /// LessThan object with its right part and left part, which are both ACPI objects.
968 pub struct LessThan<'a> {
969     right: &'a dyn Aml,
970     left: &'a dyn Aml,
971 }
972 
973 impl<'a> LessThan<'a> {
974     /// Create LessThan object.
new(left: &'a dyn Aml, right: &'a dyn Aml) -> Self975     pub fn new(left: &'a dyn Aml, right: &'a dyn Aml) -> Self {
976         LessThan { left, right }
977     }
978 }
979 
980 impl<'a> Aml for LessThan<'a> {
to_aml_bytes(&self, bytes: &mut Vec<u8>)981     fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
982         bytes.push(LLESSOP);
983         self.left.to_aml_bytes(bytes);
984         self.right.to_aml_bytes(bytes);
985     }
986 }
987 
988 /// Argx object.
989 pub struct Arg(pub u8);
990 
991 impl Aml for Arg {
992     /// Per ACPI spec, there is maximum 7 Argx objects from
993     /// Arg0 ~ Arg6. Any other Arg object will not be accepted.
to_aml_bytes(&self, bytes: &mut Vec<u8>)994     fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
995         assert!(self.0 <= 6);
996         bytes.push(ARG0OP + self.0);
997     }
998 }
999 
1000 /// Localx object.
1001 pub struct Local(pub u8);
1002 
1003 impl Aml for Local {
1004     /// Per ACPI spec, there is maximum 8 Localx objects from
1005     /// Local0 ~ Local7. Any other Local object will not be accepted.
to_aml_bytes(&self, bytes: &mut Vec<u8>)1006     fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
1007         assert!(self.0 <= 7);
1008         bytes.push(LOCAL0OP + self.0);
1009     }
1010 }
1011 
1012 /// Store object with the ACPI object name which can be stored to and
1013 /// the ACPI object value which is to store.
1014 pub struct Store<'a> {
1015     name: &'a dyn Aml,
1016     value: &'a dyn Aml,
1017 }
1018 
1019 impl<'a> Store<'a> {
1020     /// Create Store object.
new(name: &'a dyn Aml, value: &'a dyn Aml) -> Self1021     pub fn new(name: &'a dyn Aml, value: &'a dyn Aml) -> Self {
1022         Store { name, value }
1023     }
1024 }
1025 
1026 impl<'a> Aml for Store<'a> {
to_aml_bytes(&self, bytes: &mut Vec<u8>)1027     fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
1028         bytes.push(STOREOP);
1029         self.value.to_aml_bytes(bytes);
1030         self.name.to_aml_bytes(bytes);
1031     }
1032 }
1033 
1034 /// Mutex object with a mutex name and a synchronization level.
1035 pub struct Mutex {
1036     path: Path,
1037     sync_level: u8,
1038 }
1039 
1040 impl Mutex {
1041     /// Create Mutex object.
new(path: Path, sync_level: u8) -> Self1042     pub fn new(path: Path, sync_level: u8) -> Self {
1043         Self { path, sync_level }
1044     }
1045 }
1046 
1047 impl Aml for Mutex {
to_aml_bytes(&self, bytes: &mut Vec<u8>)1048     fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
1049         bytes.push(EXTOPPREFIX);
1050         bytes.push(MUTEXOP);
1051         self.path.to_aml_bytes(bytes);
1052         bytes.push(self.sync_level);
1053     }
1054 }
1055 
1056 /// Acquire object with a Mutex object and timeout value.
1057 pub struct Acquire {
1058     mutex: Path,
1059     timeout: u16,
1060 }
1061 
1062 impl Acquire {
1063     /// Create Acquire object.
new(mutex: Path, timeout: u16) -> Self1064     pub fn new(mutex: Path, timeout: u16) -> Self {
1065         Acquire { mutex, timeout }
1066     }
1067 }
1068 
1069 impl Aml for Acquire {
to_aml_bytes(&self, bytes: &mut Vec<u8>)1070     fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
1071         bytes.push(EXTOPPREFIX);
1072         bytes.push(ACQUIREOP);
1073         self.mutex.to_aml_bytes(bytes);
1074         bytes.extend_from_slice(&self.timeout.to_le_bytes());
1075     }
1076 }
1077 
1078 /// Release object with a Mutex object to release.
1079 pub struct Release {
1080     mutex: Path,
1081 }
1082 
1083 impl Release {
1084     /// Create Release object.
new(mutex: Path) -> Self1085     pub fn new(mutex: Path) -> Self {
1086         Release { mutex }
1087     }
1088 }
1089 
1090 impl Aml for Release {
to_aml_bytes(&self, bytes: &mut Vec<u8>)1091     fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
1092         bytes.push(EXTOPPREFIX);
1093         bytes.push(RELEASEOP);
1094         self.mutex.to_aml_bytes(bytes);
1095     }
1096 }
1097 
1098 /// Notify object with an object which is to be notified with the value.
1099 pub struct Notify<'a> {
1100     object: &'a dyn Aml,
1101     value: &'a dyn Aml,
1102 }
1103 
1104 impl<'a> Notify<'a> {
1105     /// Create Notify object.
new(object: &'a dyn Aml, value: &'a dyn Aml) -> Self1106     pub fn new(object: &'a dyn Aml, value: &'a dyn Aml) -> Self {
1107         Notify { object, value }
1108     }
1109 }
1110 
1111 impl<'a> Aml for Notify<'a> {
to_aml_bytes(&self, bytes: &mut Vec<u8>)1112     fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
1113         bytes.push(NOTIFYOP);
1114         self.object.to_aml_bytes(bytes);
1115         self.value.to_aml_bytes(bytes);
1116     }
1117 }
1118 
1119 /// While object with the while condition objects(predicate) and
1120 /// the while body objects(while_children).
1121 pub struct While<'a> {
1122     predicate: &'a dyn Aml,
1123     while_children: Vec<&'a dyn Aml>,
1124 }
1125 
1126 impl<'a> While<'a> {
1127     /// Create While object.
new(predicate: &'a dyn Aml, while_children: Vec<&'a dyn Aml>) -> Self1128     pub fn new(predicate: &'a dyn Aml, while_children: Vec<&'a dyn Aml>) -> Self {
1129         While {
1130             predicate,
1131             while_children,
1132         }
1133     }
1134 }
1135 
1136 impl<'a> Aml for While<'a> {
to_aml_bytes(&self, aml: &mut Vec<u8>)1137     fn to_aml_bytes(&self, aml: &mut Vec<u8>) {
1138         let mut bytes = Vec::new();
1139         self.predicate.to_aml_bytes(&mut bytes);
1140         for child in self.while_children.iter() {
1141             child.to_aml_bytes(&mut bytes);
1142         }
1143 
1144         let mut pkg_length = create_pkg_length(&bytes, true);
1145         pkg_length.reverse();
1146         for byte in pkg_length {
1147             bytes.insert(0, byte);
1148         }
1149 
1150         bytes.insert(0, WHILEOP);
1151         aml.append(&mut bytes)
1152     }
1153 }
1154 
1155 macro_rules! binary_op {
1156     ($name:ident, $opcode:expr) => {
1157         /// General operation object with the operator a/b and a target.
1158         pub struct $name<'a> {
1159             a: &'a dyn Aml,
1160             b: &'a dyn Aml,
1161             target: &'a dyn Aml,
1162         }
1163 
1164         impl<'a> $name<'a> {
1165             /// Create the object.
1166             pub fn new(target: &'a dyn Aml, a: &'a dyn Aml, b: &'a dyn Aml) -> Self {
1167                 $name { target, a, b }
1168             }
1169         }
1170 
1171         impl<'a> Aml for $name<'a> {
1172             fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
1173                 bytes.push($opcode); /* Op for the binary operator */
1174                 self.a.to_aml_bytes(bytes);
1175                 self.b.to_aml_bytes(bytes);
1176                 self.target.to_aml_bytes(bytes);
1177             }
1178         }
1179     };
1180 }
1181 
1182 binary_op!(Add, ADDOP);
1183 binary_op!(Concat, CONCATOP);
1184 binary_op!(Subtract, SUBTRACTOP);
1185 binary_op!(Multiply, MULTIPLYOP);
1186 binary_op!(ShiftLeft, SHIFTLEFTOP);
1187 binary_op!(ShiftRight, SHIFTRIGHTOP);
1188 binary_op!(And, ANDOP);
1189 binary_op!(Nand, NANDOP);
1190 binary_op!(Or, OROP);
1191 binary_op!(Nor, NOROP);
1192 binary_op!(Xor, XOROP);
1193 binary_op!(ConcatRes, CONCATRESOP);
1194 binary_op!(Mod, MODOP);
1195 binary_op!(Index, INDEXOP);
1196 binary_op!(ToString, TOSTRINGOP);
1197 
1198 /// MethodCall object with the method name and parameter objects.
1199 pub struct MethodCall<'a> {
1200     name: Path,
1201     args: Vec<&'a dyn Aml>,
1202 }
1203 
1204 impl<'a> MethodCall<'a> {
1205     /// Create MethodCall object.
new(name: Path, args: Vec<&'a dyn Aml>) -> Self1206     pub fn new(name: Path, args: Vec<&'a dyn Aml>) -> Self {
1207         MethodCall { name, args }
1208     }
1209 }
1210 
1211 impl<'a> Aml for MethodCall<'a> {
to_aml_bytes(&self, bytes: &mut Vec<u8>)1212     fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
1213         self.name.to_aml_bytes(bytes);
1214         for arg in self.args.iter() {
1215             arg.to_aml_bytes(bytes);
1216         }
1217     }
1218 }
1219 
1220 /// Buffer object with the data in it.
1221 pub struct Buffer {
1222     data: Vec<u8>,
1223 }
1224 
1225 impl Buffer {
1226     /// Create Buffer object.
new(data: Vec<u8>) -> Self1227     pub fn new(data: Vec<u8>) -> Self {
1228         Buffer { data }
1229     }
1230 }
1231 
1232 impl Aml for Buffer {
to_aml_bytes(&self, aml: &mut Vec<u8>)1233     fn to_aml_bytes(&self, aml: &mut Vec<u8>) {
1234         let mut bytes = Vec::new();
1235         self.data.len().to_aml_bytes(&mut bytes);
1236         bytes.extend_from_slice(&self.data);
1237 
1238         let mut pkg_length = create_pkg_length(&bytes, true);
1239         pkg_length.reverse();
1240         for byte in pkg_length {
1241             bytes.insert(0, byte);
1242         }
1243 
1244         bytes.insert(0, BUFFEROP);
1245 
1246         aml.append(&mut bytes)
1247     }
1248 }
1249 
1250 #[cfg(test)]
1251 mod tests {
1252     use super::*;
1253 
1254     #[test]
test_device()1255     fn test_device() {
1256         /*
1257         Device (_SB.COM1)
1258         {
1259             Name (_HID, EisaId ("PNP0501") /* 16550A-compatible COM Serial Port */) // _HID: Hardware ID
1260             Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource Settings
1261             {
1262                 Interrupt (ResourceConsumer, Edge, ActiveHigh, Exclusive, ,, )
1263                 {
1264                     0x00000004,
1265                 }
1266                 IO (Decode16,
1267                     0x03F8,             // Range Minimum
1268                     0x03F8,             // Range Maximum
1269                     0x00,               // Alignment
1270                     0x08,               // Length
1271                     )
1272             }
1273         }
1274             */
1275         let com1_device = [
1276             0x5B, 0x82, 0x30, 0x2E, 0x5F, 0x53, 0x42, 0x5F, 0x43, 0x4F, 0x4D, 0x31, 0x08, 0x5F,
1277             0x48, 0x49, 0x44, 0x0C, 0x41, 0xD0, 0x05, 0x01, 0x08, 0x5F, 0x43, 0x52, 0x53, 0x11,
1278             0x16, 0x0A, 0x13, 0x89, 0x06, 0x00, 0x03, 0x01, 0x04, 0x00, 0x00, 0x00, 0x47, 0x01,
1279             0xF8, 0x03, 0xF8, 0x03, 0x00, 0x08, 0x79, 0x00,
1280         ];
1281         let mut aml = Vec::new();
1282 
1283         Device::new(
1284             "_SB_.COM1".into(),
1285             vec![
1286                 &Name::new("_HID".into(), &EISAName::new("PNP0501")),
1287                 &Name::new(
1288                     "_CRS".into(),
1289                     &ResourceTemplate::new(vec![
1290                         &Interrupt::new(true, true, false, false, 4),
1291                         &IO::new(0x3f8, 0x3f8, 0, 0x8),
1292                     ]),
1293                 ),
1294             ],
1295         )
1296         .to_aml_bytes(&mut aml);
1297         assert_eq!(aml, &com1_device[..]);
1298     }
1299 
1300     #[test]
test_scope()1301     fn test_scope() {
1302         /*
1303         Scope (_SB.MBRD)
1304         {
1305             Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource Settings
1306             {
1307                 Memory32Fixed (ReadWrite,
1308                     0xE8000000,         // Address Base
1309                     0x10000000,         // Address Length
1310                     )
1311             })
1312         }
1313         */
1314 
1315         let mbrd_scope = [
1316             0x10, 0x21, 0x2E, 0x5F, 0x53, 0x42, 0x5F, 0x4D, 0x42, 0x52, 0x44, 0x08, 0x5F, 0x43,
1317             0x52, 0x53, 0x11, 0x11, 0x0A, 0x0E, 0x86, 0x09, 0x00, 0x01, 0x00, 0x00, 0x00, 0xE8,
1318             0x00, 0x00, 0x00, 0x10, 0x79, 0x00,
1319         ];
1320         let mut aml = Vec::new();
1321 
1322         Scope::new(
1323             "_SB_.MBRD".into(),
1324             vec![&Name::new(
1325                 "_CRS".into(),
1326                 &ResourceTemplate::new(vec![&Memory32Fixed::new(true, 0xE800_0000, 0x1000_0000)]),
1327             )],
1328         )
1329         .to_aml_bytes(&mut aml);
1330         assert_eq!(aml, &mbrd_scope[..]);
1331     }
1332 
1333     #[test]
test_resource_template()1334     fn test_resource_template() {
1335         /*
1336         Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource Settings
1337         {
1338             Memory32Fixed (ReadWrite,
1339                 0xE8000000,         // Address Base
1340                 0x10000000,         // Address Length
1341                 )
1342         })
1343         */
1344         let crs_memory_32_fixed = [
1345             0x08, 0x5F, 0x43, 0x52, 0x53, 0x11, 0x11, 0x0A, 0x0E, 0x86, 0x09, 0x00, 0x01, 0x00,
1346             0x00, 0x00, 0xE8, 0x00, 0x00, 0x00, 0x10, 0x79, 0x00,
1347         ];
1348         let mut aml = Vec::new();
1349 
1350         Name::new(
1351             "_CRS".into(),
1352             &ResourceTemplate::new(vec![&Memory32Fixed::new(true, 0xE800_0000, 0x1000_0000)]),
1353         )
1354         .to_aml_bytes(&mut aml);
1355         assert_eq!(aml, crs_memory_32_fixed);
1356 
1357         /*
1358             Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource Settings
1359             {
1360                 WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode,
1361                     0x0000,             // Granularity
1362                     0x0000,             // Range Minimum
1363                     0x00FF,             // Range Maximum
1364                     0x0000,             // Translation Offset
1365                     0x0100,             // Length
1366                     ,, )
1367                 WordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
1368                     0x0000,             // Granularity
1369                     0x0000,             // Range Minimum
1370                     0x0CF7,             // Range Maximum
1371                     0x0000,             // Translation Offset
1372                     0x0CF8,             // Length
1373                     ,, , TypeStatic, DenseTranslation)
1374                 WordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
1375                     0x0000,             // Granularity
1376                     0x0D00,             // Range Minimum
1377                     0xFFFF,             // Range Maximum
1378                     0x0000,             // Translation Offset
1379                     0xF300,             // Length
1380                     ,, , TypeStatic, DenseTranslation)
1381                 DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
1382                     0x00000000,         // Granularity
1383                     0x000A0000,         // Range Minimum
1384                     0x000BFFFF,         // Range Maximum
1385                     0x00000000,         // Translation Offset
1386                     0x00020000,         // Length
1387                     ,, , AddressRangeMemory, TypeStatic)
1388                 DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
1389                     0x00000000,         // Granularity
1390                     0xC0000000,         // Range Minimum
1391                     0xFEBFFFFF,         // Range Maximum
1392                     0x00000000,         // Translation Offset
1393                     0x3EC00000,         // Length
1394                     ,, , AddressRangeMemory, TypeStatic)
1395                 QWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
1396                     0x0000000000000000, // Granularity
1397                     0x0000000800000000, // Range Minimum
1398                     0x0000000FFFFFFFFF, // Range Maximum
1399                     0x0000000000000000, // Translation Offset
1400                     0x0000000800000000, // Length
1401                     ,, , AddressRangeMemory, TypeStatic)
1402             })
1403         */
1404 
1405         // WordBusNumber from above
1406         let crs_word_bus_number = [
1407             0x08, 0x5F, 0x43, 0x52, 0x53, 0x11, 0x15, 0x0A, 0x12, 0x88, 0x0D, 0x00, 0x02, 0x0C,
1408             0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x01, 0x79, 0x00,
1409         ];
1410         aml.clear();
1411 
1412         Name::new(
1413             "_CRS".into(),
1414             &ResourceTemplate::new(vec![&AddressSpace::new_bus_number(0x0u16, 0xffu16)]),
1415         )
1416         .to_aml_bytes(&mut aml);
1417         assert_eq!(aml, &crs_word_bus_number);
1418 
1419         // WordIO blocks (x 2) from above
1420         let crs_word_io = [
1421             0x08, 0x5F, 0x43, 0x52, 0x53, 0x11, 0x25, 0x0A, 0x22, 0x88, 0x0D, 0x00, 0x01, 0x0C,
1422             0x03, 0x00, 0x00, 0x00, 0x00, 0xF7, 0x0C, 0x00, 0x00, 0xF8, 0x0C, 0x88, 0x0D, 0x00,
1423             0x01, 0x0C, 0x03, 0x00, 0x00, 0x00, 0x0D, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xF3, 0x79,
1424             0x00,
1425         ];
1426         aml.clear();
1427 
1428         Name::new(
1429             "_CRS".into(),
1430             &ResourceTemplate::new(vec![
1431                 &AddressSpace::new_io(0x0u16, 0xcf7u16),
1432                 &AddressSpace::new_io(0xd00u16, 0xffffu16),
1433             ]),
1434         )
1435         .to_aml_bytes(&mut aml);
1436         assert_eq!(aml, &crs_word_io[..]);
1437 
1438         // DWordMemory blocks (x 2) from above
1439         let crs_dword_memory = [
1440             0x08, 0x5F, 0x43, 0x52, 0x53, 0x11, 0x39, 0x0A, 0x36, 0x87, 0x17, 0x00, 0x00, 0x0C,
1441             0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0xFF, 0xFF, 0x0B, 0x00, 0x00,
1442             0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x87, 0x17, 0x00, 0x00, 0x0C, 0x01, 0x00,
1443             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0xBF, 0xFE, 0x00, 0x00, 0x00,
1444             0x00, 0x00, 0x00, 0xC0, 0x3E, 0x79, 0x00,
1445         ];
1446         aml.clear();
1447 
1448         Name::new(
1449             "_CRS".into(),
1450             &ResourceTemplate::new(vec![
1451                 &AddressSpace::new_memory(
1452                     AddressSpaceCachable::Cacheable,
1453                     true,
1454                     0xa_0000u32,
1455                     0xb_ffffu32,
1456                 ),
1457                 &AddressSpace::new_memory(
1458                     AddressSpaceCachable::NotCacheable,
1459                     true,
1460                     0xc000_0000u32,
1461                     0xfebf_ffffu32,
1462                 ),
1463             ]),
1464         )
1465         .to_aml_bytes(&mut aml);
1466         assert_eq!(aml, &crs_dword_memory[..]);
1467 
1468         // QWordMemory from above
1469         let crs_qword_memory = [
1470             0x08, 0x5F, 0x43, 0x52, 0x53, 0x11, 0x33, 0x0A, 0x30, 0x8A, 0x2B, 0x00, 0x00, 0x0C,
1471             0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
1472             0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1473             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x79,
1474             0x00,
1475         ];
1476         aml.clear();
1477         Name::new(
1478             "_CRS".into(),
1479             &ResourceTemplate::new(vec![&AddressSpace::new_memory(
1480                 AddressSpaceCachable::Cacheable,
1481                 true,
1482                 0x8_0000_0000u64,
1483                 0xf_ffff_ffffu64,
1484             )]),
1485         )
1486         .to_aml_bytes(&mut aml);
1487 
1488         assert_eq!(aml, &crs_qword_memory[..]);
1489 
1490         /*
1491             Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource Settings
1492             {
1493                 Interrupt (ResourceConsumer, Edge, ActiveHigh, Exclusive, ,, )
1494                 {
1495                     0x00000004,
1496                 }
1497                 IO (Decode16,
1498                     0x03F8,             // Range Minimum
1499                     0x03F8,             // Range Maximum
1500                     0x00,               // Alignment
1501                     0x08,               // Length
1502                     )
1503             })
1504 
1505         */
1506         let interrupt_io_data = [
1507             0x08, 0x5F, 0x43, 0x52, 0x53, 0x11, 0x16, 0x0A, 0x13, 0x89, 0x06, 0x00, 0x03, 0x01,
1508             0x04, 0x00, 0x00, 0x00, 0x47, 0x01, 0xF8, 0x03, 0xF8, 0x03, 0x00, 0x08, 0x79, 0x00,
1509         ];
1510         aml.clear();
1511         Name::new(
1512             "_CRS".into(),
1513             &ResourceTemplate::new(vec![
1514                 &Interrupt::new(true, true, false, false, 4),
1515                 &IO::new(0x3f8, 0x3f8, 0, 0x8),
1516             ]),
1517         )
1518         .to_aml_bytes(&mut aml);
1519 
1520         assert_eq!(aml, &interrupt_io_data[..]);
1521     }
1522 
1523     #[test]
test_pkg_length()1524     fn test_pkg_length() {
1525         assert_eq!(create_pkg_length(&[0u8; 62].to_vec(), true), vec![63]);
1526         assert_eq!(
1527             create_pkg_length(&[0u8; 64].to_vec(), true),
1528             vec![1 << 6 | (66 & 0xf), 66 >> 4]
1529         );
1530         assert_eq!(
1531             create_pkg_length(&[0u8; 4096].to_vec(), true),
1532             vec![
1533                 2 << 6 | (4099 & 0xf) as u8,
1534                 (4099 >> 4) as u8,
1535                 (4099 >> 12) as u8
1536             ]
1537         );
1538     }
1539 
1540     #[test]
test_package()1541     fn test_package() {
1542         /*
1543         Name (_S5, Package (0x01)  // _S5_: S5 System State
1544         {
1545             0x05
1546         })
1547         */
1548         let s5_sleep_data = [0x08, 0x5F, 0x53, 0x35, 0x5F, 0x12, 0x04, 0x01, 0x0A, 0x05];
1549         let mut aml = Vec::new();
1550 
1551         Name::new("_S5_".into(), &Package::new(vec![&5u8])).to_aml_bytes(&mut aml);
1552 
1553         assert_eq!(s5_sleep_data.to_vec(), aml);
1554     }
1555 
1556     #[test]
test_eisa_name()1557     fn test_eisa_name() {
1558         let mut aml = Vec::new();
1559         Name::new("_HID".into(), &EISAName::new("PNP0501")).to_aml_bytes(&mut aml);
1560         assert_eq!(
1561             aml,
1562             [0x08, 0x5F, 0x48, 0x49, 0x44, 0x0C, 0x41, 0xD0, 0x05, 0x01],
1563         )
1564     }
1565     #[test]
test_name_path()1566     fn test_name_path() {
1567         let mut aml = Vec::new();
1568         (&"_SB_".into() as &Path).to_aml_bytes(&mut aml);
1569         assert_eq!(aml, [0x5Fu8, 0x53, 0x42, 0x5F]);
1570         aml.clear();
1571         (&"\\_SB_".into() as &Path).to_aml_bytes(&mut aml);
1572         assert_eq!(aml, [0x5C, 0x5F, 0x53, 0x42, 0x5F]);
1573         aml.clear();
1574         (&"_SB_.COM1".into() as &Path).to_aml_bytes(&mut aml);
1575         assert_eq!(aml, [0x2E, 0x5F, 0x53, 0x42, 0x5F, 0x43, 0x4F, 0x4D, 0x31]);
1576         aml.clear();
1577         (&"_SB_.PCI0._HID".into() as &Path).to_aml_bytes(&mut aml);
1578         assert_eq!(
1579             aml,
1580             [0x2F, 0x03, 0x5F, 0x53, 0x42, 0x5F, 0x50, 0x43, 0x49, 0x30, 0x5F, 0x48, 0x49, 0x44]
1581         );
1582     }
1583 
1584     #[test]
test_numbers()1585     fn test_numbers() {
1586         let mut aml = Vec::new();
1587         128u8.to_aml_bytes(&mut aml);
1588         assert_eq!(aml, [0x0a, 0x80]);
1589         aml.clear();
1590         1024u16.to_aml_bytes(&mut aml);
1591         assert_eq!(aml, [0x0b, 0x0, 0x04]);
1592         aml.clear();
1593         (16u32 << 20).to_aml_bytes(&mut aml);
1594         assert_eq!(aml, [0x0c, 0x00, 0x00, 0x0, 0x01]);
1595         aml.clear();
1596         0xdeca_fbad_deca_fbadu64.to_aml_bytes(&mut aml);
1597         assert_eq!(aml, [0x0e, 0xad, 0xfb, 0xca, 0xde, 0xad, 0xfb, 0xca, 0xde]);
1598     }
1599 
1600     #[test]
test_name()1601     fn test_name() {
1602         let mut aml = Vec::new();
1603         Name::new("_SB_.PCI0._UID".into(), &0x1234u16).to_aml_bytes(&mut aml);
1604         assert_eq!(
1605             aml,
1606             [
1607                 0x08, /* NameOp */
1608                 0x2F, /* MultiNamePrefix */
1609                 0x03, /* 3 name parts */
1610                 0x5F, 0x53, 0x42, 0x5F, /* _SB_ */
1611                 0x50, 0x43, 0x49, 0x30, /* PCI0 */
1612                 0x5F, 0x55, 0x49, 0x44, /* _UID  */
1613                 0x0b, /* WordPrefix */
1614                 0x34, 0x12
1615             ]
1616         );
1617     }
1618 
1619     #[test]
test_string()1620     fn test_string() {
1621         let mut aml = Vec::new();
1622         (&"ACPI" as &dyn Aml).to_aml_bytes(&mut aml);
1623         assert_eq!(aml, [0x0d, b'A', b'C', b'P', b'I', 0]);
1624         aml.clear();
1625         "ACPI".to_owned().to_aml_bytes(&mut aml);
1626         assert_eq!(aml, [0x0d, b'A', b'C', b'P', b'I', 0]);
1627     }
1628 
1629     #[test]
test_method()1630     fn test_method() {
1631         let mut aml = Vec::new();
1632         Method::new("_STA".into(), 0, false, vec![&Return::new(&0xfu8)]).to_aml_bytes(&mut aml);
1633         assert_eq!(
1634             aml,
1635             [0x14, 0x09, 0x5F, 0x53, 0x54, 0x41, 0x00, 0xA4, 0x0A, 0x0F]
1636         );
1637     }
1638 
1639     #[test]
test_field()1640     fn test_field() {
1641         /*
1642             Field (PRST, ByteAcc, NoLock, WriteAsZeros)
1643             {
1644                 Offset (0x04),
1645                 CPEN,   1,
1646                 CINS,   1,
1647                 CRMV,   1,
1648                 CEJ0,   1,
1649                 Offset (0x05),
1650                 CCMD,   8
1651             }
1652 
1653         */
1654 
1655         let field_data = [
1656             0x5Bu8, 0x81, 0x23, 0x50, 0x52, 0x53, 0x54, 0x41, 0x00, 0x20, 0x43, 0x50, 0x45, 0x4E,
1657             0x01, 0x43, 0x49, 0x4E, 0x53, 0x01, 0x43, 0x52, 0x4D, 0x56, 0x01, 0x43, 0x45, 0x4A,
1658             0x30, 0x01, 0x00, 0x04, 0x43, 0x43, 0x4D, 0x44, 0x08,
1659         ];
1660         let mut aml = Vec::new();
1661 
1662         Field::new(
1663             "PRST".into(),
1664             FieldAccessType::Byte,
1665             FieldUpdateRule::WriteAsZeroes,
1666             vec![
1667                 FieldEntry::Reserved(32),
1668                 FieldEntry::Named(*b"CPEN", 1),
1669                 FieldEntry::Named(*b"CINS", 1),
1670                 FieldEntry::Named(*b"CRMV", 1),
1671                 FieldEntry::Named(*b"CEJ0", 1),
1672                 FieldEntry::Reserved(4),
1673                 FieldEntry::Named(*b"CCMD", 8),
1674             ],
1675         )
1676         .to_aml_bytes(&mut aml);
1677         assert_eq!(aml, &field_data[..]);
1678 
1679         /*
1680             Field (PRST, DWordAcc, NoLock, Preserve)
1681             {
1682                 CSEL,   32,
1683                 Offset (0x08),
1684                 CDAT,   32
1685             }
1686         */
1687 
1688         let field_data = [
1689             0x5Bu8, 0x81, 0x12, 0x50, 0x52, 0x53, 0x54, 0x03, 0x43, 0x53, 0x45, 0x4C, 0x20, 0x00,
1690             0x20, 0x43, 0x44, 0x41, 0x54, 0x20,
1691         ];
1692         aml.clear();
1693 
1694         Field::new(
1695             "PRST".into(),
1696             FieldAccessType::DWord,
1697             FieldUpdateRule::Preserve,
1698             vec![
1699                 FieldEntry::Named(*b"CSEL", 32),
1700                 FieldEntry::Reserved(32),
1701                 FieldEntry::Named(*b"CDAT", 32),
1702             ],
1703         )
1704         .to_aml_bytes(&mut aml);
1705         assert_eq!(aml, &field_data[..]);
1706     }
1707 
1708     #[test]
test_op_region()1709     fn test_op_region() {
1710         /*
1711             OperationRegion (PRST, SystemIO, 0x0CD8, 0x0C)
1712         */
1713         let op_region_data = [
1714             0x5Bu8, 0x80, 0x50, 0x52, 0x53, 0x54, 0x01, 0x0B, 0xD8, 0x0C, 0x0A, 0x0C,
1715         ];
1716         let mut aml = Vec::new();
1717 
1718         OpRegion::new("PRST".into(), OpRegionSpace::SystemIO, 0xcd8, 0xc).to_aml_bytes(&mut aml);
1719         assert_eq!(aml, &op_region_data[..]);
1720     }
1721 
1722     #[test]
test_arg_if()1723     fn test_arg_if() {
1724         /*
1725             Method(TEST, 1, NotSerialized) {
1726                 If (Arg0 == Zero) {
1727                         Return(One)
1728                 }
1729                 Return(Zero)
1730             }
1731         */
1732         let arg_if_data = [
1733             0x14, 0x0F, 0x54, 0x45, 0x53, 0x54, 0x01, 0xA0, 0x06, 0x93, 0x68, 0x00, 0xA4, 0x01,
1734             0xA4, 0x00,
1735         ];
1736         let mut aml = Vec::new();
1737 
1738         Method::new(
1739             "TEST".into(),
1740             1,
1741             false,
1742             vec![
1743                 &If::new(&Equal::new(&Arg(0), &ZERO), vec![&Return::new(&ONE)]),
1744                 &Return::new(&ZERO),
1745             ],
1746         )
1747         .to_aml_bytes(&mut aml);
1748         assert_eq!(aml, &arg_if_data);
1749     }
1750 
1751     #[test]
test_local_if()1752     fn test_local_if() {
1753         /*
1754             Method(TEST, 0, NotSerialized) {
1755                 Local0 = One
1756                 If (Local0 == Zero) {
1757                         Return(One)
1758                 }
1759                 Return(Zero)
1760             }
1761         */
1762         let local_if_data = [
1763             0x14, 0x12, 0x54, 0x45, 0x53, 0x54, 0x00, 0x70, 0x01, 0x60, 0xA0, 0x06, 0x93, 0x60,
1764             0x00, 0xA4, 0x01, 0xA4, 0x00,
1765         ];
1766         let mut aml = Vec::new();
1767 
1768         Method::new(
1769             "TEST".into(),
1770             0,
1771             false,
1772             vec![
1773                 &Store::new(&Local(0), &ONE),
1774                 &If::new(&Equal::new(&Local(0), &ZERO), vec![&Return::new(&ONE)]),
1775                 &Return::new(&ZERO),
1776             ],
1777         )
1778         .to_aml_bytes(&mut aml);
1779         assert_eq!(aml, &local_if_data);
1780     }
1781 
1782     #[test]
test_mutex()1783     fn test_mutex() {
1784         /*
1785         Device (_SB_.MHPC)
1786         {
1787                 Name (_HID, EisaId("PNP0A06") /* Generic Container Device */)  // _HID: Hardware ID
1788                 Mutex (MLCK, 0x00)
1789                 Method (TEST, 0, NotSerialized)
1790                 {
1791                     Acquire (MLCK, 0xFFFF)
1792                     Local0 = One
1793                     Release (MLCK)
1794                 }
1795         }
1796         */
1797 
1798         let mutex_data = [
1799             0x5B, 0x82, 0x33, 0x2E, 0x5F, 0x53, 0x42, 0x5F, 0x4D, 0x48, 0x50, 0x43, 0x08, 0x5F,
1800             0x48, 0x49, 0x44, 0x0C, 0x41, 0xD0, 0x0A, 0x06, 0x5B, 0x01, 0x4D, 0x4C, 0x43, 0x4B,
1801             0x00, 0x14, 0x17, 0x54, 0x45, 0x53, 0x54, 0x00, 0x5B, 0x23, 0x4D, 0x4C, 0x43, 0x4B,
1802             0xFF, 0xFF, 0x70, 0x01, 0x60, 0x5B, 0x27, 0x4D, 0x4C, 0x43, 0x4B,
1803         ];
1804         let mut aml = Vec::new();
1805 
1806         let mutex = Mutex::new("MLCK".into(), 0);
1807         Device::new(
1808             "_SB_.MHPC".into(),
1809             vec![
1810                 &Name::new("_HID".into(), &EISAName::new("PNP0A06")),
1811                 &mutex,
1812                 &Method::new(
1813                     "TEST".into(),
1814                     0,
1815                     false,
1816                     vec![
1817                         &Acquire::new("MLCK".into(), 0xffff),
1818                         &Store::new(&Local(0), &ONE),
1819                         &Release::new("MLCK".into()),
1820                     ],
1821                 ),
1822             ],
1823         )
1824         .to_aml_bytes(&mut aml);
1825         assert_eq!(aml, &mutex_data[..]);
1826     }
1827 
1828     #[test]
test_notify()1829     fn test_notify() {
1830         /*
1831         Device (_SB.MHPC)
1832         {
1833             Name (_HID, EisaId ("PNP0A06") /* Generic Container Device */)  // _HID: Hardware ID
1834             Method (TEST, 0, NotSerialized)
1835             {
1836                 Notify (MHPC, One) // Device Check
1837             }
1838         }
1839         */
1840         let notify_data = [
1841             0x5B, 0x82, 0x21, 0x2E, 0x5F, 0x53, 0x42, 0x5F, 0x4D, 0x48, 0x50, 0x43, 0x08, 0x5F,
1842             0x48, 0x49, 0x44, 0x0C, 0x41, 0xD0, 0x0A, 0x06, 0x14, 0x0C, 0x54, 0x45, 0x53, 0x54,
1843             0x00, 0x86, 0x4D, 0x48, 0x50, 0x43, 0x01,
1844         ];
1845         let mut aml = Vec::new();
1846 
1847         Device::new(
1848             "_SB_.MHPC".into(),
1849             vec![
1850                 &Name::new("_HID".into(), &EISAName::new("PNP0A06")),
1851                 &Method::new(
1852                     "TEST".into(),
1853                     0,
1854                     false,
1855                     vec![&Notify::new(&Path::new("MHPC"), &ONE)],
1856                 ),
1857             ],
1858         )
1859         .to_aml_bytes(&mut aml);
1860         assert_eq!(aml, &notify_data[..]);
1861     }
1862 
1863     #[test]
test_while()1864     fn test_while() {
1865         /*
1866         Device (_SB.MHPC)
1867         {
1868             Name (_HID, EisaId ("PNP0A06") /* Generic Container Device */)  // _HID: Hardware ID
1869             Method (TEST, 0, NotSerialized)
1870             {
1871                 Local0 = Zero
1872                 While ((Local0 < 0x04))
1873                 {
1874                     Local0 += One
1875                 }
1876             }
1877         }
1878         */
1879 
1880         let while_data = [
1881             0x5B, 0x82, 0x28, 0x2E, 0x5F, 0x53, 0x42, 0x5F, 0x4D, 0x48, 0x50, 0x43, 0x08, 0x5F,
1882             0x48, 0x49, 0x44, 0x0C, 0x41, 0xD0, 0x0A, 0x06, 0x14, 0x13, 0x54, 0x45, 0x53, 0x54,
1883             0x00, 0x70, 0x00, 0x60, 0xA2, 0x09, 0x95, 0x60, 0x0A, 0x04, 0x72, 0x60, 0x01, 0x60,
1884         ];
1885         let mut aml = Vec::new();
1886 
1887         Device::new(
1888             "_SB_.MHPC".into(),
1889             vec![
1890                 &Name::new("_HID".into(), &EISAName::new("PNP0A06")),
1891                 &Method::new(
1892                     "TEST".into(),
1893                     0,
1894                     false,
1895                     vec![
1896                         &Store::new(&Local(0), &ZERO),
1897                         &While::new(
1898                             &LessThan::new(&Local(0), &4usize),
1899                             vec![&Add::new(&Local(0), &Local(0), &ONE)],
1900                         ),
1901                     ],
1902                 ),
1903             ],
1904         )
1905         .to_aml_bytes(&mut aml);
1906         assert_eq!(aml, &while_data[..])
1907     }
1908 
1909     #[test]
test_method_call()1910     fn test_method_call() {
1911         /*
1912             Method (TST1, 1, NotSerialized)
1913             {
1914                 TST2 (One, One)
1915             }
1916 
1917             Method (TST2, 2, NotSerialized)
1918             {
1919                 TST1 (One)
1920             }
1921         */
1922         let test_data = [
1923             0x14, 0x0C, 0x54, 0x53, 0x54, 0x31, 0x01, 0x54, 0x53, 0x54, 0x32, 0x01, 0x01, 0x14,
1924             0x0B, 0x54, 0x53, 0x54, 0x32, 0x02, 0x54, 0x53, 0x54, 0x31, 0x01,
1925         ];
1926 
1927         let mut methods = Vec::new();
1928         Method::new(
1929             "TST1".into(),
1930             1,
1931             false,
1932             vec![&MethodCall::new("TST2".into(), vec![&ONE, &ONE])],
1933         )
1934         .to_aml_bytes(&mut methods);
1935         Method::new(
1936             "TST2".into(),
1937             2,
1938             false,
1939             vec![&MethodCall::new("TST1".into(), vec![&ONE])],
1940         )
1941         .to_aml_bytes(&mut methods);
1942         assert_eq!(&methods[..], &test_data[..])
1943     }
1944 
1945     #[test]
test_buffer()1946     fn test_buffer() {
1947         /*
1948         Name (_MAT, Buffer (0x08)  // _MAT: Multiple APIC Table Entry
1949         {
1950             0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00   /* ........ */
1951         })
1952         */
1953         let buffer_data = [
1954             0x08, 0x5F, 0x4D, 0x41, 0x54, 0x11, 0x0B, 0x0A, 0x08, 0x00, 0x08, 0x00, 0x00, 0x01,
1955             0x00, 0x00, 0x00,
1956         ];
1957         let mut aml = Vec::new();
1958 
1959         Name::new(
1960             "_MAT".into(),
1961             &Buffer::new(vec![0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00]),
1962         )
1963         .to_aml_bytes(&mut aml);
1964         assert_eq!(aml, &buffer_data[..])
1965     }
1966 }
1967