acpi_tables/
aml.rs

1// Copyright 2020 The ChromiumOS Authors
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.
8pub 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.
12    fn to_aml_bytes(&self, bytes: &mut Vec<u8>);
13}
14
15// AML byte stream defines
16const ZEROOP: u8 = 0x00;
17const ONEOP: u8 = 0x01;
18const NAMEOP: u8 = 0x08;
19const BYTEPREFIX: u8 = 0x0a;
20const WORDPREFIX: u8 = 0x0b;
21const DWORDPREFIX: u8 = 0x0c;
22const STRINGOP: u8 = 0x0d;
23const QWORDPREFIX: u8 = 0x0e;
24const SCOPEOP: u8 = 0x10;
25const BUFFEROP: u8 = 0x11;
26const PACKAGEOP: u8 = 0x12;
27const VARPACKAGEOP: u8 = 0x13;
28const METHODOP: u8 = 0x14;
29const DUALNAMEPREFIX: u8 = 0x2e;
30const MULTINAMEPREFIX: u8 = 0x2f;
31const NAMECHARBASE: u8 = 0x40;
32
33const EXTOPPREFIX: u8 = 0x5b;
34const MUTEXOP: u8 = 0x01;
35const CREATEFIELDOP: u8 = 0x13;
36const ACQUIREOP: u8 = 0x23;
37const RELEASEOP: u8 = 0x27;
38const OPREGIONOP: u8 = 0x80;
39const FIELDOP: u8 = 0x81;
40const DEVICEOP: u8 = 0x82;
41const POWERRESOURCEOP: u8 = 0x84;
42
43const LOCAL0OP: u8 = 0x60;
44const ARG0OP: u8 = 0x68;
45const STOREOP: u8 = 0x70;
46const ADDOP: u8 = 0x72;
47const CONCATOP: u8 = 0x73;
48const SUBTRACTOP: u8 = 0x74;
49const MULTIPLYOP: u8 = 0x77;
50const SHIFTLEFTOP: u8 = 0x79;
51const SHIFTRIGHTOP: u8 = 0x7a;
52const ANDOP: u8 = 0x7b;
53const NANDOP: u8 = 0x7c;
54const OROP: u8 = 0x7d;
55const NOROP: u8 = 0x7e;
56const XOROP: u8 = 0x7f;
57const DEREFOFOP: u8 = 0x83;
58const CONCATRESOP: u8 = 0x84;
59const MODOP: u8 = 0x85;
60const NOTIFYOP: u8 = 0x86;
61const SIZEOFOP: u8 = 0x87;
62const INDEXOP: u8 = 0x88;
63const CREATEDWFIELDOP: u8 = 0x8a;
64const OBJECTTYPEOP: u8 = 0x8e;
65const CREATEQWFIELDOP: u8 = 0x8f;
66const LNOTOP: u8 = 0x92;
67const LEQUALOP: u8 = 0x93;
68const LGREATEROP: u8 = 0x94;
69const LLESSOP: u8 = 0x95;
70const TOBUFFEROP: u8 = 0x96;
71const TOINTEGEROP: u8 = 0x99;
72const TOSTRINGOP: u8 = 0x9c;
73const MIDOP: u8 = 0x9e;
74const IFOP: u8 = 0xa0;
75const ELSEOP: u8 = 0xa1;
76const WHILEOP: u8 = 0xa2;
77const RETURNOP: u8 = 0xa4;
78const ONESOP: u8 = 0xff;
79
80// AML resouce data fields
81const IOPORTDESC: u8 = 0x47;
82const ENDTAG: u8 = 0x79;
83const MEMORY32FIXEDDESC: u8 = 0x86;
84const DWORDADDRSPACEDESC: u8 = 0x87;
85const WORDADDRSPACEDESC: u8 = 0x88;
86const EXTIRQDESC: u8 = 0x89;
87const QWORDADDRSPACEDESC: u8 = 0x8A;
88
89/// Zero object in ASL.
90pub const ZERO: Zero = Zero {};
91pub struct Zero {}
92
93impl Aml for Zero {
94    fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
95        bytes.push(ZEROOP);
96    }
97}
98
99/// One object in ASL.
100pub const ONE: One = One {};
101pub struct One {}
102
103impl Aml for One {
104    fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
105        bytes.push(ONEOP);
106    }
107}
108
109/// Ones object represents all bits 1.
110pub const ONES: Ones = Ones {};
111pub struct Ones {}
112
113impl Aml for Ones {
114    fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
115        bytes.push(ONESOP);
116    }
117}
118
119/// Represents Namestring to construct ACPI objects like
120/// Name/Device/Method/Scope and so on...
121pub struct Path {
122    root: bool,
123    name_parts: Vec<[u8; 4]>,
124}
125
126impl Aml for Path {
127    fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
128        if self.root {
129            bytes.push(b'\\');
130        }
131
132        match self.name_parts.len() {
133            0 => panic!("Name cannot be empty"),
134            1 => {}
135            2 => {
136                bytes.push(DUALNAMEPREFIX);
137            }
138            n => {
139                bytes.push(MULTINAMEPREFIX);
140                bytes.push(n as u8);
141            }
142        };
143
144        for part in &self.name_parts {
145            bytes.extend_from_slice(part);
146        }
147    }
148}
149
150impl Path {
151    /// Per ACPI Spec, the Namestring split by "." has 4 bytes long. So any name
152    /// not has 4 bytes will not be accepted.
153    pub fn new(name: &str) -> Self {
154        let root = name.starts_with('\\');
155        let offset = root as usize;
156        let mut name_parts = Vec::new();
157        for part in name[offset..].split('.') {
158            assert_eq!(part.len(), 4);
159            let mut name_part = [0u8; 4];
160            name_part.copy_from_slice(part.as_bytes());
161            name_parts.push(name_part);
162        }
163
164        Path { root, name_parts }
165    }
166}
167
168impl From<&str> for Path {
169    fn from(s: &str) -> Self {
170        Path::new(s)
171    }
172}
173
174pub type Byte = u8;
175
176impl Aml for Byte {
177    fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
178        match *self {
179            0 => ZERO.to_aml_bytes(bytes),
180            1 => ONE.to_aml_bytes(bytes),
181            _ => {
182                bytes.push(BYTEPREFIX);
183                bytes.push(*self);
184            }
185        }
186    }
187}
188
189pub type Word = u16;
190
191impl Aml for Word {
192    fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
193        if *self <= Byte::MAX.into() {
194            (*self as Byte).to_aml_bytes(bytes);
195        } else {
196            bytes.push(WORDPREFIX);
197            bytes.extend_from_slice(&self.to_le_bytes());
198        }
199    }
200}
201
202pub type DWord = u32;
203
204impl Aml for DWord {
205    fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
206        if *self <= Word::MAX.into() {
207            (*self as Word).to_aml_bytes(bytes);
208        } else {
209            bytes.push(DWORDPREFIX);
210            bytes.extend_from_slice(&self.to_le_bytes());
211        }
212    }
213}
214
215pub type QWord = u64;
216
217impl Aml for QWord {
218    fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
219        if *self <= DWord::MAX.into() {
220            (*self as DWord).to_aml_bytes(bytes);
221        } else {
222            bytes.push(QWORDPREFIX);
223            bytes.extend_from_slice(&self.to_le_bytes());
224        }
225    }
226}
227
228/// Name object. bytes represents the raw AML data for it.
229pub struct Name {
230    bytes: Vec<u8>,
231}
232
233impl Aml for Name {
234    fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
235        bytes.extend_from_slice(&self.bytes);
236    }
237}
238
239impl Name {
240    /// Create Name object:
241    ///
242    /// * `path` - The namestring.
243    /// * `inner` - AML objects contained in this namespace.
244    pub fn new(path: Path, inner: &dyn Aml) -> Self {
245        let mut bytes = vec![NAMEOP];
246        path.to_aml_bytes(&mut bytes);
247        inner.to_aml_bytes(&mut bytes);
248        Name { bytes }
249    }
250
251    /// Create Field name object
252    ///
253    /// * 'field_name' - name string
254    pub fn new_field_name(field_name: &str) -> Self {
255        let bytes = field_name.as_bytes().to_vec();
256        Name { bytes }
257    }
258}
259
260/// Package object. 'children' represents the ACPI objects contained in this package.
261pub struct Package {
262    children_bytes: Vec<u8>,
263}
264
265impl Aml for Package {
266    fn to_aml_bytes(&self, aml: &mut Vec<u8>) {
267        aml.push(PACKAGEOP);
268        append_pkg_length(aml, self.children_bytes.len());
269        aml.extend_from_slice(&self.children_bytes);
270    }
271}
272
273impl Package {
274    /// Create Package object:
275    pub fn new(children: Vec<&dyn Aml>) -> Package {
276        let mut bytes = vec![children.len() as u8];
277        for child in &children {
278            child.to_aml_bytes(&mut bytes);
279        }
280        Package {
281            children_bytes: bytes,
282        }
283    }
284}
285
286/// Variable Package Term
287pub struct VarPackageTerm<'a> {
288    data: &'a dyn Aml,
289}
290
291impl Aml for VarPackageTerm<'_> {
292    fn to_aml_bytes(&self, aml: &mut Vec<u8>) {
293        aml.push(VARPACKAGEOP);
294
295        let start = aml.len();
296        self.data.to_aml_bytes(aml);
297        let data_len = aml.len() - start;
298
299        insert_pkg_length(aml, start, data_len);
300    }
301}
302
303impl<'a> VarPackageTerm<'a> {
304    /// Create Variable Package Term
305    pub fn new(data: &'a dyn Aml) -> Self {
306        VarPackageTerm { data }
307    }
308}
309
310/*
311
312From the ACPI spec for PkgLength:
313
314"The high 2 bits of the first byte reveal how many follow bytes are in the PkgLength. If the
315PkgLength has only one byte, bit 0 through 5 are used to encode the package length (in other
316words, values 0-63). If the package length value is more than 63, more than one byte must be
317used for the encoding in which case bit 4 and 5 of the PkgLeadByte are reserved and must be zero.
318If the multiple bytes encoding is used, bits 0-3 of the PkgLeadByte become the least significant 4
319bits of the resulting package length value. The next ByteData will become the next least
320significant 8 bits of the resulting value and so on, up to 3 ByteData bytes. Thus, the maximum
321package length is 2**28."
322
323*/
324
325/* Also used for NamedField but in that case the length is not included in itself */
326fn insert_length(aml: &mut Vec<u8>, position: usize, len: usize, include_self: bool) {
327    /* PkgLength is inclusive and includes the length bytes */
328    let length_length = if len < (2usize.pow(6) - 1) {
329        1
330    } else if len < (2usize.pow(12) - 2) {
331        2
332    } else if len < (2usize.pow(20) - 3) {
333        3
334    } else {
335        4
336    };
337
338    let length = len + if include_self { length_length } else { 0 };
339
340    match length_length {
341        1 => aml.insert(position, length as u8),
342        2 => {
343            aml.splice(
344                position..position,
345                [(1u8 << 6) | (length & 0xf) as u8, (length >> 4) as u8],
346            );
347        }
348        3 => {
349            aml.splice(
350                position..position,
351                [
352                    (2u8 << 6) | (length & 0xf) as u8,
353                    (length >> 4) as u8,
354                    (length >> 12) as u8,
355                ],
356            );
357        }
358        _ => {
359            aml.splice(
360                position..position,
361                [
362                    (3u8 << 6) | (length & 0xf) as u8,
363                    (length >> 4) as u8,
364                    (length >> 12) as u8,
365                    (length >> 20) as u8,
366                ],
367            );
368        }
369    }
370}
371
372fn insert_pkg_length(aml: &mut Vec<u8>, position: usize, len: usize) {
373    insert_length(aml, position, len, true);
374}
375
376fn append_pkg_length(aml: &mut Vec<u8>, len: usize) {
377    insert_length(aml, aml.len(), len, true);
378}
379
380// Append a NamedField length, which does not count the size of the encoded length itself.
381fn append_named_field_length(aml: &mut Vec<u8>, len: usize) {
382    insert_length(aml, aml.len(), len, false);
383}
384
385/// EISAName object. 'value' means the encoded u32 EisaIdString.
386pub struct EISAName {
387    value: DWord,
388}
389
390impl EISAName {
391    /// Per ACPI Spec, the EisaIdString must be a String
392    /// object of the form UUUNNNN, where U is an uppercase letter
393    /// and N is a hexadecimal digit. No asterisks or other characters
394    /// are allowed in the string.
395    pub fn new(name: &str) -> Self {
396        assert_eq!(name.len(), 7);
397
398        let data = name.as_bytes();
399
400        let value: u32 = (u32::from(data[0].checked_sub(NAMECHARBASE).unwrap()) << 26
401            | u32::from(data[1].checked_sub(NAMECHARBASE).unwrap()) << 21
402            | u32::from(data[2].checked_sub(NAMECHARBASE).unwrap()) << 16
403            | name.chars().nth(3).unwrap().to_digit(16).unwrap() << 12
404            | name.chars().nth(4).unwrap().to_digit(16).unwrap() << 8
405            | name.chars().nth(5).unwrap().to_digit(16).unwrap() << 4
406            | name.chars().nth(6).unwrap().to_digit(16).unwrap())
407        .swap_bytes();
408
409        EISAName { value }
410    }
411}
412
413impl Aml for EISAName {
414    fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
415        self.value.to_aml_bytes(bytes);
416    }
417}
418
419pub type Usize = usize;
420
421impl Aml for Usize {
422    fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
423        #[cfg(target_pointer_width = "16")]
424        (*self as u16).to_aml_bytes(bytes);
425        #[cfg(target_pointer_width = "32")]
426        (*self as u32).to_aml_bytes(bytes);
427        #[cfg(target_pointer_width = "64")]
428        (*self as u64).to_aml_bytes(bytes);
429    }
430}
431
432fn append_aml_string(data: &mut Vec<u8>, v: &str) {
433    data.push(STRINGOP);
434    data.extend_from_slice(v.as_bytes());
435    data.push(0x0); /* NullChar */
436}
437
438/// implement Aml trait for 'str' so that 'str' can be directly append to the aml vector
439pub type AmlStr = &'static str;
440
441impl Aml for AmlStr {
442    fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
443        append_aml_string(bytes, self);
444    }
445}
446
447/// implement Aml trait for 'String'. So purpose with str.
448pub type AmlString = String;
449
450impl Aml for AmlString {
451    fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
452        append_aml_string(bytes, self);
453    }
454}
455
456/// ResouceTemplate object. 'children' represents the ACPI objects in it.
457pub struct ResourceTemplate<'a> {
458    children: Vec<&'a dyn Aml>,
459}
460
461impl Aml for ResourceTemplate<'_> {
462    fn to_aml_bytes(&self, aml: &mut Vec<u8>) {
463        aml.push(BUFFEROP);
464
465        let pos = aml.len();
466
467        // Add buffer data
468        for child in &self.children {
469            child.to_aml_bytes(aml);
470        }
471
472        // Mark with end and mark checksum as as always valid
473        aml.push(ENDTAG);
474        aml.push(0); /* zero checksum byte */
475
476        // Buffer length is an encoded integer including buffer data
477        // and EndTag and checksum byte
478        let buffer_length = aml.len() - pos;
479        let mut buffer_length_bytes = Vec::new();
480        buffer_length.to_aml_bytes(&mut buffer_length_bytes);
481        aml.splice(pos..pos, buffer_length_bytes);
482
483        // PkgLength is everything else
484        let len = aml.len() - pos;
485        insert_pkg_length(aml, pos, len);
486    }
487}
488
489impl<'a> ResourceTemplate<'a> {
490    /// Create ResouceTemplate object
491    pub fn new(children: Vec<&'a dyn Aml>) -> Self {
492        ResourceTemplate { children }
493    }
494}
495
496/// Memory32Fixed object with read_write accessing type, and the base address/length.
497pub struct Memory32Fixed {
498    read_write: bool, /* true for read & write, false for read only */
499    base: u32,
500    length: u32,
501}
502
503impl Memory32Fixed {
504    /// Create Memory32Fixed object.
505    pub fn new(read_write: bool, base: u32, length: u32) -> Self {
506        Memory32Fixed {
507            read_write,
508            base,
509            length,
510        }
511    }
512}
513
514impl Aml for Memory32Fixed {
515    fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
516        bytes.push(MEMORY32FIXEDDESC); /* 32bit Fixed Memory Range Descriptor */
517        bytes.extend_from_slice(&9u16.to_le_bytes());
518
519        // 9 bytes of payload
520        bytes.push(self.read_write as u8);
521        bytes.extend_from_slice(&self.base.to_le_bytes());
522        bytes.extend_from_slice(&self.length.to_le_bytes());
523    }
524}
525
526#[derive(Copy, Clone)]
527enum AddressSpaceType {
528    Memory,
529    IO,
530    BusNumber,
531}
532
533/// AddressSpaceCachable represent cache types for AddressSpace object
534#[derive(Copy, Clone)]
535pub enum AddressSpaceCachable {
536    NotCacheable,
537    Cacheable,
538    WriteCombining,
539    PreFetchable,
540}
541
542/// AddressSpace structure with type, resouce range and flags to
543/// construct Memory/IO/BusNumber objects
544pub struct AddressSpace<T> {
545    type_: AddressSpaceType,
546    min: T,
547    max: T,
548    type_flags: u8,
549}
550
551impl<T> AddressSpace<T> {
552    /// Create DWordMemory/QWordMemory object
553    pub fn new_memory(cacheable: AddressSpaceCachable, read_write: bool, min: T, max: T) -> Self {
554        AddressSpace {
555            type_: AddressSpaceType::Memory,
556            min,
557            max,
558            type_flags: (cacheable as u8) << 1 | read_write as u8,
559        }
560    }
561
562    /// Create WordIO/DWordIO/QWordIO object
563    pub fn new_io(min: T, max: T) -> Self {
564        AddressSpace {
565            type_: AddressSpaceType::IO,
566            min,
567            max,
568            type_flags: 3, /* EntireRange */
569        }
570    }
571
572    /// Create WordBusNumber object
573    pub fn new_bus_number(min: T, max: T) -> Self {
574        AddressSpace {
575            type_: AddressSpaceType::BusNumber,
576            min,
577            max,
578            type_flags: 0,
579        }
580    }
581
582    fn push_header(&self, bytes: &mut Vec<u8>, descriptor: u8, length: usize) {
583        bytes.push(descriptor); /* Word Address Space Descriptor */
584        bytes.extend_from_slice(&(length as u16).to_le_bytes());
585        bytes.push(self.type_ as u8); /* type */
586        let generic_flags = 1 << 2 /* Min Fixed */ | 1 << 3; /* Max Fixed */
587        bytes.push(generic_flags);
588        bytes.push(self.type_flags);
589    }
590}
591
592impl Aml for AddressSpace<u16> {
593    fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
594        self.push_header(
595            bytes,
596            WORDADDRSPACEDESC,                  /* Word Address Space Descriptor */
597            3 + 5 * std::mem::size_of::<u16>(), /* 3 bytes of header + 5 u16 fields */
598        );
599
600        bytes.extend_from_slice(&0u16.to_le_bytes()); /* Granularity */
601        bytes.extend_from_slice(&self.min.to_le_bytes()); /* Min */
602        bytes.extend_from_slice(&self.max.to_le_bytes()); /* Max */
603        bytes.extend_from_slice(&0u16.to_le_bytes()); /* Translation */
604        let len = self.max - self.min + 1;
605        bytes.extend_from_slice(&len.to_le_bytes()); /* Length */
606    }
607}
608
609impl Aml for AddressSpace<u32> {
610    fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
611        self.push_header(
612            bytes,
613            DWORDADDRSPACEDESC, /* DWord Address Space Descriptor */
614            3 + 5 * std::mem::size_of::<u32>(), /* 3 bytes of header + 5 u32 fields */
615        );
616
617        bytes.extend_from_slice(&0u32.to_le_bytes()); /* Granularity */
618        bytes.extend_from_slice(&self.min.to_le_bytes()); /* Min */
619        bytes.extend_from_slice(&self.max.to_le_bytes()); /* Max */
620        bytes.extend_from_slice(&0u32.to_le_bytes()); /* Translation */
621        let len = self.max - self.min + 1;
622        bytes.extend_from_slice(&len.to_le_bytes()); /* Length */
623    }
624}
625
626impl Aml for AddressSpace<u64> {
627    fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
628        self.push_header(
629            bytes,
630            QWORDADDRSPACEDESC, /* QWord Address Space Descriptor */
631            3 + 5 * std::mem::size_of::<u64>(), /* 3 bytes of header + 5 u64 fields */
632        );
633
634        bytes.extend_from_slice(&0u64.to_le_bytes()); /* Granularity */
635        bytes.extend_from_slice(&self.min.to_le_bytes()); /* Min */
636        bytes.extend_from_slice(&self.max.to_le_bytes()); /* Max */
637        bytes.extend_from_slice(&0u64.to_le_bytes()); /* Translation */
638        let len = self.max - self.min + 1;
639        bytes.extend_from_slice(&len.to_le_bytes()); /* Length */
640    }
641}
642
643/// IO resouce object with the IO range, alignment and length
644pub struct IO {
645    min: u16,
646    max: u16,
647    alignment: u8,
648    length: u8,
649}
650
651impl IO {
652    /// Create IO object
653    pub fn new(min: u16, max: u16, alignment: u8, length: u8) -> Self {
654        IO {
655            min,
656            max,
657            alignment,
658            length,
659        }
660    }
661}
662
663impl Aml for IO {
664    fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
665        bytes.push(IOPORTDESC); /* IO Port Descriptor */
666        bytes.push(1); /* IODecode16 */
667        bytes.extend_from_slice(&self.min.to_le_bytes());
668        bytes.extend_from_slice(&self.max.to_le_bytes());
669        bytes.push(self.alignment);
670        bytes.push(self.length);
671    }
672}
673
674/// Interrupt resouce object with the interrupt characters.
675pub struct Interrupt {
676    consumer: bool,
677    edge_triggered: bool,
678    active_low: bool,
679    shared: bool,
680    number: u32,
681}
682
683impl Interrupt {
684    /// Create Interrupt object
685    pub fn new(
686        consumer: bool,
687        edge_triggered: bool,
688        active_low: bool,
689        shared: bool,
690        number: u32,
691    ) -> Self {
692        Interrupt {
693            consumer,
694            edge_triggered,
695            active_low,
696            shared,
697            number,
698        }
699    }
700}
701
702impl Aml for Interrupt {
703    fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
704        bytes.push(EXTIRQDESC); /* Extended IRQ Descriptor */
705        bytes.extend_from_slice(&6u16.to_le_bytes());
706        let flags = (self.shared as u8) << 3
707            | (self.active_low as u8) << 2
708            | (self.edge_triggered as u8) << 1
709            | self.consumer as u8;
710        bytes.push(flags);
711        bytes.push(1u8); /* count */
712        bytes.extend_from_slice(&self.number.to_le_bytes());
713    }
714}
715
716/// Device object with its device name and children objects in it.
717pub struct Device<'a> {
718    path: Path,
719    children: Vec<&'a dyn Aml>,
720}
721
722impl Aml for Device<'_> {
723    fn to_aml_bytes(&self, aml: &mut Vec<u8>) {
724        aml.push(EXTOPPREFIX); /* ExtOpPrefix */
725        aml.push(DEVICEOP); /* DeviceOp */
726
727        let start = aml.len();
728        self.path.to_aml_bytes(aml);
729        for child in &self.children {
730            child.to_aml_bytes(aml);
731        }
732        let len = aml.len() - start;
733
734        insert_pkg_length(aml, start, len);
735    }
736}
737
738impl<'a> Device<'a> {
739    /// Create Device object
740    pub fn new(path: Path, children: Vec<&'a dyn Aml>) -> Self {
741        Device { path, children }
742    }
743}
744
745/// Scope object with its name and children objects in it.
746pub struct Scope<'a> {
747    path: Path,
748    children: Vec<&'a dyn Aml>,
749}
750
751impl Aml for Scope<'_> {
752    fn to_aml_bytes(&self, aml: &mut Vec<u8>) {
753        aml.push(SCOPEOP);
754
755        let start = aml.len();
756        self.path.to_aml_bytes(aml);
757        for child in &self.children {
758            child.to_aml_bytes(aml);
759        }
760        let len = aml.len() - start;
761
762        insert_pkg_length(aml, start, len);
763    }
764}
765
766impl<'a> Scope<'a> {
767    /// Create Scope object
768    pub fn new(path: Path, children: Vec<&'a dyn Aml>) -> Self {
769        Scope { path, children }
770    }
771
772    /// Create raw bytes representing a Scope from its children in raw bytes
773    pub fn raw(path: Path, mut children: Vec<u8>) -> Vec<u8> {
774        let mut bytes = Vec::new();
775        bytes.push(SCOPEOP);
776
777        let start = bytes.len();
778        path.to_aml_bytes(&mut bytes);
779        bytes.append(&mut children);
780        let len = bytes.len() - start;
781
782        insert_pkg_length(&mut bytes, start, len);
783
784        bytes
785    }
786}
787
788/// Method object with its name, children objects, arguments and serialized character.
789pub struct Method<'a> {
790    path: Path,
791    children: Vec<&'a dyn Aml>,
792    args: u8,
793    serialized: bool,
794}
795
796impl<'a> Method<'a> {
797    /// Create Method object.
798    pub fn new(path: Path, args: u8, serialized: bool, children: Vec<&'a dyn Aml>) -> Self {
799        Method {
800            path,
801            children,
802            args,
803            serialized,
804        }
805    }
806}
807
808impl Aml for Method<'_> {
809    fn to_aml_bytes(&self, aml: &mut Vec<u8>) {
810        aml.push(METHODOP);
811
812        let start = aml.len();
813        self.path.to_aml_bytes(aml);
814        let flags: u8 = (self.args & 0x7) | (self.serialized as u8) << 3;
815        aml.push(flags);
816        for child in &self.children {
817            child.to_aml_bytes(aml);
818        }
819        let len = aml.len() - start;
820
821        insert_pkg_length(aml, start, len);
822    }
823}
824
825/// FieldAccessType defines the field accessing types.
826#[derive(Clone, Copy)]
827pub enum FieldAccessType {
828    Any,
829    Byte,
830    Word,
831    DWord,
832    QWord,
833    Buffer,
834}
835
836/// FieldLockRule defines the rules whether to use the Global Lock.
837#[derive(Clone, Copy)]
838pub enum FieldLockRule {
839    NoLock = 0,
840    Lock = 1,
841}
842
843/// FieldUpdateRule defines the rules to update the field.
844#[derive(Clone, Copy)]
845pub enum FieldUpdateRule {
846    Preserve = 0,
847    WriteAsOnes = 1,
848    WriteAsZeroes = 2,
849}
850
851/// FieldEntry defines the field entry.
852pub enum FieldEntry {
853    Named([u8; 4], usize),
854    Reserved(usize),
855}
856
857/// Field object with the region name, field entries, access type and update rules.
858pub struct Field {
859    path: Path,
860
861    fields: Vec<FieldEntry>,
862    access_type: FieldAccessType,
863    lock_rule: FieldLockRule,
864    update_rule: FieldUpdateRule,
865}
866
867impl Field {
868    /// Create Field object
869    pub fn new(
870        path: Path,
871        access_type: FieldAccessType,
872        lock_rule: FieldLockRule,
873        update_rule: FieldUpdateRule,
874        fields: Vec<FieldEntry>,
875    ) -> Self {
876        Field {
877            path,
878            access_type,
879            lock_rule,
880            update_rule,
881            fields,
882        }
883    }
884}
885
886impl Aml for Field {
887    fn to_aml_bytes(&self, aml: &mut Vec<u8>) {
888        aml.push(EXTOPPREFIX);
889        aml.push(FIELDOP);
890
891        let start = aml.len();
892        self.path.to_aml_bytes(aml);
893
894        let flags: u8 =
895            self.access_type as u8 | (self.lock_rule as u8) << 4 | (self.update_rule as u8) << 5;
896        aml.push(flags);
897
898        for field in self.fields.iter() {
899            match field {
900                FieldEntry::Named(name, length) => {
901                    aml.extend_from_slice(name);
902                    append_named_field_length(aml, *length);
903                }
904                FieldEntry::Reserved(length) => {
905                    aml.push(0x0);
906                    append_named_field_length(aml, *length);
907                }
908            }
909        }
910
911        let len = aml.len() - start;
912        insert_pkg_length(aml, start, len);
913    }
914}
915
916/// The space type for OperationRegion object
917#[derive(Clone, Copy)]
918pub enum OpRegionSpace {
919    SystemMemory,
920    SystemIO,
921    PCIConfig,
922    EmbeddedControl,
923    SMBus,
924    SystemCMOS,
925    PciBarTarget,
926    IPMI,
927    GeneralPurposeIO,
928    GenericSerialBus,
929}
930
931/// OperationRegion object with region name, region space type, its offset and length.
932pub struct OpRegion<'a> {
933    path: Path,
934    space: OpRegionSpace,
935    offset: &'a dyn Aml,
936    length: &'a dyn Aml,
937}
938
939impl<'a> OpRegion<'a> {
940    /// Create OperationRegion object.
941    pub fn new(path: Path, space: OpRegionSpace, offset: &'a dyn Aml, length: &'a dyn Aml) -> Self {
942        OpRegion {
943            path,
944            space,
945            offset,
946            length,
947        }
948    }
949}
950
951impl Aml for OpRegion<'_> {
952    fn to_aml_bytes(&self, aml: &mut Vec<u8>) {
953        aml.push(EXTOPPREFIX);
954        aml.push(OPREGIONOP);
955
956        self.path.to_aml_bytes(aml);
957        aml.push(self.space as u8);
958        self.offset.to_aml_bytes(aml); /* RegionOffset */
959        self.length.to_aml_bytes(aml); /* RegionLen */
960    }
961}
962
963/// If object with the if condition(predicate) and the body presented by the if_children objects.
964pub struct If<'a> {
965    predicate: &'a dyn Aml,
966    if_children: Vec<&'a dyn Aml>,
967}
968
969impl<'a> If<'a> {
970    /// Create If object.
971    pub fn new(predicate: &'a dyn Aml, if_children: Vec<&'a dyn Aml>) -> Self {
972        If {
973            predicate,
974            if_children,
975        }
976    }
977}
978
979impl Aml for If<'_> {
980    fn to_aml_bytes(&self, aml: &mut Vec<u8>) {
981        aml.push(IFOP);
982
983        let start = aml.len();
984        self.predicate.to_aml_bytes(aml);
985        for child in self.if_children.iter() {
986            child.to_aml_bytes(aml);
987        }
988        let len = aml.len() - start;
989
990        insert_pkg_length(aml, start, len);
991    }
992}
993
994/// Else object
995pub struct Else<'a> {
996    body: Vec<&'a dyn Aml>,
997}
998
999impl<'a> Else<'a> {
1000    /// Create Else object.
1001    pub fn new(body: Vec<&'a dyn Aml>) -> Self {
1002        Else { body }
1003    }
1004}
1005
1006impl Aml for Else<'_> {
1007    fn to_aml_bytes(&self, aml: &mut Vec<u8>) {
1008        aml.push(ELSEOP);
1009
1010        let start = aml.len();
1011        for child in self.body.iter() {
1012            child.to_aml_bytes(aml);
1013        }
1014        let len = aml.len() - start;
1015
1016        insert_pkg_length(aml, start, len);
1017    }
1018}
1019
1020macro_rules! compare_op {
1021    ($name:ident, $opcode:expr, $invert:expr) => {
1022        /// Compare object with its right part and left part, which are both ACPI Object.
1023        pub struct $name<'a> {
1024            right: &'a dyn Aml,
1025            left: &'a dyn Aml,
1026        }
1027
1028        impl<'a> $name<'a> {
1029            /// Create the compare object method.
1030            pub fn new(left: &'a dyn Aml, right: &'a dyn Aml) -> Self {
1031                $name { left, right }
1032            }
1033        }
1034
1035        impl<'a> Aml for $name<'a> {
1036            fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
1037                if $invert {
1038                    bytes.push(LNOTOP);
1039                }
1040                bytes.push($opcode);
1041                self.left.to_aml_bytes(bytes);
1042                self.right.to_aml_bytes(bytes);
1043            }
1044        }
1045    };
1046}
1047
1048compare_op!(Equal, LEQUALOP, false);
1049compare_op!(LessThan, LLESSOP, false);
1050compare_op!(GreaterThan, LGREATEROP, false);
1051compare_op!(NotEqual, LEQUALOP, true);
1052compare_op!(GreaterEqual, LLESSOP, true);
1053compare_op!(LessEqual, LGREATEROP, true);
1054
1055/// Argx object.
1056pub struct Arg(pub u8);
1057
1058impl Aml for Arg {
1059    /// Per ACPI spec, there is maximum 7 Argx objects from
1060    /// Arg0 ~ Arg6. Any other Arg object will not be accepted.
1061    fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
1062        assert!(self.0 <= 6);
1063        bytes.push(ARG0OP + self.0);
1064    }
1065}
1066
1067/// Localx object.
1068pub struct Local(pub u8);
1069
1070impl Aml for Local {
1071    /// Per ACPI spec, there is maximum 8 Localx objects from
1072    /// Local0 ~ Local7. Any other Local object will not be accepted.
1073    fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
1074        assert!(self.0 <= 7);
1075        bytes.push(LOCAL0OP + self.0);
1076    }
1077}
1078
1079/// Store object with the ACPI object name which can be stored to and
1080/// the ACPI object value which is to store.
1081pub struct Store<'a> {
1082    name: &'a dyn Aml,
1083    value: &'a dyn Aml,
1084}
1085
1086impl<'a> Store<'a> {
1087    /// Create Store object.
1088    pub fn new(name: &'a dyn Aml, value: &'a dyn Aml) -> Self {
1089        Store { name, value }
1090    }
1091}
1092
1093impl Aml for Store<'_> {
1094    fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
1095        bytes.push(STOREOP);
1096        self.value.to_aml_bytes(bytes);
1097        self.name.to_aml_bytes(bytes);
1098    }
1099}
1100
1101/// Mutex object with a mutex name and a synchronization level.
1102pub struct Mutex {
1103    path: Path,
1104    sync_level: u8,
1105}
1106
1107impl Mutex {
1108    /// Create Mutex object.
1109    pub fn new(path: Path, sync_level: u8) -> Self {
1110        Self { path, sync_level }
1111    }
1112}
1113
1114impl Aml for Mutex {
1115    fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
1116        bytes.push(EXTOPPREFIX);
1117        bytes.push(MUTEXOP);
1118        self.path.to_aml_bytes(bytes);
1119        bytes.push(self.sync_level);
1120    }
1121}
1122
1123/// Acquire object with a Mutex object and timeout value.
1124pub struct Acquire {
1125    mutex: Path,
1126    timeout: u16,
1127}
1128
1129impl Acquire {
1130    /// Create Acquire object.
1131    pub fn new(mutex: Path, timeout: u16) -> Self {
1132        Acquire { mutex, timeout }
1133    }
1134}
1135
1136impl Aml for Acquire {
1137    fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
1138        bytes.push(EXTOPPREFIX);
1139        bytes.push(ACQUIREOP);
1140        self.mutex.to_aml_bytes(bytes);
1141        bytes.extend_from_slice(&self.timeout.to_le_bytes());
1142    }
1143}
1144
1145/// Release object with a Mutex object to release.
1146pub struct Release {
1147    mutex: Path,
1148}
1149
1150impl Release {
1151    /// Create Release object.
1152    pub fn new(mutex: Path) -> Self {
1153        Release { mutex }
1154    }
1155}
1156
1157impl Aml for Release {
1158    fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
1159        bytes.push(EXTOPPREFIX);
1160        bytes.push(RELEASEOP);
1161        self.mutex.to_aml_bytes(bytes);
1162    }
1163}
1164
1165/// Notify object with an object which is to be notified with the value.
1166pub struct Notify<'a> {
1167    object: &'a dyn Aml,
1168    value: &'a dyn Aml,
1169}
1170
1171impl<'a> Notify<'a> {
1172    /// Create Notify object.
1173    pub fn new(object: &'a dyn Aml, value: &'a dyn Aml) -> Self {
1174        Notify { object, value }
1175    }
1176}
1177
1178impl Aml for Notify<'_> {
1179    fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
1180        bytes.push(NOTIFYOP);
1181        self.object.to_aml_bytes(bytes);
1182        self.value.to_aml_bytes(bytes);
1183    }
1184}
1185
1186/// While object with the while condition objects(predicate) and
1187/// the while body objects(while_children).
1188pub struct While<'a> {
1189    predicate: &'a dyn Aml,
1190    while_children: Vec<&'a dyn Aml>,
1191}
1192
1193impl<'a> While<'a> {
1194    /// Create While object.
1195    pub fn new(predicate: &'a dyn Aml, while_children: Vec<&'a dyn Aml>) -> Self {
1196        While {
1197            predicate,
1198            while_children,
1199        }
1200    }
1201}
1202
1203impl Aml for While<'_> {
1204    fn to_aml_bytes(&self, aml: &mut Vec<u8>) {
1205        aml.push(WHILEOP);
1206
1207        let start = aml.len();
1208        self.predicate.to_aml_bytes(aml);
1209        for child in self.while_children.iter() {
1210            child.to_aml_bytes(aml);
1211        }
1212        let len = aml.len() - start;
1213
1214        insert_pkg_length(aml, start, len);
1215    }
1216}
1217
1218macro_rules! object_op {
1219    ($name:ident, $opcode:expr) => {
1220        /// General operation on a object.
1221        pub struct $name<'a> {
1222            a: &'a dyn Aml,
1223        }
1224
1225        impl<'a> $name<'a> {
1226            /// Create the object method.
1227            pub fn new(a: &'a dyn Aml) -> Self {
1228                $name { a }
1229            }
1230        }
1231
1232        impl<'a> Aml for $name<'a> {
1233            fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
1234                bytes.push($opcode);
1235                self.a.to_aml_bytes(bytes);
1236            }
1237        }
1238    };
1239}
1240
1241object_op!(ObjectType, OBJECTTYPEOP);
1242object_op!(SizeOf, SIZEOFOP);
1243object_op!(Return, RETURNOP);
1244object_op!(DeRefOf, DEREFOFOP);
1245
1246macro_rules! binary_op {
1247    ($name:ident, $opcode:expr) => {
1248        /// General operation object with the operator a/b and a target.
1249        pub struct $name<'a> {
1250            a: &'a dyn Aml,
1251            b: &'a dyn Aml,
1252            target: &'a dyn Aml,
1253        }
1254
1255        impl<'a> $name<'a> {
1256            /// Create the object.
1257            pub fn new(target: &'a dyn Aml, a: &'a dyn Aml, b: &'a dyn Aml) -> Self {
1258                $name { target, a, b }
1259            }
1260        }
1261
1262        impl<'a> Aml for $name<'a> {
1263            fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
1264                bytes.push($opcode); /* Op for the binary operator */
1265                self.a.to_aml_bytes(bytes);
1266                self.b.to_aml_bytes(bytes);
1267                self.target.to_aml_bytes(bytes);
1268            }
1269        }
1270    };
1271}
1272
1273binary_op!(Add, ADDOP);
1274binary_op!(Concat, CONCATOP);
1275binary_op!(Subtract, SUBTRACTOP);
1276binary_op!(Multiply, MULTIPLYOP);
1277binary_op!(ShiftLeft, SHIFTLEFTOP);
1278binary_op!(ShiftRight, SHIFTRIGHTOP);
1279binary_op!(And, ANDOP);
1280binary_op!(Nand, NANDOP);
1281binary_op!(Or, OROP);
1282binary_op!(Nor, NOROP);
1283binary_op!(Xor, XOROP);
1284binary_op!(ConcatRes, CONCATRESOP);
1285binary_op!(Mod, MODOP);
1286binary_op!(Index, INDEXOP);
1287binary_op!(ToString, TOSTRINGOP);
1288binary_op!(CreateDWordField, CREATEDWFIELDOP);
1289binary_op!(CreateQWordField, CREATEQWFIELDOP);
1290
1291macro_rules! convert_op {
1292    ($name:ident, $opcode:expr) => {
1293        /// General operation object with the operator a/b and a target.
1294        pub struct $name<'a> {
1295            a: &'a dyn Aml,
1296            target: &'a dyn Aml,
1297        }
1298
1299        impl<'a> $name<'a> {
1300            /// Create the object.
1301            pub fn new(target: &'a dyn Aml, a: &'a dyn Aml) -> Self {
1302                $name { target, a }
1303            }
1304        }
1305
1306        impl<'a> Aml for $name<'a> {
1307            fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
1308                bytes.push($opcode); /* Op for the binary operator */
1309                self.a.to_aml_bytes(bytes);
1310                self.target.to_aml_bytes(bytes);
1311            }
1312        }
1313    };
1314}
1315
1316convert_op!(ToBuffer, TOBUFFEROP);
1317convert_op!(ToInteger, TOINTEGEROP);
1318
1319/// Create Field Object.
1320pub struct CreateField<'a> {
1321    name_string: &'a dyn Aml,
1322    source: &'a dyn Aml,
1323    bit_index: &'a dyn Aml,
1324    bit_num: &'a dyn Aml,
1325}
1326
1327impl<'a> CreateField<'a> {
1328    pub fn new(
1329        name_string: &'a dyn Aml,
1330        source: &'a dyn Aml,
1331        bit_index: &'a dyn Aml,
1332        bit_num: &'a dyn Aml,
1333    ) -> Self {
1334        CreateField {
1335            name_string,
1336            source,
1337            bit_index,
1338            bit_num,
1339        }
1340    }
1341}
1342
1343impl Aml for CreateField<'_> {
1344    fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
1345        bytes.push(EXTOPPREFIX);
1346        bytes.push(CREATEFIELDOP);
1347        self.source.to_aml_bytes(bytes);
1348        self.bit_index.to_aml_bytes(bytes);
1349        self.bit_num.to_aml_bytes(bytes);
1350        self.name_string.to_aml_bytes(bytes);
1351    }
1352}
1353
1354/// Mid object with the source, index, length, and result objects.
1355pub struct Mid<'a> {
1356    source: &'a dyn Aml,
1357    index: &'a dyn Aml,
1358    length: &'a dyn Aml,
1359    result: &'a dyn Aml,
1360}
1361
1362impl<'a> Mid<'a> {
1363    pub fn new(
1364        source: &'a dyn Aml,
1365        index: &'a dyn Aml,
1366        length: &'a dyn Aml,
1367        result: &'a dyn Aml,
1368    ) -> Self {
1369        Mid {
1370            source,
1371            index,
1372            length,
1373            result,
1374        }
1375    }
1376}
1377
1378impl Aml for Mid<'_> {
1379    fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
1380        bytes.push(MIDOP);
1381        self.source.to_aml_bytes(bytes);
1382        self.index.to_aml_bytes(bytes);
1383        self.length.to_aml_bytes(bytes);
1384        self.result.to_aml_bytes(bytes);
1385    }
1386}
1387
1388/// MethodCall object with the method name and parameter objects.
1389pub struct MethodCall<'a> {
1390    name: Path,
1391    args: Vec<&'a dyn Aml>,
1392}
1393
1394impl<'a> MethodCall<'a> {
1395    /// Create MethodCall object.
1396    pub fn new(name: Path, args: Vec<&'a dyn Aml>) -> Self {
1397        MethodCall { name, args }
1398    }
1399}
1400
1401impl Aml for MethodCall<'_> {
1402    fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
1403        self.name.to_aml_bytes(bytes);
1404        for arg in self.args.iter() {
1405            arg.to_aml_bytes(bytes);
1406        }
1407    }
1408}
1409
1410/// Buffer object with the TermArg in it.
1411pub struct BufferTerm<'a> {
1412    data: &'a dyn Aml,
1413}
1414
1415impl<'a> BufferTerm<'a> {
1416    /// Create BufferTerm object.
1417    pub fn new(data: &'a dyn Aml) -> Self {
1418        BufferTerm { data }
1419    }
1420}
1421
1422impl Aml for BufferTerm<'_> {
1423    fn to_aml_bytes(&self, aml: &mut Vec<u8>) {
1424        aml.push(BUFFEROP);
1425
1426        let start = aml.len();
1427        self.data.to_aml_bytes(aml);
1428        let len = aml.len() - start;
1429
1430        insert_pkg_length(aml, start, len);
1431    }
1432}
1433
1434/// Buffer object with the data in it.
1435pub struct BufferData {
1436    data: Vec<u8>,
1437}
1438
1439impl BufferData {
1440    /// Create BufferData object.
1441    pub fn new(data: Vec<u8>) -> Self {
1442        BufferData { data }
1443    }
1444}
1445
1446impl Aml for BufferData {
1447    fn to_aml_bytes(&self, aml: &mut Vec<u8>) {
1448        aml.push(BUFFEROP);
1449
1450        let start = aml.len();
1451        self.data.len().to_aml_bytes(aml);
1452        aml.extend_from_slice(&self.data);
1453        let len = aml.len() - start;
1454
1455        insert_pkg_length(aml, start, len);
1456    }
1457}
1458
1459pub struct Uuid {
1460    name: BufferData,
1461}
1462
1463fn hex2byte(v1: char, v2: char) -> u8 {
1464    let hi = v1.to_digit(16).unwrap() as u8;
1465    assert!(hi <= 15);
1466    let lo = v2.to_digit(16).unwrap() as u8;
1467    assert!(lo <= 15);
1468
1469    (hi << 4) | lo
1470}
1471
1472impl Uuid {
1473    // Create Uuid object
1474    // eg. UUID: aabbccdd-eeff-gghh-iijj-kkllmmnnoopp
1475    pub fn new(name: &str) -> Self {
1476        let name_vec: Vec<char> = name.chars().collect();
1477        let mut data = Vec::new();
1478
1479        assert_eq!(name_vec.len(), 36);
1480        assert_eq!(name_vec[8], '-');
1481        assert_eq!(name_vec[13], '-');
1482        assert_eq!(name_vec[18], '-');
1483        assert_eq!(name_vec[23], '-');
1484
1485        // dd - at offset 00
1486        data.push(hex2byte(name_vec[6], name_vec[7]));
1487        // cc - at offset 01
1488        data.push(hex2byte(name_vec[4], name_vec[5]));
1489        // bb - at offset 02
1490        data.push(hex2byte(name_vec[2], name_vec[3]));
1491        // aa - at offset 03
1492        data.push(hex2byte(name_vec[0], name_vec[1]));
1493
1494        // ff - at offset 04
1495        data.push(hex2byte(name_vec[11], name_vec[12]));
1496        // ee - at offset 05
1497        data.push(hex2byte(name_vec[9], name_vec[10]));
1498
1499        // hh - at offset 06
1500        data.push(hex2byte(name_vec[16], name_vec[17]));
1501        // gg - at offset 07
1502        data.push(hex2byte(name_vec[14], name_vec[15]));
1503
1504        // ii - at offset 08
1505        data.push(hex2byte(name_vec[19], name_vec[20]));
1506        // jj - at offset 09
1507        data.push(hex2byte(name_vec[21], name_vec[22]));
1508
1509        // kk - at offset 10
1510        data.push(hex2byte(name_vec[24], name_vec[25]));
1511        // ll - at offset 11
1512        data.push(hex2byte(name_vec[26], name_vec[27]));
1513        // mm - at offset 12
1514        data.push(hex2byte(name_vec[28], name_vec[29]));
1515        // nn - at offset 13
1516        data.push(hex2byte(name_vec[30], name_vec[31]));
1517        // oo - at offset 14
1518        data.push(hex2byte(name_vec[32], name_vec[33]));
1519        // pp - at offset 15
1520        data.push(hex2byte(name_vec[34], name_vec[35]));
1521
1522        Uuid {
1523            name: BufferData::new(data),
1524        }
1525    }
1526}
1527
1528impl Aml for Uuid {
1529    fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
1530        self.name.to_aml_bytes(bytes)
1531    }
1532}
1533
1534/// Power Resource object. 'children' represents Power Resource method.
1535pub struct PowerResource<'a> {
1536    name: Path,
1537    level: u8,
1538    order: u16,
1539    children: Vec<&'a dyn Aml>,
1540}
1541
1542impl<'a> PowerResource<'a> {
1543    /// Create Power Resouce object
1544    pub fn new(name: Path, level: u8, order: u16, children: Vec<&'a dyn Aml>) -> Self {
1545        PowerResource {
1546            name,
1547            level,
1548            order,
1549            children,
1550        }
1551    }
1552}
1553
1554impl Aml for PowerResource<'_> {
1555    fn to_aml_bytes(&self, aml: &mut Vec<u8>) {
1556        aml.push(EXTOPPREFIX);
1557        aml.push(POWERRESOURCEOP);
1558
1559        let start = aml.len();
1560
1561        // Add name string
1562        self.name.to_aml_bytes(aml);
1563        // Add system level
1564        aml.push(self.level);
1565        // Add Resource Order
1566        let orders = self.order.to_le_bytes();
1567        aml.push(orders[0]);
1568        aml.push(orders[1]);
1569        // Add child data
1570        for child in &self.children {
1571            child.to_aml_bytes(aml);
1572        }
1573
1574        let len = aml.len() - start;
1575
1576        insert_pkg_length(aml, start, len);
1577    }
1578}
1579
1580#[cfg(test)]
1581mod tests {
1582    use super::*;
1583
1584    #[test]
1585    fn test_device() {
1586        /*
1587        Device (_SB.COM1)
1588        {
1589            Name (_HID, EisaId ("PNP0501") /* 16550A-compatible COM Serial Port */) // _HID: Hardware ID
1590            Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource Settings
1591            {
1592                Interrupt (ResourceConsumer, Edge, ActiveHigh, Exclusive, ,, )
1593                {
1594                    0x00000004,
1595                }
1596                IO (Decode16,
1597                    0x03F8,             // Range Minimum
1598                    0x03F8,             // Range Maximum
1599                    0x00,               // Alignment
1600                    0x08,               // Length
1601                    )
1602            }
1603        }
1604            */
1605        let com1_device = [
1606            0x5B, 0x82, 0x30, 0x2E, 0x5F, 0x53, 0x42, 0x5F, 0x43, 0x4F, 0x4D, 0x31, 0x08, 0x5F,
1607            0x48, 0x49, 0x44, 0x0C, 0x41, 0xD0, 0x05, 0x01, 0x08, 0x5F, 0x43, 0x52, 0x53, 0x11,
1608            0x16, 0x0A, 0x13, 0x89, 0x06, 0x00, 0x03, 0x01, 0x04, 0x00, 0x00, 0x00, 0x47, 0x01,
1609            0xF8, 0x03, 0xF8, 0x03, 0x00, 0x08, 0x79, 0x00,
1610        ];
1611        let mut aml = Vec::new();
1612
1613        Device::new(
1614            "_SB_.COM1".into(),
1615            vec![
1616                &Name::new("_HID".into(), &EISAName::new("PNP0501")),
1617                &Name::new(
1618                    "_CRS".into(),
1619                    &ResourceTemplate::new(vec![
1620                        &Interrupt::new(true, true, false, false, 4),
1621                        &IO::new(0x3f8, 0x3f8, 0, 0x8),
1622                    ]),
1623                ),
1624            ],
1625        )
1626        .to_aml_bytes(&mut aml);
1627        assert_eq!(aml, &com1_device[..]);
1628    }
1629
1630    #[test]
1631    fn test_scope() {
1632        /*
1633        Scope (_SB.MBRD)
1634        {
1635            Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource Settings
1636            {
1637                Memory32Fixed (ReadWrite,
1638                    0xE8000000,         // Address Base
1639                    0x10000000,         // Address Length
1640                    )
1641            })
1642        }
1643        */
1644
1645        let mbrd_scope = [
1646            0x10, 0x21, 0x2E, 0x5F, 0x53, 0x42, 0x5F, 0x4D, 0x42, 0x52, 0x44, 0x08, 0x5F, 0x43,
1647            0x52, 0x53, 0x11, 0x11, 0x0A, 0x0E, 0x86, 0x09, 0x00, 0x01, 0x00, 0x00, 0x00, 0xE8,
1648            0x00, 0x00, 0x00, 0x10, 0x79, 0x00,
1649        ];
1650        let mut aml = Vec::new();
1651
1652        Scope::new(
1653            "_SB_.MBRD".into(),
1654            vec![&Name::new(
1655                "_CRS".into(),
1656                &ResourceTemplate::new(vec![&Memory32Fixed::new(true, 0xE800_0000, 0x1000_0000)]),
1657            )],
1658        )
1659        .to_aml_bytes(&mut aml);
1660        assert_eq!(aml, &mbrd_scope[..]);
1661    }
1662
1663    #[test]
1664    fn test_resource_template() {
1665        /*
1666        Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource Settings
1667        {
1668            Memory32Fixed (ReadWrite,
1669                0xE8000000,         // Address Base
1670                0x10000000,         // Address Length
1671                )
1672        })
1673        */
1674        let crs_memory_32_fixed = [
1675            0x08, 0x5F, 0x43, 0x52, 0x53, 0x11, 0x11, 0x0A, 0x0E, 0x86, 0x09, 0x00, 0x01, 0x00,
1676            0x00, 0x00, 0xE8, 0x00, 0x00, 0x00, 0x10, 0x79, 0x00,
1677        ];
1678        let mut aml = Vec::new();
1679
1680        Name::new(
1681            "_CRS".into(),
1682            &ResourceTemplate::new(vec![&Memory32Fixed::new(true, 0xE800_0000, 0x1000_0000)]),
1683        )
1684        .to_aml_bytes(&mut aml);
1685        assert_eq!(aml, crs_memory_32_fixed);
1686
1687        /*
1688            Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource Settings
1689            {
1690                WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode,
1691                    0x0000,             // Granularity
1692                    0x0000,             // Range Minimum
1693                    0x00FF,             // Range Maximum
1694                    0x0000,             // Translation Offset
1695                    0x0100,             // Length
1696                    ,, )
1697                WordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
1698                    0x0000,             // Granularity
1699                    0x0000,             // Range Minimum
1700                    0x0CF7,             // Range Maximum
1701                    0x0000,             // Translation Offset
1702                    0x0CF8,             // Length
1703                    ,, , TypeStatic, DenseTranslation)
1704                WordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
1705                    0x0000,             // Granularity
1706                    0x0D00,             // Range Minimum
1707                    0xFFFF,             // Range Maximum
1708                    0x0000,             // Translation Offset
1709                    0xF300,             // Length
1710                    ,, , TypeStatic, DenseTranslation)
1711                DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
1712                    0x00000000,         // Granularity
1713                    0x000A0000,         // Range Minimum
1714                    0x000BFFFF,         // Range Maximum
1715                    0x00000000,         // Translation Offset
1716                    0x00020000,         // Length
1717                    ,, , AddressRangeMemory, TypeStatic)
1718                DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
1719                    0x00000000,         // Granularity
1720                    0xC0000000,         // Range Minimum
1721                    0xFEBFFFFF,         // Range Maximum
1722                    0x00000000,         // Translation Offset
1723                    0x3EC00000,         // Length
1724                    ,, , AddressRangeMemory, TypeStatic)
1725                QWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
1726                    0x0000000000000000, // Granularity
1727                    0x0000000800000000, // Range Minimum
1728                    0x0000000FFFFFFFFF, // Range Maximum
1729                    0x0000000000000000, // Translation Offset
1730                    0x0000000800000000, // Length
1731                    ,, , AddressRangeMemory, TypeStatic)
1732            })
1733        */
1734
1735        // WordBusNumber from above
1736        let crs_word_bus_number = [
1737            0x08, 0x5F, 0x43, 0x52, 0x53, 0x11, 0x15, 0x0A, 0x12, 0x88, 0x0D, 0x00, 0x02, 0x0C,
1738            0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x01, 0x79, 0x00,
1739        ];
1740        aml.clear();
1741
1742        Name::new(
1743            "_CRS".into(),
1744            &ResourceTemplate::new(vec![&AddressSpace::new_bus_number(0x0u16, 0xffu16)]),
1745        )
1746        .to_aml_bytes(&mut aml);
1747        assert_eq!(aml, &crs_word_bus_number);
1748
1749        // WordIO blocks (x 2) from above
1750        let crs_word_io = [
1751            0x08, 0x5F, 0x43, 0x52, 0x53, 0x11, 0x25, 0x0A, 0x22, 0x88, 0x0D, 0x00, 0x01, 0x0C,
1752            0x03, 0x00, 0x00, 0x00, 0x00, 0xF7, 0x0C, 0x00, 0x00, 0xF8, 0x0C, 0x88, 0x0D, 0x00,
1753            0x01, 0x0C, 0x03, 0x00, 0x00, 0x00, 0x0D, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xF3, 0x79,
1754            0x00,
1755        ];
1756        aml.clear();
1757
1758        Name::new(
1759            "_CRS".into(),
1760            &ResourceTemplate::new(vec![
1761                &AddressSpace::new_io(0x0u16, 0xcf7u16),
1762                &AddressSpace::new_io(0xd00u16, 0xffffu16),
1763            ]),
1764        )
1765        .to_aml_bytes(&mut aml);
1766        assert_eq!(aml, &crs_word_io[..]);
1767
1768        // DWordMemory blocks (x 2) from above
1769        let crs_dword_memory = [
1770            0x08, 0x5F, 0x43, 0x52, 0x53, 0x11, 0x39, 0x0A, 0x36, 0x87, 0x17, 0x00, 0x00, 0x0C,
1771            0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0xFF, 0xFF, 0x0B, 0x00, 0x00,
1772            0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x87, 0x17, 0x00, 0x00, 0x0C, 0x01, 0x00,
1773            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0xBF, 0xFE, 0x00, 0x00, 0x00,
1774            0x00, 0x00, 0x00, 0xC0, 0x3E, 0x79, 0x00,
1775        ];
1776        aml.clear();
1777
1778        Name::new(
1779            "_CRS".into(),
1780            &ResourceTemplate::new(vec![
1781                &AddressSpace::new_memory(
1782                    AddressSpaceCachable::Cacheable,
1783                    true,
1784                    0xa_0000u32,
1785                    0xb_ffffu32,
1786                ),
1787                &AddressSpace::new_memory(
1788                    AddressSpaceCachable::NotCacheable,
1789                    true,
1790                    0xc000_0000u32,
1791                    0xfebf_ffffu32,
1792                ),
1793            ]),
1794        )
1795        .to_aml_bytes(&mut aml);
1796        assert_eq!(aml, &crs_dword_memory[..]);
1797
1798        // QWordMemory from above
1799        let crs_qword_memory = [
1800            0x08, 0x5F, 0x43, 0x52, 0x53, 0x11, 0x33, 0x0A, 0x30, 0x8A, 0x2B, 0x00, 0x00, 0x0C,
1801            0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
1802            0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1803            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x79,
1804            0x00,
1805        ];
1806        aml.clear();
1807        Name::new(
1808            "_CRS".into(),
1809            &ResourceTemplate::new(vec![&AddressSpace::new_memory(
1810                AddressSpaceCachable::Cacheable,
1811                true,
1812                0x8_0000_0000u64,
1813                0xf_ffff_ffffu64,
1814            )]),
1815        )
1816        .to_aml_bytes(&mut aml);
1817
1818        assert_eq!(aml, &crs_qword_memory[..]);
1819
1820        /*
1821            Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource Settings
1822            {
1823                Interrupt (ResourceConsumer, Edge, ActiveHigh, Exclusive, ,, )
1824                {
1825                    0x00000004,
1826                }
1827                IO (Decode16,
1828                    0x03F8,             // Range Minimum
1829                    0x03F8,             // Range Maximum
1830                    0x00,               // Alignment
1831                    0x08,               // Length
1832                    )
1833            })
1834
1835        */
1836        let interrupt_io_data = [
1837            0x08, 0x5F, 0x43, 0x52, 0x53, 0x11, 0x16, 0x0A, 0x13, 0x89, 0x06, 0x00, 0x03, 0x01,
1838            0x04, 0x00, 0x00, 0x00, 0x47, 0x01, 0xF8, 0x03, 0xF8, 0x03, 0x00, 0x08, 0x79, 0x00,
1839        ];
1840        aml.clear();
1841        Name::new(
1842            "_CRS".into(),
1843            &ResourceTemplate::new(vec![
1844                &Interrupt::new(true, true, false, false, 4),
1845                &IO::new(0x3f8, 0x3f8, 0, 0x8),
1846            ]),
1847        )
1848        .to_aml_bytes(&mut aml);
1849
1850        assert_eq!(aml, &interrupt_io_data[..]);
1851    }
1852
1853    #[test]
1854    fn test_pkg_length() {
1855        let mut pkg_len_62 = Vec::new();
1856        insert_pkg_length(&mut pkg_len_62, 0, 62);
1857        assert_eq!(pkg_len_62, [63]);
1858
1859        let mut pkg_len_64 = Vec::new();
1860        insert_pkg_length(&mut pkg_len_64, 0, 64);
1861        assert_eq!(pkg_len_64, [1 << 6 | (66 & 0xf), 66 >> 4]);
1862
1863        let mut pkg_len_4096 = Vec::new();
1864        insert_pkg_length(&mut pkg_len_4096, 0, 4096);
1865        assert_eq!(
1866            pkg_len_4096,
1867            [
1868                2 << 6 | (4099 & 0xf) as u8,
1869                (4099 >> 4) as u8,
1870                (4099 >> 12) as u8
1871            ]
1872        );
1873    }
1874
1875    #[test]
1876    fn test_package() {
1877        /*
1878        Name (_S5, Package (0x01)  // _S5_: S5 System State
1879        {
1880            0x05
1881        })
1882        */
1883        let s5_sleep_data = [0x08, 0x5F, 0x53, 0x35, 0x5F, 0x12, 0x04, 0x01, 0x0A, 0x05];
1884        let mut aml = Vec::new();
1885
1886        Name::new("_S5_".into(), &Package::new(vec![&5u8])).to_aml_bytes(&mut aml);
1887
1888        assert_eq!(s5_sleep_data.to_vec(), aml);
1889    }
1890
1891    #[test]
1892    fn test_eisa_name() {
1893        let mut aml = Vec::new();
1894        Name::new("_HID".into(), &EISAName::new("PNP0501")).to_aml_bytes(&mut aml);
1895        assert_eq!(
1896            aml,
1897            [0x08, 0x5F, 0x48, 0x49, 0x44, 0x0C, 0x41, 0xD0, 0x05, 0x01],
1898        )
1899    }
1900    #[test]
1901    fn test_name_path() {
1902        let mut aml = Vec::new();
1903        (&"_SB_".into() as &Path).to_aml_bytes(&mut aml);
1904        assert_eq!(aml, [0x5Fu8, 0x53, 0x42, 0x5F]);
1905        aml.clear();
1906        (&"\\_SB_".into() as &Path).to_aml_bytes(&mut aml);
1907        assert_eq!(aml, [0x5C, 0x5F, 0x53, 0x42, 0x5F]);
1908        aml.clear();
1909        (&"_SB_.COM1".into() as &Path).to_aml_bytes(&mut aml);
1910        assert_eq!(aml, [0x2E, 0x5F, 0x53, 0x42, 0x5F, 0x43, 0x4F, 0x4D, 0x31]);
1911        aml.clear();
1912        (&"_SB_.PCI0._HID".into() as &Path).to_aml_bytes(&mut aml);
1913        assert_eq!(
1914            aml,
1915            [0x2F, 0x03, 0x5F, 0x53, 0x42, 0x5F, 0x50, 0x43, 0x49, 0x30, 0x5F, 0x48, 0x49, 0x44]
1916        );
1917    }
1918
1919    #[test]
1920    fn test_numbers() {
1921        let mut aml = Vec::new();
1922        128u8.to_aml_bytes(&mut aml);
1923        assert_eq!(aml, [0x0a, 0x80]);
1924        aml.clear();
1925        1024u16.to_aml_bytes(&mut aml);
1926        assert_eq!(aml, [0x0b, 0x0, 0x04]);
1927        aml.clear();
1928        (16u32 << 20).to_aml_bytes(&mut aml);
1929        assert_eq!(aml, [0x0c, 0x00, 0x00, 0x0, 0x01]);
1930        aml.clear();
1931        0xdeca_fbad_deca_fbadu64.to_aml_bytes(&mut aml);
1932        assert_eq!(aml, [0x0e, 0xad, 0xfb, 0xca, 0xde, 0xad, 0xfb, 0xca, 0xde]);
1933        aml.clear();
1934
1935        // u8
1936        0x00_u8.to_aml_bytes(&mut aml);
1937        assert_eq!(aml, [0x00]);
1938        aml.clear();
1939        0x01_u8.to_aml_bytes(&mut aml);
1940        assert_eq!(aml, [0x01]);
1941        aml.clear();
1942        0x86_u8.to_aml_bytes(&mut aml);
1943        assert_eq!(aml, [0x0a, 0x86]);
1944        aml.clear();
1945
1946        // u16
1947        0x00_u16.to_aml_bytes(&mut aml);
1948        assert_eq!(aml, [0x00]);
1949        aml.clear();
1950        0x01_u16.to_aml_bytes(&mut aml);
1951        assert_eq!(aml, [0x01]);
1952        aml.clear();
1953        0x86_u16.to_aml_bytes(&mut aml);
1954        assert_eq!(aml, [0x0a, 0x86]);
1955        aml.clear();
1956        0xF00D_u16.to_aml_bytes(&mut aml);
1957        assert_eq!(aml, [0x0b, 0x0d, 0xf0]);
1958        aml.clear();
1959
1960        // u32
1961        0x00_u32.to_aml_bytes(&mut aml);
1962        assert_eq!(aml, [0x00]);
1963        aml.clear();
1964        0x01_u32.to_aml_bytes(&mut aml);
1965        assert_eq!(aml, [0x01]);
1966        aml.clear();
1967        0x86_u32.to_aml_bytes(&mut aml);
1968        assert_eq!(aml, [0x0a, 0x86]);
1969        aml.clear();
1970        0xF00D_u32.to_aml_bytes(&mut aml);
1971        assert_eq!(aml, [0x0b, 0x0d, 0xf0]);
1972        aml.clear();
1973        0xDECAF_u32.to_aml_bytes(&mut aml);
1974        assert_eq!(aml, [0x0c, 0xaf, 0xec, 0x0d, 0x00]);
1975        aml.clear();
1976
1977        // u64
1978        0x00_u64.to_aml_bytes(&mut aml);
1979        assert_eq!(aml, [0x00]);
1980        aml.clear();
1981        0x01_u64.to_aml_bytes(&mut aml);
1982        assert_eq!(aml, [0x01]);
1983        aml.clear();
1984        0x86_u64.to_aml_bytes(&mut aml);
1985        assert_eq!(aml, [0x0a, 0x86]);
1986        aml.clear();
1987        0xF00D_u64.to_aml_bytes(&mut aml);
1988        assert_eq!(aml, [0x0b, 0x0d, 0xf0]);
1989        aml.clear();
1990        0xDECAF_u64.to_aml_bytes(&mut aml);
1991        assert_eq!(aml, [0x0c, 0xaf, 0xec, 0x0d, 0x00]);
1992        aml.clear();
1993        0xDECAFC0FFEE_u64.to_aml_bytes(&mut aml);
1994        assert_eq!(aml, [0x0e, 0xee, 0xff, 0xc0, 0xaf, 0xec, 0x0d, 0x00, 0x00]);
1995        aml.clear();
1996
1997        // usize
1998        0x00_usize.to_aml_bytes(&mut aml);
1999        assert_eq!(aml, [0x00]);
2000        aml.clear();
2001        0x01_usize.to_aml_bytes(&mut aml);
2002        assert_eq!(aml, [0x01]);
2003        aml.clear();
2004        0x86_usize.to_aml_bytes(&mut aml);
2005        assert_eq!(aml, [0x0a, 0x86]);
2006        aml.clear();
2007        0xF00D_usize.to_aml_bytes(&mut aml);
2008        assert_eq!(aml, [0x0b, 0x0d, 0xf0]);
2009        aml.clear();
2010        0xDECAF_usize.to_aml_bytes(&mut aml);
2011        assert_eq!(aml, [0x0c, 0xaf, 0xec, 0x0d, 0x00]);
2012        aml.clear();
2013        #[cfg(target_pointer_width = "64")]
2014        {
2015            0xDECAFC0FFEE_usize.to_aml_bytes(&mut aml);
2016            assert_eq!(aml, [0x0e, 0xee, 0xff, 0xc0, 0xaf, 0xec, 0x0d, 0x00, 0x00]);
2017            aml.clear();
2018        }
2019    }
2020
2021    #[test]
2022    fn test_name() {
2023        let mut aml = Vec::new();
2024        Name::new("_SB_.PCI0._UID".into(), &0x1234u16).to_aml_bytes(&mut aml);
2025        assert_eq!(
2026            aml,
2027            [
2028                0x08, /* NameOp */
2029                0x2F, /* MultiNamePrefix */
2030                0x03, /* 3 name parts */
2031                0x5F, 0x53, 0x42, 0x5F, /* _SB_ */
2032                0x50, 0x43, 0x49, 0x30, /* PCI0 */
2033                0x5F, 0x55, 0x49, 0x44, /* _UID */
2034                0x0b, /* WordPrefix */
2035                0x34, 0x12
2036            ]
2037        );
2038    }
2039
2040    #[test]
2041    fn test_string() {
2042        let mut aml = Vec::new();
2043        (&"ACPI" as &dyn Aml).to_aml_bytes(&mut aml);
2044        assert_eq!(aml, [0x0d, b'A', b'C', b'P', b'I', 0]);
2045        aml.clear();
2046        "ACPI".to_owned().to_aml_bytes(&mut aml);
2047        assert_eq!(aml, [0x0d, b'A', b'C', b'P', b'I', 0]);
2048    }
2049
2050    #[test]
2051    fn test_method() {
2052        let mut aml = Vec::new();
2053        Method::new("_STA".into(), 0, false, vec![&Return::new(&0xfu8)]).to_aml_bytes(&mut aml);
2054        assert_eq!(
2055            aml,
2056            [0x14, 0x09, 0x5F, 0x53, 0x54, 0x41, 0x00, 0xA4, 0x0A, 0x0F]
2057        );
2058    }
2059
2060    #[test]
2061    fn test_field() {
2062        /*
2063            Field (PRST, ByteAcc, NoLock, WriteAsZeros)
2064            {
2065                Offset (0x04),
2066                CPEN,   1,
2067                CINS,   1,
2068                CRMV,   1,
2069                CEJ0,   1,
2070                Offset (0x05),
2071                CCMD,   8
2072            }
2073
2074        */
2075
2076        let field_data = [
2077            0x5Bu8, 0x81, 0x23, 0x50, 0x52, 0x53, 0x54, 0x41, 0x00, 0x20, 0x43, 0x50, 0x45, 0x4E,
2078            0x01, 0x43, 0x49, 0x4E, 0x53, 0x01, 0x43, 0x52, 0x4D, 0x56, 0x01, 0x43, 0x45, 0x4A,
2079            0x30, 0x01, 0x00, 0x04, 0x43, 0x43, 0x4D, 0x44, 0x08,
2080        ];
2081        let mut aml = Vec::new();
2082
2083        Field::new(
2084            "PRST".into(),
2085            FieldAccessType::Byte,
2086            FieldLockRule::NoLock,
2087            FieldUpdateRule::WriteAsZeroes,
2088            vec![
2089                FieldEntry::Reserved(32),
2090                FieldEntry::Named(*b"CPEN", 1),
2091                FieldEntry::Named(*b"CINS", 1),
2092                FieldEntry::Named(*b"CRMV", 1),
2093                FieldEntry::Named(*b"CEJ0", 1),
2094                FieldEntry::Reserved(4),
2095                FieldEntry::Named(*b"CCMD", 8),
2096            ],
2097        )
2098        .to_aml_bytes(&mut aml);
2099        assert_eq!(aml, &field_data[..]);
2100
2101        /*
2102            Field (PRST, DWordAcc, Lock, Preserve)
2103            {
2104                CSEL,   32,
2105                Offset (0x08),
2106                CDAT,   32
2107            }
2108        */
2109
2110        let field_data = [
2111            0x5Bu8, 0x81, 0x12, 0x50, 0x52, 0x53, 0x54, 0x13, 0x43, 0x53, 0x45, 0x4C, 0x20, 0x00,
2112            0x20, 0x43, 0x44, 0x41, 0x54, 0x20,
2113        ];
2114        aml.clear();
2115
2116        Field::new(
2117            "PRST".into(),
2118            FieldAccessType::DWord,
2119            FieldLockRule::Lock,
2120            FieldUpdateRule::Preserve,
2121            vec![
2122                FieldEntry::Named(*b"CSEL", 32),
2123                FieldEntry::Reserved(32),
2124                FieldEntry::Named(*b"CDAT", 32),
2125            ],
2126        )
2127        .to_aml_bytes(&mut aml);
2128        assert_eq!(aml, &field_data[..]);
2129    }
2130
2131    #[test]
2132    fn test_op_region() {
2133        /*
2134            OperationRegion (PRST, SystemIO, 0x0CD8, 0x0C)
2135        */
2136        let op_region_data = [
2137            0x5Bu8, 0x80, 0x50, 0x52, 0x53, 0x54, 0x01, 0x0B, 0xD8, 0x0C, 0x0A, 0x0C,
2138        ];
2139        let mut aml = Vec::new();
2140
2141        OpRegion::new(
2142            "PRST".into(),
2143            OpRegionSpace::SystemIO,
2144            &0xcd8_usize,
2145            &0xc_usize,
2146        )
2147        .to_aml_bytes(&mut aml);
2148        assert_eq!(aml, &op_region_data[..]);
2149    }
2150
2151    #[test]
2152    fn test_arg_if() {
2153        /*
2154            Method(TEST, 1, NotSerialized) {
2155                If (Arg0 == Zero) {
2156                        Return(One)
2157                }
2158                Return(Zero)
2159            }
2160        */
2161        let arg_if_data = [
2162            0x14, 0x0F, 0x54, 0x45, 0x53, 0x54, 0x01, 0xA0, 0x06, 0x93, 0x68, 0x00, 0xA4, 0x01,
2163            0xA4, 0x00,
2164        ];
2165        let mut aml = Vec::new();
2166
2167        Method::new(
2168            "TEST".into(),
2169            1,
2170            false,
2171            vec![
2172                &If::new(&Equal::new(&Arg(0), &ZERO), vec![&Return::new(&ONE)]),
2173                &Return::new(&ZERO),
2174            ],
2175        )
2176        .to_aml_bytes(&mut aml);
2177        assert_eq!(aml, &arg_if_data);
2178    }
2179
2180    #[test]
2181    fn test_local_if() {
2182        /*
2183            Method(TEST, 0, NotSerialized) {
2184                Local0 = One
2185                If (Local0 == Zero) {
2186                        Return(One)
2187                }
2188                Return(Zero)
2189            }
2190        */
2191        let local_if_data = [
2192            0x14, 0x12, 0x54, 0x45, 0x53, 0x54, 0x00, 0x70, 0x01, 0x60, 0xA0, 0x06, 0x93, 0x60,
2193            0x00, 0xA4, 0x01, 0xA4, 0x00,
2194        ];
2195        let mut aml = Vec::new();
2196
2197        Method::new(
2198            "TEST".into(),
2199            0,
2200            false,
2201            vec![
2202                &Store::new(&Local(0), &ONE),
2203                &If::new(&Equal::new(&Local(0), &ZERO), vec![&Return::new(&ONE)]),
2204                &Return::new(&ZERO),
2205            ],
2206        )
2207        .to_aml_bytes(&mut aml);
2208        assert_eq!(aml, &local_if_data);
2209    }
2210
2211    #[test]
2212    fn test_mutex() {
2213        /*
2214        Device (_SB_.MHPC)
2215        {
2216                Name (_HID, EisaId("PNP0A06") /* Generic Container Device */)  // _HID: Hardware ID
2217                Mutex (MLCK, 0x00)
2218                Method (TEST, 0, NotSerialized)
2219                {
2220                    Acquire (MLCK, 0xFFFF)
2221                    Local0 = One
2222                    Release (MLCK)
2223                }
2224        }
2225        */
2226
2227        let mutex_data = [
2228            0x5B, 0x82, 0x33, 0x2E, 0x5F, 0x53, 0x42, 0x5F, 0x4D, 0x48, 0x50, 0x43, 0x08, 0x5F,
2229            0x48, 0x49, 0x44, 0x0C, 0x41, 0xD0, 0x0A, 0x06, 0x5B, 0x01, 0x4D, 0x4C, 0x43, 0x4B,
2230            0x00, 0x14, 0x17, 0x54, 0x45, 0x53, 0x54, 0x00, 0x5B, 0x23, 0x4D, 0x4C, 0x43, 0x4B,
2231            0xFF, 0xFF, 0x70, 0x01, 0x60, 0x5B, 0x27, 0x4D, 0x4C, 0x43, 0x4B,
2232        ];
2233        let mut aml = Vec::new();
2234
2235        let mutex = Mutex::new("MLCK".into(), 0);
2236        Device::new(
2237            "_SB_.MHPC".into(),
2238            vec![
2239                &Name::new("_HID".into(), &EISAName::new("PNP0A06")),
2240                &mutex,
2241                &Method::new(
2242                    "TEST".into(),
2243                    0,
2244                    false,
2245                    vec![
2246                        &Acquire::new("MLCK".into(), 0xffff),
2247                        &Store::new(&Local(0), &ONE),
2248                        &Release::new("MLCK".into()),
2249                    ],
2250                ),
2251            ],
2252        )
2253        .to_aml_bytes(&mut aml);
2254        assert_eq!(aml, &mutex_data[..]);
2255    }
2256
2257    #[test]
2258    fn test_notify() {
2259        /*
2260        Device (_SB.MHPC)
2261        {
2262            Name (_HID, EisaId ("PNP0A06") /* Generic Container Device */)  // _HID: Hardware ID
2263            Method (TEST, 0, NotSerialized)
2264            {
2265                Notify (MHPC, One) // Device Check
2266            }
2267        }
2268        */
2269        let notify_data = [
2270            0x5B, 0x82, 0x21, 0x2E, 0x5F, 0x53, 0x42, 0x5F, 0x4D, 0x48, 0x50, 0x43, 0x08, 0x5F,
2271            0x48, 0x49, 0x44, 0x0C, 0x41, 0xD0, 0x0A, 0x06, 0x14, 0x0C, 0x54, 0x45, 0x53, 0x54,
2272            0x00, 0x86, 0x4D, 0x48, 0x50, 0x43, 0x01,
2273        ];
2274        let mut aml = Vec::new();
2275
2276        Device::new(
2277            "_SB_.MHPC".into(),
2278            vec![
2279                &Name::new("_HID".into(), &EISAName::new("PNP0A06")),
2280                &Method::new(
2281                    "TEST".into(),
2282                    0,
2283                    false,
2284                    vec![&Notify::new(&Path::new("MHPC"), &ONE)],
2285                ),
2286            ],
2287        )
2288        .to_aml_bytes(&mut aml);
2289        assert_eq!(aml, &notify_data[..]);
2290    }
2291
2292    #[test]
2293    fn test_while() {
2294        /*
2295        Device (_SB.MHPC)
2296        {
2297            Name (_HID, EisaId ("PNP0A06") /* Generic Container Device */)  // _HID: Hardware ID
2298            Method (TEST, 0, NotSerialized)
2299            {
2300                Local0 = Zero
2301                While ((Local0 < 0x04))
2302                {
2303                    Local0 += One
2304                }
2305            }
2306        }
2307        */
2308
2309        let while_data = [
2310            0x5B, 0x82, 0x28, 0x2E, 0x5F, 0x53, 0x42, 0x5F, 0x4D, 0x48, 0x50, 0x43, 0x08, 0x5F,
2311            0x48, 0x49, 0x44, 0x0C, 0x41, 0xD0, 0x0A, 0x06, 0x14, 0x13, 0x54, 0x45, 0x53, 0x54,
2312            0x00, 0x70, 0x00, 0x60, 0xA2, 0x09, 0x95, 0x60, 0x0A, 0x04, 0x72, 0x60, 0x01, 0x60,
2313        ];
2314        let mut aml = Vec::new();
2315
2316        Device::new(
2317            "_SB_.MHPC".into(),
2318            vec![
2319                &Name::new("_HID".into(), &EISAName::new("PNP0A06")),
2320                &Method::new(
2321                    "TEST".into(),
2322                    0,
2323                    false,
2324                    vec![
2325                        &Store::new(&Local(0), &ZERO),
2326                        &While::new(
2327                            &LessThan::new(&Local(0), &4usize),
2328                            vec![&Add::new(&Local(0), &Local(0), &ONE)],
2329                        ),
2330                    ],
2331                ),
2332            ],
2333        )
2334        .to_aml_bytes(&mut aml);
2335        assert_eq!(aml, &while_data[..])
2336    }
2337
2338    #[test]
2339    fn test_method_call() {
2340        /*
2341            Method (TST1, 1, NotSerialized)
2342            {
2343                TST2 (One, One)
2344            }
2345
2346            Method (TST2, 2, NotSerialized)
2347            {
2348                TST1 (One)
2349            }
2350        */
2351        let test_data = [
2352            0x14, 0x0C, 0x54, 0x53, 0x54, 0x31, 0x01, 0x54, 0x53, 0x54, 0x32, 0x01, 0x01, 0x14,
2353            0x0B, 0x54, 0x53, 0x54, 0x32, 0x02, 0x54, 0x53, 0x54, 0x31, 0x01,
2354        ];
2355
2356        let mut methods = Vec::new();
2357        Method::new(
2358            "TST1".into(),
2359            1,
2360            false,
2361            vec![&MethodCall::new("TST2".into(), vec![&ONE, &ONE])],
2362        )
2363        .to_aml_bytes(&mut methods);
2364        Method::new(
2365            "TST2".into(),
2366            2,
2367            false,
2368            vec![&MethodCall::new("TST1".into(), vec![&ONE])],
2369        )
2370        .to_aml_bytes(&mut methods);
2371        assert_eq!(&methods[..], &test_data[..])
2372    }
2373
2374    #[test]
2375    fn test_buffer() {
2376        /*
2377        Name (_MAT, Buffer (0x08)  // _MAT: Multiple APIC Table Entry
2378        {
2379            0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00   /* ........ */
2380        })
2381        */
2382        let buffer_data = [
2383            0x08, 0x5F, 0x4D, 0x41, 0x54, 0x11, 0x0B, 0x0A, 0x08, 0x00, 0x08, 0x00, 0x00, 0x01,
2384            0x00, 0x00, 0x00,
2385        ];
2386        let mut aml = Vec::new();
2387
2388        Name::new(
2389            "_MAT".into(),
2390            &BufferData::new(vec![0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00]),
2391        )
2392        .to_aml_bytes(&mut aml);
2393        assert_eq!(aml, &buffer_data[..])
2394    }
2395}