Skip to content

Commit ca0bacb

Browse files
authored
Merge pull request #1967 from JarlEvanson/pxe-migration
Remove duplications in `uefi` and `uefi-raw`
2 parents 949ad3c + 06726d2 commit ca0bacb

4 files changed

Lines changed: 253 additions & 391 deletions

File tree

uefi-raw/CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,15 @@
1212
implementations of `PartialEq`, `Eq`, `PartialOrd`, `Ord`, and `Hash` to match
1313
the type's logical properties. If you rely on the specific bit pattern,
1414
please use `.0` to access the underlying value.
15+
- Added `PxeBaseCodeDhcpV4Flags`.
16+
- Added `PxeBaseCodeDhcpV4Packet::{DHCP_MAGIK, bootp_ident(), bootp_seconds(),
17+
bootp_flags(), dhcp_magik()}`.
18+
- Added `PxeBaseCodeDhcpV6Packet::transaction_id()`.
19+
- Added `AsRef` implementations to `PxeBaseCodePacket`.
20+
- Added `PxeBaseCodeIpFilter::{new(), ip_list()}`.
21+
- Added `PxeBaseCodeSrvlist::{new(), ip_addr()}`.
22+
- `PxeBaseCodeIcmpError` and `PxeBaseCodeTftpError` now implement `Display` and
23+
`core::error::Error`.
1524

1625

1726
# uefi-raw - v0.14.0 (2026-03-22)

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

Lines changed: 201 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use crate::{Boolean, Char8, Guid, IpAddress, MacAddress, Status, guid, newtype_enum};
44
use bitflags::bitflags;
55
use core::ffi::c_void;
6-
use core::fmt::{self, Debug, Formatter};
6+
use core::fmt::{self, Debug, Display, Formatter};
77

88
#[derive(Debug)]
99
#[repr(C)]
@@ -154,6 +154,9 @@ pub struct PxeBaseCodeDiscoverInfo {
154154
pub srv_list: [PxeBaseCodeSrvlist; 0],
155155
}
156156

