33use crate :: { Boolean , Char8 , Guid , IpAddress , MacAddress , Status , guid, newtype_enum} ;
44use bitflags:: bitflags;
55use 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 ) ]
159162pub 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+
166194pub 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 ) ]
170201pub 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 ) ]
246291pub 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 ) ]
260326pub 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 ) ]
281404pub 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 ) ]
289428pub 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+
296468bitflags ! {
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 ) ]
317492pub 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 ) ]
324502pub 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 ) ]
332513pub 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 ) ]
368560pub 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 { }
0 commit comments