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}