Skip to content

Commit 0e368cb

Browse files
committed
uefi: Extend ConfigurationString parsing with alt_cfg_id variant
1 parent 32fed3e commit 0e368cb

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 {
@@ -266,6 +280,7 @@ impl ConfigurationString {
266280
guid,
267281
name,
268282
device_path,
283+
alt_cfg_id,
269284
elements,
270285
})
271286
}
@@ -340,6 +355,60 @@ mod tests {
340355
guid!("4b47d616-a8d6-4552-9d44-ccad2e0f4cf9")
341356
);
342357
assert_eq!(parsed[0].name, "ISCSI_CONFIG_IFR_NVDATA");
358+
assert_eq!(parsed[0].alt_cfg_id, None);
359+
assert_eq!(parsed[0].elements.len(), 1);
360+
assert_eq!(parsed[0].elements[0].offset, 0x01d8);
361+
assert_eq!(parsed[0].elements[0].width, 1);
362+
assert_eq!(&parsed[0].elements[0].value, &[0x00]);
363+
364+
assert_eq!(
365+
parsed[1].guid,
366+
guid!("4b47d616-a8d6-4552-9d44-ccad2e0f4cf9")
367+
);
368+
assert_eq!(parsed[1].name, "ISCSI_CONFIG_IFR_NVDATA");
369+
assert_eq!(parsed[1].alt_cfg_id, None);
370+
assert_eq!(parsed[1].elements.len(), 2);
371+
assert_eq!(parsed[1].elements[1].offset, 0x1337);
372+
assert_eq!(parsed[1].elements[1].width, 5);
373+
assert_eq!(
374+
&parsed[1].elements[1].value,
375+
&[0x55, 0x44, 0x33, 0x22, 0x11]
376+
);
377+
}
378+
379+
#[test]
380+
fn parse_single_altcfg() {
381+
// exemplary (shortened / manually constructed) UEFI configuration string
382+
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";
383+
let parsed = ConfigurationString::from_str(input).unwrap();
384+
assert_eq!(parsed.guid, guid!("4b47d616-a8d6-4552-9d44-ccad2e0f4cf9"));
385+
assert_eq!(parsed.name, "ISCSI_CONFIG_IFR_NVDATA");
386+
assert_eq!(parsed.alt_cfg_id, Some(1));
387+
assert_eq!(parsed.elements.len(), 11);
388+
assert_eq!(parsed.elements[0].offset, 0x01d8);
389+
assert_eq!(parsed.elements[0].width, 1);
390+
assert_eq!(&parsed.elements[0].value, &[0x00]);
391+
assert_eq!(parsed.elements[10].offset, 0x0fd5);
392+
assert_eq!(parsed.elements[10].width, 1);
393+
assert_eq!(&parsed.elements[10].value, &[0x00]);
394+
}
395+
396+
#[test]
397+
fn parse_multiple_altcfg() {
398+
// exemplary (shortened / manually constructed) UEFI configuration string
399+
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";
400+
let parsed: Vec<_> = MultiConfigurationStringIter::new(input)
401+
.collect::<Result<_, _>>()
402+
.unwrap();
403+
404+
assert_eq!(parsed.len(), 2);
405+
406+
assert_eq!(
407+
parsed[0].guid,
408+
guid!("4b47d616-a8d6-4552-9d44-ccad2e0f4cf9")
409+
);
410+
assert_eq!(parsed[0].name, "ISCSI_CONFIG_IFR_NVDATA");
411+
assert_eq!(parsed[0].alt_cfg_id, Some(2));
343412
assert_eq!(parsed[0].elements.len(), 1);
344413
assert_eq!(parsed[0].elements[0].offset, 0x01d8);
345414
assert_eq!(parsed[0].elements[0].width, 1);
@@ -350,6 +419,7 @@ mod tests {
350419
guid!("4b47d616-a8d6-4552-9d44-ccad2e0f4cf9")
351420
);
352421
assert_eq!(parsed[1].name, "ISCSI_CONFIG_IFR_NVDATA");
422+
assert_eq!(parsed[1].alt_cfg_id, Some(1));
353423
assert_eq!(parsed[1].elements.len(), 2);
354424
assert_eq!(parsed[1].elements[1].offset, 0x1337);
355425
assert_eq!(parsed[1].elements[1].width, 5);

0 commit comments

Comments
 (0)