From 0a67eebcfc1babe0a1b121b754faacf6dc81f9bf Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Sat, 23 Aug 2025 14:23:33 +0200 Subject: [PATCH 1/4] uefi-raw: improve doc --- uefi-raw/src/net.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/uefi-raw/src/net.rs b/uefi-raw/src/net.rs index 71662aefe..1bcb0d8b7 100644 --- a/uefi-raw/src/net.rs +++ b/uefi-raw/src/net.rs @@ -1,6 +1,12 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 //! UEFI network types. +//! +//! The main exports of this module are: +//! - [`MacAddress`] +//! - [`IpAddress`] +//! - [`Ipv4Address`] +//! - [`Ipv6Address`] use core::fmt; use core::fmt::{Debug, Formatter}; @@ -39,7 +45,7 @@ impl From for core::net::Ipv6Addr { } } -/// An IPv4 or IPv6 internet protocol address. +/// An IPv4 or IPv6 internet protocol address that is ABI compatible with EFI. /// /// Corresponds to the `EFI_IP_ADDRESS` type in the UEFI specification. This /// type is defined in the same way as edk2 for compatibility with C code. Note @@ -106,7 +112,15 @@ impl From for IpAddress { } } -/// A Media Access Control (MAC) address. +/// UEFI Media Access Control (MAC) address. +/// +/// UEFI supports multiple network protocols and hardware types, not just +/// Ethernet. Some of them may use MAC addresses longer than 6 bytes. To be +/// protocol-agnostic and future-proof, the UEFI spec chooses a maximum size +/// that can hold any supported media access control address. +/// +/// In most cases, this is just a typical `[u8; 6]` Ethernet style MAC +/// address with the rest of the bytes being zero. #[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)] #[repr(transparent)] pub struct MacAddress(pub [u8; 32]); From 2690aea57fbea6f0e88e5d8693ac1e7ff1295118 Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Sat, 23 Aug 2025 14:25:43 +0200 Subject: [PATCH 2/4] uefi-raw: add .octets() for most types This aligns the API with the core::net API. We don't do it for IpAddress as `unsafe { addr.v4 }.octets()` or `unsafe { addr.v6 }.octets()` are sufficient. --- uefi-raw/CHANGELOG.md | 2 ++ uefi-raw/src/net.rs | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/uefi-raw/CHANGELOG.md b/uefi-raw/CHANGELOG.md index fc2a6ad61..cfe07ebe6 100644 --- a/uefi-raw/CHANGELOG.md +++ b/uefi-raw/CHANGELOG.md @@ -5,6 +5,8 @@ - Added `PciRootBridgeIoProtocol`. - Added `ConfigKeywordHandlerProtocol`. - Added `HiiConfigAccessProtocol`. +- Added `::octets()` for `Ipv4Address`, `Ipv6Address`, and + `MacAddress` to streamline the API with `core::net`. ## Changed - The documentation for UEFI protocols has been streamlined and improved. diff --git a/uefi-raw/src/net.rs b/uefi-raw/src/net.rs index 1bcb0d8b7..c1c346fac 100644 --- a/uefi-raw/src/net.rs +++ b/uefi-raw/src/net.rs @@ -16,6 +16,14 @@ use core::fmt::{Debug, Formatter}; #[repr(transparent)] pub struct Ipv4Address(pub [u8; 4]); +impl Ipv4Address { + /// Returns the octets of the IP address. + #[must_use] + pub const fn octets(self) -> [u8; 4] { + self.0 + } +} + impl From for Ipv4Address { fn from(ip: core::net::Ipv4Addr) -> Self { Self(ip.octets()) @@ -33,6 +41,14 @@ impl From for core::net::Ipv4Addr { #[repr(transparent)] pub struct Ipv6Address(pub [u8; 16]); +impl Ipv6Address { + /// Returns the octets of the IP address. + #[must_use] + pub const fn octets(self) -> [u8; 16] { + self.0 + } +} + impl From for Ipv6Address { fn from(ip: core::net::Ipv6Addr) -> Self { Self(ip.octets()) @@ -125,6 +141,15 @@ impl From for IpAddress { #[repr(transparent)] pub struct MacAddress(pub [u8; 32]); +impl MacAddress { + /// Returns the octets of the MAC address. + #[must_use] + pub const fn octets(self) -> [u8; 32] { + self.0 + } +} + +// Normal/typical MAC addresses, such as in Ethernet. impl From<[u8; 6]> for MacAddress { fn from(octets: [u8; 6]) -> Self { let mut buffer = [0; 32]; From bae8971a833ac718d69825a91896713fe455f11a Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Sat, 23 Aug 2025 14:38:25 +0200 Subject: [PATCH 3/4] uefi-raw: code improvements for MacAddress --- uefi-raw/src/net.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/uefi-raw/src/net.rs b/uefi-raw/src/net.rs index c1c346fac..9fcb7f23f 100644 --- a/uefi-raw/src/net.rs +++ b/uefi-raw/src/net.rs @@ -153,12 +153,7 @@ impl MacAddress { impl From<[u8; 6]> for MacAddress { fn from(octets: [u8; 6]) -> Self { let mut buffer = [0; 32]; - buffer[0] = octets[0]; - buffer[1] = octets[1]; - buffer[2] = octets[2]; - buffer[3] = octets[3]; - buffer[4] = octets[4]; - buffer[5] = octets[5]; + buffer[..6].copy_from_slice(&octets); Self(buffer) } } From 2fd32a7331713fd1cd8e68413cd75ac810259a6b Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Sat, 16 Aug 2025 13:37:50 +0200 Subject: [PATCH 4/4] uefi-raw: add ABI test for IpAddress --- uefi-raw/src/net.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/uefi-raw/src/net.rs b/uefi-raw/src/net.rs index 9fcb7f23f..773dd2e8f 100644 --- a/uefi-raw/src/net.rs +++ b/uefi-raw/src/net.rs @@ -202,4 +202,18 @@ mod tests { let uefi_addr = IpAddress::from(core_addr); assert_eq!(unsafe { uefi_addr.v6.0 }, TEST_IPV6); } + + // Ensure that our IpAddress type can be put into a packed struct, + // even when it is normally 4 byte aligned. + #[test] + fn test_efi_ip_address_abi() { + #[repr(C, packed)] + struct PackedHelper(T); + + assert_eq!(align_of::(), 4); + assert_eq!(size_of::(), 16); + + assert_eq!(align_of::>(), 1); + assert_eq!(size_of::>(), 16); + } }