From cc48a0af798bc4e07023bfeae438b4fd83325b48 Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Sun, 20 Apr 2025 11:35:31 +0200 Subject: [PATCH 1/4] uefi-raw: improve documentation of IpAddress and MacAddress --- uefi-raw/src/lib.rs | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/uefi-raw/src/lib.rs b/uefi-raw/src/lib.rs index 7f8050b56..dc437a91e 100644 --- a/uefi-raw/src/lib.rs +++ b/uefi-raw/src/lib.rs @@ -144,21 +144,21 @@ impl From for core::net::Ipv6Addr { /// /// 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 -/// that this is an untagged union, so there's no way to tell which type of +/// that this is an **untagged union**, so there's no way to tell which type of /// address an `IpAddress` value contains without additional context. #[derive(Clone, Copy)] #[repr(C)] pub union IpAddress { - /// This member serves to align the whole type to a 4 bytes as required by - /// the spec. Note that this is slightly different from `repr(align(4))`, - /// which would prevent placing this type in a packed structure. - pub addr: [u32; 4], - /// An IPv4 internet protocol address. pub v4: Ipv4Address, /// An IPv6 internet protocol address. pub v6: Ipv6Address, + + /// This member serves to align the whole type to 4 bytes as required by + /// the spec. Note that this is slightly different from `repr(align(4))`, + /// which would prevent placing this type in a packed structure. + pub _align_helper: [u32; 4], } impl IpAddress { @@ -190,7 +190,7 @@ impl Debug for IpAddress { impl Default for IpAddress { fn default() -> Self { - Self { addr: [0u32; 4] } + Self { _align_helper: [0u32; 4] } } } @@ -207,7 +207,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]); @@ -215,12 +223,7 @@ pub struct MacAddress(pub [u8; 32]); 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.copy_from_slice(&octets); Self(buffer) } } From d960acd437554a2e78f10cc53ae45d46440a76dd Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Sun, 20 Apr 2025 11:51:08 +0200 Subject: [PATCH 2/4] uefi-raw: IpAddress: remove type duplications; use core::net types This simplifies things as we have less types to work with. The overall convenience is improved and people will be less confused with the automated imports suggested by their IDE. As the core::Net types are ABI compatible, and it is unlikely that they will ever change in core, we should go for this simplification. --- uefi-raw/CHANGELOG.md | 3 + uefi-raw/src/lib.rs | 93 ++++++-------------- uefi-raw/src/protocol/network/dhcp4.rs | 29 +++--- uefi-raw/src/protocol/network/http.rs | 24 +++-- uefi-raw/src/protocol/network/ip4.rs | 8 +- uefi-raw/src/protocol/network/ip4_config2.rs | 11 +-- 6 files changed, 74 insertions(+), 94 deletions(-) diff --git a/uefi-raw/CHANGELOG.md b/uefi-raw/CHANGELOG.md index 3d0d44b0d..16b4f87a4 100644 --- a/uefi-raw/CHANGELOG.md +++ b/uefi-raw/CHANGELOG.md @@ -17,6 +17,9 @@ - Added `DevicePathProtocol::length()` properly constructing the `u16` value ## Changed +- **Breaking:** Types `Ipv4Address` and `Ipv6Address` have been removed. They + were replaced by `core::net::Ipv4Addr` and `core::net::Ipv6Addr`, as they are + ABI compatible. This mainly affects the `IpAddress` wrapper type. - `DevicePathProtocol` now derives `Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash` diff --git a/uefi-raw/src/lib.rs b/uefi-raw/src/lib.rs index dc437a91e..52da7914a 100644 --- a/uefi-raw/src/lib.rs +++ b/uefi-raw/src/lib.rs @@ -38,6 +38,7 @@ pub use uguid::{guid, Guid}; use core::ffi::c_void; use core::fmt::{self, Debug, Formatter}; +use core::net::{IpAddr, Ipv4Addr, Ipv6Addr}; /// Handle to an event structure. pub type Event = *mut c_void; @@ -106,40 +107,6 @@ impl From for bool { } } -/// An IPv4 internet protocol address. -#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)] -#[repr(transparent)] -pub struct Ipv4Address(pub [u8; 4]); - -impl From for Ipv4Address { - fn from(ip: core::net::Ipv4Addr) -> Self { - Self(ip.octets()) - } -} - -impl From for core::net::Ipv4Addr { - fn from(ip: Ipv4Address) -> Self { - Self::from(ip.0) - } -} - -/// An IPv6 internet protocol address. -#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)] -#[repr(transparent)] -pub struct Ipv6Address(pub [u8; 16]); - -impl From for Ipv6Address { - fn from(ip: core::net::Ipv6Addr) -> Self { - Self(ip.octets()) - } -} - -impl From for core::net::Ipv6Addr { - fn from(ip: Ipv6Address) -> Self { - Self::from(ip.0) - } -} - /// An IPv4 or IPv6 internet protocol address. /// /// Corresponds to the `EFI_IP_ADDRESS` type in the UEFI specification. This @@ -150,10 +117,10 @@ impl From for core::net::Ipv6Addr { #[repr(C)] pub union IpAddress { /// An IPv4 internet protocol address. - pub v4: Ipv4Address, + pub v4: Ipv4Addr, /// An IPv6 internet protocol address. - pub v6: Ipv6Address, + pub v6: Ipv6Addr, /// This member serves to align the whole type to 4 bytes as required by /// the spec. Note that this is slightly different from `repr(align(4))`, @@ -164,17 +131,17 @@ pub union IpAddress { impl IpAddress { /// Construct a new IPv4 address. #[must_use] - pub const fn new_v4(ip_addr: [u8; 4]) -> Self { + pub fn new_v4(ip_addr: [u8; 4]) -> Self { Self { - v4: Ipv4Address(ip_addr), + v4: Ipv4Addr::from(ip_addr), } } /// Construct a new IPv6 address. #[must_use] - pub const fn new_v6(ip_addr: [u8; 16]) -> Self { + pub fn new_v6(ip_addr: [u8; 16]) -> Self { Self { - v6: Ipv6Address(ip_addr), + v6: Ipv6Addr::from(ip_addr), } } } @@ -190,18 +157,20 @@ impl Debug for IpAddress { impl Default for IpAddress { fn default() -> Self { - Self { _align_helper: [0u32; 4] } + Self { + _align_helper: [0u32; 4], + } } } -impl From for IpAddress { - fn from(t: core::net::IpAddr) -> Self { +impl From for IpAddress { + fn from(t: IpAddr) -> Self { match t { - core::net::IpAddr::V4(ip) => Self { - v4: Ipv4Address::from(ip), + IpAddr::V4(ip) => Self { + v4: Ipv4Addr::from(ip), }, - core::net::IpAddr::V6(ip) => Self { - v6: Ipv6Address::from(ip), + IpAddr::V6(ip) => Self { + v6: Ipv6Addr::from(ip), }, } } @@ -261,33 +230,27 @@ mod tests { assert!(bool::from(Boolean(0b11111111))); } - /// Test round-trip conversion between `Ipv4Address` and `core::net::Ipv4Addr`. - #[test] - fn test_ip_addr4_conversion() { - let uefi_addr = Ipv4Address(TEST_IPV4); - let core_addr = core::net::Ipv4Addr::from(uefi_addr); - assert_eq!(uefi_addr, Ipv4Address::from(core_addr)); - } - - /// Test round-trip conversion between `Ipv6Address` and `core::net::Ipv6Addr`. + /// We test that the core::net-types are ABI compatible with the EFI types. + /// As long as this is the case, we can reuse core functionality and + /// prevent type duplication. #[test] - fn test_ip_addr6_conversion() { - let uefi_addr = Ipv6Address(TEST_IPV6); - let core_addr = core::net::Ipv6Addr::from(uefi_addr); - assert_eq!(uefi_addr, Ipv6Address::from(core_addr)); + fn net_abi() { + assert_eq!(size_of::(), 4); + assert_eq!(align_of::(), 1); + assert_eq!(size_of::(), 16); + assert_eq!(align_of::(), 1); } - /// Test conversion from `core::net::IpAddr` to `IpvAddress`. /// /// Note that conversion in the other direction is not possible. #[test] fn test_ip_addr_conversion() { - let core_addr = core::net::IpAddr::V4(core::net::Ipv4Addr::from(TEST_IPV4)); + let core_addr = IpAddr::V4(core::net::Ipv4Addr::from(TEST_IPV4)); let uefi_addr = IpAddress::from(core_addr); - assert_eq!(unsafe { uefi_addr.v4.0 }, TEST_IPV4); + assert_eq!(unsafe { uefi_addr.v4.octets() }, TEST_IPV4); - let core_addr = core::net::IpAddr::V6(core::net::Ipv6Addr::from(TEST_IPV6)); + let core_addr = IpAddr::V6(core::net::Ipv6Addr::from(TEST_IPV6)); let uefi_addr = IpAddress::from(core_addr); - assert_eq!(unsafe { uefi_addr.v6.0 }, TEST_IPV6); + assert_eq!(unsafe { uefi_addr.v6.octets() }, TEST_IPV6); } } diff --git a/uefi-raw/src/protocol/network/dhcp4.rs b/uefi-raw/src/protocol/network/dhcp4.rs index 9f26dc0ef..95de9a200 100644 --- a/uefi-raw/src/protocol/network/dhcp4.rs +++ b/uefi-raw/src/protocol/network/dhcp4.rs @@ -1,7 +1,8 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 -use crate::{guid, Boolean, Char8, Event, Guid, Ipv4Address, MacAddress, Status}; +use crate::{guid, Boolean, Char8, Event, Guid, MacAddress, Status}; use core::ffi::c_void; +use core::net::Ipv4Addr; newtype_enum! { pub enum Dhcp4Event: i32 => { @@ -58,10 +59,10 @@ pub struct Dhcp4Header { pub xid: u32, pub seconds: u16, pub reserved: u16, - pub client_addr: Ipv4Address, - pub your_addr: Ipv4Address, - pub server_addr: Ipv4Address, - pub gateway_addr: Ipv4Address, + pub client_addr: Ipv4Addr, + pub your_addr: Ipv4Addr, + pub server_addr: Ipv4Addr, + pub gateway_addr: Ipv4Addr, pub client_hw_addr: [u8; 16], pub server_name: [Char8; 64], pub boot_file_name: [Char8; 128], @@ -86,7 +87,7 @@ pub struct Dhcp4ConfigData { pub discover_timeout: *mut u32, pub request_try_count: u32, pub request_timeout: *mut u32, - pub client_address: Ipv4Address, + pub client_address: Ipv4Addr, pub callback: Option< unsafe extern "efiapi" fn( this: *mut Dhcp4Protocol, @@ -107,11 +108,11 @@ pub struct Dhcp4ConfigData { pub struct Dhcp4ModeData { pub state: Dhcp4State, pub config_data: Dhcp4ConfigData, - pub client_address: Ipv4Address, + pub client_address: Ipv4Addr, pub client_mac_address: MacAddress, - pub server_address: Ipv4Address, - pub router_address: Ipv4Address, - pub subnet_mask: Ipv4Address, + pub server_address: Ipv4Addr, + pub router_address: Ipv4Addr, + pub subnet_mask: Ipv4Addr, pub lease_time: u32, pub reply_packet: *const Dhcp4Packet, } @@ -119,8 +120,8 @@ pub struct Dhcp4ModeData { #[derive(Debug)] #[repr(C)] pub struct Dhcp4ListenPoint { - pub listen_address: Ipv4Address, - pub subnet_mask: Ipv4Address, + pub listen_address: Ipv4Addr, + pub subnet_mask: Ipv4Addr, pub listen_port: u16, } @@ -129,9 +130,9 @@ pub struct Dhcp4ListenPoint { pub struct Dhcp4TransmitReceiveToken { pub status: Status, pub completion_event: Event, - pub remote_address: Ipv4Address, + pub remote_address: Ipv4Addr, pub remote_port: u16, - pub gateway_address: Ipv4Address, + pub gateway_address: Ipv4Addr, pub listen_point_count: u32, pub listen_points: *mut Dhcp4ListenPoint, pub timeout_value: u32, diff --git a/uefi-raw/src/protocol/network/http.rs b/uefi-raw/src/protocol/network/http.rs index 99ff1220b..62687e3b2 100644 --- a/uefi-raw/src/protocol/network/http.rs +++ b/uefi-raw/src/protocol/network/http.rs @@ -1,8 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 -use crate::{guid, Boolean, Char16, Char8, Event, Guid, Ipv4Address, Ipv6Address, Status}; +use crate::{guid, Boolean, Char16, Char8, Event, Guid, Status}; use core::ffi::c_void; use core::fmt::{self, Debug, Formatter}; +use core::net::{Ipv4Addr, Ipv6Addr}; use core::ptr; #[derive(Debug, Default)] @@ -23,19 +24,30 @@ newtype_enum! { } } -#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)] +#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] #[repr(C)] pub struct HttpV4AccessPoint { pub use_default_addr: Boolean, - pub local_address: Ipv4Address, - pub local_subnet: Ipv4Address, + pub local_address: Ipv4Addr, + pub local_subnet: Ipv4Addr, pub local_port: u16, } -#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)] +impl Default for HttpV4AccessPoint { + fn default() -> Self { + Self { + use_default_addr: Default::default(), + local_address: Ipv4Addr::from([0; 4]), + local_subnet: Ipv4Addr::from([0; 4]), + local_port: 0, + } + } +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] #[repr(C)] pub struct HttpV6AccessPoint { - pub local_address: Ipv6Address, + pub local_address: Ipv6Addr, pub local_port: u16, } diff --git a/uefi-raw/src/protocol/network/ip4.rs b/uefi-raw/src/protocol/network/ip4.rs index 88fb04d65..bb16ec13a 100644 --- a/uefi-raw/src/protocol/network/ip4.rs +++ b/uefi-raw/src/protocol/network/ip4.rs @@ -1,11 +1,11 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 -use crate::Ipv4Address; +use core::net::Ipv4Addr; #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] #[repr(C)] pub struct Ip4RouteTable { - pub subnet_addr: Ipv4Address, - pub subnet_mask: Ipv4Address, - pub gateway_addr: Ipv4Address, + pub subnet_addr: Ipv4Addr, + pub subnet_mask: Ipv4Addr, + pub gateway_addr: Ipv4Addr, } diff --git a/uefi-raw/src/protocol/network/ip4_config2.rs b/uefi-raw/src/protocol/network/ip4_config2.rs index 41f334b05..f79937aec 100644 --- a/uefi-raw/src/protocol/network/ip4_config2.rs +++ b/uefi-raw/src/protocol/network/ip4_config2.rs @@ -1,8 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 use crate::protocol::network::ip4::Ip4RouteTable; -use crate::{guid, Char16, Event, Guid, Ipv4Address, MacAddress, Status}; +use crate::{guid, Char16, Event, Guid, MacAddress, Status}; use core::ffi::c_void; +use core::net::Ipv4Addr; newtype_enum! { pub enum Ip4Config2DataType: i32 => { @@ -22,8 +23,8 @@ pub struct Ip4Config2InterfaceInfo { pub if_type: u8, pub hw_addr_size: u32, pub hw_addr: MacAddress, - pub station_addr: Ipv4Address, - pub subnet_mask: Ipv4Address, + pub station_addr: Ipv4Addr, + pub subnet_mask: Ipv4Addr, pub route_table_size: u32, pub route_table: *mut Ip4RouteTable, } @@ -39,8 +40,8 @@ newtype_enum! { #[derive(Debug)] #[repr(C)] pub struct Ip4Config2ManualAddress { - pub address: Ipv4Address, - pub subnet_mask: Ipv4Address, + pub address: Ipv4Addr, + pub subnet_mask: Ipv4Addr, } #[derive(Debug)] From 5ff316526a1fdac970297b84fa014b20bc3eb8db Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Mon, 21 Apr 2025 10:50:21 +0200 Subject: [PATCH 3/4] uefi-raw: add convenience for type IpAddress This tightly integrates the type with the Rust standard IpAddr type. It allows the convenient usage in `uefi` in a later commit. --- uefi-raw/CHANGELOG.md | 2 + uefi-raw/src/lib.rs | 180 ++++++++++++++++++++++++++++++++++++------ uefi/CHANGELOG.md | 2 +- 3 files changed, 161 insertions(+), 23 deletions(-) diff --git a/uefi-raw/CHANGELOG.md b/uefi-raw/CHANGELOG.md index 16b4f87a4..2aae02f98 100644 --- a/uefi-raw/CHANGELOG.md +++ b/uefi-raw/CHANGELOG.md @@ -15,6 +15,8 @@ - Added `UsbIoProtocol`. - Added `Usb2HostControllerProtocol`. - Added `DevicePathProtocol::length()` properly constructing the `u16` value +- Type `IpAddress` is now tightly integrated with `core::net::IpAddr`, e.g., + various `From` implementations are available. ## Changed - **Breaking:** Types `Ipv4Address` and `Ipv6Address` have been removed. They diff --git a/uefi-raw/src/lib.rs b/uefi-raw/src/lib.rs index 52da7914a..8df4bdc13 100644 --- a/uefi-raw/src/lib.rs +++ b/uefi-raw/src/lib.rs @@ -113,6 +113,12 @@ impl From for bool { /// type is defined in the same way as edk2 for compatibility with C code. Note /// that this is an **untagged union**, so there's no way to tell which type of /// address an `IpAddress` value contains without additional context. +/// +/// For convenience, this type is tightly integrated with the Rust standard +/// library types [`IpAddr`], [`Ipv4Addr`], and [`Ipv6Addr`]. +/// +/// The constructors ensure that all unused bytes of these type are always +/// initialized to zero. #[derive(Clone, Copy)] #[repr(C)] pub union IpAddress { @@ -132,9 +138,10 @@ impl IpAddress { /// Construct a new IPv4 address. #[must_use] pub fn new_v4(ip_addr: [u8; 4]) -> Self { - Self { - v4: Ipv4Addr::from(ip_addr), - } + // Initialize all bytes to zero first. + let mut obj = Self::default(); + obj.v4 = Ipv4Addr::from(ip_addr); + obj } /// Construct a new IPv6 address. @@ -144,20 +151,76 @@ impl IpAddress { v6: Ipv6Addr::from(ip_addr), } } + + /// Returns the octets of the union. Without additional context, it is not + /// clear whether the octets represent an IPv4 or IPv6 address. + #[must_use] + pub const fn octets(&self) -> [u8; 16] { + unsafe { self.v6.octets() } + } + + /// Returns a raw pointer to the IP address. + #[must_use] + pub const fn as_ptr(&self) -> *const Self { + core::ptr::addr_of!(*self) + } + + /// Returns a raw mutable pointer to the IP address. + #[must_use] + pub fn as_ptr_mut(&mut self) -> *mut Self { + core::ptr::addr_of_mut!(*self) + } + + /// Transforms this EFI type to the Rust standard libraries type. + /// + /// # Arguments + /// - `is_ipv6`: Whether the internal data should be interpreted as IPv6 or + /// IPv4 address. + #[must_use] + pub fn to_ip_addr(self, is_ipv6: bool) -> IpAddr { + if is_ipv6 { + IpAddr::V6(Ipv6Addr::from(unsafe { self.v6.octets() })) + } else { + IpAddr::V4(Ipv4Addr::from(unsafe { self.v4.octets() })) + } + } + + /// Returns the underlying data as [`Ipv4Addr`], if only the first four + /// octets are used. + /// + /// # Safety + /// This function is not unsafe memory-wise but callers need to ensure with + /// additional context that the IP is indeed an IPv4 address. + pub unsafe fn as_ipv4(&self) -> Result { + let extra = self.octets()[4..].iter().any(|&x| x != 0); + if !extra { + Ok(Ipv4Addr::from(unsafe { self.v4.octets() })) + } else { + Err(Ipv6Addr::from(unsafe { self.v6.octets() })) + } + } + + /// Returns the underlying data as [`Ipv6Addr`]. + /// + /// # Safety + /// This function is not unsafe memory-wise but callers need to ensure with + /// additional context that the IP is indeed an IPv6 address. + #[must_use] + pub unsafe fn as_ipv6(&self) -> Ipv6Addr { + Ipv6Addr::from(unsafe { self.v6.octets() }) + } } impl Debug for IpAddress { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - // The type is an untagged union, so we don't know whether it contains - // an IPv4 or IPv6 address. It's also not safe to just print the whole - // 16 bytes, since they might not all be initialized. - f.debug_struct("IpAddress").finish() + f.debug_tuple("IpAddress").field(&self.octets()).finish() } } impl Default for IpAddress { fn default() -> Self { Self { + // Initialize all fields to zero _align_helper: [0u32; 4], } } @@ -166,16 +229,51 @@ impl Default for IpAddress { impl From for IpAddress { fn from(t: IpAddr) -> Self { match t { - IpAddr::V4(ip) => Self { - v4: Ipv4Addr::from(ip), - }, - IpAddr::V6(ip) => Self { - v6: Ipv6Addr::from(ip), - }, + IpAddr::V4(ip) => Self::new_v4(ip.octets()), + IpAddr::V6(ip) => Self::new_v6(ip.octets()), } } } +impl From<&IpAddr> for IpAddress { + fn from(t: &IpAddr) -> Self { + match t { + IpAddr::V4(ip) => Self::new_v4(ip.octets()), + IpAddr::V6(ip) => Self::new_v6(ip.octets()), + } + } +} + +impl From<[u8; 4]> for IpAddress { + fn from(octets: [u8; 4]) -> Self { + Self::new_v4(octets) + } +} + +impl From<[u8; 16]> for IpAddress { + fn from(octets: [u8; 16]) -> Self { + Self::new_v6(octets) + } +} + +impl From for [u8; 16] { + fn from(value: IpAddress) -> Self { + value.octets() + } +} + +impl From for IpAddress { + fn from(value: Ipv4Addr) -> Self { + Self::new_v4(value.octets()) + } +} + +impl From for IpAddress { + fn from(value: Ipv6Addr) -> Self { + Self::new_v6(value.octets()) + } +} + /// UEFI Media Access Control (MAC) address. /// /// UEFI supports multiple network protocols and hardware types, not just @@ -240,17 +338,55 @@ mod tests { assert_eq!(size_of::(), 16); assert_eq!(align_of::(), 1); } - /// Test conversion from `core::net::IpAddr` to `IpvAddress`. - /// - /// Note that conversion in the other direction is not possible. + + #[test] + fn ip_ptr() { + let mut ip = IpAddress::new_v4([0; 4]); + let ptr = ip.as_ptr_mut().cast::(); + unsafe { + core::ptr::write(ptr, 192); + core::ptr::write(ptr.add(1), 168); + core::ptr::write(ptr.add(2), 42); + core::ptr::write(ptr.add(3), 73); + } + unsafe { assert_eq!(ip.v4.octets(), [192, 168, 42, 73]) } + } + + /// Test conversion from [`IpAddr`] to [`IpAddress`]. #[test] fn test_ip_addr_conversion() { - let core_addr = IpAddr::V4(core::net::Ipv4Addr::from(TEST_IPV4)); - let uefi_addr = IpAddress::from(core_addr); - assert_eq!(unsafe { uefi_addr.v4.octets() }, TEST_IPV4); + // Reference: std types + let core_ipv4_v4 = Ipv4Addr::from(TEST_IPV4); + let core_ipv4 = IpAddr::from(core_ipv4_v4); + let core_ipv6_v6 = Ipv6Addr::from(TEST_IPV6); + let core_ipv6 = IpAddr::from(core_ipv6_v6); + + // Test From [u8; N] constructors + assert_eq!(IpAddress::from(TEST_IPV4).octets()[0..4], TEST_IPV4); + assert_eq!(IpAddress::from(TEST_IPV6).octets(), TEST_IPV6); + { + let bytes: [u8; 16] = IpAddress::from(TEST_IPV6).into(); + assert_eq!(bytes, TEST_IPV6); + } - let core_addr = IpAddr::V6(core::net::Ipv6Addr::from(TEST_IPV6)); - let uefi_addr = IpAddress::from(core_addr); - assert_eq!(unsafe { uefi_addr.v6.octets() }, TEST_IPV6); + // Test From::from std type constructors + let efi_ipv4 = IpAddress::from(core_ipv4); + assert_eq!(efi_ipv4.octets()[0..4], TEST_IPV4); + assert_eq!(unsafe { efi_ipv4.as_ipv4().unwrap() }, core_ipv4); + + let efi_ipv6 = IpAddress::from(core_ipv6); + assert_eq!(efi_ipv6.octets(), TEST_IPV6); + assert_eq!(unsafe { efi_ipv6.as_ipv4().unwrap_err() }, core_ipv6); + assert_eq!(unsafe { efi_ipv6.as_ipv6() }, core_ipv6); + + // Test From::from std type constructors + let efi_ipv4 = IpAddress::from(core_ipv4_v4); + assert_eq!(efi_ipv4.octets()[0..4], TEST_IPV4); + assert_eq!(unsafe { efi_ipv4.as_ipv4().unwrap() }, core_ipv4); + + let efi_ipv6 = IpAddress::from(core_ipv6_v6); + assert_eq!(efi_ipv6.octets(), TEST_IPV6); + assert_eq!(unsafe { efi_ipv6.as_ipv4().unwrap_err() }, core_ipv6); + assert_eq!(unsafe { efi_ipv6.as_ipv6() }, core_ipv6); } } diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index fa9cb6218..dba77d39a 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -41,7 +41,7 @@ - The `Display` impl for `CStr8` now excludes the trailing null character. - `VariableKeys` initializes with a larger name buffer to work around firmware bugs on some devices. -- The UEFI `allocator::Allocator` has been optimized for page-aligned +- The UEFI `allocator::Allocator` has been optimized for page-aligned allocations. From 86aa5ce104702fc450b96a11d85a6dea160f91a7 Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Mon, 21 Apr 2025 10:56:18 +0200 Subject: [PATCH 4/4] uefi: remove duplicated types, use uefi-raw's IpAddress This does not use core::net::IpAddr in all possible public interfaces. Although there is opportunity for that, this commit only makes `uefi` compatible with the new `uefi-raw` type. --- uefi-test-runner/src/proto/network/pxe.rs | 4 +- uefi-test-runner/src/proto/network/snp.rs | 4 +- uefi/CHANGELOG.md | 5 + uefi/src/proto/device_path/device_path_gen.rs | 2 +- uefi/src/proto/network/ip4config2.rs | 19 +-- uefi/src/proto/network/mod.rs | 98 +------------- uefi/src/proto/network/pxe.rs | 121 +++++++++--------- uefi/src/proto/network/snp.rs | 21 +-- xtask/src/device_path/mod.rs | 2 +- 9 files changed, 92 insertions(+), 184 deletions(-) diff --git a/uefi-test-runner/src/proto/network/pxe.rs b/uefi-test-runner/src/proto/network/pxe.rs index 9f29733f7..f7a3cb751 100644 --- a/uefi-test-runner/src/proto/network/pxe.rs +++ b/uefi-test-runner/src/proto/network/pxe.rs @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 use uefi::proto::network::pxe::{BaseCode, DhcpV4Packet, IpFilter, IpFilters, UdpOpFlags}; -use uefi::proto::network::IpAddress; +use uefi::proto::network::EfiIpAddr; use uefi::{boot, CStr8}; pub fn test() { @@ -27,7 +27,7 @@ pub fn test() { assert!(base_code.mode().dhcp_ack_received()); let dhcp_ack: &DhcpV4Packet = base_code.mode().dhcp_ack().as_ref(); let server_ip = dhcp_ack.bootp_si_addr; - let server_ip = IpAddress::new_v4(server_ip); + let server_ip = EfiIpAddr::new_v4(server_ip); const EXAMPLE_FILE_NAME: &[u8] = b"example-file.txt\0"; const EXAMPLE_FILE_CONTENT: &[u8] = b"Hello world!"; diff --git a/uefi-test-runner/src/proto/network/snp.rs b/uefi-test-runner/src/proto/network/snp.rs index a0c2ccba4..83989636c 100644 --- a/uefi-test-runner/src/proto/network/snp.rs +++ b/uefi-test-runner/src/proto/network/snp.rs @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 use uefi::proto::network::snp::{InterruptStatus, ReceiveFlags, SimpleNetwork}; -use uefi::proto::network::MacAddress; +use uefi::proto::network::EfiMacAddr; use uefi::{boot, Status}; pub fn test() { @@ -75,7 +75,7 @@ pub fn test() { \xa9\xe4\ \x04\x01\x02\x03\x04"; - let dest_addr = MacAddress([0xffu8; 32]); + let dest_addr = EfiMacAddr([0xffu8; 32]); assert!(!simple_network .get_interrupt_status() .unwrap() diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index dba77d39a..958db7356 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -29,6 +29,11 @@ defaults to the recommended value of `MemoryType::LOADER_DATA`. - **Breaking:** Removed duplication in `DevicePathHeader`. Instead of public fields, there is now a public constructor combined with public getters. +- **Breaking:** Removed type `IpAddress`. Instead, a new alias `EfiIpAddr` is + exported which forwards to the new `IpAddress` type in `uefi-raw`. That type + is tightly integrated with `core::net::{IpAddr, Ipv4Addr, Ipv6Addr}`. + This simplifies working with IP addresses significantly. +- **Breaking:** For consistency, `MacAddress` was renamed to `EfiMacAddr`. - `boot::memory_map()` will never return `Status::BUFFER_TOO_SMALL` from now on, as this is considered a hard internal error where users can't do anything about it anyway. It will panic instead. diff --git a/uefi/src/proto/device_path/device_path_gen.rs b/uefi/src/proto/device_path/device_path_gen.rs index d30b93ee8..0d0764496 100644 --- a/uefi/src/proto/device_path/device_path_gen.rs +++ b/uefi/src/proto/device_path/device_path_gen.rs @@ -14,13 +14,13 @@ use crate::polyfill::maybe_uninit_slice_as_mut_ptr; use crate::proto::device_path::{ self, DevicePathHeader, DevicePathNode, DeviceSubType, DeviceType, NodeConversionError, }; -use crate::proto::network::IpAddress; use crate::{guid, Guid}; use bitflags::bitflags; use core::mem::{size_of, size_of_val}; use core::ptr::addr_of; use core::{fmt, slice}; use ptr_meta::Pointee; +use uefi_raw::IpAddress; /// Device path nodes for [`DeviceType::END`]. pub mod end { use super::*; diff --git a/uefi/src/proto/network/ip4config2.rs b/uefi/src/proto/network/ip4config2.rs index 013c659d4..1e642219f 100644 --- a/uefi/src/proto/network/ip4config2.rs +++ b/uefi/src/proto/network/ip4config2.rs @@ -7,7 +7,7 @@ use alloc::vec; use alloc::vec::Vec; use core::ffi::c_void; - +use core::net::Ipv4Addr; use uefi::boot::ScopedProtocol; use uefi::prelude::*; use uefi::proto::unsafe_protocol; @@ -15,7 +15,6 @@ use uefi::{print, println}; use uefi_raw::protocol::network::ip4_config2::{ Ip4Config2DataType, Ip4Config2InterfaceInfo, Ip4Config2Policy, Ip4Config2Protocol, }; -use uefi_raw::Ipv4Address; /// IP4 Config2 [`Protocol`]. Configure IPv4 networking. /// @@ -101,29 +100,19 @@ impl Ip4Config2 { }) } - fn print_info(info: &Ip4Config2InterfaceInfo) { - println!( - "addr v4: {}.{}.{}.{}", - info.station_addr.0[0], - info.station_addr.0[1], - info.station_addr.0[2], - info.station_addr.0[3], - ); - } - /// Bring up network interface. Does nothing in case the network /// is already set up. Otherwise turns on DHCP and waits until an /// IPv4 address has been assigned. Reports progress on the /// console if verbose is set to true. Returns TIMEOUT error in /// case DHCP configuration does not finish within 30 seconds. pub fn ifup(&mut self, verbose: bool) -> uefi::Result<()> { - let no_address = Ipv4Address::default(); + let no_address = Ipv4Addr::from_bits(0); let info = self.get_interface_info()?; if info.station_addr != no_address { if verbose { print!("Network is already up: "); - Self::print_info(&info); + println!("addr v4: {}", info.station_addr); } return Ok(()); } @@ -142,7 +131,7 @@ impl Ip4Config2 { if info.station_addr != no_address { if verbose { print!(" OK: "); - Self::print_info(&info); + println!("addr v4: {}", info.station_addr); } return Ok(()); } diff --git a/uefi/src/proto/network/mod.rs b/uefi/src/proto/network/mod.rs index b3eb665b6..2e874212a 100644 --- a/uefi/src/proto/network/mod.rs +++ b/uefi/src/proto/network/mod.rs @@ -3,101 +3,15 @@ //! Network access protocols. //! //! These protocols can be used to interact with network resources. +//! +//! To work with Mac and IP addresses, `uefi` uses with the types: +//! - [`EfiIpAddr`] that is tightly integrated with the [`core::net::IpAddr`] +//! type, +//! - [`EfiMacAddr`] pub mod http; pub mod ip4config2; pub mod pxe; pub mod snp; -pub use uefi_raw::MacAddress; - -/// Represents an IPv4/v6 address. -/// -/// Corresponds to the `EFI_IP_ADDRESS` type in the C API. -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] -#[repr(C, align(4))] -pub struct IpAddress(pub [u8; 16]); - -impl IpAddress { - /// Construct a new IPv4 address. - #[must_use] - pub const fn new_v4(ip_addr: [u8; 4]) -> Self { - let mut buffer = [0; 16]; - buffer[0] = ip_addr[0]; - buffer[1] = ip_addr[1]; - buffer[2] = ip_addr[2]; - buffer[3] = ip_addr[3]; - Self(buffer) - } - - /// Construct a new IPv6 address. - #[must_use] - pub const fn new_v6(ip_addr: [u8; 16]) -> Self { - Self(ip_addr) - } - - /// Construct from a `uefi_raw::IpAddress` union. - /// - /// # Safety - /// - /// `is_ipv6` must accurately reflect how the union was initialized. - #[must_use] - const unsafe fn from_raw(ip_addr: uefi_raw::IpAddress, is_ipv6: bool) -> Self { - if is_ipv6 { - Self::new_v6(unsafe { ip_addr.v6.0 }) - } else { - Self::new_v4(unsafe { ip_addr.v4.0 }) - } - } - - #[must_use] - const fn as_raw_ptr(&self) -> *const uefi_raw::IpAddress { - // The uefi-raw type is defined differently, but the layout is - // compatible. - self.0.as_ptr().cast() - } - - #[must_use] - fn as_raw_ptr_mut(&mut self) -> *mut uefi_raw::IpAddress { - // The uefi-raw type is defined differently, but the layout is - // compatible. - self.0.as_mut_ptr().cast() - } -} - -impl From for IpAddress { - fn from(t: core::net::Ipv4Addr) -> Self { - Self::new_v4(t.octets()) - } -} - -impl From for core::net::Ipv4Addr { - fn from(IpAddress(o): IpAddress) -> Self { - Self::from([o[0], o[1], o[2], o[3]]) - } -} - -impl From for IpAddress { - fn from(t: core::net::Ipv6Addr) -> Self { - Self::new_v6(t.octets()) - } -} - -impl From for core::net::Ipv6Addr { - fn from(value: IpAddress) -> Self { - Self::from(value.0) - } -} - -impl From for IpAddress { - fn from(t: core::net::IpAddr) -> Self { - match t { - core::net::IpAddr::V4(a) => a.into(), - core::net::IpAddr::V6(a) => a.into(), - } - } -} - -// NOTE: We cannot impl From for core::net::IpAddr -// because IpAddress is a raw union, with nothing indicating -// whether it should be considered v4 or v6. +pub use uefi_raw::{IpAddress as EfiIpAddr, MacAddress as EfiMacAddr}; diff --git a/uefi/src/proto/network/pxe.rs b/uefi/src/proto/network/pxe.rs index a46162151..0cad16bab 100644 --- a/uefi/src/proto/network/pxe.rs +++ b/uefi/src/proto/network/pxe.rs @@ -2,7 +2,7 @@ //! PXE Base Code protocol. -use super::{IpAddress, MacAddress}; +use super::{EfiIpAddr, EfiMacAddr}; use crate::polyfill::maybe_uninit_slice_as_mut_ptr; use crate::proto::unsafe_protocol; use crate::util::{ptr_write_unaligned_and_add, usize_from_u32}; @@ -65,7 +65,7 @@ impl BaseCode { } /// Returns the size of a file located on a TFTP server. - pub fn tftp_get_file_size(&mut self, server_ip: &IpAddress, filename: &CStr8) -> Result { + pub fn tftp_get_file_size(&mut self, server_ip: &EfiIpAddr, filename: &CStr8) -> Result { let mut buffer_size = 0; let status = unsafe { @@ -76,7 +76,7 @@ impl BaseCode { Boolean::FALSE, &mut buffer_size, null(), - server_ip.as_raw_ptr(), + server_ip.as_ptr(), cstr8_to_ptr(filename), null(), Boolean::FALSE, @@ -88,7 +88,7 @@ impl BaseCode { /// Reads a file located on a TFTP server. pub fn tftp_read_file( &mut self, - server_ip: &IpAddress, + server_ip: &EfiIpAddr, filename: &CStr8, buffer: Option<&mut [u8]>, ) -> Result { @@ -107,7 +107,7 @@ impl BaseCode { Boolean::FALSE, &mut buffer_size, null(), - server_ip.as_raw_ptr(), + server_ip.as_ptr(), cstr8_to_ptr(filename), null(), dont_use_buffer, @@ -119,7 +119,7 @@ impl BaseCode { /// Writes to a file located on a TFTP server. pub fn tftp_write_file( &mut self, - server_ip: &IpAddress, + server_ip: &EfiIpAddr, filename: &CStr8, overwrite: bool, buffer: &[u8], @@ -135,7 +135,7 @@ impl BaseCode { overwrite.into(), &mut buffer_size, null(), - server_ip.as_raw_ptr(), + server_ip.as_ptr(), cstr8_to_ptr(filename), null(), Boolean::FALSE, @@ -147,7 +147,7 @@ impl BaseCode { /// Reads a directory listing of a directory on a TFTP server. pub fn tftp_read_dir<'a>( &mut self, - server_ip: &IpAddress, + server_ip: &EfiIpAddr, directory_name: &CStr8, buffer: &'a mut [u8], ) -> Result, ReadDirParseError>> + 'a> @@ -163,7 +163,7 @@ impl BaseCode { Boolean::FALSE, &mut buffer_size, null(), - server_ip.as_raw_ptr(), + server_ip.as_ptr(), cstr8_to_ptr(directory_name), null(), Boolean::FALSE, @@ -222,7 +222,7 @@ impl BaseCode { /// Returns the size of a file located on a MTFTP server. pub fn mtftp_get_file_size( &mut self, - server_ip: &IpAddress, + server_ip: &EfiIpAddr, filename: &CStr8, info: &MtftpInfo, ) -> Result { @@ -236,9 +236,9 @@ impl BaseCode { Boolean::FALSE, &mut buffer_size, null(), - server_ip.as_raw_ptr(), + server_ip.as_ptr(), cstr8_to_ptr(filename), - info.as_raw_ptr(), + info.as_ptr(), Boolean::FALSE, ) }; @@ -248,7 +248,7 @@ impl BaseCode { /// Reads a file located on a MTFTP server. pub fn mtftp_read_file( &mut self, - server_ip: &IpAddress, + server_ip: &EfiIpAddr, filename: &CStr8, buffer: Option<&mut [u8]>, info: &MtftpInfo, @@ -268,9 +268,9 @@ impl BaseCode { Boolean::FALSE, &mut buffer_size, null(), - server_ip.as_raw_ptr(), + server_ip.as_ptr(), cstr8_to_ptr(filename), - info.as_raw_ptr(), + info.as_ptr(), dont_use_buffer, ) }; @@ -280,7 +280,7 @@ impl BaseCode { /// Reads a directory listing of a directory on a MTFTP server. pub fn mtftp_read_dir<'a>( &mut self, - server_ip: &IpAddress, + server_ip: &EfiIpAddr, buffer: &'a mut [u8], info: &MtftpInfo, ) -> Result, ReadDirParseError>> + 'a> @@ -296,9 +296,9 @@ impl BaseCode { Boolean::FALSE, &mut buffer_size, null(), - server_ip.as_raw_ptr(), + server_ip.as_ptr(), null_mut(), - info.as_raw_ptr(), + info.as_ptr(), Boolean::FALSE, ) }; @@ -330,7 +330,7 @@ impl BaseCode { // The IP should have exact 4 octets, not more. return Err(ReadDirParseError); } - let ip_address = IpAddress::new_v4(buffer); + let ip_address = EfiIpAddr::new_v4(buffer); let information_string = iterator.next().ok_or(ReadDirParseError)?; let (_null_terminator, information_string) = information_string.split_last().unwrap(); @@ -374,10 +374,10 @@ impl BaseCode { pub fn udp_write( &mut self, op_flags: UdpOpFlags, - dest_ip: &IpAddress, + dest_ip: &EfiIpAddr, dest_port: u16, - gateway_ip: Option<&IpAddress>, - src_ip: Option<&IpAddress>, + gateway_ip: Option<&EfiIpAddr>, + src_ip: Option<&EfiIpAddr>, src_port: Option<&mut u16>, header: Option<&[u8]>, buffer: &[u8], @@ -394,7 +394,7 @@ impl BaseCode { (self.0.udp_write)( &mut self.0, op_flags, - dest_ip.as_raw_ptr(), + dest_ip.as_ptr(), &dest_port, opt_ip_addr_to_ptr(gateway_ip), opt_ip_addr_to_ptr(src_ip), @@ -413,9 +413,9 @@ impl BaseCode { pub fn udp_read( &mut self, op_flags: UdpOpFlags, - dest_ip: Option<&mut IpAddress>, + dest_ip: Option<&mut EfiIpAddr>, dest_port: Option<&mut u16>, - src_ip: Option<&mut IpAddress>, + src_ip: Option<&mut EfiIpAddr>, src_port: Option<&mut u16>, header: Option<&mut [u8]>, buffer: &mut [u8], @@ -455,9 +455,8 @@ impl BaseCode { } /// Uses the ARP protocol to resolve a MAC address. - pub fn arp(&mut self, ip_addr: &IpAddress, mac_addr: Option<&mut MacAddress>) -> Result { - unsafe { (self.0.arp)(&mut self.0, ip_addr.as_raw_ptr(), opt_mut_to_ptr(mac_addr)) } - .to_result() + pub fn arp(&mut self, ip_addr: &EfiIpAddr, mac_addr: Option<&mut EfiMacAddr>) -> Result { + unsafe { (self.0.arp)(&mut self.0, ip_addr.as_ptr(), opt_mut_to_ptr(mac_addr)) }.to_result() } /// Updates the parameters that affect the operation of the PXE Base Code @@ -487,8 +486,8 @@ impl BaseCode { /// device. pub fn set_station_ip( &mut self, - new_station_ip: Option<&IpAddress>, - new_subnet_mask: Option<&IpAddress>, + new_station_ip: Option<&EfiIpAddr>, + new_subnet_mask: Option<&EfiIpAddr>, ) -> Result { unsafe { (self.0.set_station_ip)( @@ -558,14 +557,14 @@ fn opt_bool_to_ptr(arg: &Option) -> *const Boolean { .unwrap_or_else(null) } -/// Convert an `Option<&IpAddress>` to a `*const uefi_raw::IpAddress`. -fn opt_ip_addr_to_ptr(arg: Option<&IpAddress>) -> *const uefi_raw::IpAddress { - arg.map(|arg| arg.as_raw_ptr()).unwrap_or_else(null) +/// Convert an `Option<&EfiIpAddr>` to a `*const uefi_raw::EfiIpAddr`. +fn opt_ip_addr_to_ptr(arg: Option<&EfiIpAddr>) -> *const EfiIpAddr { + arg.map(|arg| arg.as_ptr()).unwrap_or_else(null) } -/// Convert an `Option<&mut IpAddress>` to a `*mut uefi_raw::IpAddress`. -fn opt_ip_addr_to_ptr_mut(arg: Option<&mut IpAddress>) -> *mut uefi_raw::IpAddress { - arg.map(|arg| arg.as_raw_ptr_mut()).unwrap_or_else(null_mut) +/// Convert an `Option<&mut EfiIpAddr>` to a `*mut uefi_raw::EfiIpAddr`. +fn opt_ip_addr_to_ptr_mut(arg: Option<&mut EfiIpAddr>) -> *mut EfiIpAddr { + arg.map(|arg| arg.as_ptr_mut()).unwrap_or_else(null_mut) } /// Convert an `Option<&Packet>` to a `*const PxeBaseCodePacket`. @@ -600,7 +599,7 @@ pub struct DiscoverInfo { use_b_cast: bool, use_u_cast: bool, must_use_list: bool, - server_m_cast_ip: IpAddress, + server_m_cast_ip: EfiIpAddr, ip_cnt: u16, srv_list: [Server], } @@ -613,14 +612,14 @@ impl DiscoverInfo { use_b_cast: bool, use_u_cast: bool, must_use_list: bool, - server_m_cast_ip: IpAddress, + server_m_cast_ip: EfiIpAddr, srv_list: &[Server], ) -> Result<&'buf mut Self> { let server_count = srv_list.len(); assert!(server_count <= u16::MAX as usize, "too many servers"); let required_size = size_of::() * 4 - + size_of::() + + size_of::() + size_of::() + size_of_val(srv_list); @@ -675,7 +674,7 @@ impl DiscoverInfo { /// Returns the address used in multicast discovery. #[must_use] - pub const fn server_m_cast_ip(&self) -> &IpAddress { + pub const fn server_m_cast_ip(&self) -> &EfiIpAddr { &self.server_m_cast_ip } @@ -704,7 +703,7 @@ pub struct Server { accept_any_response: bool, _reserved: u8, /// The IP address of the server - ip_addr: IpAddress, + ip_addr: EfiIpAddr, } impl Server { @@ -712,19 +711,19 @@ impl Server { /// `None` only Boot Server replies with matching the IP address will be /// accepted. #[must_use] - pub fn new(ty: u16, ip_addr: Option) -> Self { + pub fn new(ty: u16, ip_addr: Option) -> Self { Self { ty, accept_any_response: ip_addr.is_none(), _reserved: 0, - ip_addr: ip_addr.unwrap_or(IpAddress([0; 16])), + ip_addr: ip_addr.unwrap_or_default(), } } - /// Returns a `None` if the any response should be accepted or the IP + /// Returns `None` if any response should be accepted, or otherwise the IP /// address of a Boot Server whose responses should be accepted. #[must_use] - pub const fn ip_addr(&self) -> Option<&IpAddress> { + pub const fn ip_addr(&self) -> Option<&EfiIpAddr> { if self.accept_any_response { None } else { @@ -741,7 +740,7 @@ impl Server { pub struct MtftpInfo { /// File multicast IP address. This is the IP address to which the server /// will send the requested file. - pub m_cast_ip: IpAddress, + pub m_cast_ip: EfiIpAddr, /// Client multicast listening port. This is the UDP port to which the /// server will send the requested file. pub c_port: u16, @@ -757,7 +756,7 @@ pub struct MtftpInfo { } impl MtftpInfo { - const fn as_raw_ptr(&self) -> *const PxeBaseCodeMtftpInfo { + const fn as_ptr(&self) -> *const PxeBaseCodeMtftpInfo { ptr::from_ref(self).cast() } } @@ -772,7 +771,7 @@ pub struct IpFilter { pub filters: IpFilters, ip_cnt: u8, _reserved: u16, - ip_list: [IpAddress; 8], + ip_list: [EfiIpAddr; 8], } impl IpFilter { @@ -782,11 +781,11 @@ impl IpFilter { /// /// Panics if `ip_list` contains more than 8 entries. #[must_use] - pub fn new(filters: IpFilters, ip_list: &[IpAddress]) -> Self { + pub fn new(filters: IpFilters, ip_list: &[EfiIpAddr]) -> Self { assert!(ip_list.len() <= 8); let ip_cnt = ip_list.len() as u8; - let mut buffer = [IpAddress([0; 16]); 8]; + let mut buffer = [EfiIpAddr::from([0; 16]); 8]; buffer[..ip_list.len()].copy_from_slice(ip_list); Self { @@ -800,7 +799,7 @@ impl IpFilter { /// A list of IP addresses other than the Station Ip that should be /// enabled. Maybe be multicast or unicast. #[must_use] - pub fn ip_list(&self) -> &[IpAddress] { + pub fn ip_list(&self) -> &[EfiIpAddr] { &self.ip_list[..usize::from(self.ip_cnt)] } } @@ -1122,8 +1121,8 @@ impl Mode { /// [`BaseCode::udp_write`], [`BaseCode::arp`] and any of the TFTP/MTFTP /// operations are called. #[must_use] - pub fn station_ip(&self) -> IpAddress { - unsafe { IpAddress::from_raw(self.0.station_ip, self.using_ipv6()) } + pub const fn station_ip(&self) -> EfiIpAddr { + self.0.station_ip } /// The device's current subnet mask. This field is initialized to a zero @@ -1135,8 +1134,8 @@ impl Mode { /// [`BaseCode::udp_read`], [`BaseCode::udp_write`], /// [`BaseCode::arp`] or any of the TFTP/MTFTP operations are called. #[must_use] - pub fn subnet_mask(&self) -> IpAddress { - unsafe { IpAddress::from_raw(self.0.subnet_mask, self.using_ipv6()) } + pub const fn subnet_mask(&self) -> EfiIpAddr { + self.0.subnet_mask } /// Cached DHCP Discover packet. This field is zero-filled by the @@ -1253,9 +1252,9 @@ impl Mode { #[derive(Debug)] pub struct ArpEntry { /// The IP address. - pub ip_addr: IpAddress, + pub ip_addr: EfiIpAddr, /// The mac address of the device that is addressed by [`Self::ip_addr`]. - pub mac_addr: MacAddress, + pub mac_addr: EfiMacAddr, } /// An entry for the route table found in [`Mode::route_table`] @@ -1265,9 +1264,9 @@ pub struct ArpEntry { #[allow(missing_docs)] #[derive(Debug)] pub struct RouteEntry { - pub ip_addr: IpAddress, - pub subnet_mask: IpAddress, - pub gw_addr: IpAddress, + pub ip_addr: EfiIpAddr, + pub subnet_mask: EfiIpAddr, + pub gw_addr: EfiIpAddr, } /// An ICMP error packet. @@ -1357,7 +1356,7 @@ pub struct TftpFileInfo<'a> { #[derive(Debug)] pub struct MtftpFileInfo<'a> { pub filename: &'a CStr8, - pub ip_address: IpAddress, + pub ip_address: EfiIpAddr, pub size: u64, pub year: u16, pub month: u8, diff --git a/uefi/src/proto/network/snp.rs b/uefi/src/proto/network/snp.rs index 208477d59..50d3c7304 100644 --- a/uefi/src/proto/network/snp.rs +++ b/uefi/src/proto/network/snp.rs @@ -9,11 +9,12 @@ //! No interface function must be called until `SimpleNetwork.start` is successfully //! called first. -use super::{IpAddress, MacAddress}; +use super::{EfiIpAddr, EfiMacAddr}; use crate::data_types::Event; use crate::proto::unsafe_protocol; use crate::{Result, StatusExt}; use core::ffi::c_void; +use core::net::IpAddr; use core::ptr; use core::ptr::NonNull; use uefi_raw::protocol::network::snp::SimpleNetworkProtocol; @@ -66,7 +67,7 @@ impl SimpleNetwork { enable: ReceiveFlags, disable: ReceiveFlags, reset_mcast_filter: bool, - mcast_filter: Option<&[MacAddress]>, + mcast_filter: Option<&[EfiMacAddr]>, ) -> Result { let filter_count = mcast_filter.map(|filters| filters.len()).unwrap_or(0); let filters = mcast_filter @@ -87,7 +88,7 @@ impl SimpleNetwork { } /// Modify or reset the current station address, if supported. - pub fn station_address(&self, reset: bool, new: Option<&MacAddress>) -> Result { + pub fn station_address(&self, reset: bool, new: Option<&EfiMacAddr>) -> Result { unsafe { (self.0.station_address)( &self.0, @@ -127,13 +128,13 @@ impl SimpleNetwork { } /// Convert a multicast IP address to a multicast HW MAC Address. - pub fn mcast_ip_to_mac(&self, ipv6: bool, ip: IpAddress) -> Result { - let mut mac_address = MacAddress([0; 32]); + pub fn mcast_ip_to_mac(&self, ipv6: bool, ip: IpAddr) -> Result { + let mut mac_address = EfiMacAddr([0; 32]); let status = unsafe { (self.0.multicast_ip_to_mac)( &self.0, Boolean::from(ipv6), - ip.as_raw_ptr(), + EfiIpAddr::from(ip).as_ptr(), &mut mac_address, ) }; @@ -191,8 +192,8 @@ impl SimpleNetwork { &self, header_size: usize, buffer: &[u8], - src_addr: Option, - dest_addr: Option, + src_addr: Option, + dest_addr: Option, protocol: Option, ) -> Result { unsafe { @@ -216,8 +217,8 @@ impl SimpleNetwork { &self, buffer: &mut [u8], header_size: Option<&mut usize>, - src_addr: Option<&mut MacAddress>, - dest_addr: Option<&mut MacAddress>, + src_addr: Option<&mut EfiMacAddr>, + dest_addr: Option<&mut EfiMacAddr>, protocol: Option<&mut u16>, ) -> Result { let mut buffer_size = buffer.len(); diff --git a/xtask/src/device_path/mod.rs b/xtask/src/device_path/mod.rs index b03fa5e03..55b2c83aa 100644 --- a/xtask/src/device_path/mod.rs +++ b/xtask/src/device_path/mod.rs @@ -79,12 +79,12 @@ fn gen_uefi_code_as_string(groups: &[NodeGroup]) -> Result { self, DevicePathHeader, DevicePathNode, DeviceSubType, DeviceType, NodeConversionError, }; - use crate::proto::network::IpAddress; use crate::mem::memory_map::MemoryType; use core::mem::{size_of, size_of_val}; use core::ptr::addr_of; use core::{fmt, slice}; use ptr_meta::Pointee; + use uefi_raw::IpAddress; #(#packed_modules)*