Skip to content

Commit 12d461e

Browse files
committed
Skip unsupported _CRS resource descriptors
Skip unsupported _CRS resource descriptors instead of panicking. Callers can still consume the MMIO/IRQ descriptors they understand from mixed resource buffers containing GPIO or GenericSerialBus descriptors.
1 parent 044480a commit 12d461e

1 file changed

Lines changed: 74 additions & 21 deletions

File tree

src/aml/resource.rs

Lines changed: 74 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,30 @@ pub enum Resource {
1414
Dma(DMADescriptor),
1515
}
1616

17+
const UNSUPPORTED_LARGE_RESOURCE_DESCRIPTORS: &[(u8, &str)] = &[
18+
(0x01, "24-bit Memory Range Descriptor"),
19+
(0x02, "Generic Register Descriptor"),
20+
(0x03, "0x03 Reserved"),
21+
(0x04, "Vendor-defined Descriptor"),
22+
(0x05, "32-bit Memory Range Descriptor"),
23+
(0x0b, "Extended Address Space Descriptor"),
24+
(0x0c, "GPIO Connection Descriptor"),
25+
(0x0d, "Pin Function Descriptor"),
26+
(0x0e, "GenericSerialBus Connection Descriptor"),
27+
(0x0f, "Pin Configuration Descriptor"),
28+
(0x10, "Pin Group Descriptor"),
29+
(0x11, "Pin Group Function Descriptor"),
30+
(0x12, "Pin Group Configuration Descriptor"),
31+
];
32+
33+
const UNSUPPORTED_SMALL_RESOURCE_DESCRIPTORS: &[(u8, &str)] = &[
34+
(0x06, "Start Dependent Functions Descriptor"),
35+
(0x07, "End Dependent Functions Descriptor"),
36+
(0x09, "Fixed Location IO Port Descriptor"),
37+
(0x0a, "Fixed DMA Descriptor"),
38+
(0x0e, "Vendor Defined Descriptor"),
39+
];
40+
1741
/// Parse a `ResourceDescriptor` buffer into a list of resources.
1842
pub fn resource_descriptor_list(descriptor: WrappedObject) -> Result<Vec<Resource>, AmlError> {
1943
if let Object::Buffer(ref bytes) = *descriptor {
@@ -25,10 +49,8 @@ pub fn resource_descriptor_list(descriptor: WrappedObject) -> Result<Vec<Resourc
2549

2650
if let Some(descriptor) = descriptor {
2751
descriptors.push(descriptor);
28-
bytes = remaining_bytes;
29-
} else {
30-
break;
3152
}
53+
bytes = remaining_bytes;
3254
}
3355

3456
Ok(descriptors)
@@ -37,6 +59,20 @@ pub fn resource_descriptor_list(descriptor: WrappedObject) -> Result<Vec<Resourc
3759
}
3860
}
3961

