kernel/acpi/aml/parser/
resource_template.rs

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    // ignore in extended address space
117    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            // only word has bus number
201            (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                // contain extra 1 byte
462                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                // DMA
493                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            // TODO: support rest of the resource types
753            _ => None,
754        };
755
756        // still there is more data to parse
757        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        // is this a resource template anyway?
784        {
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            // The checksum must match or the last element can be 0
791            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            // TODO: this is not correct, it should have a list of terms inside it, but meh, do it later
1171            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}