Skip to content

Commit 716ac24

Browse files
committed
device_path: enhance DevicePath with convenient methods
1 parent 2720436 commit 716ac24

File tree

3 files changed

+76
-4
lines changed

3 files changed

+76
-4
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# Changelog
22

33
## uefi - [Unreleased]
4+
- added `DevicePath::to_boxed`, `DevicePath::to_owned`, and `DevicePath::raw`
5+
- added `DevicePathInstance::to_boxed`, `DevicePathInstance::to_owned`, and `DevicePathInstance::raw`
46

57
## uefi-macros - [Unreleased]
68

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: 73 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;
@@ -226,6 +228,21 @@ impl DevicePathInstance {
226228
stop_condition: StopCondition::AnyEndNode,
227229
}
228230
}
231+
232+
/// Returns a slice of the underlying bytes.
233+
#[must_use]
234+
pub const fn as_bytes(&self) -> &[u8] {
235+
&self.data
236+
}
237+
238+
/// Returns a boxed copy of that value.
239+
#[cfg(feature = "alloc")]
240+
#[must_use]
241+
pub fn to_boxed(&self) -> Box<Self> {
242+
let data = self.data.to_owned();
243+
let data = data.into_boxed_slice();
244+
unsafe { mem::transmute(data) }
245+
}
229246
}
230247

231248
impl Debug for DevicePathInstance {
@@ -242,10 +259,23 @@ impl PartialEq for DevicePathInstance {
242259
}
243260
}
244261

262+
#[cfg(feature = "alloc")]
263+
impl ToOwned for DevicePathInstance {
264+
type Owned = Box<DevicePathInstance>;
265+
266+
fn to_owned(&self) -> Self::Owned {
267+
self.to_boxed()
268+
}
269+
}
270+
245271
/// Device path protocol.
246272
///
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.
273+
/// Can be used on any device handle to obtain generic path/location information
274+
/// concerning the physical device or logical device. If the handle does not
275+
/// logically map to a physical device, the handle may not necessarily support
276+
/// the device path protocol. The device path describes the location of the
277+
/// device the handle is for. The size of the Device Path can be determined from
278+
/// the structures that make up the Device Path.
249279
///
250280
/// See the [module-level documentation] for more details.
251281
///
@@ -326,6 +356,21 @@ impl DevicePath {
326356
stop_condition: StopCondition::EndEntireNode,
327357
}
328358
}
359+
360+
/// Returns a slice of the underlying bytes.
361+
#[must_use]
362+
pub const fn as_bytes(&self) -> &[u8] {
363+
&self.data
364+
}
365+
366+
/// Returns a boxed copy of that value.
367+
#[cfg(feature = "alloc")]
368+
#[must_use]
369+
pub fn to_boxed(&self) -> Box<Self> {
370+
let data = self.data.to_owned();
371+
let data = data.into_boxed_slice();
372+
unsafe { mem::transmute(data) }
373+
}
329374
}
330375

331376
impl Debug for DevicePath {
@@ -342,6 +387,15 @@ impl PartialEq for DevicePath {
342387
}
343388
}
344389

390+
#[cfg(feature = "alloc")]
391+
impl ToOwned for DevicePath {
392+
type Owned = Box<DevicePath>;
393+
394+
fn to_owned(&self) -> Self::Owned {
395+
self.to_boxed()
396+
}
397+
}
398+
345399
/// Iterator over the [`DevicePathInstance`]s in a [`DevicePath`].
346400
///
347401
/// This struct is returned by [`DevicePath::instance_iter`].
@@ -644,6 +698,7 @@ impl Deref for LoadedImageDevicePath {
644698
mod tests {
645699
use super::*;
646700
use alloc::vec::Vec;
701+
use core::mem::{size_of, size_of_val};
647702

648703
/// Create a node to `path` from raw data.
649704
fn add_node(path: &mut Vec<u8>, device_type: u8, sub_type: u8, node_data: &[u8]) {
@@ -748,4 +803,20 @@ mod tests {
748803
// Only two instances.
749804
assert!(iter.next().is_none());
750805
}
806+
807+
#[test]
808+
fn test_to_owned() {
809+
// Relevant assertion to verify the transmute is fine.
810+
assert_eq!(size_of::<&DevicePath>(), size_of::<&[u8]>());
811+
812+
let raw_data = create_raw_device_path();
813+
let dp = unsafe { DevicePath::from_ffi_ptr(raw_data.as_ptr().cast()) };
814+
815+
// Relevant assertion to verify the transmute is fine.
816+
assert_eq!(size_of_val(dp), size_of_val(&dp.data));
817+
818+
let owned_dp = dp.to_owned();
819+
let owned_dp_ref = &*owned_dp;
820+
assert_eq!(owned_dp_ref, dp)
821+
}
751822
}

0 commit comments

Comments
 (0)