62+
fn unsupported_resource_descriptor_name(descriptors: &[(u8, &'static str)], descriptor_type: u8) -> Option<&'static str> {
63+
descriptors.iter().find_map(|(typ, name)| (*typ == descriptor_type).then_some(*name))
64+
}
65+
66+
fn skip_unsupported_resource<'a>(
67+
size: &str,
68+
descriptor_type: u8,
69+
descriptor_name: &str,
70+
remaining_bytes: &'a [u8],
71+
) -> Result<(Option<Resource>, &'a [u8]), AmlError> {
72+
log::warn!("skipping unsupported {size} resource descriptor type {descriptor_type:#x}: {descriptor_name}");
73+
Ok((None, remaining_bytes))
74+
}
75+
4076
fn resource_descriptor(bytes: &[u8]) -> Result<(Option<Resource>, &[u8]), AmlError> {
4177
/*
4278
* If bit 7 of Byte 0 is set, it's a large descriptor. If not, it's a small descriptor.
@@ -73,27 +109,19 @@ fn resource_descriptor(bytes: &[u8]) -> Result<(Option<Resource>, &[u8]), AmlErr
73109
let (descriptor_bytes, remaining_bytes) = bytes.split_at(length + 3);
74110

75111
let descriptor = match descriptor_type {
76-
0x01 => unimplemented!("24-bit Memory Range Descriptor"),
77-
0x02 => unimplemented!("Generic Register Descriptor"),
78-
0x03 => unimplemented!("0x03 Reserved"),
79-
0x04 => unimplemented!("Vendor-defined Descriptor"),
80-
0x05 => unimplemented!("32-bit Memory Range Descriptor"),
81112
0x06 => fixed_memory_descriptor(descriptor_bytes),
82113
0x07 => address_space_descriptor::<u32>(descriptor_bytes),
83114
0x08 => address_space_descriptor::<u16>(descriptor_bytes),
84115
0x09 => extended_interrupt_descriptor(descriptor_bytes),
85116
0x0a => address_space_descriptor::<u64>(descriptor_bytes),
86-
0x0b => unimplemented!("Extended Address Space Descriptor"),
87-
0x0c => unimplemented!("GPIO Connection Descriptor"),
88-
0x0d => unimplemented!("Pin Function Descriptor"),
89-
0x0e => unimplemented!("GenericSerialBus Connection Descriptor"),
90-
0x0f => unimplemented!("Pin Configuration Descriptor"),
91-
0x10 => unimplemented!("Pin Group Descriptor"),
92-
0x11 => unimplemented!("Pin Group Function Descriptor"),
93-
0x12 => unimplemented!("Pin Group Configuration Descriptor"),
94117

95118
0x00 | 0x13..=0x7f => Err(AmlError::InvalidResourceDescriptor),
96119
0x80..=0xff => unreachable!(),
120+
_ => {
121+
let descriptor_name =
122+
unsupported_resource_descriptor_name(UNSUPPORTED_LARGE_RESOURCE_DESCRIPTORS, descriptor_type).unwrap();
123+
return skip_unsupported_resource("large", descriptor_type, descriptor_name, remaining_bytes);
124+
}
97125
}?;
98126

99127
Ok((Some(descriptor), remaining_bytes))
@@ -127,15 +155,15 @@ fn resource_descriptor(bytes: &[u8]) -> Result<(Option<Resource>, &[u8]), AmlErr
127155
0x00..=0x03 => Err(AmlError::InvalidResourceDescriptor),
128156
0x04 => irq_format_descriptor(descriptor_bytes),
129157
0x05 => dma_format_descriptor(descriptor_bytes),
130-
0x06 => unimplemented!("Start Dependent Functions Descriptor"),
131-
0x07 => unimplemented!("End Dependent Functions Descriptor"),
132158
0x08 => io_port_descriptor(descriptor_bytes),
133-
0x09 => unimplemented!("Fixed Location IO Port Descriptor"),
134-
0x0A => unimplemented!("Fixed DMA Descriptor"),
135159
0x0B..=0x0D => Err(AmlError::InvalidResourceDescriptor),
136-
0x0E => unimplemented!("Vendor Defined Descriptor"),
137160
0x0F => return Ok((None, &[])),
138161
0x10..=0xFF => unreachable!(),
162+
_ => {
163+
let descriptor_name =
164+
unsupported_resource_descriptor_name(UNSUPPORTED_SMALL_RESOURCE_DESCRIPTORS, descriptor_type).unwrap();
165+
return skip_unsupported_resource("small", descriptor_type, descriptor_name, remaining_bytes);
166+
}
139167
}?;
140168

141169
Ok((Some(descriptor), remaining_bytes))
@@ -760,6 +788,31 @@ mod tests {
760788
);
761789
}
762790

791+
#[test]
792+
fn skips_unsupported_large_resource_descriptors() {
793+
let bytes: Vec<u8> = [
794+
// GenericSerialBus descriptor with one byte of payload.
795+
0x8e, 0x01, 0x00, 0x00,
796+
// Memory32Fixed(ReadWrite, 0x1000, 0x1000)
797+
0x86, 0x09, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
798+
// End tag.
799+
0x79, 0x00,
800+
]
801+
.to_vec();
802+
803+
let value = Object::Buffer(bytes).wrap();
804+
let resources = resource_descriptor_list(value).unwrap();
805+
806+
assert_eq!(
807+
resources,
808+
Vec::from([Resource::MemoryRange(MemoryRangeDescriptor::FixedLocation {
809+
is_writable: true,
810+
base_address: 0x1000,
811+
range_length: 0x1000,
812+
})])
813+
);
814+
}
815+
763816
#[test]
764817
fn test_fdc_crs() {
765818
let bytes: Vec<u8> = [

0 commit comments

Comments
 (0)