Skip to content
  • Sponsor
  • Notifications You must be signed in to change notification settings
  • Fork 169

relicensing: Rewrite PR "DevicePathToText and DevicePathFromText Protocol" #1528

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 5, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 38 additions & 41 deletions uefi/src/proto/device_path/text.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//! `DevicePathToText` and `DevicePathFromText` Protocol
//! Protocols for converting between UEFI strings and [`DevicePath`]/[`DevicePathNode`].

// Note on return types: the specification of the conversion functions
// is a little unusual in that they return a pointer rather than
@@ -16,32 +16,39 @@ use core::ops::Deref;
use core::ptr::NonNull;
use uefi_raw::protocol::device_path::{DevicePathFromTextProtocol, DevicePathToTextProtocol};

/// This struct is a wrapper of `display_only` parameter
/// used by Device Path to Text protocol.
/// Parameter for [`DevicePathToText`] that alters the output format.
///
/// The `display_only` parameter controls whether the longer
/// (parseable) or shorter (display-only) form of the conversion
/// is used. If `display_only` is TRUE, then the shorter text
/// representation of the display node is used, where applicable.
/// If `display_only` is FALSE, then the longer text representation
/// of the display node is used.
/// * `DisplayOnly(false)` produces parseable output.
/// * `DisplayOnly(true)` produces output that _may_ be shorter and not
/// parseable.
///
/// Example of how a node's text representation may be altered by this
/// parameter:
/// * `DisplayOnly(false)`: `Ata(Primary,Master,0x1)`
/// * `DisplayOnly(true)`: `Ata(0x1)`
#[derive(Clone, Copy, Debug)]
pub struct DisplayOnly(pub bool);

/// This struct is a wrapper of `allow_shortcuts` parameter
/// used by Device Path to Text protocol.
/// Parameter for [`DevicePathToText`] that alters the output format.
///
/// * `AllowShortcuts(false)`: node names are based only on the node's type and
/// subtype.
/// * `AllowShortcuts(true)` _may_ alter the node name based on other fields
/// within the node.
///
/// The `allow_shortcuts` is FALSE, then the shortcut forms of
/// text representation for a device node cannot be used. A
/// shortcut form is one which uses information other than the
/// type or subtype. If `allow_shortcuts is TRUE, then the
/// shortcut forms of text representation for a device node
/// can be used, where applicable.
/// Example of how a node's text representation may be altered by this
/// parameter:
/// * `AllowShortcuts(false)`: `VenMsg(E0C14753-F9BE-11D2-9A0C-0090273FC14D)`
/// * `AllowShortcuts(true)`: `VenPcAnsi()`
#[derive(Clone, Copy, Debug)]
pub struct AllowShortcuts(pub bool);

/// Wrapper for a string internally allocated from
/// UEFI boot services memory.
/// UCS-2 string allocated from UEFI pool memory.
///
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

General question: Why do we have this type? I think, this can also be a CString16?

Do we at least want to write how it differs from CString16?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the docstring to clarify. Since this is allocated internally by UEFI, we'd have to do a second memory allocation to copy it to a CString16. (Or alternatively, the CString16 type could be modified to contain either a Vec or a pool allocation, and switch out how it's dropped at the end, but that's probably more complicated than it's worth.) I'm not necessarily opposed to doing something else here, like just accept an extra memory copy, but should probably think about that as part of #1303 since CString16 requires the alloc feature.

/// This is similar to a [`CString16`], but used for memory that was allocated
/// internally by UEFI rather than the Rust allocator.
///
/// [`CString16`]: crate::CString16
#[derive(Debug)]
pub struct PoolString(PoolAllocation);

@@ -85,17 +92,14 @@ impl Deref for PoolDevicePathNode {
}
}

/// Device Path to Text protocol.
///
/// This protocol provides common utility functions for converting device
/// nodes and device paths to a text representation.
/// Protocol for converting a [`DevicePath`] or `DevicePathNode`] to a string.
#[derive(Debug)]
#[repr(transparent)]
#[unsafe_protocol(DevicePathToTextProtocol::GUID)]
pub struct DevicePathToText(DevicePathToTextProtocol);

impl DevicePathToText {
/// Convert a device node to its text representation.
/// Convert a [`DevicePathNode`] to a [`PoolString`].
///
/// Returns an [`OUT_OF_RESOURCES`] error if there is insufficient
/// memory for the conversion.
@@ -107,17 +111,17 @@ impl DevicePathToText {
display_only: DisplayOnly,
allow_shortcuts: AllowShortcuts,
) -> Result<PoolString> {
let text_device_node = unsafe {
let text = unsafe {
(self.0.convert_device_node_to_text)(
device_node.as_ffi_ptr().cast(),
display_only.0,
allow_shortcuts.0,
)
};
PoolString::new(text_device_node.cast())
PoolString::new(text.cast())
}

/// Convert a device path to its text representation.
/// Convert a [`DevicePath`] to a [`PoolString`].
///
/// Returns an [`OUT_OF_RESOURCES`] error if there is insufficient
/// memory for the conversion.
@@ -129,32 +133,27 @@ impl DevicePathToText {
display_only: DisplayOnly,
allow_shortcuts: AllowShortcuts,
) -> Result<PoolString> {
let text_device_path = unsafe {
let text = unsafe {
(self.0.convert_device_path_to_text)(
device_path.as_ffi_ptr().cast(),
display_only.0,
allow_shortcuts.0,
)
};
PoolString::new(text_device_path.cast())
PoolString::new(text.cast())
}
}

/// Device Path from Text protocol.
///
/// This protocol provides common utilities for converting text to
/// device paths and device nodes.
/// Protocol for converting a string to a [`DevicePath`] or `DevicePathNode`].
#[derive(Debug)]
#[repr(transparent)]
#[unsafe_protocol("05c99a21-c70f-4ad2-8a5f-35df3343f51e")]
pub struct DevicePathFromText(DevicePathFromTextProtocol);

impl DevicePathFromText {
/// Convert text to the binary representation of a device node.
/// Convert a [`CStr16`] to a [`DevicePathNode`].
///
/// `text_device_node` is the text representation of a device node.
/// Conversion starts with the first character and continues until
/// the first non-device node character.
/// If a non-device-node character is encountered, the rest of the string is ignored.
///
/// Returns an [`OUT_OF_RESOURCES`] error if there is insufficient
/// memory for the conversion.
@@ -172,11 +171,9 @@ impl DevicePathFromText {
}
}

/// Convert a text to its binary device path representation.
/// Convert a [`CStr16`] to a [`DevicePath`].
///
/// `text_device_path` is the text representation of a device path.
/// Conversion starts with the first character and continues until
/// the first non-device path character.
/// If a non-device-node character is encountered, the rest of the string is ignored.
///
/// Returns an [`OUT_OF_RESOURCES`] error if there is insufficient
/// memory for the conversion.