Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit e3d5afb

Browse files
authoredApr 19, 2025··
Merge pull request #1613 from rust-osdev/dvcp
uefi: remove duplication in DevicePathHeader; use uefi-raw
2 parents ae01a75 + 762905a commit e3d5afb

File tree

7 files changed

+427
-401
lines changed

7 files changed

+427
-401
lines changed
 

‎uefi-raw/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@
1414
- Added `DevicePathUtilitiesProtocol`.
1515
- Added `UsbIoProtocol`.
1616
- Added `Usb2HostControllerProtocol`.
17+
- Added `DevicePathProtocol::length()` properly constructing the `u16` value
18+
19+
## Changed
20+
- `DevicePathProtocol` now derives
21+
`Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash`
1722

1823

1924
# uefi-raw - 0.10.0 (2025-02-07)

‎uefi-raw/src/protocol/device_path.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,29 @@ pub use device_path_gen::{acpi, bios_boot_spec, end, hardware, media, messaging}
88

99
/// Device path protocol.
1010
///
11-
/// A device path contains one or more device path instances made of up
11+
/// A device path contains one or more device path instances made up of
1212
/// variable-length nodes.
1313
///
1414
/// Note that the fields in this struct define the header at the start of each
1515
/// node; a device path is typically larger than these four bytes.
16-
#[derive(Debug)]
16+
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
1717
#[repr(C)]
1818
pub struct DevicePathProtocol {
1919
pub major_type: DeviceType,
2020
pub sub_type: DeviceSubType,
21+
/// Total length of the type including the fixed header as u16 in LE order.
2122
pub length: [u8; 2],
2223
// followed by payload (dynamically sized)
2324
}
2425

2526
impl DevicePathProtocol {
2627
pub const GUID: Guid = guid!("09576e91-6d3f-11d2-8e39-00a0c969723b");
28+
29+
/// Returns the total length of the device path node.
30+
#[must_use]
31+
pub const fn length(&self) -> u16 {
32+
u16::from_le_bytes(self.length)
33+
}
2734
}
2835

