Skip to content

Commit a5ad978

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 a5ad978

File tree

2 files changed

+46
-1
lines changed

2 files changed

+46
-1
lines changed

uefi/CHANGELOG.md

+1-1
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

+45
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,22 @@ 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+
if mem::size_of::<DevicePathHeader>() <= bytes.len() {
274+
let dp = <&DevicePathHeader>::try_from(bytes)?;
275+
if dp.length as usize <= bytes.len() {
276+
unsafe {
277+
return Ok(DevicePathNode::from_ffi_ptr(bytes.as_ptr().cast()));
278+
}
279+
}
280+
}
281+
Err(ByteConversionError::InvalidLength)
282+
}
283+
}
284+
269285
/// A single device path instance that ends with either an [`END_INSTANCE`]
270286
/// or [`END_ENTIRE`] node. Use [`DevicePath::instance_iter`] to get the
271287
/// path instances in a [`DevicePath`].
@@ -975,4 +991,33 @@ mod tests {
975991
let owned_dp_ref = &*owned_dp;
976992
assert_eq!(owned_dp_ref, dp)
977993
}
994+
995+
#[test]
996+
fn test_device_path_from_bytes() {
997+
let mut raw_data = Vec::new();
998+
let node = [0xa0, 0xb0];
999+
let node_data = &[10, 11];
1000+
let mut dp;
1001+
1002+
// Raw data is less than size of a [`DevicePathNode`].
1003+
raw_data.push(node[0]);
1004+
dp = <&DevicePathNode>::try_from(raw_data.as_slice());
1005+
assert!(dp.is_err());
1006+
1007+
// Raw data is long enough to hold a [`DevicePathNode`].
1008+
raw_data.push(node[1]);
1009+
raw_data.extend(
1010+
u16::try_from(mem::size_of::<DevicePathHeader>() + node_data.len())
1011+
.unwrap()
1012+
.to_le_bytes(),
1013+
);
1014+
raw_data.extend(node_data);
1015+
dp = <&DevicePathNode>::try_from(raw_data.as_slice());
1016+
assert!(dp.is_ok());
1017+
1018+
// [`DevicePathNode`] data length exceeds the raw_data slice.
1019+
raw_data[2] += 1;
1020+
dp = <&DevicePathNode>::try_from(raw_data.as_slice());
1021+
assert!(dp.is_err());
1022+
}
9781023
}

0 commit comments

Comments
 (0)