157+
/// An entry in the boot server list.
158+
///
159+
/// In the C API, this corresponds to the `EFI_PXE_BASE_CODE_SRVLIST` type.
157160
#[derive(Clone, Copy, Debug)]
158161
#[repr(C)]
159162
pub struct PxeBaseCodeSrvlist {
@@ -163,15 +166,54 @@ pub struct PxeBaseCodeSrvlist {
163166
pub ip_addr: IpAddress,
164167
}
165168

169+
impl PxeBaseCodeSrvlist {
170+
/// Construct a [`PxeBaseCodeSrvlist`] for a boot server reply type. If `ip_addr` is not `None`,
171+
/// only boot server replies matching the provided IP address will be accepted.
172+
#[must_use]
173+
pub fn new(server_type: u16, ip_addr: Option<IpAddress>) -> Self {
174+
Self {
175+
server_type,
176+
accept_any_response: Boolean::from(ip_addr.is_none()),
177+
reserved: 0,
178+
ip_addr: ip_addr.unwrap_or_default(),
179+
}
180+
}
181+
182+
/// Returns `None` if any response should be accepted, or otherwise the IP
183+
/// address of a boot server whose responses should be accepted.
184+
#[must_use]
185+
pub fn ip_addr(&self) -> Option<&IpAddress> {
186+
if self.accept_any_response.into() {
187+
None
188+
} else {
189+
Some(&self.ip_addr)
190+
}
191+
}
192+
}
193+
166194
pub type PxeBaseCodeUdpPort = u16;
167195

196+
/// MTFTP connection parameters.
197+
///
198+
/// In the C API, this corresponds to the `EFI_PXE_BASE_CODE_MTFTP_INFO` type.
168199
#[derive(Clone, Copy, Debug)]
169200
#[repr(C)]
170201
pub struct PxeBaseCodeMtftpInfo {
202+
/// We need a low level type and a high-level type with `IpAddr`
203+
/// File multicast IP address. This is the IP address to which the server
204+
/// will send the requested file.
171205
pub m_cast_ip: IpAddress,
206+
/// Client multicast listening port. This is the UDP port to which the
207+
/// server will send the requested file.
172208
pub c_port: PxeBaseCodeUdpPort,
209+
/// Server multicast listening port. This is the UDP port on which the
210+
/// server listens for multicast open requests and data acks.
173211
pub s_port: PxeBaseCodeUdpPort,
212+
/// The number of seconds a client should listen for an active multicast
213+
/// session before requesting a new multicast session.
174214
pub listen_timeout: u16,
215+
/// The number of seconds a client should wait for a packet from the server
216+
/// before retransmitting the previous open request or data ack packet.
175217
pub transmit_timeout: u16,
176218
}
177219

@@ -241,6 +283,9 @@ pub struct PxeBaseCodeMode {
241283
pub tftp_error: PxeBaseCodeTftpError,
242284
}
243285

286+
/// A network packet.
287+
///
288+
/// In the C API, this corresponds to the `EFI_PXE_BASE_CODE_PACKET` type.
244289
#[derive(Clone, Copy)]
245290
#[repr(C)]
246291
pub union PxeBaseCodePacket {
@@ -255,35 +300,129 @@ impl Debug for PxeBaseCodePacket {
255300
}
256301
}
257302

303+
impl AsRef<[u8; 1472]> for PxeBaseCodePacket {
304+
fn as_ref(&self) -> &[u8; 1472] {
305+
unsafe { &self.raw }
306+
}
307+
}
308+
309+
impl AsRef<PxeBaseCodeDhcpV4Packet> for PxeBaseCodePacket {
310+
fn as_ref(&self) -> &PxeBaseCodeDhcpV4Packet {
311+
unsafe { &self.dhcpv4 }
312+
}
313+
}
314+
315+
impl AsRef<PxeBaseCodeDhcpV6Packet> for PxeBaseCodePacket {
316+
fn as_ref(&self) -> &PxeBaseCodeDhcpV6Packet {
317+
unsafe { &self.dhcpv6 }
318+
}
319+
}
320+
321+
/// A DHCPv4 packet.
322+
///
323+
/// In the C API, this corresponds to the `EFI_PXE_BASE_CODE_DHCPV4_PACKET` type.
258324
#[derive(Clone, Copy, Debug)]
259325
#[repr(C)]
260326
pub struct PxeBaseCodeDhcpV4Packet {
327+
/// Packet op code / message type.
261328
pub bootp_opcode: u8,
329+
/// Hardware address type.
262330
pub bootp_hw_type: u8,
331+
/// Hardware address length.
263332
pub bootp_hw_addr_len: u8,
333+
/// Client sets to zero, optionally used by gateways in cross-gateway booting.
264334
pub bootp_gate_hops: u8,
265335
pub bootp_ident: u32,
266336
pub bootp_seconds: u16,
267337
pub bootp_flags: u16,
338+
/// Client IP address, filled in by client in bootrequest if known.
268339
pub bootp_ci_addr: [u8; 4],
340+
/// 'your' (client) IP address; filled by server if client doesn't know its own address (`bootp_ci_addr` was 0).
269341
pub bootp_yi_addr: [u8; 4],
342+
/// Server IP address, returned in bootreply by server.
270343
pub bootp_si_addr: [u8; 4],
344+
/// Gateway IP address, used in optional cross-gateway booting.
271345
pub bootp_gi_addr: [u8; 4],
346+
/// Client hardware address, filled in by client.
272347
pub bootp_hw_addr: [u8; 16],
348+
/// Optional server host name, null terminated string.
273349
pub bootp_srv_name: [u8; 64],
350+
/// Boot file name, null terminated string, 'generic' name or null in
351+
/// bootrequest, fully qualified directory-path name in bootreply.
274352
pub bootp_boot_file: [u8; 128],
353+
/// Validation magic number.
275354
pub dhcp_magik: u32,
355+
/// Optional vendor-specific area, e.g. could be hardware type/serial on request, or 'capability' / remote file system handle on reply. This info may be set aside for use by a third phase bootstrap or kernel.
276356
pub dhcp_options: [u8; 56],
277357
}
278358

359+
impl PxeBaseCodeDhcpV4Packet {
360+
/// The expected value for [`Self::dhcp_magik`].
361+
pub const DHCP_MAGIK: u32 = 0x63825363;
362+
363+
/// Transaction ID, a random number, used to match this boot request with the responses it generates.
364+
#[must_use]
365+
pub const fn bootp_ident(&self) -> u32 {
366+
u32::from_be(self.bootp_ident)
367+
}
368+
369+
/// Filled in by client, seconds elapsed since client started trying to boot.
370+
#[must_use]
371+
pub const fn bootp_seconds(&self) -> u16 {
372+
u16::from_be(self.bootp_seconds)
373+
}
374+
375+
/// The flags.
376+
#[must_use]
377+
pub const fn bootp_flags(&self) -> PxeBaseCodeDhcpV4Flags {
378+
PxeBaseCodeDhcpV4Flags::from_bits_truncate(u16::from_be(self.bootp_flags))
379+
}
380+
381+
/// A magic cookie, should be [`Self::DHCP_MAGIK`].
382+
#[must_use]
383+
pub const fn dhcp_magik(&self) -> u32 {
384+
u32::from_be(self.dhcp_magik)
385+
}
386+
}
387+
388+
bitflags! {
389+
/// Represents the 'flags' field for a [`PxeBaseCodeDhcpV4Packet`].
390+
#[repr(transparent)]
391+
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
392+
pub struct PxeBaseCodeDhcpV4Flags: u16 {
393+
/// Should be set when the client cannot receive unicast IP datagrams
394+
/// until its protocol software has been configured with an IP address.
395+
const BROADCAST = 1;
396+
}
397+
}
398+
399+
/// A DHCPv6 packet.
400+
///
401+
/// In the C API, this corresponds to the `EFI_PXE_BASE_CODE_DHCPV6_PACKET` type.
279402
#[derive(Clone, Copy, Debug)]
280403
#[repr(C)]
281404
pub struct PxeBaseCodeDhcpV6Packet {
405+
/// The message type.
282406
pub message_type: u8,
407+
/// The transaction id.
283408
pub transaction_id: [u8; 3],
409+
/// A byte array containing DHCP options.
284410
pub dhcp_options: [u8; 1024],
285411
}
286412

413+
impl PxeBaseCodeDhcpV6Packet {
414+
/// The transaction id.
415+
#[must_use]
416+
pub fn transaction_id(&self) -> u32 {
417+
(u32::from(self.transaction_id[0]) << 16)
418+
| (u32::from(self.transaction_id[1]) << 8)
419+
| u32::from(self.transaction_id[2])
420+
}
421+
}
422+
423+
/// IP receive filter settings.
424+
///
425+
/// In the C API, this corresponds to the `EFI_PXE_BASE_CODE_IP_FILTER` type.
287426
#[derive(Clone, Copy, Debug)]
288427
#[repr(C)]
289428
pub struct PxeBaseCodeIpFilter {
@@ -293,6 +432,39 @@ pub struct PxeBaseCodeIpFilter {
293432
pub ip_list: [IpAddress; 8],
294433
}
295434

435+
impl PxeBaseCodeIpFilter {
436+
#[must_use]
437+
pub fn new(filters: PxeBaseCodeIpFilterFlags, ip_list: &[core::net::IpAddr]) -> Self {
438+
assert!(ip_list.len() <= 8);
439+
440+
let ip_cnt = ip_list.len() as u8;
441+
let mut buffer = [IpAddress::default(); 8];
442+
for (index, ip_address) in ip_list
443+
.iter()
444+
.cloned()
445+
.map(|value| value.into())
446+
.enumerate()
447+
{
448+
buffer[index] = ip_address;
449+
}
450+
451+
Self {
452+
filters,
453+
ip_cnt,
454+
reserved: 0,
455+
ip_list: buffer,
456+
}
457+
}
458+
459+
/// A list of IP addresses other than the station IP that should be enabled.
460+
///
461+
/// May be multicast or unicast.
462+
#[must_use]
463+
pub fn ip_list(&self) -> &[IpAddress] {
464+
&self.ip_list[..usize::from(self.ip_cnt)]
465+
}
466+
}
467+
296468
bitflags! {
297469
/// IP receive filters.
298470
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
@@ -312,13 +484,19 @@ bitflags! {
312484
}
313485
}
314486

487+
/// An entry for the ARP cache found in [`PxeBaseCodeMode::arp_cache`].
488+
///
489+
/// In the C API, this corresponds to the `EFI_PXE_BASE_CODE_ARP_ENTRY` type.
315490
#[derive(Clone, Copy, Debug)]
316491
#[repr(C)]
317492
pub struct PxeBaseCodeArpEntry {
318493
pub ip_addr: IpAddress,
319494
pub mac_addr: MacAddress,
320495
}
321496

497+
/// An entry for the route table found in [`PxeBaseCodeMode::route_table`].
498+
///
499+
/// In the C API, this corresponds to the `EFI_PXE_BASE_CODE_ROUTE_ENTRY` type.
322500
#[derive(Clone, Copy, Debug)]
323501
#[repr(C)]
324502
pub struct PxeBaseCodeRouteEntry {
@@ -327,6 +505,9 @@ pub struct PxeBaseCodeRouteEntry {
327505
pub gw_addr: IpAddress,
328506
}
329507

508+
/// An ICMP error packet.
509+
///
510+
/// In the C API, this corresponds to the `EFI_PXE_BASE_CODE_ICMP_ERROR` type.
330511
#[derive(Clone, Debug)]
331512
#[repr(C)]
332513
pub struct PxeBaseCodeIcmpError {
@@ -337,6 +518,14 @@ pub struct PxeBaseCodeIcmpError {
337518
pub data: [u8; 494],
338519
}
339520

521+
impl Display for PxeBaseCodeIcmpError {
522+
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
523+
write!(f, "{self:?}")
524+
}
525+
}
526+
527+
impl core::error::Error for PxeBaseCodeIcmpError {}
528+
340529
/// In the C API, this is an anonymous union inside the definition of
341530
/// `EFI_PXE_BASE_CODE_ICMP_ERROR`.
342531
#[derive(Clone, Copy)]
@@ -363,9 +552,20 @@ pub struct PxeBaseCodeIcmpErrorEcho {
363552
pub sequence: u16,
364553
}
365554

555+
/// A TFTP error packet.
556+
///
557+
/// In the C API, this corresponds to the `EFI_PXE_BASE_CODE_TFTP_ERROR` type.
366558
#[derive(Clone, Debug)]
367559
#[repr(C)]
368560
pub struct PxeBaseCodeTftpError {
369561
pub error_code: u8,
370562
pub error_string: [Char8; 127],
371563
}
564+
565+
impl Display for PxeBaseCodeTftpError {
566+
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
567+
write!(f, "{self:?}")
568+
}
569+
}
570+
571+
impl core::error::Error for PxeBaseCodeTftpError {}

uefi/CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,14 @@
1717
errors during exit.
1818
- **Breaking:** Renamed `PciIoAccessPci` to `PciIoAccess` and added a generic
1919
parameter to handle the PCI configuration, IO port, and MMIO address spaces.
20+
- **Breaking:** Replace `ArpEntry`, `DhcpV4Flags`, `DhcpV4Packet`,
21+
`DhcpV6Packet`, `IcmpError`, `IcmpErrorEcho`, `IcmpErrorUnion`, `IpFilter`,
22+
`MtftpInfo`, `Packet`, `RouteEntry`, `Server`, and `TftpError` with re-exports
23+
from `uefi-raw`.
24+
- **Breaking:** Changed `ArpEntry` and `RouteEntry` to fix incorrect slicing in
25+
`proto::network::pxe::Mode::{arp_cache(), route_table()}`.
26+
- **Breaking:** Changed `Server::ty` to `Server::server_type`.
27+
- **Breaking:** Changed `TftpError::error_string` from `[u8; 127]` to `[Char8; 127]`.
2028

2129
## Removed
2230
- **Breaking:** Removed the deprecated `table::cfg::*_GUID` constants. Use

0 commit comments

Comments
 (0)