Skip to content

Commit 39b76eb

Browse files
committed
uefi: remove duplication in DevicePathHeader; use uefi-raw type
1 parent 4248ee8 commit 39b76eb

File tree

8 files changed

+334
-238
lines changed

8 files changed

+334
-238
lines changed

uefi-raw/CHANGELOG.md

+5
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+
- `DevicePathHeader` 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

+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 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

+3
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@
2525
`proto::device_path::text` to `proto::device_path`.
2626
- **Breaking:** `exit_boot_services` now consumes a `Option<MemoryType>` which
2727
defaults to the recommended value of `MemoryType::LOADER_DATA`.
28+
- **Breaking:** Removed duplication in `DevicePathHeader`. This change however
29+
doesn't affect many users. Instead of public fields, there are public
30+
getters now.
2831
- `boot::memory_map()` will never return `Status::BUFFER_TOO_SMALL` from now on,
2932
as this is considered a hard internal error where users can't do anything
3033
about it anyway. It will panic instead.

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.length())
229229
}
230230

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

uefi/src/proto/device_path/device_path_gen.rs

+271-217
Large diffs are not rendered by default.

uefi/src/proto/device_path/mod.rs

+26-14
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ mod device_path_gen;
8383
pub use device_path_gen::{
8484
acpi, bios_boot_spec, end, hardware, media, messaging, DevicePathNodeEnum,
8585
};
86+
pub use uefi_raw::protocol::device_path::DevicePathProtocol as RawDevicePathProtocol;
8687
pub use uefi_raw::protocol::device_path::{DeviceSubType, DeviceType};
8788

8889
use crate::mem::PoolAllocation;
@@ -137,14 +138,25 @@ 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,
141+
#[repr(transparent)]
142+
pub struct DevicePathHeader(pub RawDevicePathProtocol);
143+
144+
impl DevicePathHeader {
145+
/// Returns the [`DeviceType`].
146+
pub const fn major_type(&self) -> DeviceType {
147+
self.0.major_type
148+
}
149+
150+
/// Returns the [`DeviceSubType`].
151+
pub const fn sub_type(&self) -> DeviceSubType {
152+
self.0.sub_type
153+
}
154+
155+
/// Returns the total length of the device path.
156+
#[must_use]
157+
pub const fn length(&self) -> u16 {
158+
self.0.length()
159+
}
148160
}
149161

150162
impl<'a> TryFrom<&'a [u8]> for &'a DevicePathHeader {
@@ -202,7 +214,7 @@ impl DevicePathNode {
202214
pub unsafe fn from_ffi_ptr<'a>(ptr: *const FfiDevicePath) -> &'a Self {
203215
let header = unsafe { *ptr.cast::<DevicePathHeader>() };
204216

205-
let data_len = usize::from(header.length) - size_of::<DevicePathHeader>();
217+
let data_len = usize::from(header.length()) - size_of::<DevicePathHeader>();
206218
unsafe { &*ptr_meta::from_raw_parts(ptr.cast(), data_len) }
207219
}
208220

@@ -216,25 +228,25 @@ impl DevicePathNode {
216228
/// Type of device
217229
#[must_use]
218230
pub const fn device_type(&self) -> DeviceType {
219-
self.header.device_type
231+
self.header.0.major_type
220232
}
221233

222234
/// Sub type of device
223235
#[must_use]
224236
pub const fn sub_type(&self) -> DeviceSubType {
225-
self.header.sub_type
237+
self.header.0.sub_type
226238
}
227239

228240
/// Tuple of the node's type and subtype.
229241
#[must_use]
230242
pub const fn full_type(&self) -> (DeviceType, DeviceSubType) {
231-
(self.header.device_type, self.header.sub_type)
243+
(self.header.0.major_type, self.header.0.sub_type)
232244
}
233245

234246
/// Size (in bytes) of the full [`DevicePathNode`], including the header.
235247
#[must_use]
236248
pub const fn length(&self) -> u16 {
237-
self.header.length
249+
self.header.0.length()
238250
}
239251

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

298310
fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
299311
let dp = <&DevicePathHeader>::try_from(bytes)?;
300-
if usize::from(dp.length) <= bytes.len() {
312+
if usize::from(dp.length()) <= bytes.len() {
301313
unsafe { Ok(DevicePathNode::from_ffi_ptr(bytes.as_ptr().cast())) }
302314
} else {
303315
Err(ByteConversionError::InvalidLength)

xtask/src/device_path/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ fn gen_uefi_code_as_string(groups: &[NodeGroup]) -> Result<String> {
9797
use core::mem::{MaybeUninit, size_of_val};
9898
use crate::CStr16;
9999
use crate::proto::device_path::build::{BuildError, BuildNode};
100-
use crate::proto::device_path::{DeviceSubType, DeviceType};
100+
use crate::proto::device_path::{DeviceSubType, DeviceType, RawDevicePathProtocol};
101101

102102
#(#build_modules)*
103103
}

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();RawDevicePathProtocol
476477
unsafe {
477-
out_ptr.cast::<DevicePathHeader>().write_unaligned(DevicePathHeader {
478-
device_type: DeviceType::#device_type,
478+
out_ptr.cast::<DevicePathHeader>().write_unaligned(DevicePathHeader(RawDevicePathProtocol {
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)