1use core::fmt;
2
3use alloc::vec::Vec;
4
5use crate::{acpi::aml::display::AmlDisplayer, io::ByteStr};
6
7use super::{AccessType, AmlParseError, Buffer, RegionSpace};
8
9#[allow(dead_code)]
10mod consts {
11 pub const END_TAG_FULL: u8 = 0x79;
12}
13
14pub struct Parser<'a> {
15 buffer: &'a [u8],
16 pos: usize,
17}
18
19impl Parser<'_> {
20 pub fn get_next_byte(&mut self) -> Result<u8, AmlParseError> {
21 if self.pos >= self.buffer.len() {
22 return Err(AmlParseError::UnexpectedEndOfCode);
23 }
24 let byte = self.buffer[self.pos];
25 self.pos += 1;
26 Ok(byte)
27 }
28
29 pub fn get_next_u16(&mut self) -> Result<u16, AmlParseError> {
30 let low = self.get_next_byte()? as u16;
31 let high = self.get_next_byte()? as u16;
32
33 Ok((high << 8) | low)
34 }
35
36 pub fn get_next_u32(&mut self) -> Result<u32, AmlParseError> {
37 Ok(u32::from_le_bytes([
38 self.get_next_byte()?,
39 self.get_next_byte()?,
40 self.get_next_byte()?,
41 self.get_next_byte()?,
42 ]))
43 }
44
45 pub fn get_next_u64(&mut self) -> Result<u64, AmlParseError> {
46 Ok(u64::from_le_bytes([
47 self.get_next_byte()?,
48 self.get_next_byte()?,
49 self.get_next_byte()?,
50 self.get_next_byte()?,
51 self.get_next_byte()?,
52 self.get_next_byte()?,
53 self.get_next_byte()?,
54 self.get_next_byte()?,
55 ]))
56 }
57
58 pub fn get_next_address_data<W: AddressWidth>(&mut self) -> Result<W, AmlParseError> {
59 W::from_parser(self)
60 }
61
62 pub fn get_inner(&mut self, len: usize) -> Result<Self, AmlParseError> {
63 if self.pos + len > self.buffer.len() {
64 return Err(AmlParseError::UnexpectedEndOfCode);
65 }
66
67 let buffer = &self.buffer[self.pos..self.pos + len];
68 self.pos += len;
69 Ok(Parser { buffer, pos: 0 })
70 }
71
72 pub fn get_remaining_data(&mut self) -> Result<&[u8], AmlParseError> {
73 if self.pos >= self.buffer.len() {
74 return Err(AmlParseError::UnexpectedEndOfCode);
75 }
76 self.pos = self.buffer.len();
77 Ok(&self.buffer[self.pos..])
78 }
79
80 pub fn is_done(&self) -> bool {
81 self.pos >= self.buffer.len()
82 }
83}
84
85#[derive(Debug, Clone)]
86pub enum DmaSpeedType {
87 Compatibility,
88 TypeA,
89 TypeB,
90 TypeF,
91}
92
93#[derive(Debug, Clone)]
94pub enum DmaTrasferType {
95 Transfer8,
96 Transfer16,
97 Transfer8_16,
98}
99
100#[derive(Debug, Clone)]
101#[allow(clippy::enum_variant_names)]
102pub enum DmaTransferWidth {
103 Width8Bit,
104 Width16Bit,
105 Width32Bit,
106 Width64Bit,
107 Width128Bit,
108 Width256Bit,
109}
110
111#[derive(Debug, Clone)]
112pub enum SpaceMemoryType {
113 NonCacheable,
114 Cacheable,
115 WriteCombining,
116 Prefetchable,
118}
119
120#[derive(Debug, Clone)]
121pub enum SpaceMemoryRangeType {
122 AddressRangeMemory,
123 AddressRangeReserved,
124 AddressRangeACPI,
125 AddressRangeNVS,
126}
127
128#[derive(Debug, Clone)]
129pub enum SpaceIoRangeType {
130 NonISAOnlyRanges,
131 ISAOnlyRanges,
132 EntireRange,
133}
134
135#[derive(Debug, Clone)]
136pub enum AddressSpaceType {
137 Memory {
138 is_read_write: bool,
139 ty: SpaceMemoryType,
140 range_ty: SpaceMemoryRangeType,
141 is_type_translation: bool,
142 },
143 Io {
144 is_type_translation: bool,
145 range_ty: SpaceIoRangeType,
146 is_sparse_translation: bool,
147 },
148 BusNumber,
149 VendorDefined {
150 value: u8,
151 flags: u8,
152 },
153}
154
155impl AddressSpaceType {
156 pub fn parse<W: AddressWidth>(value: u8, flags: u8) -> Result<Self, AmlParseError> {
157 let result = match (W::width(), value) {
158 (_, 0) => {
159 let is_read_write = flags & 1 != 0;
160 let ty = match (flags >> 1) & 0b11 {
161 0 => SpaceMemoryType::NonCacheable,
162 1 => SpaceMemoryType::Cacheable,
163 2 => SpaceMemoryType::WriteCombining,
164 3 => SpaceMemoryType::Prefetchable,
165 _ => unreachable!(),
166 };
167 let range_ty = match (flags >> 3) & 0b11 {
168 0 => SpaceMemoryRangeType::AddressRangeMemory,
169 1 => SpaceMemoryRangeType::AddressRangeReserved,
170 2 => SpaceMemoryRangeType::AddressRangeACPI,
171 3 => SpaceMemoryRangeType::AddressRangeNVS,
172 _ => unreachable!(),
173 };
174 let is_type_translation = (flags >> 5) & 1 != 0;
175
176 Self::Memory {
177 is_read_write,
178 ty,
179 range_ty,
180 is_type_translation,
181 }
182 }
183 (_, 1) => {
184 let range_ty = match flags & 0b11 {
185 0 => return Err(AmlParseError::ReservedValue),
186 1 => SpaceIoRangeType::NonISAOnlyRanges,
187 2 => SpaceIoRangeType::ISAOnlyRanges,
188 3 => SpaceIoRangeType::EntireRange,
189 _ => unreachable!(),
190 };
191 let is_type_translation = (flags >> 4) & 1 != 0;
192 let is_sparse_translation = (flags >> 5) & 1 != 0;
193
194 Self::Io {
195 is_type_translation,
196 range_ty,
197 is_sparse_translation,
198 }
199 }
200 (2, 2) => Self::BusNumber,
202 (_, 192..=255) => Self::VendorDefined { value, flags },
203 _ => return Err(AmlParseError::ReservedValue),
204 };
205
206 Ok(result)
207 }
208}
209
210#[derive(Debug, Clone)]
211pub enum ResourceSourceOrTypeSpecificAttrs {
212 ResourceSource(ResourceSource),
213 TypeSpecificAttrs(u64),
214}
215
216#[derive(Debug, Clone)]
217pub struct AddressSpace<W: AddressWidth> {
218 ty: AddressSpaceType,
219 is_consumer: bool,
220 is_max_fixed: bool,
221 is_min_fixed: bool,
222 is_subtract_decode: bool,
223 granularity: W,
224 min: W,
225 max: W,
226 translation_offset: W,
227 len: W,
228 extra: ResourceSourceOrTypeSpecificAttrs,
229}
230
231impl<W: AddressWidth> AddressSpace<W> {
232 fn parse_address_ranges_nums(parser: &mut Parser) -> Result<(W, W, W, W, W), AmlParseError> {
233 let granularity = parser.get_next_address_data::<W>()?;
234 let min = parser.get_next_address_data::<W>()?;
235 let max = parser.get_next_address_data::<W>()?;
236 let translation_offset = parser.get_next_address_data::<W>()?;
237 let len = parser.get_next_address_data::<W>()?;
238
239 Ok((granularity, min, max, translation_offset, len))
240 }
241
242 fn parse_start_flags(
243 parser: &mut Parser,
244 ) -> Result<(AddressSpaceType, bool, bool, bool, bool), AmlParseError> {
245 let ty_byte = parser.get_next_byte()?;
246 let flags = parser.get_next_byte()?;
247 let ty_flags = parser.get_next_byte()?;
248
249 let ty = AddressSpaceType::parse::<W>(ty_byte, ty_flags)?;
250 let is_max_fixed = flags & (1 << 3) != 0;
251 let is_min_fixed = flags & (1 << 2) != 0;
252 let is_subtract_decode = flags & (1 << 1) != 0;
253 let is_consumer = flags & 1 != 0;
254
255 Ok((
256 ty,
257 is_consumer,
258 is_max_fixed,
259 is_min_fixed,
260 is_subtract_decode,
261 ))
262 }
263
264 pub fn parse(parser: &mut Parser) -> Result<Self, AmlParseError> {
265 let (ty, is_consumer, is_max_fixed, is_min_fixed, is_subtract_decode) =
266 Self::parse_start_flags(parser)?;
267 let (granularity, min, max, translation_offset, len) =
268 Self::parse_address_ranges_nums(parser)?;
269
270 let resource_source = ResourceSource::parse(parser)?;
271
272 Ok(Self {
273 ty,
274 is_consumer,
275 is_max_fixed,
276 is_min_fixed,
277 is_subtract_decode,
278 granularity,
279 min,
280 max,
281 translation_offset,
282 len,
283 extra: ResourceSourceOrTypeSpecificAttrs::ResourceSource(resource_source),
284 })
285 }
286
287 pub fn parse_extended(parser: &mut Parser) -> Result<Self, AmlParseError> {
288 assert_eq!(W::width(), 8, "only support 64-bit address space");
289 let (ty, is_consumer, is_max_fixed, is_min_fixed, is_subtract_decode) =
290 Self::parse_start_flags(parser)?;
291
292 let revision = parser.get_next_byte()?;
293 assert_eq!(revision, 1, "only support revision 1");
294 let reserved = parser.get_next_byte()?;
295 if reserved != 0 {
296 return Err(AmlParseError::ReservedValue);
297 }
298
299 let (granularity, min, max, translation_offset, len) =
300 Self::parse_address_ranges_nums(parser)?;
301
302 let type_specific_attribute = parser.get_next_u64()?;
303
304 Ok(Self {
305 ty,
306 is_consumer,
307 is_max_fixed,
308 is_min_fixed,
309 is_subtract_decode,
310 granularity,
311 min,
312 max,
313 translation_offset,
314 len,
315 extra: ResourceSourceOrTypeSpecificAttrs::TypeSpecificAttrs(type_specific_attribute),
316 })
317 }
318}
319
320#[derive(Debug, Clone)]
321pub struct ResourceSource {
322 index: Option<u8>,
323 source: Option<Vec<u8>>,
324}
325
326impl ResourceSource {
327 fn empty() -> Self {
328 Self {
329 index: None,
330 source: None,
331 }
332 }
333
334 fn parse(parser: &mut Parser) -> Result<Self, AmlParseError> {
335 let index = if !parser.is_done() {
336 Some(parser.get_next_byte()?)
337 } else {
338 None
339 };
340
341 let source = if !parser.is_done() {
342 Some(parser.get_remaining_data()?.to_vec())
343 } else {
344 None
345 };
346
347 Ok(Self { index, source })
348 }
349
350 fn display<'a, 'b, 'r>(&self, d: &'r mut AmlDisplayer<'a, 'b>) -> &'r mut AmlDisplayer<'a, 'b> {
351 d.paren_arg(|f| {
352 if let Some(index) = self.index {
353 write!(f, "{index}")
354 } else {
355 Ok(())
356 }
357 });
358 d.paren_arg(|f| {
359 if let Some(source) = &self.source {
360 write!(f, "{:?}", ByteStr(source))
361 } else {
362 Ok(())
363 }
364 });
365
366 d
367 }
368}
369
370#[derive(Debug, Clone)]
371pub enum ResourceMacro {
372 Irq {
373 wake_capable: bool,
374 is_shared: bool,
375 active_low: bool,
376 edge_triggered: bool,
377 irqs_mask: u16,
378 },
379 Dma {
380 speed_ty: DmaSpeedType,
381 is_bus_master: bool,
382 transfer_type: DmaTrasferType,
383 channels_mask: u8,
384 },
385 StartDependentFunctions {
386 compatibility_priority: u8,
387 performance_priority: u8,
388 },
389 EndDependentFunctions,
390 Io {
391 is_16_bit_decode: bool,
392 min_addr: u16,
393 max_addr: u16,
394 alignment: u8,
395 len: u8,
396 },
397 FixedIo {
398 base: u16,
399 len: u8,
400 },
401 FixedDma {
402 dma_req: u16,
403 channel: u16,
404 transfer_width: DmaTransferWidth,
405 },
406 VendorShort {
407 data: [u8; 6],
408 len: u8,
409 },
410 VendorLarge {
411 data: Vec<u8>,
412 },
413 Memory24 {
414 is_read_write: bool,
415 min_addr: u32,
416 max_addr: u32,
417 alignment: u16,
418 len: u16,
419 },
420 Memory32Fixed {
421 is_read_write: bool,
422 base_addr: u32,
423 len: u32,
424 },
425 Memory32 {
426 is_read_write: bool,
427 min_addr: u32,
428 max_addr: u32,
429 alignment: u32,
430 len: u32,
431 },
432 Interrupt {
433 is_consumer: bool,
434 edge_triggered: bool,
435 active_low: bool,
436 is_shared: bool,
437 wake_capable: bool,
438 interrupts: Vec<u32>,
439 resource_source: ResourceSource,
440 },
441 Register {
442 address_space: RegionSpace,
443 bit_width: u8,
444 offset: u8,
445 address: u64,
446 access_size: AccessType,
447 },
448 AddressSpaceWord(AddressSpace<u16>),
449 AddressSpaceDWord(AddressSpace<u32>),
450 AddressSpaceQWord(AddressSpace<u64>),
451 AddressSpaceExtended(AddressSpace<u64>),
452}
453
454impl ResourceMacro {
455 fn try_parse_small_resource(
456 parser: &mut Parser,
457 first: u8,
458 ) -> Result<Option<Self>, AmlParseError> {
459 let result = match first {
460 0x22 | 0x23 => {
461 let contain_info = first == 0x23;
463
464 let irqs_mask = parser.get_next_u16()?;
465
466 let mut wake_capable = false;
467 let mut is_shared = false;
468 let mut active_low = false;
469 let mut edge_triggered = true;
470
471 if contain_info {
472 let flags = parser.get_next_byte()?;
473 edge_triggered = flags & 1 != 0;
474 active_low = flags & (1 << 3) != 0;
475 is_shared = flags & (1 << 4) != 0;
476 wake_capable = flags & (1 << 5) != 0;
477
478 if flags & (0b11 << 6) != 0 {
479 return Err(AmlParseError::ReservedFieldSet);
480 }
481 }
482
483 Some(ResourceMacro::Irq {
484 wake_capable,
485 is_shared,
486 active_low,
487 edge_triggered,
488 irqs_mask,
489 })
490 }
491 0x2A => {
492 let channels_mask = parser.get_next_byte()?;
494 let flags = parser.get_next_byte()?;
495
496 if flags & 0x80 != 0 {
497 return Err(AmlParseError::ReservedFieldSet);
498 }
499
500 let transfer_type = match flags & 0b11 {
501 0b00 => DmaTrasferType::Transfer8,
502 0b01 => DmaTrasferType::Transfer8_16,
503 0b10 => DmaTrasferType::Transfer16,
504 _ => return Err(AmlParseError::ReservedFieldSet),
505 };
506 let is_bus_master = (flags >> 2) & 1 == 1;
507 let speed_ty = match (flags >> 5) & 0b11 {
508 0b00 => DmaSpeedType::Compatibility,
509 0b01 => DmaSpeedType::TypeA,
510 0b10 => DmaSpeedType::TypeB,
511 0b11 => DmaSpeedType::TypeF,
512 _ => unreachable!(),
513 };
514
515 Some(ResourceMacro::Dma {
516 speed_ty,
517 is_bus_master,
518 transfer_type,
519 channels_mask,
520 })
521 }
522 0x30 | 0x31 => {
523 let contain_priority_byte = first == 0x31;
524
525 let mut compatibility_priority = 1;
526 let mut performance_priority = 1;
527
528 if contain_priority_byte {
529 let flags = parser.get_next_byte()?;
530 compatibility_priority = flags & 0b11;
531 performance_priority = (flags >> 2) & 0b11;
532
533 if flags & (0b1111 << 4) != 0 {
534 return Err(AmlParseError::ReservedFieldSet);
535 }
536 }
537
538 Some(ResourceMacro::StartDependentFunctions {
539 compatibility_priority,
540 performance_priority,
541 })
542 }
543 0x38 => Some(ResourceMacro::EndDependentFunctions),
544 0x47 => {
545 let flags = parser.get_next_byte()?;
546 let min_addr = parser.get_next_u16()?;
547 let max_addr = parser.get_next_u16()?;
548 let alignment = parser.get_next_byte()?;
549 let len = parser.get_next_byte()?;
550
551 Some(ResourceMacro::Io {
552 is_16_bit_decode: flags & 1 == 1,
553 min_addr,
554 max_addr,
555 alignment,
556 len,
557 })
558 }
559 0x4B => {
560 let base = parser.get_next_u16()? & 0x3FF;
561 let len = parser.get_next_byte()?;
562
563 Some(ResourceMacro::FixedIo { base, len })
564 }
565 0x55 => {
566 let dma_req = parser.get_next_u16()?;
567 let channel = parser.get_next_u16()?;
568
569 let transfer_width = match parser.get_next_byte()? {
570 0 => DmaTransferWidth::Width8Bit,
571 1 => DmaTransferWidth::Width16Bit,
572 2 => DmaTransferWidth::Width32Bit,
573 3 => DmaTransferWidth::Width64Bit,
574 4 => DmaTransferWidth::Width128Bit,
575 5 => DmaTransferWidth::Width256Bit,
576 _ => return Err(AmlParseError::ReservedFieldSet),
577 };
578
579 Some(ResourceMacro::FixedDma {
580 dma_req,
581 channel,
582 transfer_width,
583 })
584 }
585 0x71..=0x77 => {
586 let len = (first & 0b111) - 1;
587
588 let mut data = [0; 6];
589
590 for d in data.iter_mut().take(len as usize) {
591 *d = parser.get_next_byte()?;
592 }
593
594 Some(ResourceMacro::VendorShort { data, len })
595 }
596 0x79 => {
597 return Err(AmlParseError::ResourceTemplateReservedTag);
598 }
599 _ => None,
600 };
601
602 Ok(result)
603 }
604
605 fn try_parse_large_resource(
606 parser: &mut Parser,
607 first: u8,
608 ) -> Result<Option<Self>, AmlParseError> {
609 if first & 0x80 != 0x80 {
610 return Ok(None);
611 }
612
613 let data_len = parser.get_next_u16()?;
614
615 let mut parser = parser.get_inner(data_len as usize)?;
616
617 let result = match first & 0x7F {
618 0x00 | 0x03 | 0x13..=0x7F => {
619 return Err(AmlParseError::ResourceTemplateReservedTag);
620 }
621 0x01 => {
622 assert_eq!(data_len, 9);
623 let flags = parser.get_next_byte()?;
624
625 let min_addr = parser.get_next_u16()?;
626 let max_addr = parser.get_next_u16()?;
627 let alignment = parser.get_next_u16()?;
628 let len = parser.get_next_u16()?;
629
630 Some(ResourceMacro::Memory24 {
631 is_read_write: flags & 1 == 1,
632 min_addr: (min_addr as u32) << 8,
633 max_addr: (max_addr as u32) << 8,
634 alignment,
635 len,
636 })
637 }
638 0x02 => {
639 assert_eq!(data_len, 12);
640 let mut address_space = parser.get_next_byte()?.into();
641
642 if let RegionSpace::Other(other) = address_space {
643 if other == 0x7F {
644 address_space = RegionSpace::FFixedHW;
645 } else {
646 return Err(AmlParseError::ReservedFieldSet);
647 }
648 }
649 let bit_width = parser.get_next_byte()?;
650 let offset = parser.get_next_byte()?;
651 let access_size = parser.get_next_byte()?.try_into()?;
652 let address = parser.get_next_u64()?;
653
654 if let AccessType::Buffer = access_size {
655 return Err(AmlParseError::ReservedFieldSet);
656 }
657
658 Some(ResourceMacro::Register {
659 address_space,
660 bit_width,
661 offset,
662 address,
663 access_size,
664 })
665 }
666 0x04 => Some(ResourceMacro::VendorLarge {
667 data: parser.get_remaining_data()?.to_vec(),
668 }),
669 0x05 => {
670 assert_eq!(data_len, 17);
671 let flags = parser.get_next_byte()?;
672
673 let min_addr = parser.get_next_u32()?;
674 let max_addr = parser.get_next_u32()?;
675 let alignment = parser.get_next_u32()?;
676 let len = parser.get_next_u32()?;
677
678 Some(ResourceMacro::Memory32 {
679 is_read_write: flags & 1 == 1,
680 min_addr,
681 max_addr,
682 alignment,
683 len,
684 })
685 }
686 0x06 => {
687 assert_eq!(data_len, 9);
688 let flags = parser.get_next_byte()?;
689
690 let base_addr = parser.get_next_u32()?;
691 let len = parser.get_next_u32()?;
692
693 Some(ResourceMacro::Memory32Fixed {
694 is_read_write: flags & 1 == 1,
695 base_addr,
696 len,
697 })
698 }
699 0x07 => {
700 assert!(data_len >= 23);
701 Some(ResourceMacro::AddressSpaceDWord(
702 AddressSpace::<u32>::parse(&mut parser)?,
703 ))
704 }
705 0x08 => {
706 assert!(data_len >= 13);
707 Some(ResourceMacro::AddressSpaceWord(AddressSpace::<u16>::parse(
708 &mut parser,
709 )?))
710 }
711 0x09 => {
712 assert!(data_len >= 6);
713
714 let flags = parser.get_next_byte()?;
715 let is_consumed = flags & 1 != 0;
716 let edge_triggered = flags & (1 << 1) != 0;
717 let active_low = flags & (1 << 2) != 0;
718 let is_shared = flags & (1 << 3) != 0;
719 let wake_capable = flags & (1 << 4) != 0;
720
721 let table_len = parser.get_next_byte()?;
722
723 let mut interrupts = Vec::with_capacity(table_len as usize);
724 for _ in 0..table_len {
725 interrupts.push(parser.get_next_u32()?);
726 }
727
728 let resource_source = ResourceSource::parse(&mut parser)?;
729
730 Some(ResourceMacro::Interrupt {
731 is_consumer: is_consumed,
732 edge_triggered,
733 active_low,
734 is_shared,
735 wake_capable,
736 interrupts,
737 resource_source,
738 })
739 }
740 0x0A => {
741 assert!(data_len >= 43);
742 Some(ResourceMacro::AddressSpaceQWord(
743 AddressSpace::<u64>::parse(&mut parser)?,
744 ))
745 }
746 0x0B => {
747 assert!(data_len >= 53);
748 Some(ResourceMacro::AddressSpaceExtended(
749 AddressSpace::<u64>::parse_extended(&mut parser)?,
750 ))
751 }
752 _ => None,
754 };
755
756 if result.is_some() && !parser.is_done() {
758 return Err(AmlParseError::InvalidResourceTemplate);
759 }
760
761 Ok(result)
762 }
763
764 pub fn try_parse_buffer(parser: &mut Parser) -> Result<Option<Self>, AmlParseError> {
765 let first = parser.get_next_byte()?;
766
767 if let Some(result) = Self::try_parse_small_resource(parser, first)? {
768 return Ok(Some(result));
769 };
770
771 Self::try_parse_large_resource(parser, first)
772 }
773}
774
775#[derive(Debug, Clone)]
776pub struct ResourceTemplate {
777 pub(super) items: Vec<ResourceMacro>,
778}
779
780impl ResourceTemplate {
781 pub fn try_parse_buffer(buf: &Buffer) -> Result<Option<Self>, AmlParseError> {
782 let data = buf.data.as_slice();
783 {
785 if data.len() < 2 || data[data.len() - 2] != consts::END_TAG_FULL {
786 return Ok(None);
787 }
788
789 let sum: u8 = buf.data.iter().fold(0, |a, b| a.wrapping_add(*b));
790 if sum != 0 && data.last() != Some(&0) {
792 return Ok(None);
793 }
794 }
795
796 let data = &data[0..buf.data.len() - 2];
797
798 let mut parser = Parser {
799 buffer: data,
800 pos: 0,
801 };
802
803 let mut items = Vec::new();
804 while !parser.is_done() {
805 let Some(item) = ResourceMacro::try_parse_buffer(&mut parser)? else {
806 return Ok(None);
807 };
808
809 items.push(item);
810 }
811
812 Ok(Some(ResourceTemplate { items }))
813 }
814}
815
816pub trait AddressWidth {
817 fn width() -> u8
818 where
819 Self: Sized;
820 fn fmt_hex(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result;
821 fn from_parser(parser: &mut Parser) -> Result<Self, AmlParseError>
822 where
823 Self: Sized;
824}
825
826impl AddressWidth for u16 {
827 fn width() -> u8 {
828 2
829 }
830
831 fn fmt_hex(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
832 write!(f, "0x{self:04X}")
833 }
834
835 fn from_parser(parser: &mut Parser) -> Result<Self, AmlParseError> {
836 parser.get_next_u16()
837 }
838}
839
840impl AddressWidth for u32 {
841 fn width() -> u8 {
842 4
843 }
844
845 fn fmt_hex(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
846 write!(f, "0x{self:08X}")
847 }
848
849 fn from_parser(parser: &mut Parser) -> Result<Self, AmlParseError> {
850 parser.get_next_u32()
851 }
852}
853
854impl AddressWidth for u64 {
855 fn width() -> u8 {
856 8
857 }
858
859 fn fmt_hex(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
860 write!(f, "0x{self:016X}")
861 }
862
863 fn from_parser(parser: &mut Parser) -> Result<Self, AmlParseError> {
864 parser.get_next_u64()
865 }
866}
867
868#[allow(clippy::too_many_arguments)]
869fn display_interrupt_args<'a, 'b, 'r>(
870 d: &'r mut AmlDisplayer<'a, 'b>,
871 is_consumer: Option<bool>,
872 wake_capable: bool,
873 is_shared: bool,
874 active_low: bool,
875 edge_triggered: bool,
876 resource_source: &ResourceSource,
877) -> &'r mut AmlDisplayer<'a, 'b> {
878 if let Some(is_consumer) = is_consumer {
879 d.paren_arg(|f| {
880 f.write_str(if is_consumer {
881 "ResourceConsumer"
882 } else {
883 "ResourceProducer"
884 })
885 });
886 }
887
888 d.paren_arg(|f| f.write_str(if edge_triggered { "Edge" } else { "Level" }))
889 .paren_arg(|f| {
890 f.write_str(if active_low {
891 "ActiveLow"
892 } else {
893 "ActiveHigh"
894 })
895 })
896 .paren_arg(|f| {
897 f.write_str(if is_shared { "Shared" } else { "Exclusive" })?;
898 if wake_capable {
899 f.write_str("WakeCapable")
900 } else {
901 Ok(())
902 }
903 });
904
905 resource_source.display(d);
906
907 d
908}
909
910fn display_memory_args<'a, 'b>(
911 f: &'a mut fmt::Formatter<'b>,
912 name: &str,
913 is_read_write: bool,
914 nums: &[&dyn AddressWidth],
915) -> AmlDisplayer<'a, 'b> {
916 let mut d = AmlDisplayer::start(f, name);
917
918 d.paren_arg(|f| {
919 f.write_str(if is_read_write {
920 "ReadWrite"
921 } else {
922 "ReadOnly"
923 })
924 });
925
926 for num in nums {
927 d.paren_arg(|f| num.fmt_hex(f));
928 }
929
930 d
931}
932
933impl fmt::Display for SpaceMemoryRangeType {
934 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
935 fmt::Debug::fmt(self, f)
936 }
937}
938
939impl fmt::Display for SpaceIoRangeType {
940 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
941 fmt::Debug::fmt(self, f)
942 }
943}
944
945impl fmt::Display for SpaceMemoryType {
946 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
947 fmt::Debug::fmt(self, f)
948 }
949}
950
951impl<W: AddressWidth> fmt::Display for AddressSpace<W> {
952 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
953 let width_name = match W::width() {
954 2 => "Word",
955 4 => "DWord",
956 8 => "QWord",
957 _ => unreachable!(),
958 };
959 let space_name = match self.ty {
960 AddressSpaceType::Memory { .. } => "Memory",
961 AddressSpaceType::Io { .. } => "IO",
962 AddressSpaceType::BusNumber => "BusNumber",
963 AddressSpaceType::VendorDefined { .. } => "Space",
964 };
965 let write_min_fixed = |f: &mut fmt::Formatter<'_>| {
966 if self.is_min_fixed {
967 f.write_str("MinFixed")
968 } else {
969 f.write_str("MinNotFixed")
970 }
971 };
972 let write_max_fixed = |f: &mut fmt::Formatter<'_>| {
973 if self.is_max_fixed {
974 f.write_str("MaxFixed")
975 } else {
976 f.write_str("MaxNotFixed")
977 }
978 };
979 let write_decode = |f: &mut fmt::Formatter<'_>| {
980 if self.is_subtract_decode {
981 f.write_str("SubDecode")
982 } else {
983 f.write_str("PosDecode")
984 }
985 };
986
987 f.write_str(width_name)?;
988 f.write_str(space_name)?;
989 let mut d = AmlDisplayer::start(f, "");
990
991 if let AddressSpaceType::VendorDefined { value, .. } = self.ty {
992 d.paren_arg(|f| write!(f, "0x{value:02X}"));
993 }
994 d.paren_arg(|f| {
995 f.write_str(if self.is_consumer {
996 "ResourceConsumer"
997 } else {
998 "ResourceProducer"
999 })
1000 });
1001
1002 match &self.ty {
1003 AddressSpaceType::Memory {
1004 is_read_write, ty, ..
1005 } => {
1006 d.paren_arg(write_decode);
1007 d.paren_arg(write_min_fixed);
1008 d.paren_arg(write_max_fixed);
1009 d.paren_arg(|f| ty.fmt(f));
1010 d.paren_arg(|f| {
1011 f.write_str(if *is_read_write {
1012 "ReadWrite"
1013 } else {
1014 "ReadOnly"
1015 })
1016 });
1017 }
1018 AddressSpaceType::Io { range_ty, .. } => {
1019 d.paren_arg(write_min_fixed);
1020 d.paren_arg(write_max_fixed);
1021 d.paren_arg(write_decode);
1022 d.paren_arg(|f| range_ty.fmt(f));
1023 }
1024 AddressSpaceType::BusNumber => {
1025 d.paren_arg(write_min_fixed);
1026 d.paren_arg(write_max_fixed);
1027 d.paren_arg(write_decode);
1028 }
1029 AddressSpaceType::VendorDefined { flags, .. } => {
1030 d.paren_arg(write_decode);
1031 d.paren_arg(write_min_fixed);
1032 d.paren_arg(write_max_fixed);
1033 d.paren_arg(|f| write!(f, "0x{flags:02X}"));
1034 }
1035 }
1036
1037 d.paren_arg(|f| self.granularity.fmt_hex(f));
1038 d.paren_arg(|f| self.min.fmt_hex(f));
1039 d.paren_arg(|f| self.max.fmt_hex(f));
1040 d.paren_arg(|f| self.translation_offset.fmt_hex(f));
1041 d.paren_arg(|f| self.len.fmt_hex(f));
1042
1043 match &self.extra {
1044 ResourceSourceOrTypeSpecificAttrs::ResourceSource(resource_source) => {
1045 resource_source.display(&mut d);
1046 }
1047 ResourceSourceOrTypeSpecificAttrs::TypeSpecificAttrs(type_attrs) => {
1048 d.paren_arg(|f| write!(f, "0x{type_attrs:8X}"));
1049 }
1050 }
1051
1052 match &self.ty {
1053 AddressSpaceType::Memory {
1054 range_ty,
1055 is_type_translation,
1056 ..
1057 } => {
1058 d.paren_arg(|f| range_ty.fmt(f));
1059 d.paren_arg(|f| {
1060 f.write_str(if *is_type_translation {
1061 "TypeTranslation"
1062 } else {
1063 "TypeStatic"
1064 })
1065 });
1066 }
1067 AddressSpaceType::Io {
1068 is_type_translation,
1069 is_sparse_translation,
1070 ..
1071 } => {
1072 d.paren_arg(|f| {
1073 f.write_str(if *is_type_translation {
1074 "TypeTranslation"
1075 } else {
1076 "TypeStatic"
1077 })
1078 });
1079 d.paren_arg(|f| {
1080 f.write_str(if *is_sparse_translation {
1081 "SparseTranslation"
1082 } else {
1083 "DenseTranslation"
1084 })
1085 });
1086 }
1087 AddressSpaceType::BusNumber | AddressSpaceType::VendorDefined { .. } => {}
1088 }
1089
1090 d.finish()
1091 }
1092}
1093
1094impl fmt::Display for DmaSpeedType {
1095 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1096 fmt::Debug::fmt(self, f)
1097 }
1098}
1099
1100impl fmt::Display for DmaTrasferType {
1101 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1102 fmt::Debug::fmt(self, f)
1103 }
1104}
1105
1106impl fmt::Display for DmaTransferWidth {
1107 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1108 fmt::Debug::fmt(self, f)
1109 }
1110}
1111
1112impl fmt::Display for ResourceMacro {
1113 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1114 match self {
1115 ResourceMacro::Irq {
1116 wake_capable,
1117 is_shared,
1118 active_low,
1119 edge_triggered,
1120 irqs_mask,
1121 } => {
1122 let mut d = AmlDisplayer::start(f, "IRQ");
1123 display_interrupt_args(
1124 &mut d,
1125 None,
1126 *wake_capable,
1127 *is_shared,
1128 *active_low,
1129 *edge_triggered,
1130 &ResourceSource::empty(),
1131 )
1132 .finish_paren_arg()
1133 .set_list(true);
1134
1135 for i in 0..15 {
1136 if irqs_mask & (1 << i) != 0 {
1137 d.body_field(|f| write!(f, "{i}"));
1138 }
1139 }
1140
1141 d.at_least_empty_body().finish()
1142 }
1143 ResourceMacro::Dma {
1144 speed_ty,
1145 is_bus_master,
1146 transfer_type,
1147 channels_mask,
1148 } => {
1149 let mut d = AmlDisplayer::start(f, "DMA");
1150 d.paren_arg(|f| speed_ty.fmt(f))
1151 .paren_arg(|f| {
1152 f.write_str(if *is_bus_master {
1153 "BusMaster"
1154 } else {
1155 "NotBusMaster"
1156 })
1157 })
1158 .paren_arg(|f| transfer_type.fmt(f))
1159 .finish_paren_arg()
1160 .set_list(true);
1161
1162 for i in 0..7 {
1163 if channels_mask & (1 << i) != 0 {
1164 d.body_field(|f| write!(f, "{i}"));
1165 }
1166 }
1167
1168 d.at_least_empty_body().finish()
1169 }
1170 ResourceMacro::StartDependentFunctions {
1172 compatibility_priority,
1173 performance_priority,
1174 } => AmlDisplayer::start(f, "StartDependentFn")
1175 .paren_arg(|f| write!(f, "{compatibility_priority}"))
1176 .paren_arg(|f| write!(f, "{performance_priority}"))
1177 .finish(),
1178 ResourceMacro::EndDependentFunctions => AmlDisplayer::start(f, "EndDependentFn")
1179 .at_least_empty_paren_arg()
1180 .finish(),
1181 ResourceMacro::Io {
1182 is_16_bit_decode,
1183 min_addr,
1184 max_addr,
1185 alignment,
1186 len,
1187 } => AmlDisplayer::start(f, "IO")
1188 .paren_arg(|f| {
1189 f.write_str(if *is_16_bit_decode {
1190 "Decode16"
1191 } else {
1192 "Decode10"
1193 })
1194 })
1195 .paren_arg(|f| write!(f, "0x{min_addr:04X}"))
1196 .paren_arg(|f| write!(f, "0x{max_addr:04X}"))
1197 .paren_arg(|f| write!(f, "0x{alignment:02X}"))
1198 .paren_arg(|f| write!(f, "0x{len:02X}"))
1199 .finish(),
1200 ResourceMacro::FixedIo { base, len } => AmlDisplayer::start(f, "FixedIO")
1201 .paren_arg(|f| write!(f, "0x{base:04X}"))
1202 .paren_arg(|f| write!(f, "0x{len:02X}"))
1203 .finish(),
1204 ResourceMacro::FixedDma {
1205 dma_req,
1206 channel,
1207 transfer_width,
1208 } => AmlDisplayer::start(f, "FixedDMA")
1209 .paren_arg(|f| write!(f, "0x{dma_req:04X}"))
1210 .paren_arg(|f| write!(f, "0x{channel:04X}"))
1211 .paren_arg(|f| transfer_width.fmt(f))
1212 .finish(),
1213 ResourceMacro::VendorShort { data, len } => {
1214 let mut d = AmlDisplayer::start(f, "VendorShort");
1215 d.at_least_empty_paren_arg().set_list(true);
1216
1217 for e in data.iter().take(*len as usize) {
1218 d.body_field(|f| write!(f, "0x{e:02X}"));
1219 }
1220
1221 d.at_least_empty_body().finish()
1222 }
1223 ResourceMacro::VendorLarge { data } => {
1224 let mut d = AmlDisplayer::start(f, "VendorLarge");
1225 d.at_least_empty_paren_arg().set_list(true);
1226
1227 for e in data {
1228 d.body_field(|f| write!(f, "0x{e:02X}"));
1229 }
1230
1231 d.at_least_empty_body().finish()
1232 }
1233 ResourceMacro::Memory24 {
1234 is_read_write,
1235 min_addr,
1236 max_addr,
1237 alignment,
1238 len,
1239 } => display_memory_args(
1240 f,
1241 "Memory24",
1242 *is_read_write,
1243 &[min_addr, max_addr, alignment, len],
1244 )
1245 .finish(),
1246 ResourceMacro::Memory32Fixed {
1247 is_read_write,
1248 base_addr,
1249 len,
1250 } => {
1251 display_memory_args(f, "Memory32Fixed", *is_read_write, &[base_addr, len]).finish()
1252 }
1253 ResourceMacro::Memory32 {
1254 is_read_write,
1255 min_addr,
1256 max_addr,
1257 alignment,
1258 len,
1259 } => display_memory_args(
1260 f,
1261 "Memory32",
1262 *is_read_write,
1263 &[min_addr, max_addr, alignment, len],
1264 )
1265 .finish(),
1266 ResourceMacro::Interrupt {
1267 is_consumer,
1268 edge_triggered,
1269 active_low,
1270 is_shared,
1271 wake_capable,
1272 interrupts,
1273 resource_source,
1274 } => {
1275 let mut d = AmlDisplayer::start(f, "Interrupt");
1276 display_interrupt_args(
1277 &mut d,
1278 Some(*is_consumer),
1279 *wake_capable,
1280 *is_shared,
1281 *active_low,
1282 *edge_triggered,
1283 resource_source,
1284 )
1285 .finish_paren_arg()
1286 .set_list(true);
1287
1288 for i in interrupts {
1289 d.body_field(|f| write!(f, "0x{i:08X}"));
1290 }
1291
1292 d.at_least_empty_body().finish()
1293 }
1294 ResourceMacro::Register {
1295 address_space,
1296 bit_width,
1297 offset,
1298 address,
1299 access_size,
1300 } => AmlDisplayer::start(f, "Register")
1301 .paren_arg(|f| address_space.fmt(f))
1302 .paren_arg(|f| write!(f, "0x{bit_width:02X}"))
1303 .paren_arg(|f| write!(f, "0x{offset:02X}"))
1304 .paren_arg(|f| write!(f, "0x{address:08X}"))
1305 .paren_arg(|f| write!(f, "{}", access_size.clone() as u8))
1306 .finish(),
1307 ResourceMacro::AddressSpaceWord(address_space) => address_space.fmt(f),
1308 ResourceMacro::AddressSpaceDWord(address_space) => address_space.fmt(f),
1309 ResourceMacro::AddressSpaceQWord(address_space) => address_space.fmt(f),
1310 ResourceMacro::AddressSpaceExtended(address_space) => address_space.fmt(f),
1311 }
1312 }
1313}
1314
1315impl fmt::Display for ResourceTemplate {
1316 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1317 let mut d = AmlDisplayer::start(f, "ResourceTemplate");
1318 d.at_least_empty_paren_arg();
1319
1320 for item in &self.items {
1321 d.body_field(|f| item.fmt(f));
1322 }
1323
1324 d.at_least_empty_body().finish()
1325 }
1326}