Skip to content

Commit 962475e

Browse files
committed
uefi: Add TryFrom u8 slice to DevicePathNode
Adds the capability to convert a byte slice to a DevicePathNode. This will be used to convert a byte slice to a DevicePath in a followup PR, which allows easier interaction with the data returned from UEFI variable services.
1 parent 99a2433 commit 962475e

File tree

2 files changed

+44
-1
lines changed

2 files changed

+44
-1
lines changed

uefi/CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
- Added `table::{set_system_table, system_table_boot, system_table_runtime}`.
1212
This provides an initial API for global tables that do not require passing
1313
around a reference.
14-
- Added `TryFrom<&[u8]>` for `DevicePathHeader`.
14+
- Added `TryFrom<&[u8]>` for `DevicePathHeader` and `DevicePathNode`.
1515
- Added `ByteConversionError`.
1616

1717
## Changed

uefi/src/proto/device_path/mod.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,20 @@ impl PartialEq for DevicePathNode {
266266
}
267267
}
268268

269+
impl<'a> TryFrom<&[u8]> for &'a DevicePathNode {
270+
type Error = ByteConversionError;
271+
272+
fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
273+
let dp = <&DevicePathHeader>::try_from(bytes)?;
274+
if usize::from(dp.length) <= bytes.len() {
275+
unsafe {
276+
return Ok(DevicePathNode::from_ffi_ptr(bytes.as_ptr().cast()));
277+
}
278+
}
279+
Err(ByteConversionError::InvalidLength)
280+
}
281+
}
282+
269283
/// A single device path instance that ends with either an [`END_INSTANCE`]
270284
/// or [`END_ENTIRE`] node. Use [`DevicePath::instance_iter`] to get the
271285
/// path instances in a [`DevicePath`].
@@ -975,4 +989,33 @@ mod tests {
975989
let owned_dp_ref = &*owned_dp;
976990
assert_eq!(owned_dp_ref, dp)
977991
}
992+
993+
#[test]
994+
fn test_device_path_from_bytes() {
995+
let mut raw_data = Vec::new();
996+
let node = [0xa0, 0xb0];
997+
let node_data = &[10, 11];
998+
let mut dp;
999+
1000+
// Raw data is less than size of a [`DevicePathNode`].
1001+
raw_data.push(node[0]);
1002+
dp = <&DevicePathNode>::try_from(raw_data.as_slice());
1003+
assert!(dp.is_err());
1004+
1005+
// Raw data is long enough to hold a [`DevicePathNode`].
1006+
raw_data.push(node[1]);
1007+
raw_data.extend(
1008+
u16::try_from(mem::size_of::<DevicePathHeader>() + node_data.len())
1009+
.unwrap()
1010+
.to_le_bytes(),
1011+
);
1012+
raw_data.extend(node_data);
1013+
dp = <&DevicePathNode>::try_from(raw_data.as_slice());
1014+
assert!(dp.is_ok());
1015+
1016+
// [`DevicePathNode`] data length exceeds the raw_data slice.
1017+
raw_data[2] += 1;
1018+
dp = <&DevicePathNode>::try_from(raw_data.as_slice());
1019+
assert!(dp.is_err());
1020+
}
9781021
}

0 commit comments

Comments
 (0)