Skip to content

Commit 80b5e7a

Browse files
phip1611nicholasbishop
authored andcommitted
device_path: enhance device path structs with convenient methods
1 parent 2720436 commit 80b5e7a

File tree

3 files changed

+89
-4
lines changed

3 files changed

+89
-4
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@
22

33
## uefi - [Unreleased]
44

5+
### Added
6+
- `DevicePath::to_boxed`, `DevicePath::to_owned`, and `DevicePath::as_bytes`
7+
- `DevicePathInstance::to_boxed`, `DevicePathInstance::to_owned`, and `DevicePathInstance::as_bytes`
8+
- `DevicePathNode::data`
9+
10+
### Changed
11+
12+
### Removed
13+
514
## uefi-macros - [Unreleased]
615

716
## uefi-services - [Unreleased]

uefi/src/fs/file_system/error.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use crate::fs::{PathBuf, PathError};
22
use alloc::string::FromUtf8Error;
3-
use core::fmt::Debug;
4-
use core::fmt::{self, Display, Formatter};
3+
use core::fmt::{self, Debug, Display, Formatter};
54

65
/// All errors that can happen when working with the [`FileSystem`].
76
///

uefi/src/proto/device_path/mod.rs

Lines changed: 79 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ mod device_path_gen;
8080
pub use device_path_gen::{
8181
acpi, bios_boot_spec, end, hardware, media, messaging, DevicePathNodeEnum,
8282
};
83+
#[cfg(feature = "alloc")]
84+
use {alloc::borrow::ToOwned, alloc::boxed::Box};
8385

8486
use crate::proto::{unsafe_protocol, ProtocolPointer};
8587
use core::ffi::c_void;
@@ -176,6 +178,12 @@ impl DevicePathNode {
176178
self.full_type() == (DeviceType::END, DeviceSubType::END_ENTIRE)
177179
}
178180

181+
/// Returns the payload data of this node.
182+
#[must_use]
183+
pub fn data(&self) -> &[u8] {
184+
&self.data
185+
}
186+
179187
/// Convert from a generic [`DevicePathNode`] reference to an enum
180188
/// of more specific node types.
181189
pub fn as_enum(&self) -> Result<DevicePathNodeEnum, NodeConversionError> {
@@ -226,6 +234,21 @@ impl DevicePathInstance {
226234
stop_condition: StopCondition::AnyEndNode,
227235
}
228236
}
237+
238+
/// Returns a slice of the underlying bytes.
239+
#[must_use]
240+
pub const fn as_bytes(&self) -> &[u8] {
241+
&self.data
242+
}
243+
244+
/// Returns a boxed copy of that value.
245+
#[cfg(feature = "alloc")]
246+
#[must_use]
247+
pub fn to_boxed(&self) -> Box<Self> {
248+
let data = self.data.to_owned();
249+
let data = data.into_boxed_slice();
250+
unsafe { mem::transmute(data) }
251+
}
229252
}
230253

231254
impl Debug for DevicePathInstance {
@@ -242,10 +265,23 @@ impl PartialEq for DevicePathInstance {
242265
}
243266
}
244267

268+
#[cfg(feature = "alloc")]
269+
impl ToOwned for DevicePathInstance {
270+
type Owned = Box<DevicePathInstance>;
271+
272+
fn to_owned(&self) -> Self::Owned {
273+
self.to_boxed()
274+
}
275+
}
276+
245277
/// Device path protocol.
246278
///
247-
/// A device path contains one or more device path instances made of up
248-
/// variable-length nodes. It ends with an [`END_ENTIRE`] node.
279+
/// Can be used on any device handle to obtain generic path/location information
280+
/// concerning the physical device or logical device. If the handle does not
281+
/// logically map to a physical device, the handle may not necessarily support
282+
/// the device path protocol. The device path describes the location of the
283+
/// device the handle is for. The size of the Device Path can be determined from
284+
/// the structures that make up the Device Path.
249285
///
250286
/// See the [module-level documentation] for more details.
251287
///
@@ -326,6 +362,21 @@ impl DevicePath {
326362
stop_condition: StopCondition::EndEntireNode,
327363
}
328364
}
365+
366+
/// Returns a slice of the underlying bytes.
367+
#[must_use]
368+
pub const fn as_bytes(&self) -> &[u8] {
369+
&self.data
370+
}
371+
372+
/// Returns a boxed copy of that value.
373+
#[cfg(feature = "alloc")]
374+
#[must_use]
375+
pub fn to_boxed(&self) -> Box<Self> {
376+
let data = self.data.to_owned();
377+
let data = data.into_boxed_slice();
378+
unsafe { mem::transmute(data) }
379+
}
329380
}
330381

331382
impl Debug for DevicePath {
@@ -342,6 +393,15 @@ impl PartialEq for DevicePath {
342393
}
343394
}
344395

396+
#[cfg(feature = "alloc")]
397+
impl ToOwned for DevicePath {
398+
type Owned = Box<DevicePath>;
399+
400+
fn to_owned(&self) -> Self::Owned {
401+
self.to_boxed()
402+
}
403+
}
404+
345405
/// Iterator over the [`DevicePathInstance`]s in a [`DevicePath`].
346406
///
347407
/// This struct is returned by [`DevicePath::instance_iter`].
@@ -644,6 +704,7 @@ impl Deref for LoadedImageDevicePath {
644704
mod tests {
645705
use super::*;
646706
use alloc::vec::Vec;
707+
use core::mem::{size_of, size_of_val};
647708

648709
/// Create a node to `path` from raw data.
649710
fn add_node(path: &mut Vec<u8>, device_type: u8, sub_type: u8, node_data: &[u8]) {
@@ -748,4 +809,20 @@ mod tests {
748809
// Only two instances.
749810
assert!(iter.next().is_none());
750811
}
812+
813+
#[test]
814+
fn test_to_owned() {
815+
// Relevant assertion to verify the transmute is fine.
816+
assert_eq!(size_of::<&DevicePath>(), size_of::<&[u8]>());
817+
818+
let raw_data = create_raw_device_path();
819+
let dp = unsafe { DevicePath::from_ffi_ptr(raw_data.as_ptr().cast()) };
820+
821+
// Relevant assertion to verify the transmute is fine.
822+
assert_eq!(size_of_val(dp), size_of_val(&dp.data));
823+
824+
let owned_dp = dp.to_owned();
825+
let owned_dp_ref = &*owned_dp;
826+
assert_eq!(owned_dp_ref, dp)
827+
}
751828
}

0 commit comments

Comments
 (0)