Skip to content

Commit db50eef

Browse files
committed
uefi-raw: move types to net module
We have enough network-related types to justify a dedicated module: - IpAddress - Ipv4Address - Ipv6Address - MacAddress And lots of corresponding impl{} blocks, tests, etc.
1 parent fc0c76f commit db50eef

File tree

13 files changed

+199
-175
lines changed

13 files changed

+199
-175
lines changed

uefi-raw/src/lib.rs

Lines changed: 1 addition & 160 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ mod enums;
2727

2828
pub mod capsule;
2929
pub mod firmware_storage;
30+
pub mod net;
3031
pub mod protocol;
3132
pub mod table;
3233
pub mod time;
@@ -37,7 +38,6 @@ pub use status::Status;
3738
pub use uguid::{Guid, guid};
3839

3940
use core::ffi::c_void;
40-
use core::fmt::{self, Debug, Formatter};
4141

4242
/// Handle to an event structure.
4343
pub type Event = *mut c_void;
@@ -106,140 +106,10 @@ impl From<Boolean> for bool {
106106
}
107107
}
108108

109-
/// An IPv4 internet protocol address.
110-
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
111-
#[repr(transparent)]
112-
pub struct Ipv4Address(pub [u8; 4]);
113-
114-
impl From<core::net::Ipv4Addr> for Ipv4Address {
115-
fn from(ip: core::net::Ipv4Addr) -> Self {
116-
Self(ip.octets())
117-
}
118-
}
119-
120-
impl From<Ipv4Address> for core::net::Ipv4Addr {
121-
fn from(ip: Ipv4Address) -> Self {
122-
Self::from(ip.0)
123-
}
124-
}
125-
126-
/// An IPv6 internet protocol address.
127-
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
128-
#[repr(transparent)]
129-
pub struct Ipv6Address(pub [u8; 16]);
130-
131-
impl From<core::net::Ipv6Addr> for Ipv6Address {
132-
fn from(ip: core::net::Ipv6Addr) -> Self {
133-
Self(ip.octets())
134-
}
135-
}
136-
137-
impl From<Ipv6Address> for core::net::Ipv6Addr {
138-
fn from(ip: Ipv6Address) -> Self {
139-
Self::from(ip.0)
140-
}
141-
}
142-
143-
/// An IPv4 or IPv6 internet protocol address.
144-
///
145-
/// Corresponds to the `EFI_IP_ADDRESS` type in the UEFI specification. This
146-
/// type is defined in the same way as edk2 for compatibility with C code. Note
147-
/// that this is an untagged union, so there's no way to tell which type of
148-
/// address an `IpAddress` value contains without additional context.
149-
#[derive(Clone, Copy)]
150-
#[repr(C)]
151-
pub union IpAddress {
152-
/// This member serves to align the whole type to a 4 bytes as required by
153-
/// the spec. Note that this is slightly different from `repr(align(4))`,
154-
/// which would prevent placing this type in a packed structure.
155-
pub addr: [u32; 4],
156-
157-
/// An IPv4 internet protocol address.
158-
pub v4: Ipv4Address,
159-
160-
/// An IPv6 internet protocol address.
161-
pub v6: Ipv6Address,
162-
}
163-
164-
impl IpAddress {
165-
/// Construct a new IPv4 address.
166-
#[must_use]
167-
pub const fn new_v4(ip_addr: [u8; 4]) -> Self {
168-
Self {
169-
v4: Ipv4Address(ip_addr),
170-
}
171-
}
172-
173-
/// Construct a new IPv6 address.
174-
#[must_use]
175-
pub const fn new_v6(ip_addr: [u8; 16]) -> Self {
176-
Self {
177-
v6: Ipv6Address(ip_addr),
178-
}
179-
}
180-
}
181-
182-
impl Debug for IpAddress {
183-
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
184-
// The type is an untagged union, so we don't know whether it contains
185-
// an IPv4 or IPv6 address. It's also not safe to just print the whole
186-
// 16 bytes, since they might not all be initialized.
187-
f.debug_struct("IpAddress").finish()
188-
}
189-
}
190-
191-
impl Default for IpAddress {
192-
fn default() -> Self {
193-
Self { addr: [0u32; 4] }
194-
}
195-
}
196-
197-
impl From<core::net::IpAddr> for IpAddress {
198-
fn from(t: core::net::IpAddr) -> Self {
199-
match t {
200-
core::net::IpAddr::V4(ip) => Self {
201-
v4: Ipv4Address::from(ip),
202-
},
203-
core::net::IpAddr::V6(ip) => Self {
204-
v6: Ipv6Address::from(ip),
205-
},
206-
}
207-
}
208-
}
209-
210-
/// A Media Access Control (MAC) address.
211-
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
212-
#[repr(transparent)]
213-
pub struct MacAddress(pub [u8; 32]);
214-
215-
impl From<[u8; 6]> for MacAddress {
216-
fn from(octets: [u8; 6]) -> Self {
217-
let mut buffer = [0; 32];
218-
buffer[0] = octets[0];
219-
buffer[1] = octets[1];
220-
buffer[2] = octets[2];
221-
buffer[3] = octets[3];
222-
buffer[4] = octets[4];
223-
buffer[5] = octets[5];
224-
Self(buffer)
225-
}
226-
}
227-
228-
impl From<MacAddress> for [u8; 6] {
229-
fn from(MacAddress(o): MacAddress) -> Self {
230-
[o[0], o[1], o[2], o[3], o[4], o[5]]
231-
}
232-
}
233-
234109
#[cfg(test)]
235110
mod tests {
236111
use super::*;
237112

238-
const TEST_IPV4: [u8; 4] = [91, 92, 93, 94];
239-
const TEST_IPV6: [u8; 16] = [
240-
101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
241-
];
242-
243113
#[test]
244114
/// Test the properties promised in [0]. This also applies for the other
245115
/// architectures.
@@ -258,33 +128,4 @@ mod tests {
258128
assert!(bool::from(Boolean(0b11111111)));
259129
}
260130

261-
/// Test round-trip conversion between `Ipv4Address` and `core::net::Ipv4Addr`.
262-
#[test]
263-
fn test_ip_addr4_conversion() {
264-
let uefi_addr = Ipv4Address(TEST_IPV4);
265-
let core_addr = core::net::Ipv4Addr::from(uefi_addr);
266-
assert_eq!(uefi_addr, Ipv4Address::from(core_addr));
267-
}
268-
269-
/// Test round-trip conversion between `Ipv6Address` and `core::net::Ipv6Addr`.
270-
#[test]
271-
fn test_ip_addr6_conversion() {
272-
let uefi_addr = Ipv6Address(TEST_IPV6);
273-
let core_addr = core::net::Ipv6Addr::from(uefi_addr);
274-
assert_eq!(uefi_addr, Ipv6Address::from(core_addr));
275-
}
276-
277-
/// Test conversion from `core::net::IpAddr` to `IpvAddress`.
278-
///
279-
/// Note that conversion in the other direction is not possible.
280-
#[test]
281-
fn test_ip_addr_conversion() {
282-
let core_addr = core::net::IpAddr::V4(core::net::Ipv4Addr::from(TEST_IPV4));
283-
let uefi_addr = IpAddress::from(core_addr);
284-
assert_eq!(unsafe { uefi_addr.v4.0 }, TEST_IPV4);
285-
286-
let core_addr = core::net::IpAddr::V6(core::net::Ipv6Addr::from(TEST_IPV6));
287-
let uefi_addr = IpAddress::from(core_addr);
288-
assert_eq!(unsafe { uefi_addr.v6.0 }, TEST_IPV6);
289-
}
290131
}

