Skip to content

doc: streamline device path documentation between uefi-raw and uefi #1641

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
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
1 change: 1 addition & 0 deletions uefi-raw/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
## Changed
- `DevicePathProtocol` now derives
`Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash`
- The documentation for UEFI device paths has been streamlined and improved.


# uefi-raw - 0.10.0 (2025-02-07)
Expand Down
49 changes: 45 additions & 4 deletions uefi-raw/src/protocol/device_path.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,45 @@
// SPDX-License-Identifier: MIT OR Apache-2.0

//! The UEFI device path protocol, i.e., UEFI device paths.
//!
//! This module provides (generated) ABI-compatible bindings to all known device
//! path node types.
//!
//! # Terminology: Device Paths, Device Path Instances, and Device Path Nodes
//! An open UEFI device path [protocol], also called _device path_, is a
//! flexible and structured sequence of binary nodes that describe a route from
//! the UEFI root to a particular device, controller, or file.
//!
//! An entire device path can be made up of multiple device path instances,
//! and each instance is made up of multiple device path nodes. A device path
//! _may_ contain multiple device-path instances separated by [`END_INSTANCE`]
//! nodes, but typical paths contain only a single instance (in which case no
//! [`END_INSTANCE`] node is needed). The entire device path is terminated with
//! an [`END_ENTIRE`] node.
//!
//! Each node represents a step in the path: PCI device, partition, filesystem,
//! file path, etc. Each node represents a step in the path: PCI device,
//! partition, filesystem, file path, etc.
//!
//! Example of what a device path containing two instances (each comprised of
//! three nodes) might look like:
//!
//! ```text
//! ┌──────┬──────┬──────────────╥───────┬──────────┬────────────┐
//! │ ACPI │ PCI │ END_INSTANCE ║ CDROM │ FILEPATH │ END_ENTIRE │
//! └──────┴──────┴──────────────╨───────┴──────────┴────────────┘
//! ↑ ↑ ↑ ↑ ↑ ↑ ↑
//! ├─Node─╨─Node─╨─────Node─────╨─Node──╨───Node───╨────Node────┤
//! ↑ ↑ ↑
//! ├─── DevicePathInstance ─────╨────── DevicePathInstance ─────┤
//! │ │
//! └──────────────────── Entire DevicePath ─────────────────────┘
//! ```
//!
//! [`END_ENTIRE`]: DeviceSubType::END_ENTIRE
//! [`END_INSTANCE`]: DeviceSubType::END_INSTANCE
//! [protocol]: crate::protocol

mod device_path_gen;

use crate::{guid, Boolean, Char16, Guid};
Expand All @@ -8,11 +48,12 @@ pub use device_path_gen::{acpi, bios_boot_spec, end, hardware, media, messaging}

