Skip to content

Commit ac0f872

Browse files
authored
Merge pull request #1983 from rust-osdev/doc-dp-builder
uefi: minor improvements to device path protocol code
2 parents facc028 + 9e855ab commit ac0f872

2 files changed

Lines changed: 41 additions & 29 deletions

File tree

uefi/src/proto/device_path/build.rs

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ impl<'a> DevicePathBuilder<'a> {
9999
/// Add a node to the device path.
100100
///
101101
/// An error will be returned if an [`END_ENTIRE`] node is passed to
102-
/// this function, as that node will be added when `finalize` is
102+
/// this function, as that node will be added when [`Self::finalize`] is
103103
/// called.
104104
///
105105
/// [`END_ENTIRE`]: uefi::proto::device_path::DeviceSubType::END_ENTIRE
@@ -150,6 +150,7 @@ impl<'a> DevicePathBuilder<'a> {
150150
}
151151
}
152152

153+
/// Reference to the backup storage for [`DevicePathBuilder`]
153154
#[derive(Debug)]
154155
enum BuilderStorage<'a> {
155156
Buf {
@@ -246,11 +247,6 @@ mod tests {
246247
use crate::proto::device_path::messaging::{
247248
Ipv4AddressOrigin, IscsiLoginOptions, IscsiProtocol, RestServiceAccessMode, RestServiceType,
248249
};
249-
use core::slice;
250-
251-
const fn path_to_bytes(path: &DevicePath) -> &[u8] {
252-
unsafe { slice::from_raw_parts(path.as_ffi_ptr().cast::<u8>(), size_of_val(path)) }
253-
}
254250

255251
/// Test building an ACPI ADR node.
256252
#[test]
@@ -267,10 +263,8 @@ mod tests {
267263
let node: &crate::proto::device_path::acpi::Adr =
268264
path.node_iter().next().unwrap().try_into().unwrap();
269265
assert_eq!(node.adr().iter().collect::<Vec<_>>(), [1, 2]);
270-
271-
let bytes = path_to_bytes(path);
272266
#[rustfmt::skip]
273-
assert_eq!(bytes, [
267+
assert_eq!(path.as_bytes(), [
274268
// ACPI ADR node
275269
0x02, 0x03, 0x0c, 0x00,
276270
// Values
@@ -308,9 +302,8 @@ mod tests {
308302
assert_eq!(node.uid_str(), b"bc\0");
309303
assert_eq!(node.cid_str(), b"def\0");
310304

311-
let bytes = path_to_bytes(path);
312305
#[rustfmt::skip]
313-
assert_eq!(bytes, [
306+
assert_eq!(path.as_bytes(), [
314307
// ACPI Expanded node
315308
0x02, 0x02, 0x19, 0x00,
316309
// HID
@@ -365,9 +358,8 @@ mod tests {
365358
assert_eq!(node.vendor_guid_and_data().unwrap().0, vendor_guid);
366359
assert_eq!(node.vendor_guid_and_data().unwrap().1, &[1, 2, 3, 4, 5]);
367360

368-
let bytes = path_to_bytes(path);
369361
#[rustfmt::skip]
370-
assert_eq!(bytes, [
362+
assert_eq!(path.as_bytes(), [
371363
// Messaging REST Service node.
372364
0x03, 0x21, 0x06, 0x00,
373365
// Type and access mode
@@ -428,27 +420,32 @@ mod tests {
428420
/// from the UEFI Specification.
429421
#[test]
430422
fn test_fibre_channel_ex_device_path_example() -> Result<(), BuildError> {
431-
// Arbitrarily choose this test to use a statically-sized
432-
// buffer, just to make sure that code path is tested.
433-
let mut buf = [MaybeUninit::uninit(); 256];
434-
let path = DevicePathBuilder::with_buf(&mut buf)
435-
.push(&acpi::Acpi {
423+
let nodes: &[&dyn BuildNode] = &[
424+
&acpi::Acpi {
436425
hid: 0x41d0_0a03,
437426
uid: 0x0000_0000,
438-
})?
439-
.push(&hardware::Pci {
427+
},
428+
&hardware::Pci {
440429
function: 0x00,
441430
device: 0x1f,
442-
})?
443-
.push(&messaging::FibreChannelEx {
431+
},
432+
&messaging::FibreChannelEx {
444433
world_wide_name: [0, 1, 2, 3, 4, 5, 6, 7],
445434
logical_unit_number: [0, 1, 2, 3, 4, 5, 6, 7],
446-
})?
435+
},
436+
];
437+
438+
// Arbitrarily choose this test to use a statically-sized
439+
// buffer, just to make sure that code path is tested.
440+
let mut buf = [MaybeUninit::uninit(); 256];
441+
let path1 = DevicePathBuilder::with_buf(&mut buf)
442+
.push(nodes[0])?
443+
.push(nodes[1])?
444+
.push(nodes[2])?
447445
.finalize()?;
448446

449-
let bytes = path_to_bytes(path);
450447
#[rustfmt::skip]
451-
assert_eq!(bytes, [
448+
const EXPECTED: [u8; 46] = [
452449
// ACPI node
453450
0x02, 0x01, 0x0c, 0x00,
454451
// HID
@@ -477,7 +474,9 @@ mod tests {
477474

478475
// End-entire node
479476
0x7f, 0xff, 0x04, 0x00,
480-
]);
477+
];
478+
479+
assert_eq!(path1.as_bytes(), EXPECTED);
481480

482481
Ok(())
483482
}
@@ -532,9 +531,8 @@ mod tests {
532531
})?
533532
.finalize()?;
534533

535-
let bytes = path_to_bytes(path);
536534
#[rustfmt::skip]
537-
assert_eq!(bytes, [
535+
assert_eq!(path.as_bytes(), [
538536
// ACPI node
539537
0x02, 0x01, 0x0c, 0x00,
540538
// HID

uefi/src/proto/device_path/mod.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@
7575
//! other types in this module are DSTs, so pointers to the type are
7676
//! "fat" and not suitable for FFI.
7777
//!
78+
//! * [`PoolDevicePath`] is an owned device path on the UEFI heap.
79+
//!
7880
//! All of these types use a packed layout and may appear on any byte
7981
//! boundary.
8082
//!
@@ -134,6 +136,10 @@ opaque_type! {
134136
}
135137

136138
/// Device path allocated from UEFI pool memory.
139+
///
140+
/// Please note that this differs from <code>Box<[DevicePath]></code>. Although
141+
/// both represent owned values, a <code>Box<[DevicePath]></code> is on the Rust
142+
/// heap which may or may not be backed by the UEFI heap.
137143
#[derive(Debug)]
138144
pub struct PoolDevicePath(pub(crate) PoolAllocation);
139145

@@ -408,11 +414,15 @@ impl DevicePathInstance {
408414
}
409415

410416
/// Returns a boxed copy of that value.
417+
///
418+
/// The semantics slightly differs from a [`PoolDevicePath`] but is
419+
/// generally more idiomatic to use.
411420
#[cfg(feature = "alloc")]
412421
#[must_use]
413422
pub fn to_boxed(&self) -> Box<Self> {
414423
let data = self.data.to_owned();
415424
let data = data.into_boxed_slice();
425+
// SAFETY: This is safe as a DevicePath has the same layout.
416426
unsafe { mem::transmute(data) }
417427
}
418428
}
@@ -595,12 +605,16 @@ impl DevicePath {
595605
&self.data
596606
}
597607

598-
/// Returns a boxed copy of that value.
608+
/// Returns a boxed copy of that value on the Rust heap.
609+
///
610+
/// The semantics slightly differs from a [`PoolDevicePath`] but is
611+
/// generally more idiomatic to use.
599612
#[cfg(feature = "alloc")]
600613
#[must_use]
601614
pub fn to_boxed(&self) -> Box<Self> {
602615
let data = self.data.to_owned();
603616
let data = data.into_boxed_slice();
617+
// SAFETY: This is safe as a DevicePath has the same layout.
604618
unsafe { mem::transmute(data) }
605619
}
606620

0 commit comments

Comments
 (0)