uefi-raw/src/net.rs

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
// SPDX-License-Identifier: MIT OR Apache-2.0
2+
3+
//! UEFI network types.
4+
5+
use core::fmt;
6+
use core::fmt::{Debug, Formatter};
7+
8+
/// An IPv4 internet protocol address.
9+
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
10+
#[repr(transparent)]
11+
pub struct Ipv4Address(pub [u8; 4]);
12+
13+
impl From<core::net::Ipv4Addr> for Ipv4Address {
14+
fn from(ip: core::net::Ipv4Addr) -> Self {
15+
Self(ip.octets())
16+
}
17+
}
18+
19+
impl From<Ipv4Address> for core::net::Ipv4Addr {
20+
fn from(ip: Ipv4Address) -> Self {
21+
Self::from(ip.0)
22+
}
23+
}
24+
25+
/// An IPv6 internet protocol address.
26+
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
27+
#[repr(transparent)]
28+
pub struct Ipv6Address(pub [u8; 16]);
29+
30+
impl From<core::net::Ipv6Addr> for Ipv6Address {
31+
fn from(ip: core::net::Ipv6Addr) -> Self {
32+
Self(ip.octets())
33+
}
34+
}
35+
36+
impl From<Ipv6Address> for core::net::Ipv6Addr {
37+
fn from(ip: Ipv6Address) -> Self {
38+
Self::from(ip.0)
39+
}
40+
}
41+
42+
/// An IPv4 or IPv6 internet protocol address.
43+
///
44+
/// Corresponds to the `EFI_IP_ADDRESS` type in the UEFI specification. This
45+
/// type is defined in the same way as edk2 for compatibility with C code. Note
46+
/// that this is an **untagged union**, so there's no way to tell which type of
47+
/// address an `IpAddress` value contains without additional context.
48+
#[derive(Clone, Copy)]
49+
#[repr(C)]
50+
pub union IpAddress {
51+
/// An IPv4 internet protocol address.
52+
pub v4: Ipv4Address,
53+
54+
/// An IPv6 internet protocol address.
55+
pub v6: Ipv6Address,
56+
57+
/// This member serves to align the whole type to 4 bytes as required by
58+
/// the spec. Note that this is slightly different from `repr(align(4))`,
59+
/// which would prevent placing this type in a packed structure.
60+
pub _align_helper: [u32; 4],
61+
}
62+
63+
impl IpAddress {
64+
/// Construct a new IPv4 address.
65+
#[must_use]
66+
pub const fn new_v4(ip_addr: [u8; 4]) -> Self {
67+
Self {
68+
v4: Ipv4Address(ip_addr),
69+
}
70+
}
71+
72+
/// Construct a new IPv6 address.
73+
#[must_use]
74+
pub const fn new_v6(ip_addr: [u8; 16]) -> Self {
75+
Self {
76+
v6: Ipv6Address(ip_addr),
77+
}
78+
}
79+
}
80+
81+
impl Debug for IpAddress {
82+
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
83+
// The type is an untagged union, so we don't know whether it contains
84+
// an IPv4 or IPv6 address. It's also not safe to just print the whole
85+
// 16 bytes, since they might not all be initialized.
86+
f.debug_struct("IpAddress").finish()
87+
}
88+
}
89+
90+
impl Default for IpAddress {
91+
fn default() -> Self {
92+
Self {
93+
_align_helper: [0u32; 4],
94+
}
95+
}
96+
}
97+
98+
impl From<core::net::IpAddr> for IpAddress {
99+
fn from(t: core::net::IpAddr) -> Self {
100+
match t {
101+
core::net::IpAddr::V4(ip) => Self {
102+
v4: Ipv4Address::from(ip),
103+
},
104+
core::net::IpAddr::V6(ip) => Self {
105+
v6: Ipv6Address::from(ip),
106+
},
107+
}
108+
}
109+
}
110+
111+
/// UEFI Media Access Control (MAC) address.
112+
///
113+
/// UEFI supports multiple network protocols and hardware types, not just
114+
/// Ethernet. Some of them may use MAC addresses longer than 6 bytes. To be
115+
/// protocol-agnostic and future-proof, the UEFI spec chooses a maximum size
116+
/// that can hold any supported media access control address.
117+
///
118+
/// In most cases, this is just a typical `[u8; 6]` Ethernet style MAC
119+
/// address with the rest of the bytes being zero.
120+
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
121+
#[repr(transparent)]
122+
pub struct MacAddress(pub [u8; 32]);
123+
124+
impl From<[u8; 6]> for MacAddress {
125+
fn from(octets: [u8; 6]) -> Self {
126+
let mut buffer = [0; 32];
127+
buffer.copy_from_slice(&octets);
128+
Self(buffer)
129+
}
130+
}
131+
132+
impl From<MacAddress> for [u8; 6] {
133+
fn from(MacAddress(o): MacAddress) -> Self {
134+
[o[0], o[1], o[2], o[3], o[4], o[5]]
135+
}
136+
}
137+
138+
#[cfg(test)]
139+
mod tests {
140+
use super::*;
141+
142+
const TEST_IPV4: [u8; 4] = [91, 92, 93, 94];
143+
const TEST_IPV6: [u8; 16] = [
144+
101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
145+
];
146+
147+
/// Test round-trip conversion between `Ipv4Address` and `core::net::Ipv4Addr`.
148+
#[test]
149+
fn test_ip_addr4_conversion() {
150+
let uefi_addr = Ipv4Address(TEST_IPV4);
151+
let core_addr = core::net::Ipv4Addr::from(uefi_addr);
152+
assert_eq!(uefi_addr, Ipv4Address::from(core_addr));
153+
}
154+
155+
/// Test round-trip conversion between `Ipv6Address` and `core::net::Ipv6Addr`.
156+
#[test]
157+
fn test_ip_addr6_conversion() {
158+
let uefi_addr = Ipv6Address(TEST_IPV6);
159+
let core_addr = core::net::Ipv6Addr::from(uefi_addr);
160+
assert_eq!(uefi_addr, Ipv6Address::from(core_addr));
161+
}
162+
163+
/// Test conversion from `core::net::IpAddr` to `IpvAddress`.
164+
///
165+
/// Note that conversion in the other direction is not possible.
166+
#[test]
167+
fn test_ip_addr_conversion() {
168+
let core_addr = core::net::IpAddr::V4(core::net::Ipv4Addr::from(TEST_IPV4));
169+
let uefi_addr = IpAddress::from(core_addr);
170+
assert_eq!(unsafe { uefi_addr.v4.0 }, TEST_IPV4);
171+
172+
let core_addr = core::net::IpAddr::V6(core::net::Ipv6Addr::from(TEST_IPV6));
173+
let uefi_addr = IpAddress::from(core_addr);
174+
assert_eq!(unsafe { uefi_addr.v6.0 }, TEST_IPV6);
175+
}
176+
}

