Skip to content

Commit 47095b1

Browse files
committed
uefi: impl Display for DevicePath, DevicePathNode, and ScopedProtocol
For device paths, it is very convenient to use the DevicePathToText protocol to visualize/print the device path. By providing a convenient Display impl, we improve the ergonomics of device paths significantly and reducing boilerplate.
1 parent 86f82fa commit 47095b1

3 files changed

Lines changed: 49 additions & 2 deletions

File tree

uefi/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@
1111
- Added `proto::device_path::DevicePathUtilities::duplicate_path()`.
1212
- Added `proto::pci::enumeration::PciTree::device_path()`.
1313
- Added `revision()` and `device_type_guid()` to `Serial` protocol
14+
- Implemented `Display` for `DevicePath`, `DevicePathNode` and `ScopedProtocol`,
15+
enabling a easy and convenient way to visualize a device path. For example,
16+
this may print `PciRoot(0x0)/Pci(0x6,0x0)/MAC(525400000001,0x1)`.
17+
`ScopedProtocol` only implements `Display` if the underlying protocol also
18+
implements `Display`.
1419

1520
## Changed
1621
- export all `text::{input, output}::*` types

uefi/src/boot.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ use crate::table::Revision;
4545
use crate::util::opt_nonnull_to_ptr;
4646
use crate::{Char16, Error, Event, Guid, Handle, Result, Status, StatusExt, table};
4747
use core::ffi::c_void;
48+
use core::fmt::{Display, Formatter};
4849
use core::mem::MaybeUninit;
4950
use core::ops::{Deref, DerefMut};
5051
use core::ptr::{self, NonNull};
@@ -1619,6 +1620,20 @@ impl<P: Protocol + ?Sized> ScopedProtocol<P> {
16191620
}
16201621
}
16211622

1623+
// Forward Display impl to inner protocol:
1624+
impl<P: Protocol + ?Sized + Display> Display for ScopedProtocol<P> {
1625+
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
1626+
match self.get() {
1627+
Some(proto) => {
1628+
write!(f, "{proto}")
1629+
}
1630+
None => {
1631+
write!(f, "<none>")
1632+
}
1633+
}
1634+
}
1635+
}
1636+
16221637
impl<P: Protocol + ?Sized> Drop for ScopedProtocol<P> {
16231638
fn drop(&mut self) {
16241639
let bt = boot_services_raw_panicking();

uefi/src/proto/device_path/mod.rs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,20 @@ impl DevicePathNode {
323323
}
324324
}
325325

326+
#[cfg(feature = "alloc")]
327+
impl Display for DevicePathNode {
328+
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
329+
if boot::are_boot_services_active() {
330+
let cstring16 = self
331+
.to_string16(DisplayOnly(true), AllowShortcuts(true))
332+
.unwrap();
333+
write!(f, "{}", cstring16)
334+
} else {
335+
write!(f, "<device path node: {} bytes>", self.data.len())
336+
}
337+
}
338+
}
339+
326340
impl Debug for DevicePathNode {
327341
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
328342
f.debug_struct("DevicePathNode")
@@ -459,8 +473,7 @@ impl ToOwned for DevicePathInstance {
459473
/// let device_path: ScopedProtocol<DevicePath>
460474
/// = open_protocol_exclusive::<DevicePath>(device_handle).unwrap();
461475
/// log::debug!(
462-
/// "Device path: {}",
463-
/// device_path.to_string16(DisplayOnly(true), AllowShortcuts(true)).unwrap()
476+
/// "Device path: {device_path}",
464477
/// );
465478
/// }
466479
/// ```
@@ -640,6 +653,20 @@ impl DevicePath {
640653
}
641654
}
642655

656+
#[cfg(feature = "alloc")]
657+
impl Display for DevicePath {
658+
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
659+
if boot::are_boot_services_active() {
660+
let cstring16 = self
661+
.to_string16(DisplayOnly(true), AllowShortcuts(true))
662+
.unwrap();
663+
write!(f, "{}", cstring16)
664+
} else {
665+
write!(f, "<device path: {} bytes>", self.data.len())
666+
}
667+
}
668+
}
669+
643670
impl Debug for DevicePath {
644671
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
645672
f.debug_struct("DevicePath")

0 commit comments

Comments
 (0)