Skip to content

Commit bd7e078

Browse files
committed
uefi: Extend ConfigurationString parsing with alt_cfg_id variant
1 parent e331f06 commit bd7e078

File tree

1 file changed

+70
-0
lines changed

1 file changed

+70
-0
lines changed

uefi/src/proto/hii/config_str.rs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ pub enum ConfigHdrSection {
6666
Name,
6767
/// UEFI ConfigurationString {PathHdr} element
6868
Path,
69+
/// UEFI ConfigurationString {DescHdr} element
70+
DescHdr,
6971
}
7072

7173
/// Enum representing possible parsing errors encountered when processing
@@ -108,6 +110,8 @@ pub struct ConfigurationString {
108110
pub name: String,
109111
/// Associated UEFI device path
110112
pub device_path: Box<DevicePath>,
113+
/// Identifier of a configuration declared in the corresponding IFR.
114+
pub alt_cfg_id: Option<u16>,
111115
/// Parsed UEFI {ConfigElement} sections
112116
pub elements: Vec<ConfigurationStringElement>,
113117
}
@@ -220,6 +224,16 @@ impl ConfigurationString {
220224
let v = <&DevicePath>::try_from(v.as_slice()).ok()?;
221225
Some(v.to_boxed())
222226
})?;
227+
let alt_cfg_id = match splitter.peek() {
228+
Some(("ALTCFG", _)) => Some(Self::try_parse_with(
229+
ParseError::ConfigHdr(ConfigHdrSection::DescHdr),
230+
|| {
231+
let v = splitter.next()?.1?;
232+
Self::parse_number_from_hex(v).map(|v| v as u16)
233+
},
234+
)?),
235+
_ => None,
236+
};
223237

224238
let mut elements = Vec::new();
225239
loop {
@@ -263,6 +277,7 @@ impl ConfigurationString {
263277
guid,
264278
name,
265279
device_path,
280+
alt_cfg_id,
266281
elements,
267282
})
268283
}
@@ -337,6 +352,60 @@ mod tests {
337352
guid!("4b47d616-a8d6-4552-9d44-ccad2e0f4cf9")
338353
);
339354
assert_eq!(parsed[0].name, "ISCSI_CONFIG_IFR_NVDATA");
355+
assert_eq!(parsed[0].alt_cfg_id, None);
356+
assert_eq!(parsed[0].elements.len(), 1);
357+
assert_eq!(parsed[0].elements[0].offset, 0x01d8);
358+
assert_eq!(parsed[0].elements[0].width, 1);
359+
assert_eq!(&parsed[0].elements[0].value, &[0x00]);
360+
361+
assert_eq!(
362+
parsed[1].guid,
363+
guid!("4b47d616-a8d6-4552-9d44-ccad2e0f4cf9")
364+
);
365+
assert_eq!(parsed[1].name, "ISCSI_CONFIG_IFR_NVDATA");
366+
assert_eq!(parsed[1].alt_cfg_id, None);
367+
assert_eq!(parsed[1].elements.len(), 2);
368+
assert_eq!(parsed[1].elements[1].offset, 0x1337);
369+
assert_eq!(parsed[1].elements[1].width, 5);
370+
assert_eq!(
371+
&parsed[1].elements[1].value,
372+
&[0x55, 0x44, 0x33, 0x22, 0x11]
373+
);
374+
}
375+
376+
#[test]
377+
fn parse_single_altcfg() {
378+
// exemplary (shortened / manually constructed) UEFI configuration string
379+
let input = "GUID=16d6474bd6a852459d44ccad2e0f4cf9&NAME=00490053004300530049005f0043004f004e004600490047005f004900460052005f004e00560044004100540041&PATH=0104140016d6474bd6a852459d44ccad2e0f4cf97fff0400&ALTCFG=0001&OFFSET=01d8&WIDTH=0001&VALUE=00&OFFSET=01d9&WIDTH=0001&VALUE=00&OFFSET=01da&WIDTH=0001&VALUE=00&OFFSET=01dc&WIDTH=0002&VALUE=03e8&OFFSET=01de&WIDTH=0001&VALUE=00&OFFSET=01df&WIDTH=0001&VALUE=00&OFFSET=05fe&WIDTH=0002&VALUE=0000&OFFSET=062a&WIDTH=0001&VALUE=00&OFFSET=062b&WIDTH=0001&VALUE=01&OFFSET=0fd4&WIDTH=0001&VALUE=00&OFFSET=0fd5&WIDTH=0001&VALUE=00";
380+
let parsed = ConfigurationString::from_str(input).unwrap();
381+
assert_eq!(parsed.guid, guid!("4b47d616-a8d6-4552-9d44-ccad2e0f4cf9"));
382+
assert_eq!(parsed.name, "ISCSI_CONFIG_IFR_NVDATA");
383+
assert_eq!(parsed.alt_cfg_id, Some(1));
384+
assert_eq!(parsed.elements.len(), 11);
385+
assert_eq!(parsed.elements[0].offset, 0x01d8);
386+
assert_eq!(parsed.elements[0].width, 1);
387+
assert_eq!(&parsed.elements[0].value, &[0x00]);
388+
assert_eq!(parsed.elements[10].offset, 0x0fd5);
389+
assert_eq!(parsed.elements[10].width, 1);
390+
assert_eq!(&parsed.elements[10].value, &[0x00]);
391+
}
392+
393+
#[test]
394+
fn parse_multiple_altcfg() {
395+
// exemplary (shortened / manually constructed) UEFI configuration string
396+
let input = "GUID=16d6474bd6a852459d44ccad2e0f4cf9&NAME=00490053004300530049005f0043004f004e004600490047005f004900460052005f004e00560044004100540041&PATH=0104140016d6474bd6a852459d44ccad2e0f4cf97fff0400&ALTCFG=0002&OFFSET=01d8&WIDTH=0001&VALUE=00&GUID=16d6474bd6a852459d44ccad2e0f4cf9&NAME=00490053004300530049005f0043004f004e004600490047005f004900460052005f004e00560044004100540041&PATH=0104140016d6474bd6a852459d44ccad2e0f4cf97fff0400&ALTCFG=0001&OFFSET=01d8&WIDTH=0001&VALUE=00&OFFSET=1337&WIDTH=0005&VALUE=1122334455";
397+
let parsed: Vec<_> = MultiConfigurationStringIter::new(input)
398+
.collect::<Result<_, _>>()
399+
.unwrap();
400+
401+
assert_eq!(parsed.len(), 2);
402+
403+
assert_eq!(
404+
parsed[0].guid,
405+
guid!("4b47d616-a8d6-4552-9d44-ccad2e0f4cf9")
406+
);
407+
assert_eq!(parsed[0].name, "ISCSI_CONFIG_IFR_NVDATA");
408+
assert_eq!(parsed[0].alt_cfg_id, Some(2));
340409
assert_eq!(parsed[0].elements.len(), 1);
341410
assert_eq!(parsed[0].elements[0].offset, 0x01d8);
342411
assert_eq!(parsed[0].elements[0].width, 1);
@@ -347,6 +416,7 @@ mod tests {
347416
guid!("4b47d616-a8d6-4552-9d44-ccad2e0f4cf9")
348417
);
349418
assert_eq!(parsed[1].name, "ISCSI_CONFIG_IFR_NVDATA");
419+
assert_eq!(parsed[1].alt_cfg_id, Some(1));
350420
assert_eq!(parsed[1].elements.len(), 2);
351421
assert_eq!(parsed[1].elements[1].offset, 0x1337);
352422
assert_eq!(parsed[1].elements[1].width, 5);

0 commit comments

Comments
 (0)