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, ¬ify_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