uefi-raw/src/protocol/device_path/device_path_gen.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@
88
// See `/xtask/src/device_path/README.md` for more details.
99
#![allow(clippy::missing_const_for_fn)]
1010
#![allow(missing_debug_implementations)]
11+
use crate::net::IpAddress;
1112
use crate::protocol::device_path;
1213
use crate::table::boot::MemoryType;
13-
use crate::{Guid, IpAddress, guid};
14+
use crate::{Guid, guid};
1415
use bitflags::bitflags;
1516
use device_path::DevicePathProtocol as DevicePathHeader;
1617
#[cfg(doc)]

uefi-raw/src/protocol/network/dhcp4.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// SPDX-License-Identifier: MIT OR Apache-2.0
22

3-
use crate::{Boolean, Char8, Event, Guid, Ipv4Address, MacAddress, Status, guid};
3+
use crate::net::{Ipv4Address, MacAddress};
4+
use crate::{Boolean, Char8, Event, Guid, Status, guid};
45
use core::ffi::c_void;
56

67
newtype_enum! {

uefi-raw/src/protocol/network/http.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// SPDX-License-Identifier: MIT OR Apache-2.0
22

3-
use crate::{Boolean, Char8, Char16, Event, Guid, Ipv4Address, Ipv6Address, Status, guid};
3+
use crate::net::{Ipv4Address, Ipv6Address};
4+
use crate::{Boolean, Char8, Char16, Event, Guid, Status, guid};
45
use core::ffi::c_void;
56
use core::fmt::{self, Debug, Formatter};
67
use core::ptr;

0 commit comments

Comments
 (0)