Skip to content

Commit 8720aef

Browse files
committed
uefi: Extend ConfigurationString parsing with alt_cfg_id variant
1 parent d07f890 commit 8720aef

File tree

1 file changed

+69
-0
lines changed

1 file changed

+69
-0
lines changed

uefi/src/proto/hii/config_str.rs

Lines changed: 69 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
}
@@ -311,6 +326,7 @@ mod tests {
311326
let parsed = ConfigurationString::from_str(input).unwrap();
312327
assert_eq!(parsed.guid, guid!("4b47d616-a8d6-4552-9d44-ccad2e0f4cf9"));
313328
assert_eq!(parsed.name, "ISCSI_CONFIG_IFR_NVDATA");
329+
assert_eq!(parsed.alt_cfg_id, None);
314330
assert_eq!(parsed.elements.len(), 11);
315331
assert_eq!(parsed.elements[0].offset, 0x01d8);
316332
assert_eq!(parsed.elements[0].width, 2);
@@ -334,6 +350,58 @@ mod tests {
334350
guid!("4b47d616-a8d6-4552-9d44-ccad2e0f4cf9")
335351
);
336352
assert_eq!(parsed[0].name, "ISCSI_CONFIG_IFR_NVDATA");
353+
assert_eq!(parsed[0].alt_cfg_id, None);
354+
assert_eq!(parsed[0].elements.len(), 1);
355+
assert_eq!(parsed[0].elements[0].offset, 0x01d8);
356+
assert_eq!(parsed[0].elements[0].width, 1);
357+
assert_eq!(&parsed[0].elements[0].value, &[0x00]);
358+
359+
assert_eq!(
360+
parsed[1].guid,
361+
guid!("4b47d616-a8d6-4552-9d44-ccad2e0f4cf9")
362+
);
363+
assert_eq!(parsed[1].name, "ISCSI_CONFIG_IFR_NVDATA");
364+
assert_eq!(parsed[1].alt_cfg_id, None);
365+
assert_eq!(parsed[1].elements.len(), 2);
366+
assert_eq!(parsed[1].elements[1].offset, 0x1337);
367+
assert_eq!(parsed[1].elements[1].width, 5);
368+
assert_eq!(
369+
&parsed[1].elements[1].value,
370+
&[0x55, 0x44, 0x33, 0x22, 0x11]
371+
);
372+
}
373+
374+
#[test]
375+
fn parse_single_altcfg() {
376+
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";
377+
let parsed = ConfigurationString::from_str(input).unwrap();
378+
assert_eq!(parsed.guid, guid!("4b47d616-a8d6-4552-9d44-ccad2e0f4cf9"));
379+
assert_eq!(parsed.name, "ISCSI_CONFIG_IFR_NVDATA");
380+
assert_eq!(parsed.alt_cfg_id, Some(1));
381+
assert_eq!(parsed.elements.len(), 11);
382+
assert_eq!(parsed.elements[0].offset, 0x01d8);
383+
assert_eq!(parsed.elements[0].width, 1);
384+
assert_eq!(&parsed.elements[0].value, &[0x00]);
385+
assert_eq!(parsed.elements[10].offset, 0x0fd5);
386+
assert_eq!(parsed.elements[10].width, 1);
387+
assert_eq!(&parsed.elements[10].value, &[0x00]);
388+
}
389+
390+
#[test]
391+
fn parse_multiple_altcfg() {
392+
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";
393+
let parsed: Vec<_> = MultiConfigurationStringIter::new(input)
394+
.collect::<Result<_, _>>()
395+
.unwrap();
396+
397+
assert_eq!(parsed.len(), 2);
398+
399+
assert_eq!(
400+
parsed[0].guid,
401+
guid!("4b47d616-a8d6-4552-9d44-ccad2e0f4cf9")
402+
);
403+
assert_eq!(parsed[0].name, "ISCSI_CONFIG_IFR_NVDATA");
404+
assert_eq!(parsed[0].alt_cfg_id, Some(2));
337405
assert_eq!(parsed[0].elements.len(), 1);
338406
assert_eq!(parsed[0].elements[0].offset, 0x01d8);
339407
assert_eq!(parsed[0].elements[0].width, 1);
@@ -344,6 +412,7 @@ mod tests {
344412
guid!("4b47d616-a8d6-4552-9d44-ccad2e0f4cf9")
345413
);
346414
assert_eq!(parsed[1].name, "ISCSI_CONFIG_IFR_NVDATA");
415+
assert_eq!(parsed[1].alt_cfg_id, Some(1));
347416
assert_eq!(parsed[1].elements.len(), 2);
348417
assert_eq!(parsed[1].elements[1].offset, 0x1337);
349418
assert_eq!(parsed[1].elements[1].width, 5);

0 commit comments

Comments
 (0)