From a402aa6f33576e20ac3420000e4bbb469a927e0f Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Sun, 23 Aug 2026 12:18:24 +0200 Subject: [PATCH] uefi-raw: pack USB descriptor structs The USB 2.0 specification defines all standard descriptors with 1-byte packing, and EDK2 declares EFI_USB_*_DESCRIPTOR inside #pragma pack(1) accordingly [0]. With natural repr(C) layout, ConfigDescriptor was 10 bytes (spec: 9) and EndpointDescriptor 8 bytes (spec: 7) due to the u16 member; DeviceRequest and DeviceDescriptor deviated in alignment only. [0]: https://github.com/tianocore/edk2/blob/7735ed4f8eb3afaf1a97d27a8862f382c387f0bc/MdePkg/Include/IndustryStandard/Usb.h#L85 --- uefi-raw/CHANGELOG.md | 3 +++ uefi-raw/src/protocol/usb/mod.rs | 35 +++++++++++++++++++++++++++----- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/uefi-raw/CHANGELOG.md b/uefi-raw/CHANGELOG.md index 3b656954..500c78a3 100644 --- a/uefi-raw/CHANGELOG.md +++ b/uefi-raw/CHANGELOG.md @@ -5,6 +5,9 @@ ## Changed - **Breaking**: `MemoryDescriptor` now has a new member to ensure correct layout on all non-UEFI 32-bit targets. +- **Breaking**: The USB descriptor types in `protocol::usb` are now packed to + match their layout in the USB specification. `ConfigDescriptor` and + `EndpointDescriptor` previously had a too-large `size_of`. ## Removed diff --git a/uefi-raw/src/protocol/usb/mod.rs b/uefi-raw/src/protocol/usb/mod.rs index 42aa9574..013c9171 100644 --- a/uefi-raw/src/protocol/usb/mod.rs +++ b/uefi-raw/src/protocol/usb/mod.rs @@ -18,7 +18,7 @@ newtype_enum! { } #[derive(Clone, Copy, Debug, PartialEq, Eq)] -#[repr(C)] +#[repr(C, packed)] pub struct DeviceRequest { pub request_type: u8, pub request: u8, @@ -27,6 +27,11 @@ pub struct DeviceRequest { pub length: u16, } +// Compile-time ABI check. +const _: () = { + assert!(size_of::() == 8); +}; + bitflags! { #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] #[repr(transparent)] @@ -55,7 +60,7 @@ pub type AsyncUsbTransferCallback = unsafe extern "efiapi" fn( ) -> Status; #[derive(Clone, Copy, Debug, PartialEq, Eq)] -#[repr(C)] +#[repr(C, packed)] pub struct DeviceDescriptor { pub length: u8, pub descriptor_type: u8, @@ -73,8 +78,13 @@ pub struct DeviceDescriptor { pub num_configurations: u8, } +// Compile-time ABI check. +const _: () = { + assert!(size_of::() == 18); +}; + #[derive(Clone, Copy, Debug, PartialEq, Eq)] -#[repr(C)] +#[repr(C, packed)] pub struct ConfigDescriptor { pub length: u8, pub descriptor_type: u8, @@ -86,8 +96,13 @@ pub struct ConfigDescriptor { pub max_power: u8, } +// Compile-time ABI check. +const _: () = { + assert!(size_of::() == 9); +}; + #[derive(Clone, Copy, Debug, PartialEq, Eq)] -#[repr(C)] +#[repr(C, packed)] pub struct InterfaceDescriptor { pub length: u8, pub descriptor_type: u8, @@ -100,8 +115,13 @@ pub struct InterfaceDescriptor { pub interface: u8, } +// Compile-time ABI check. +const _: () = { + assert!(size_of::() == 9); +}; + #[derive(Clone, Copy, Debug, PartialEq, Eq)] -#[repr(C)] +#[repr(C, packed)] pub struct EndpointDescriptor { pub length: u8, pub descriptor_type: u8, @@ -110,3 +130,8 @@ pub struct EndpointDescriptor { pub max_packet_size: u16, pub interval: u8, } + +// Compile-time ABI check. +const _: () = { + assert!(size_of::() == 7); +};