2936
newtype_enum! {
@@ -252,3 +259,17 @@ pub struct DevicePathUtilitiesProtocol {
252259
impl DevicePathUtilitiesProtocol {
253260
pub const GUID: Guid = guid!("0379be4e-d706-437d-b037-edb82fb772a4");
254261
}
262+
263+
#[cfg(test)]
264+
mod tests {
265+
use super::*;
266+
use core::mem;
267+
268+
/// Test that ensures the struct is packed. Thus, we don't need to
269+
/// explicitly specify `packed`.
270+
#[test]
271+
fn abi() {
272+
assert_eq!(mem::size_of::<DevicePathProtocol>(), 4);
273+
assert_eq!(mem::align_of::<DevicePathProtocol>(), 1);
274+
}
275+
}

‎uefi/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
`proto::device_path::text` to `proto::device_path`.
2828
- **Breaking:** `exit_boot_services` now consumes a `Option<MemoryType>` which
2929
defaults to the recommended value of `MemoryType::LOADER_DATA`.
30+
- **Breaking:** Removed duplication in `DevicePathHeader`. Instead of public fields,
31+
there is now a public constructor combined with public getters.
3032
- `boot::memory_map()` will never return `Status::BUFFER_TOO_SMALL` from now on,
3133
as this is considered a hard internal error where users can't do anything
3234
about it anyway. It will panic instead.

‎uefi/src/proto/device_path/build.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ pub unsafe trait BuildNode {
225225

226226
unsafe impl BuildNode for &DevicePathNode {
227227
fn size_in_bytes(&self) -> Result<u16, BuildError> {
228-
Ok(self.header.length)
228+
Ok(self.header.length())
229229
}
230230

231231
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {

‎uefi/src/proto/device_path/device_path_gen.rs

Lines changed: 347 additions & 378 deletions
Large diffs are not rendered by default.

‎uefi/src/proto/device_path/mod.rs

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ pub mod text;
8080
pub mod util;
8181

8282
mod device_path_gen;
83+
8384
pub use device_path_gen::{
8485
acpi, bios_boot_spec, end, hardware, media, messaging, DevicePathNodeEnum,
8586
};
@@ -92,6 +93,7 @@ use core::fmt::{self, Debug, Display, Formatter};
9293
use core::ops::Deref;
9394
use ptr_meta::Pointee;
9495

96+
use uefi_raw::protocol::device_path::DevicePathProtocol;
9597
#[cfg(feature = "alloc")]
9698
use {
9799
crate::boot::{self, OpenProtocolAttributes, OpenProtocolParams, ScopedProtocol, SearchType},
@@ -135,16 +137,41 @@ impl Deref for PoolDevicePathNode {
135137
}
136138
}
137139

138-
/// Header that appears at the start of every [`DevicePathNode`].
140+
/// Fixed header that appears at the start of every [`DevicePathNode`].
141+
///
142+
/// This type is ABI-compatible with `EFI_DEVICE_PATH_PROTOCOL`.
139143
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
140-
#[repr(C, packed)]
141-
pub struct DevicePathHeader {
142-
/// Type of device
143-
pub device_type: DeviceType,
144-
/// Sub type of device
145-
pub sub_type: DeviceSubType,
146-
/// Size (in bytes) of the [`DevicePathNode`], including this header.
147-
pub length: u16,
144+
#[repr(transparent)]
145+
pub struct DevicePathHeader(DevicePathProtocol);
146+
147+
impl DevicePathHeader {
148+
/// Constructs a new [`DevicePathHeader`].
149+
#[must_use]
150+
pub const fn new(major_type: DeviceType, sub_type: DeviceSubType, length: u16) -> Self {
151+
Self(DevicePathProtocol {
152+
major_type,
153+
sub_type,
154+
length: length.to_le_bytes(),
155+
})
156+
}
157+
158+
/// Returns the [`DeviceType`].
159+
#[must_use]
160+
pub const fn device_type(&self) -> DeviceType {
161+
self.0.major_type
162+
}
163+
164+
/// Returns the [`DeviceSubType`].
165+
#[must_use]
166+
pub const fn sub_type(&self) -> DeviceSubType {
167+
self.0.sub_type
168+
}
169+
170+
/// Returns the total length of the device path node.
171+
#[must_use]
172+
pub const fn length(&self) -> u16 {
173+
self.0.length()
174+
}
148175
}
149176

150177
impl<'a> TryFrom<&'a [u8]> for &'a DevicePathHeader {
@@ -202,7 +229,7 @@ impl DevicePathNode {
202229
pub unsafe fn from_ffi_ptr<'a>(ptr: *const FfiDevicePath) -> &'a Self {
203230
let header = unsafe { *ptr.cast::<DevicePathHeader>() };
204231

205-
let data_len = usize::from(header.length) - size_of::<DevicePathHeader>();
232+
let data_len = usize::from(header.length()) - size_of::<DevicePathHeader>();
206233
unsafe { &*ptr_meta::from_raw_parts(ptr.cast(), data_len) }
207234
}
208235

@@ -216,25 +243,25 @@ impl DevicePathNode {
216243
/// Type of device
217244
#[must_use]
218245
pub const fn device_type(&self) -> DeviceType {
219-
self.header.device_type
246+
self.header.device_type()
220247
}
221248

222249
/// Sub type of device
223250
#[must_use]
224251
pub const fn sub_type(&self) -> DeviceSubType {
225-
self.header.sub_type
252+
self.header.sub_type()
226253
}
227254

228255
/// Tuple of the node's type and subtype.
229256
#[must_use]
230257
pub const fn full_type(&self) -> (DeviceType, DeviceSubType) {
231-
(self.header.device_type, self.header.sub_type)
258+
(self.device_type(), self.sub_type())
232259
}
233260

234261
/// Size (in bytes) of the full [`DevicePathNode`], including the header.
235262
#[must_use]
236263
pub const fn length(&self) -> u16 {
237-
self.header.length
264+
self.header.length()
238265
}
239266

240267
/// True if this node ends an entire [`DevicePath`].
@@ -297,7 +324,7 @@ impl<'a> TryFrom<&'a [u8]> for &'a DevicePathNode {
297324

298325
fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
299326
let dp = <&DevicePathHeader>::try_from(bytes)?;
300-
if usize::from(dp.length) <= bytes.len() {
327+
if usize::from(dp.length()) <= bytes.len() {
301328
unsafe { Ok(DevicePathNode::from_ffi_ptr(bytes.as_ptr().cast())) }
302329
} else {
303330
Err(ByteConversionError::InvalidLength)

‎xtask/src/device_path/node.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -473,12 +473,14 @@ impl Node {
473473
assert_eq!(size, out.len());
474474

475475
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
476+
let length = u16::try_from(size).unwrap();
477+
let header = DevicePathHeader::new(
478+
DeviceType::#device_type,
479+
DeviceSubType::#sub_type,
480+
length,
481+
);
476482
unsafe {
477-
out_ptr.cast::<DevicePathHeader>().write_unaligned(DevicePathHeader {
478-
device_type: DeviceType::#device_type,
479-
sub_type: DeviceSubType::#sub_type,
480-
length: u16::try_from(size).unwrap(),
481-
});
483+
out_ptr.cast::<DevicePathHeader>().write_unaligned(header);
482484
#(#copy_stmts)*
483485
}
484486
}

0 commit comments

Comments
 (0)
Please sign in to comment.