Skip to main content

stable_aml/
resource.rs

1use crate::{
2    value::{AmlType, AmlValue},
3    AmlError,
4};
5use alloc::vec::Vec;
6use bit_field::BitField;
7use byteorder::{ByteOrder, LittleEndian};
8use core::mem;
9
10#[derive(Debug, PartialEq, Eq)]
11pub enum Resource {
12    Irq(IrqDescriptor),
13    AddressSpace(AddressSpaceDescriptor),
14    MemoryRange(MemoryRangeDescriptor),
15    IOPort(IOPortDescriptor),
16    Dma(DMADescriptor),
17}
18
19/// Parse a `ResourceDescriptor` into a list of resources. Returns `AmlError::IncompatibleValueConversion` if the passed value is not a
20/// `Buffer`.
21pub fn resource_descriptor_list(descriptor: &AmlValue) -> Result<Vec<Resource>, AmlError> {
22    if let AmlValue::Buffer(bytes) = descriptor {
23        let mut descriptors = Vec::new();
24        let buffer_data = bytes.lock();
25        let mut bytes = buffer_data.as_slice();
26
27        while bytes.len() > 0 {
28            let (descriptor, remaining_bytes) = resource_descriptor(bytes)?;
29
30            if let Some(descriptor) = descriptor {
31                descriptors.push(descriptor);
32                bytes = remaining_bytes;
33            } else {
34                break;
35            }
36        }
37
38        Ok(descriptors)
39    } else {
40        Err(AmlError::IncompatibleValueConversion {
41            current: descriptor.type_of(),
42            target: AmlType::Buffer,
43        })
44    }
45}
46
47/// Parse a `ResourceDescriptor`. Returns `AmlError::IncompatibleValueConversion` if the passed value is not a
48/// `Buffer`.
49fn resource_descriptor(bytes: &[u8]) -> Result<(Option<Resource>, &[u8]), AmlError> {
50    /*
51     * If bit 7 of Byte 0 is set, it's a large descriptor. If not, it's a small descriptor.
52     */
53    if bytes[0].get_bit(7) {
54        /*
55         * We're parsing a large item. The descriptor type is encoded in Bits 0-6 of Byte 0. Valid types:
56         *      0x00: Reserved
57         *      0x01: 24-bit Memory Range Descriptor
58         *      0x02: Generic Register Descriptor
59         *      0x03: Reserved
60         *      0x04: Vendor-defined Descriptor
61         *      0x05: 32-bit Memory Range Descriptor
62         *      0x06: 32-bit Fixed Memory Range Descriptor
63         *      0x07: Address Space Resource Descriptor
64         *      0x08: Word Address Space Descriptor
65         *      0x09: Extended Interrupt Descriptor
66         *      0x0a: QWord Address Space Descriptor
67         *      0x0b: Extended Address Space Descriptor
68         *      0x0c: GPIO Connection Descriptor
69         *      0x0d: Pin Function Descriptor
70         *      0x0e: GenericSerialBus Connection Descriptor
71         *      0x0f: Pin Configuration Descriptor
72         *      0x10: Pin Group Descriptor
73         *      0x11: Pin Group Function Descriptor
74         *      0x12: Pin Group Configuration Descriptor
75         *      0x13-0x7f: Reserved
76         *
77         * Byte 1 contains bits 0-7 of the length, and Byte 2 contains bits 8-15 of the length. Subsequent
78         * bytes contain the actual data items.
79         */
80        let descriptor_type = bytes[0].get_bits(0..7);
81        let length = LittleEndian::read_u16(&bytes[1..=2]) as usize;
82        let (descriptor_bytes, remaining_bytes) = bytes.split_at(length + 3);
83
84        let descriptor = match descriptor_type {
85            0x01 => unimplemented!("24-bit Memory Range Descriptor"),
86            0x02 => unimplemented!("Generic Register Descriptor"),
87            0x03 => unimplemented!("0x03 Reserved"),
88            0x04 => unimplemented!("Vendor-defined Descriptor"),
89            0x05 => unimplemented!("32-bit Memory Range Descriptor"),
90            0x06 => fixed_memory_descriptor(descriptor_bytes),
91            0x07 => address_space_descriptor::<u32>(descriptor_bytes),
92            0x08 => address_space_descriptor::<u16>(descriptor_bytes),
93            0x09 => extended_interrupt_descriptor(descriptor_bytes),
94            0x0a => address_space_descriptor::<u64>(descriptor_bytes),
95            0x0b => unimplemented!("Extended Address Space Descriptor"),
96            0x0c => unimplemented!("GPIO Connection Descriptor"),
97            0x0d => unimplemented!("Pin Function Descriptor"),
98            0x0e => unimplemented!("GenericSerialBus Connection Descriptor"),
99            0x0f => unimplemented!("Pin Configuration Descriptor"),
100            0x10 => unimplemented!("Pin Group Descriptor"),
101            0x11 => unimplemented!("Pin Group Function Descriptor"),
102            0x12 => unimplemented!("Pin Group Configuration Descriptor"),
103
104            0x00 | 0x13..=0x7f => Err(AmlError::ReservedResourceType),
105            0x80..=0xff => unreachable!(),
106        }?;
107
108        Ok((Some(descriptor), remaining_bytes))
109    } else {
110        /*
111         * We're parsing a small descriptor. Byte 0 has the format:
112         *    | Bits        | Field             |
113         *    |-------------|-------------------|
114         *    | 0-2         | Length - n bytes  |
115         *    | 3-6         | Small item type   |
116         *    | 7           | 0 = small item    |
117         *
118         * The valid types are:
119         *      0x00-0x03: Reserved
120         *      0x04: IRQ Format Descriptor
121         *      0x05: DMA Format Descriptor
122         *      0x06: Start Dependent Functions Descriptor
123         *      0x07: End Dependent Functions Descriptor
124         *      0x08: IO Port Descriptor
125         *      0x09: Fixed Location IO Port Descriptor
126         *      0x0A: Fixed DMA Descriptor
127         *      0x0B-0x0D: Reserved
128         *      0x0E: Vendor Defined Descriptor
129         *      0x0F: End Tag Descriptor
130         */
131        let descriptor_type = bytes[0].get_bits(3..=6);
132        let length: usize = bytes[0].get_bits(0..=2) as usize;
133        let (descriptor_bytes, remaining_bytes) = bytes.split_at(length + 1);
134
135        let descriptor = match descriptor_type {
136            0x00..=0x03 => Err(AmlError::ReservedResourceType),
137            0x04 => irq_format_descriptor(descriptor_bytes),
138            0x05 => dma_format_descriptor(descriptor_bytes),
139            0x06 => unimplemented!("Start Dependent Functions Descriptor"),
140            0x07 => unimplemented!("End Dependent Functions Descriptor"),
141            0x08 => io_port_descriptor(descriptor_bytes),
142            0x09 => unimplemented!("Fixed Location IO Port Descriptor"),
143            0x0A => unimplemented!("Fixed DMA Descriptor"),
144            0x0B..=0x0D => Err(AmlError::ReservedResourceType),
145            0x0E => unimplemented!("Vendor Defined Descriptor"),
146            0x0F => return Ok((None, &[])),
147            0x10..=0xFF => unreachable!(),
148        }?;
149
150        Ok((Some(descriptor), remaining_bytes))
151    }
152}
153
154#[derive(Debug, PartialEq, Eq, Copy, Clone)]
155pub enum InterruptTrigger {
156    Edge,
157    Level,
158}
159
160#[derive(Debug, PartialEq, Eq, Copy, Clone)]
161pub enum InterruptPolarity {
162    ActiveHigh,
163    ActiveLow,
164}
165
166#[derive(Debug, PartialEq, Eq, Copy, Clone)]
167pub enum AddressSpaceResourceType {
168    MemoryRange,
169    IORange,
170    BusNumberRange,
171}
172
173#[derive(Debug, PartialEq, Eq, Copy, Clone)]
174pub enum AddressSpaceDecodeType {
175    Additive,
176    Subtractive,
177}
178
179#[derive(Debug, PartialEq, Eq)]
180pub struct AddressSpaceDescriptor {
181    resource_type: AddressSpaceResourceType,
182    is_maximum_address_fixed: bool,
183    is_minimum_address_fixed: bool,
184    decode_type: AddressSpaceDecodeType,
185
186    granularity: u64,
187    address_range: (u64, u64),
188    translation_offset: u64,
189    length: u64,
190}
191
192#[derive(Debug, PartialEq, Eq)]
193pub enum MemoryRangeDescriptor {
194    FixedLocation {
195        is_writable: bool,
196        base_address: u32,
197        range_length: u32,
198    },
199}
200
201fn fixed_memory_descriptor(bytes: &[u8]) -> Result<Resource, AmlError> {
202    /*
203     * -- 32-bit Fixed Memory Descriptor ---
204     * Offset     Field Name                              Definition
205     * Byte 0     32-bit Fixed Memory Range Descriptor    Value = 0x86 (10000110B) – Type = 1, Large item name = 0x06
206     * Byte 1     Length, bits [7:0]                      Value = 0x09 (9)
207     * Byte 2     Length, bits [15:8]                     Value = 0x00
208     * Byte 3     Information                             This field provides extra information about this memory.
209     *                                                    Bit [7:1]   Ignored
210     *                                                    Bit [0]     Write status, _RW
211     *                                                        1  writeable (read/write)
212     *                                                        0  non-writeable (read-only)
213     * Byte 4     Range base address, _BAS bits [7:0]     Address bits [7:0] of the base memory address for which the card may be configured.
214     * Byte 5     Range base address, _BAS bits [15:8]    Address bits [15:8] of the base memory address for which the card may be configured.
215     * Byte 6     Range base address, _BAS bits [23:16]   Address bits [23:16] of the base memory address for which the card may be configured.
216     * Byte 7     Range base address, _BAS bits [31:24]   Address bits [31:24] of the base memory address for which the card may be configured.
217     * Byte 8     Range length, _LEN bits [7:0]           This field contains bits [7:0] of the memory range length. The range length provides the length of the memory range in 1-byte blocks.
218     * Byte 9     Range length, _LEN bits [15:8]          This field contains bits [15:8] of the memory range length. The range length provides the length of the memory range in 1-byte blocks.
219     * Byte 10    Range length, _LEN bits [23:16]         This field contains bits [23:16] of the memory range length. The range length provides the length of the memory range in 1-byte blocks.
220     * Byte 11    Range length, _LEN bits [31:24]         This field contains bits [31:24] of the memory range length. The range length provides the length of the memory range in 1-byte blocks.
221     */
222    if bytes.len() < 12 {
223        return Err(AmlError::ResourceDescriptorTooShort);
224    }
225
226    if bytes.len() > 12 {
227        return Err(AmlError::ResourceDescriptorTooLong);
228    }
229
230    let information = bytes[3];
231    let is_writable = information.get_bit(0);
232
233    let base_address = LittleEndian::read_u32(&bytes[4..=7]);
234    let range_length = LittleEndian::read_u32(&bytes[8..=11]);
235
236    Ok(Resource::MemoryRange(
237        MemoryRangeDescriptor::FixedLocation {
238            is_writable,
239            base_address,
240            range_length,
241        },
242    ))
243}
244
245fn address_space_descriptor<T>(bytes: &[u8]) -> Result<Resource, AmlError> {
246    /*
247     * WORD Address Space Descriptor Definition
248     * Note: The definitions for DWORD and QWORD are the same other than the width of the address fields.
249     *
250     * Offset  Field Name                                   Definition
251     * Byte 0  WORD Address Space Descriptor                Value = 0x88 (10001000B) – Type = 1, Large item name = 0x08
252     * Byte 1  Length, bits [7:0]                           Variable length, minimum value = 0x0D (13)
253     * Byte 2  Length, bits [15:8]                          Variable length, minimum value = 0x00
254     * Byte 3  Resource Type                                Indicates which type of resource this descriptor describes. Defined values are:
255     *                                                        0         Memory range
256     *                                                        1         I/O range
257     *                                                        2         Bus number range
258     *                                                        3–191     Reserved
259     *                                                        192-255   Hardware Vendor Defined
260     * Byte 4  General Flags                                Flags that are common to all resource types:
261     *                                                        Bits [7:4]   Reserved (must be 0)
262     *                                                        Bit [3]     Max Address Fixed, _MAF:
263     *                                                          1  The specified maximum address is fixed
264     *                                                          0  The specified maximum address is not fixed
265     *                                                             and can be changed
266     *                                                        Bit [2]      Min Address Fixed,_MIF:
267     *                                                          1   The specified minimum address is fixed
268     *                                                          0   The specified minimum address is not fixed
269     *                                                              and can be changed
270     *                                                        Bit [1]      Decode Type, _DEC:
271     *                                                          1   This bridge subtractively decodes this address          (top level bridges only)
272     *                                                          0   This bridge positively decodes this address
273     *                                                        Bit [0]      Ignored
274     * Byte 5  Type Specific Flags                           Flags that are specific to each resource type. The meaning of the flags in this field depends on the value of the Resource Type field (see above).
275     * Byte 6  Address space granularity, _GRA bits[7:0]     A set bit in this mask means that this bit is decoded. All bits less significant than the most significant set bit must be set. (In other words, the value of the full Address Space Granularity field (all 16 bits) must be a number (2n-1).
276     * Byte 7  Address space granularity, _GRA bits[15:8]
277     * Byte 8  Address range minimum, _MIN, bits [7:0]       For bridges that translate addresses, this is the address space on the secondary side of the bridge.
278     * Byte 9  Address range minimum, _MIN, bits [15:8]
279     * Byte 10 Address range maximum, _MAX, bits [7:0]       For bridges that translate addresses, this is the address space on the secondary side of the bridge.
280     * Byte 11 Address range maximum, _MAX, bits [15:8]
281     * Byte 12 Address Translation offset, _TRA, bits [7:0]  For bridges that translate addresses across the bridge, this is the offset that must be added to the address on the secondary side to obtain the address on the primary side. Non-bridge devices must list 0 for all Address Translation offset bits.
282     * Byte 13 Address Translation offset, _TRA, bits [15:8]
283     * Byte 14 Address Length, _LEN, bits [7:0]
284     * Byte 15 Address Length, _LEN, bits [15:8]
285     * Byte 16 Resource Source Index (Optional)              Only present if Resource Source (below) is present. This field gives an index to the specific resource descriptor that this device consumes from in the current resource template for the device object pointed to in Resource Source.
286     * String  Resource Source (Optional)                    If present, the device that uses this descriptor consumes its resources from the resources produced by the named device object. If not present, the device consumes its resources out of a global pool. If not present, the device consumes this resource from its hierarchical parent.
287     */
288    let size = mem::size_of::<T>();
289
290    if bytes.len() < 6 + size * 5 {
291        return Err(AmlError::ResourceDescriptorTooShort);
292    }
293
294    let resource_type = match bytes[3] {
295        0 => AddressSpaceResourceType::MemoryRange,
296        1 => AddressSpaceResourceType::IORange,
297        2 => AddressSpaceResourceType::BusNumberRange,
298        3..=191 => return Err(AmlError::ReservedResourceType),
299        192..=255 => unimplemented!(),
300    };
301
302    let general_flags = bytes[4];
303    let is_maximum_address_fixed = general_flags.get_bit(3);
304    let is_minimum_address_fixed = general_flags.get_bit(2);
305    let decode_type = if general_flags.get_bit(1) {
306        AddressSpaceDecodeType::Subtractive
307    } else {
308        AddressSpaceDecodeType::Additive
309    };
310
311    let mut address_fields = bytes[6..].chunks_exact(size);
312
313    // it's safe to unwrap because we check the length at the top
314    let granularity = LittleEndian::read_uint(address_fields.next().unwrap(), size);
315    let address_range_min = LittleEndian::read_uint(address_fields.next().unwrap(), size);
316    let address_range_max = LittleEndian::read_uint(address_fields.next().unwrap(), size);
317    let translation_offset = LittleEndian::read_uint(address_fields.next().unwrap(), size);
318    let length = LittleEndian::read_uint(address_fields.next().unwrap(), size);
319
320    Ok(Resource::AddressSpace(AddressSpaceDescriptor {
321        resource_type,
322        is_maximum_address_fixed,
323        is_minimum_address_fixed,
324        decode_type,
325        granularity,
326        address_range: (address_range_min, address_range_max),
327        translation_offset,
328        length,
329    }))
330}
331
332#[derive(Debug, PartialEq, Eq, Clone)]
333pub struct IrqDescriptor {
334    pub is_consumer: bool,
335    pub trigger: InterruptTrigger,
336    pub polarity: InterruptPolarity,
337    pub is_shared: bool,
338    pub is_wake_capable: bool,
339    /*
340     * NOTE: We currently only support the cases where a descriptor only contains a single interrupt
341     * number.
342     */
343    pub irq: u32,
344}
345
346fn irq_format_descriptor(bytes: &[u8]) -> Result<Resource, AmlError> {
347    /*
348     * IRQ Descriptor Definition
349     *
350     * Offset   Field Name
351     * Byte 0   Value = 0x22 or 0x23 (0010001nB)– Type = 0, Small item name = 0x4, Length = 2 or 3
352     * Byte 1   IRQ mask bits[7:0], _INT
353     *          Bit [0] represents IRQ0, bit[1] is IRQ1, and so on.
354     * Byte 2   IRQ mask bits[15:8], _INT
355     *          Bit [0] represents IRQ8, bit[1] is IRQ9, and so on.
356     * Byte 3   IRQ Information. Each bit, when set, indicates this device is capable of driving a certain type of interrupt.
357     *          (Optional—if not included then assume edge sensitive, high true interrupts.)
358     *          These bits can be used both for reporting and setting IRQ resources.
359     *          Note: This descriptor is meant for describing interrupts that are connected to PIC-compatible interrupt controllers, which can only be programmed for Active-High-Edge-Triggered or Active-Low-Level-Triggered interrupts. Any other combination is invalid. The Extended Interrupt Descriptor can be used to describe other combinations.
360     *            Bit [7:6]  Reserved (must be 0)
361     *            Bit [5]    Wake Capability, _WKC
362     *              0x0 = Not Wake Capable: This interrupt is not capable of waking the system.
363     *              0x1 = Wake Capable: This interrupt is capable of waking the system from a
364     *                    low-power idle state or a system sleep state.
365     *            Bit [4]    Interrupt Sharing, _SHR
366     *              0x0 = Exclusive: This interrupt is not shared with other devices.
367     *              0x1 = Shared: This interrupt is shared with other devices.
368     *            Bit [3]    Interrupt Polarity, _LL
369     *              0  Active-High – This interrupt is sampled when the signal is high, or true
370     *              1  Active-Low – This interrupt is sampled when the signal is low, or false.
371     *            Bit [2:1]  Ignored
372     *            Bit [0]    Interrupt Mode, _HE
373     *              0  Level-Triggered – Interrupt is triggered in response to signal in a low state.
374     *              1  Edge-Triggered – Interrupt is triggered in response to a change in signal state from low to high.
375     */
376
377    match bytes.len() {
378        0..=2 => Err(AmlError::ResourceDescriptorTooShort),
379        3 => {
380            // no IRQ information ("length 2" in spec)
381            let irq = LittleEndian::read_u16(&bytes[1..=2]);
382
383            Ok(Resource::Irq(IrqDescriptor {
384                irq: irq as u32,
385                is_wake_capable: false,
386                is_shared: false,
387                polarity: InterruptPolarity::ActiveHigh,
388                trigger: InterruptTrigger::Edge,
389
390                is_consumer: false, // assumed to be producer
391            }))
392        }
393        4 => {
394            // with IRQ information ("length 3" in spec)
395            let irq = LittleEndian::read_u16(&bytes[1..=2]);
396
397            let information = bytes[3];
398            let is_wake_capable = information.get_bit(5);
399            let is_shared = information.get_bit(4);
400            let polarity = match information.get_bit(3) {
401                false => InterruptPolarity::ActiveHigh,
402                true => InterruptPolarity::ActiveLow,
403            };
404            let trigger = match information.get_bit(0) {
405                false => InterruptTrigger::Level,
406                true => InterruptTrigger::Edge,
407            };
408
409            Ok(Resource::Irq(IrqDescriptor {
410                irq: irq as u32,
411                is_wake_capable,
412                is_shared,
413                polarity,
414                trigger,
415
416                is_consumer: false, // assumed to be producer
417            }))
418        }
419        _ => Err(AmlError::ResourceDescriptorTooLong),
420    }
421}
422
423#[derive(Debug, PartialEq, Eq)]
424pub enum DMASupportedSpeed {
425    CompatibilityMode,
426    TypeA, // as described by the EISA
427    TypeB,
428    TypeF,
429}
430
431#[derive(Debug, PartialEq, Eq)]
432pub enum DMATransferTypePreference {
433    _8BitOnly,
434    _8And16Bit,
435    _16Bit,
436}
437
438#[derive(Debug, PartialEq, Eq)]
439pub struct DMADescriptor {
440    channel_mask: u8,
441    supported_speeds: DMASupportedSpeed,
442    is_bus_master: bool,
443    transfer_type_preference: DMATransferTypePreference,
444}
445
446pub fn dma_format_descriptor(bytes: &[u8]) -> Result<Resource, AmlError> {
447    /*
448     * DMA Descriptor Definition
449     * Offset  Field Name
450     * Byte 0  Value = 0x2A (00101010B) – Type = 0, Small item name = 0x5, Length = 2
451     * Byte 1  DMA channel mask bits [7:0] (channels 0 – 7), _DMA
452     *         Bit [0] is channel 0, etc.
453     * Byte 2  Bit [7]           Reserved (must be 0)
454     *         Bits [6:5]        DMA channel speed supported, _TYP
455     *           00    Indicates compatibility mode
456     *           01    Indicates Type A DMA as described in the EISA
457     *           10    Indicates Type B DMA
458     *           11    Indicates Type F
459     *         Bits [4:3]        Ignored
460     *         Bit [2]           Logical device bus master status, _BM
461     *           0      Logical device is not a bus master
462     *           1      Logical device is a bus master
463     *         Bits [1:0]       DMA transfer type preference, _SIZ
464     *           00    8-bit only
465     *           01    8- and 16-bit
466     *           10    16-bit only
467     *           11    Reserved
468     */
469    if bytes.len() < 3 {
470        return Err(AmlError::ResourceDescriptorTooShort);
471    }
472
473    if bytes.len() > 3 {
474        return Err(AmlError::ResourceDescriptorTooLong);
475    }
476
477    let channel_mask = bytes[1];
478    let options = bytes[2];
479    let supported_speeds = match options.get_bits(5..=6) {
480        0 => DMASupportedSpeed::CompatibilityMode,
481        1 => DMASupportedSpeed::TypeA,
482        2 => DMASupportedSpeed::TypeB,
483        3 => DMASupportedSpeed::TypeF,
484        _ => unreachable!(),
485    };
486    let is_bus_master = options.get_bit(2);
487    let transfer_type_preference = match options.get_bits(0..=1) {
488        0 => DMATransferTypePreference::_8BitOnly,
489        1 => DMATransferTypePreference::_8And16Bit,
490        2 => DMATransferTypePreference::_16Bit,
491        3 => unimplemented!("Reserved DMA transfer type preference"),
492        _ => unreachable!(),
493    };
494
495    Ok(Resource::Dma(DMADescriptor {
496        channel_mask,
497        supported_speeds,
498        is_bus_master,
499        transfer_type_preference,
500    }))
501}
502
503#[derive(Debug, PartialEq, Eq)]
504pub struct IOPortDescriptor {
505    decodes_full_address: bool,
506    memory_range: (u16, u16),
507    base_alignment: u8,
508    range_length: u8,
509}
510
511fn io_port_descriptor(bytes: &[u8]) -> Result<Resource, AmlError> {
512    /*
513     * I/O Port Descriptor Definition
514     * Offset   Field Name                                  Definition
515     * Byte 0   I/O Port Descriptor                         Value = 0x47 (01000111B) –
516     *                                                      Type = 0, Small item name = 0x8, Length = 7
517     * Byte 1   Information                                 Bits [7:1]     Reserved and must be 0
518     *                                                      Bit [0]          (_DEC)
519     *                                                        1    The logical device decodes 16-bit addresses
520     *                                                        0    The logical device only decodes address bits[9:0]
521     * Byte 2   Range minimum base address, _MIN bits[7:0]  Address bits [7:0] of the minimum base I/O address that the card may be configured for.
522     * Byte 3   Range minimum base address, _MIN bits[15:8] Address bits [15:8] of the minimum base I/O address that the card may be configured for.
523     * Byte 4   Range maximum base address, _MAX bits[7:0]  Address bits [7:0] of the maximum base I/O address that the card may be configured for.
524     * Byte 5   Range maximum base address, _MAX bits[15:8] Address bits [15:8] of the maximum base I/O address that the card may be configured for.
525     * Byte 6   Base alignment, _ALN                        Alignment for minimum base address, increment in 1-byte blocks.
526     * Byte 7   Range length, _LEN                          The number of contiguous I/O ports requested.
527     */
528    if bytes.len() < 8 {
529        return Err(AmlError::ResourceDescriptorTooShort);
530    }
531
532    if bytes.len() > 8 {
533        return Err(AmlError::ResourceDescriptorTooLong);
534    }
535
536    let information = bytes[1];
537    let decodes_full_address = information.get_bit(0);
538
539    let memory_range_min = LittleEndian::read_u16(&bytes[2..=3]);
540    let memory_range_max = LittleEndian::read_u16(&bytes[4..=5]);
541    let memory_range = (memory_range_min, memory_range_max);
542
543    let base_alignment = bytes[6];
544    let range_length = bytes[7];
545
546    Ok(Resource::IOPort(IOPortDescriptor {
547        decodes_full_address,
548        memory_range,
549        base_alignment,
550        range_length,
551    }))
552}
553
554fn extended_interrupt_descriptor(bytes: &[u8]) -> Result<Resource, AmlError> {
555    /*
556     * --- Extended Interrupt Descriptor ---
557     * Byte 3 contains the Interrupt Vector Flags:
558     *      Bit 0: 1 if device consumes the resource, 0 if it produces it
559     *      Bit 1: 1 if edge-triggered, 0 if level-triggered
560     *      Bit 2: 1 = active-high, 0 = active-low
561     *      Bit 3: 1 if interrupt is shared with other devices
562     *      Bit 4: 1 if this interrupt is capable of waking the system, 0 if it is not
563     * Byte 4 contains the number of interrupt numbers that follow. When this descriptor is
564     * returned from `_CRS` or send to `_SRS`, this field must be 1.
565     *
566     * From Byte 5 onwards, there are `n` interrupt numbers, each of which is encoded as a
567     * 4-byte little-endian number.
568     *
569     * NOTE: We only support the case where there is a single interrupt number.
570     */
571    if bytes.len() < 9 {
572        return Err(AmlError::ResourceDescriptorTooShort);
573    }
574
575    let number_of_interrupts = bytes[4] as usize;
576    assert_eq!(number_of_interrupts, 1);
577    let irq = LittleEndian::read_u32(&[bytes[5], bytes[6], bytes[7], bytes[8]]);
578
579    Ok(Resource::Irq(IrqDescriptor {
580        is_consumer: bytes[3].get_bit(0),
581        trigger: if bytes[3].get_bit(1) {
582            InterruptTrigger::Edge
583        } else {
584            InterruptTrigger::Level
585        },
586        polarity: if bytes[3].get_bit(2) {
587            InterruptPolarity::ActiveLow
588        } else {
589            InterruptPolarity::ActiveHigh
590        },
591        is_shared: bytes[3].get_bit(3),
592        is_wake_capable: bytes[3].get_bit(4),
593        irq,
594    }))
595}