Skip to content

Commit 6f640f4

Browse files
committed
uefi: remove duplication in DevicePathHeader; use uefi-raw
1 parent 6ab3d14 commit 6f640f4

File tree

7 files changed

+329
-238
lines changed

7 files changed

+329
-238
lines changed

Diff for: uefi-raw/CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@
1212
- Added `NvmExpressPassThruProtocol`.
1313
- Added `AtaPassThruProtocol`.
1414
- Added `DevicePathUtilitiesProtocol`.
15+
- Added `len()` to `DevicePathProtocol` properly constructing the `u16` value
16+
17+
## Changed
18+
- `DevicePathHeader` now derives
19+
`Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash`
1520

1621

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

Diff for: uefi-raw/src/protocol/device_path.rs

+22-1
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,24 @@ pub use device_path_gen::{acpi, bios_boot_spec, end, hardware, media, messaging}
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 that type as `u16`.
30+
#[must_use]
31+
pub const fn len(&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+
}

Diff for: uefi/CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
`proto::device_path::text` to `proto::device_path`.
2323
- **Breaking:** `exit_boot_services` now consumes a `Option<MemoryType>` which
2424
defaults to the recommended value of `MemoryType::LOADER_DATA`.
25+
- **Breaking:** Removed duplication in `DevicePathHeader`. This change however
26+
not affect many users.
2527
- `boot::memory_map()` will never return `Status::BUFFER_TOO_SMALL` from now on,
2628
as this is considered a hard internal error where users can't do anything
2729
about it anyway. It will panic instead.

Diff for: uefi/src/proto/device_path/build.rs

+1-1
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.len())
229229
}
230230

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

Diff for: uefi/src/proto/device_path/device_path_gen.rs

+270-216
Large diffs are not rendered by default.

Diff for: uefi/src/proto/device_path/mod.rs

+24-16
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,9 @@ use crate::mem::PoolAllocation;
8989
use crate::proto::{unsafe_protocol, ProtocolPointer};
9090
use core::ffi::c_void;
9191
use core::fmt::{self, Debug, Display, Formatter};
92-
use core::ops::Deref;
92+
use core::ops::{Deref, DerefMut};
9393
use ptr_meta::Pointee;
94+
use uefi_raw::protocol::device_path::DevicePathProtocol;
9495

9596
#[cfg(feature = "alloc")]
9697
use {
@@ -137,15 +138,8 @@ impl Deref for PoolDevicePathNode {
137138

138139
/// Header that appears at the start of every [`DevicePathNode`].
139140
#[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,
148-
}
141+
#[repr(transparent)]
142+
pub struct DevicePathHeader(DevicePathProtocol);
149143

150144
impl<'a> TryFrom<&'a [u8]> for &'a DevicePathHeader {
151145
type Error = ByteConversionError;
@@ -159,6 +153,20 @@ impl<'a> TryFrom<&'a [u8]> for &'a DevicePathHeader {
159153
}
160154
}
161155

156+
impl Deref for DevicePathHeader {
157+
type Target = DevicePathProtocol;
158+
159+
fn deref(&self) -> &Self::Target {
160+
&self.0
161+
}
162+
}
163+
164+
impl DerefMut for DevicePathHeader {
165+
fn deref_mut(&mut self) -> &mut Self::Target {
166+
&mut self.0
167+
}
168+
}
169+
162170
/// A single node within a [`DevicePath`].
163171
///
164172
/// Each node starts with a [`DevicePathHeader`]. The rest of the data
@@ -202,7 +210,7 @@ impl DevicePathNode {
202210
pub unsafe fn from_ffi_ptr<'a>(ptr: *const FfiDevicePath) -> &'a Self {
203211
let header = unsafe { *ptr.cast::<DevicePathHeader>() };
204212

205-
let data_len = usize::from(header.length) - size_of::<DevicePathHeader>();
213+
let data_len = usize::from(header.len()) - size_of::<DevicePathHeader>();
206214
unsafe { &*ptr_meta::from_raw_parts(ptr.cast(), data_len) }
207215
}
208216

@@ -216,25 +224,25 @@ impl DevicePathNode {
216224
/// Type of device
217225
#[must_use]
218226
pub const fn device_type(&self) -> DeviceType {
219-
self.header.device_type
227+
self.header.0.major_type
220228
}
221229

222230
/// Sub type of device
223231
#[must_use]
224232
pub const fn sub_type(&self) -> DeviceSubType {
225-
self.header.sub_type
233+
self.header.0.sub_type
226234
}
227235

228236
/// Tuple of the node's type and subtype.
229237
#[must_use]
230238
pub const fn full_type(&self) -> (DeviceType, DeviceSubType) {
231-
(self.header.device_type, self.header.sub_type)
239+
(self.header.0.major_type, self.header.0.sub_type)
232240
}
233241

234242
/// Size (in bytes) of the full [`DevicePathNode`], including the header.
235243
#[must_use]
236244
pub const fn length(&self) -> u16 {
237-
self.header.length
245+
self.header.0.len()
238246
}
239247

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

298306
fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
299307
let dp = <&DevicePathHeader>::try_from(bytes)?;
300-
if usize::from(dp.length) <= bytes.len() {
308+
if usize::from(dp.len()) <= bytes.len() {
301309
unsafe { Ok(DevicePathNode::from_ffi_ptr(bytes.as_ptr().cast())) }
302310
} else {
303311
Err(ByteConversionError::InvalidLength)

Diff for: xtask/src/device_path/node.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -473,12 +473,13 @@ 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();
476477
unsafe {
477-
out_ptr.cast::<DevicePathHeader>().write_unaligned(DevicePathHeader {
478-
device_type: DeviceType::#device_type,
478+
out_ptr.cast::<DevicePathHeader>().write_unaligned(DevicePathHeader(device_path::DevicePathProtocol {
479+
major_type: DeviceType::#device_type,
479480
sub_type: DeviceSubType::#sub_type,
480-
length: u16::try_from(size).unwrap(),
481-
});
481+
length: length.to_le_bytes(),
482+
}));
482483
#(#copy_stmts)*
483484
}
484485
}

0 commit comments

Comments
 (0)