/// Device path protocol.
///
/// A device path contains one or more device path instances made up of
/// variable-length nodes.
/// Note that the fields in this struct define the fixed header at the start of
/// each node; a device path is typically larger than these four bytes.
///
/// See the [module-level documentation] for more details.
///
/// Note that the fields in this struct define the header at the start of each
/// node; a device path is typically larger than these four bytes.
/// [module-level documentation]: self
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[repr(C)]
pub struct DevicePathProtocol {
Expand Down
3 changes: 2 additions & 1 deletion uefi/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@
- The `Display` impl for `CStr8` now excludes the trailing null character.
- `VariableKeys` initializes with a larger name buffer to work around firmware
bugs on some devices.
- The UEFI `allocator::Allocator` has been optimized for page-aligned
- The UEFI `allocator::Allocator` has been optimized for page-aligned
allocations.
- The documentation for UEFI device paths has been streamlined and improved.


# uefi - 0.34.1 (2025-02-07)
Expand Down
87 changes: 63 additions & 24 deletions uefi/src/proto/device_path/mod.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,38 @@
// SPDX-License-Identifier: MIT OR Apache-2.0

//! Device Path protocol
//! The UEFI device path [`Protocol`], i.e., UEFI device paths.
//!
//! A UEFI device path is a very flexible structure for encoding a
//! programmatic path such as a hard drive or console.
//! This module provides high-level wrappers to work with UEFI device paths.
//! Please find additional low-level information in the
//! [device path section of `uefi-raw`].
//!
//! A device path is made up of a packed list of variable-length nodes of
//! various types. The entire device path is terminated with an
//! [`END_ENTIRE`] node. A device path _may_ contain multiple device-path
//! instances separated by [`END_INSTANCE`] nodes, but typical paths contain
//! only a single instance (in which case no `END_INSTANCE` node is needed).
//! # Terminology: Device Paths, Device Path Instances, and Device Path Nodes
//! An open UEFI device path [`Protocol`], also called _device path_, is a
//! flexible and structured sequence of binary nodes that describe a route from
//! the UEFI root to a particular device, controller, or file.
//!
//! An entire device path can be made up of multiple device path instances,
//! and each instance is made up of multiple device path nodes. A device path
//! _may_ contain multiple device-path instances, but typical paths contain only
//! a single instance.
//!
//! Each node represents a step in the path: PCI device, partition, filesystem,
//! file path, etc. Each node represents a step in the path: PCI device,
//! partition, filesystem, file path, etc.
//!
//! Example of what a device path containing two instances (each comprised of
//! three nodes) might look like:
//!
//! ```text
//! ┌──────┬─────┬──────────────╥───────┬──────────┬────────────┐
//! │ ACPI │ PCI │ END_INSTANCE ║ CDROM │ FILEPATH │ END_ENTIRE │
//! └──────┴─────┴──────────────╨───────┴──────────┴────────────┘
//! ↑ ↑ ↑
//! ├─── DevicePathInstance ────╨────── DevicePathInstance ─────┤
//! │ │
//! └─────────────────── Entire DevicePath ─────────────────────┘
//! ┌──────┬──────┬──────────────╥───────┬──────────┬────────────┐
//! │ ACPI │ PCI │ END_INSTANCE ║ CDROM │ FILEPATH │ END_ENTIRE │
//! └──────┴──────┴──────────────╨───────┴──────────┴────────────┘
//! ↑ ↑ ↑ ↑ ↑ ↑ ↑
//! ├─Node─╨─Node─╨─────Node─────╨─Node──╨───Node───╨────Node────┤
//! ↑ ↑ ↑
//! ├─── DevicePathInstance ─────╨────── DevicePathInstance ─────┤
//! │ │
//! └──────────────────── Entire DevicePath ─────────────────────┘
//! ```
Copy link
Member

Choose a reason for hiding this comment

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

I'd like to keep this more detailed documentation in uefi, even if it's also duplicated in uefi-raw. I think users shouldn't normally have to look at uefi-raw unless they're doing something advanced.

Copy link
Member Author

@phip1611 phip1611 Apr 19, 2025

Choose a reason for hiding this comment

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

I don't have a strong opinion, but I like consistency. In #1612 I also put the main documentation into uefi-raw and just forward to it from uefi.

When in doubt, I think I prefer some overlap , as long as uefi-raw holds the majority of the low-level documentation details

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. Do you like the new version better?

//!
//! # Types
Expand Down Expand Up @@ -74,6 +85,7 @@
//! [`Protocol`]: crate::proto::Protocol
//! [`device_type`]: DevicePathNode::device_type
//! [`sub_type`]: DevicePathNode::sub_type
//! [device path section of `uefi-raw`]: uefi_raw::protocol::device_path

pub mod build;
pub mod text;
Expand All @@ -92,7 +104,6 @@ use core::ffi::c_void;
use core::fmt::{self, Debug, Display, Formatter};
use core::ops::Deref;
use ptr_meta::Pointee;

use uefi_raw::protocol::device_path::DevicePathProtocol;
#[cfg(feature = "alloc")]
use {
Expand Down Expand Up @@ -400,21 +411,49 @@ impl ToOwned for DevicePathInstance {
}
}

/// Device path protocol.
/// High-level representation of the UEFI [device path protocol].
///
/// Can be used on any device handle to obtain generic path/location information
/// concerning the physical device or logical device. If the handle does not
/// logically map to a physical device, the handle may not necessarily support
/// the device path protocol. The device path describes the location of the
/// device the handle is for. The size of the Device Path can be determined from
/// the structures that make up the Device Path.
/// This type represents an entire device path, possibly consisting of multiple
/// [`DevicePathInstance`]s and [`DevicePathNode`]s.
///
/// See the [module-level documentation] for more details.
///
/// # Usage
/// This type implements [`Protocol`] and therefore can be used on any
/// device handle to obtain generic path/location information concerning the
/// physical device or logical device. If the handle does not logically map to a
/// physical device, the handle may not necessarily support the device path
/// protocol. The device path describes the location of the device the handle is
/// for. The size of the Device Path can be determined from the structures that
/// make up the Device Path.
///
/// # Example
/// ```rust,no_run
/// use uefi::Handle;
/// use uefi::boot::{open_protocol_exclusive, ScopedProtocol};
/// use uefi::proto::device_path::DevicePath;
/// use uefi::proto::device_path::text::{AllowShortcuts, DisplayOnly};
/// use uefi::proto::loaded_image::LoadedImage;
///
/// fn open_device_path(image_handle: Handle) {
/// let loaded_image = open_protocol_exclusive::<LoadedImage>(image_handle).unwrap();
/// let device_handle = loaded_image.device().unwrap();
/// let device_path: ScopedProtocol<DevicePath>
/// = open_protocol_exclusive::<DevicePath>(device_handle).unwrap();
/// log::debug!(
/// "Device path: {}",
/// device_path.to_string(DisplayOnly(true), AllowShortcuts(true)).unwrap()
/// );
/// }
/// ```
///
/// [module-level documentation]: crate::proto::device_path
/// [`END_ENTIRE`]: DeviceSubType::END_ENTIRE
/// [`DevicePathProtocol`]: uefi_raw::protocol::device_path::DevicePathProtocol
/// [`Protocol`]: uefi::proto::Protocol
/// [device path protocol]: uefi_raw::protocol::device_path
#[repr(C, packed)]
#[unsafe_protocol(uefi_raw::protocol::device_path::DevicePathProtocol::GUID)]
#[unsafe_protocol(DevicePathProtocol::GUID)]
#[derive(Eq, Pointee)]
pub struct DevicePath {
data: [u8],
Expand Down
Loading