1 //! Simple Network Protocol
2 //!
3 //! Provides a packet level interface to a network adapter.
4 //! Once the adapter is initialized, the protocol provides services that allows
5 //! packets to be transmitted and received.
6 //!
7 //! No interface function must be called until `SimpleNetwork.start` is successfully
8 //! called first.
9 
10 use super::{IpAddress, MacAddress};
11 use crate::data_types::Event;
12 use crate::proto::unsafe_protocol;
13 use crate::{Result, Status, StatusExt};
14 use bitflags::bitflags;
15 use core::ffi::c_void;
16 use core::ptr;
17 use core::ptr::NonNull;
18 
19 /// The Simple Network Protocol
20 #[derive(Debug)]
21 #[repr(C)]
22 #[unsafe_protocol("a19832b9-ac25-11d3-9a2d-0090273fc14d")]
23 pub struct SimpleNetwork {
24     revision: u64,
25     start: extern "efiapi" fn(this: &Self) -> Status,
26     stop: extern "efiapi" fn(this: &Self) -> Status,
27     initialize: extern "efiapi" fn(
28         this: &Self,
29         extra_recv_buffer_size: usize,
30         extra_transmit_buffer_size: usize,
31     ) -> Status,
32     reset: extern "efiapi" fn(this: &Self, extended_verification: bool) -> Status,
33     shutdown: extern "efiapi" fn(this: &Self) -> Status,
34     receive_filters: extern "efiapi" fn(
35         this: &Self,
36         enable: u32,
37         disable: u32,
38         reset_mcast_filter: bool,
39         mcast_filter_count: usize,
40         mcast_filter: Option<NonNull<MacAddress>>,
41     ) -> Status,
42     station_address:
43         extern "efiapi" fn(this: &Self, reset: bool, new: Option<&MacAddress>) -> Status,
44     statistics: extern "efiapi" fn(
45         this: &Self,
46         reset: bool,
47         stats_size: Option<&mut usize>,
48         stats_table: Option<&mut NetworkStats>,
49     ) -> Status,
50     mcast_ip_to_mac:
51         extern "efiapi" fn(this: &Self, ipv6: bool, ip: &IpAddress, mac: &mut MacAddress) -> Status,
52     nv_data: extern "efiapi" fn(
53         this: &Self,
54         read_write: bool,
55         offset: usize,
56         buffer_size: usize,
57         buffer: *mut c_void,
58     ) -> Status,
59     get_status: extern "efiapi" fn(
60         this: &Self,
61         interrupt_status: Option<&mut InterruptStatus>,
62         tx_buf: Option<&mut *mut c_void>,
63     ) -> Status,
64     transmit: extern "efiapi" fn(
65         this: &Self,
66         header_size: usize,
67         buffer_size: usize,
68         buffer: *const c_void,
69         src_addr: Option<&MacAddress>,
70         dest_addr: Option<&MacAddress>,
71         protocol: Option<&u16>,
72     ) -> Status,
73     receive: extern "efiapi" fn(
74         this: &Self,
75         header_size: Option<&mut usize>,
76         buffer_size: &mut usize,
77         buffer: *mut c_void,
78         src_addr: Option<&mut MacAddress>,
79         dest_addr: Option<&mut MacAddress>,
80         protocol: Option<&mut u16>,
81     ) -> Status,
82     // On QEMU, this event seems to never fire.
83     wait_for_packet: Event,
84     mode: *const NetworkMode,
85 }
86 
87 impl SimpleNetwork {
88     /// Change the state of a network from "Stopped" to "Started".
start(&self) -> Result89     pub fn start(&self) -> Result {
90         (self.start)(self).to_result()
91     }
92 
93     /// Change the state of a network interface from "Started" to "Stopped".
stop(&self) -> Result94     pub fn stop(&self) -> Result {
95         (self.stop)(self).to_result()
96     }
97 
98     /// Reset a network adapter and allocate the transmit and receive buffers
99     /// required by the network interface; optionally, also request allocation of
100     /// additional transmit and receive buffers.
initialize(&self, extra_rx_buffer_size: usize, extra_tx_buffer_size: usize) -> Result101     pub fn initialize(&self, extra_rx_buffer_size: usize, extra_tx_buffer_size: usize) -> Result {
102         (self.initialize)(self, extra_rx_buffer_size, extra_tx_buffer_size).to_result()
103     }
104 
105     /// Reset a network adapter and reinitialize it with the parameters that were
106     /// provided in the previous call to `initialize`.
reset(&self, extended_verification: bool) -> Result107     pub fn reset(&self, extended_verification: bool) -> Result {
108         (self.reset)(self, extended_verification).to_result()
109     }
110 
111     /// Reset a network adapter, leaving it in a state that is safe
112     /// for another driver to initialize
shutdown(&self) -> Result113     pub fn shutdown(&self) -> Result {
114         (self.shutdown)(self).to_result()
115     }
116 
117     /// Manage the multicast receive filters of a network.
receive_filters( &self, enable: ReceiveFlags, disable: ReceiveFlags, reset_mcast_filter: bool, mcast_filter: Option<&[MacAddress]>, ) -> Result118     pub fn receive_filters(
119         &self,
120         enable: ReceiveFlags,
121         disable: ReceiveFlags,
122         reset_mcast_filter: bool,
123         mcast_filter: Option<&[MacAddress]>,
124     ) -> Result {
125         if let Some(mcast_filter) = mcast_filter {
126             (self.receive_filters)(
127                 self,
128                 enable.bits(),
129                 disable.bits(),
130                 reset_mcast_filter,
131                 mcast_filter.len(),
132                 NonNull::new(mcast_filter.as_ptr() as *mut _),
133             )
134             .to_result()
135         } else {
136             (self.receive_filters)(
137                 self,
138                 enable.bits(),
139                 disable.bits(),
140                 reset_mcast_filter,
141                 0,
142                 None,
143             )
144             .to_result()
145         }
146     }
147 
148     /// Modify or reset the current station address, if supported.
station_address(&self, reset: bool, new: Option<&MacAddress>) -> Result149     pub fn station_address(&self, reset: bool, new: Option<&MacAddress>) -> Result {
150         (self.station_address)(self, reset, new).to_result()
151     }
152 
153     /// Reset statistics on a network interface.
reset_statistics(&self) -> Result154     pub fn reset_statistics(&self) -> Result {
155         (self.statistics)(self, true, None, None).to_result()
156     }
157 
158     /// Collect statistics on a network interface.
collect_statistics(&self) -> Result<NetworkStats>159     pub fn collect_statistics(&self) -> Result<NetworkStats> {
160         let mut stats_table: NetworkStats = Default::default();
161         let mut stats_size = core::mem::size_of::<NetworkStats>();
162         let status = (self.statistics)(self, false, Some(&mut stats_size), Some(&mut stats_table));
163         status.to_result_with_val(|| stats_table)
164     }
165 
166     /// Convert a multicast IP address to a multicast HW MAC Address.
mcast_ip_to_mac(&self, ipv6: bool, ip: IpAddress) -> Result<MacAddress>167     pub fn mcast_ip_to_mac(&self, ipv6: bool, ip: IpAddress) -> Result<MacAddress> {
168         let mut mac_address = MacAddress([0; 32]);
169         let status = (self.mcast_ip_to_mac)(self, ipv6, &ip, &mut mac_address);
170         status.to_result_with_val(|| mac_address)
171     }
172 
173     /// Perform read operations on the NVRAM device attached to
174     /// a network interface.
read_nv_data(&self, offset: usize, buffer: &[u8]) -> Result175     pub fn read_nv_data(&self, offset: usize, buffer: &[u8]) -> Result {
176         (self.nv_data)(
177             self,
178             true,
179             offset,
180             buffer.len(),
181             buffer.as_ptr() as *mut c_void,
182         )
183         .to_result()
184     }
185 
186     /// Perform write operations on the NVRAM device attached to a network interface.
write_nv_data(&self, offset: usize, buffer: &mut [u8]) -> Result187     pub fn write_nv_data(&self, offset: usize, buffer: &mut [u8]) -> Result {
188         (self.nv_data)(
189             self,
190             false,
191             offset,
192             buffer.len(),
193             buffer.as_mut_ptr().cast(),
194         )
195         .to_result()
196     }
197 
198     /// Read the current interrupt status and recycled transmit buffer
199     /// status from a network interface.
get_interrupt_status(&self) -> Result<InterruptStatus>200     pub fn get_interrupt_status(&self) -> Result<InterruptStatus> {
201         let mut interrupt_status = InterruptStatus::empty();
202         let status = (self.get_status)(self, Some(&mut interrupt_status), None);
203         status.to_result_with_val(|| interrupt_status)
204     }
205 
206     /// Read the current recycled transmit buffer status from a
207     /// network interface.
get_recycled_transmit_buffer_status(&self) -> Result<Option<NonNull<u8>>>208     pub fn get_recycled_transmit_buffer_status(&self) -> Result<Option<NonNull<u8>>> {
209         let mut tx_buf: *mut c_void = ptr::null_mut();
210         let status = (self.get_status)(self, None, Some(&mut tx_buf));
211         status.to_result_with_val(|| NonNull::new(tx_buf.cast()))
212     }
213 
214     /// Place a packet in the transmit queue of a network interface.
transmit( &self, header_size: usize, buffer: &[u8], src_addr: Option<MacAddress>, dest_addr: Option<MacAddress>, protocol: Option<u16>, ) -> Result215     pub fn transmit(
216         &self,
217         header_size: usize,
218         buffer: &[u8],
219         src_addr: Option<MacAddress>,
220         dest_addr: Option<MacAddress>,
221         protocol: Option<u16>,
222     ) -> Result {
223         (self.transmit)(
224             self,
225             header_size,
226             buffer.len() + header_size,
227             buffer.as_ptr().cast(),
228             src_addr.as_ref(),
229             dest_addr.as_ref(),
230             protocol.as_ref(),
231         )
232         .to_result()
233     }
234 
235     /// Receive a packet from a network interface.
236     ///
237     /// On success, returns the size of bytes of the received packet.
receive( &self, buffer: &mut [u8], header_size: Option<&mut usize>, src_addr: Option<&mut MacAddress>, dest_addr: Option<&mut MacAddress>, protocol: Option<&mut u16>, ) -> Result<usize>238     pub fn receive(
239         &self,
240         buffer: &mut [u8],
241         header_size: Option<&mut usize>,
242         src_addr: Option<&mut MacAddress>,
243         dest_addr: Option<&mut MacAddress>,
244         protocol: Option<&mut u16>,
245     ) -> Result<usize> {
246         let mut buffer_size = buffer.len();
247         let status = (self.receive)(
248             self,
249             header_size,
250             &mut buffer_size,
251             buffer.as_mut_ptr().cast(),
252             src_addr,
253             dest_addr,
254             protocol,
255         );
256         status.to_result_with_val(|| buffer_size)
257     }
258 
259     /// Event that fires once a packet is available to be received.
260     ///
261     /// On QEMU, this event seems to never fire; it is suggested to verify that your implementation
262     /// of UEFI properly implements this event before using it.
263     #[must_use]
wait_for_packet(&self) -> &Event264     pub const fn wait_for_packet(&self) -> &Event {
265         &self.wait_for_packet
266     }
267 
268     /// Returns a reference to the Simple Network mode.
269     #[must_use]
mode(&self) -> &NetworkMode270     pub const fn mode(&self) -> &NetworkMode {
271         unsafe { &*self.mode }
272     }
273 }
274 
275 bitflags! {
276     /// Flags to pass to receive_filters to enable/disable reception of some kinds of packets.
277     #[repr(transparent)]
278     #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
279     pub struct ReceiveFlags : u32 {
280         /// Receive unicast packets.
281         const UNICAST = 0x01;
282         /// Receive multicast packets.
283         const MULTICAST = 0x02;
284         /// Receive broadcast packets.
285         const BROADCAST = 0x04;
286         /// Receive packets in promiscuous mode.
287         const PROMISCUOUS = 0x08;
288         /// Receive packets in promiscuous multicast mode.
289         const PROMISCUOUS_MULTICAST = 0x10;
290     }
291 }
292 
293 bitflags! {
294     /// Flags returned by get_interrupt_status to indicate which interrupts have fired on the
295     /// interface since the last call.
296     #[repr(transparent)]
297     #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
298     pub struct InterruptStatus : u32 {
299         /// Packet received.
300         const RECEIVE = 0x01;
301         /// Packet transmitted.
302         const TRANSMIT = 0x02;
303         /// Command interrupt fired.
304         const COMMAND = 0x04;
305         /// Software interrupt fired.
306         const SOFTWARE = 0x08;
307     }
308 }
309 
310 /// Network Statistics
311 ///
312 /// The description of statistics on the network with the SNP's `statistics` function
313 /// is returned in this structure
314 ///
315 /// Any of these statistics may or may not be available on the device. So, all the
316 /// retriever functions of the statistics return `None` when a statistic is not supported
317 #[repr(C)]
318 #[derive(Default, Debug)]
319 pub struct NetworkStats {
320     rx_total_frames: u64,
321     rx_good_frames: u64,
322     rx_undersize_frames: u64,
323     rx_oversize_frames: u64,
324     rx_dropped_frames: u64,
325     rx_unicast_frames: u64,
326     rx_broadcast_frames: u64,
327     rx_multicast_frames: u64,
328     rx_crc_error_frames: u64,
329     rx_total_bytes: u64,
330     tx_total_frames: u64,
331     tx_good_frames: u64,
332     tx_undersize_frames: u64,
333     tx_oversize_frames: u64,
334     tx_dropped_frames: u64,
335     tx_unicast_frames: u64,
336     tx_broadcast_frames: u64,
337     tx_multicast_frames: u64,
338     tx_crc_error_frames: u64,
339     tx_total_bytes: u64,
340     collisions: u64,
341     unsupported_protocol: u64,
342     rx_duplicated_frames: u64,
343     rx_decrypt_error_frames: u64,
344     tx_error_frames: u64,
345     tx_retry_frames: u64,
346 }
347 
348 impl NetworkStats {
349     /// Any statistic value of -1 is not available
available(&self, stat: u64) -> bool350     const fn available(&self, stat: u64) -> bool {
351         stat as i64 != -1
352     }
353 
354     /// Takes a statistic and converts it to an option
355     ///
356     /// When the statistic is not available, `None` is returned
to_option(&self, stat: u64) -> Option<u64>357     const fn to_option(&self, stat: u64) -> Option<u64> {
358         match self.available(stat) {
359             true => Some(stat),
360             false => None,
361         }
362     }
363 
364     /// The total number of frames received, including error frames
365     /// and dropped frames
366     #[must_use]
rx_total_frames(&self) -> Option<u64>367     pub const fn rx_total_frames(&self) -> Option<u64> {
368         self.to_option(self.rx_total_frames)
369     }
370 
371     /// The total number of good frames received and copied
372     /// into receive buffers
373     #[must_use]
rx_good_frames(&self) -> Option<u64>374     pub const fn rx_good_frames(&self) -> Option<u64> {
375         self.to_option(self.rx_good_frames)
376     }
377 
378     /// The number of frames below the minimum length for the
379     /// communications device
380     #[must_use]
rx_undersize_frames(&self) -> Option<u64>381     pub const fn rx_undersize_frames(&self) -> Option<u64> {
382         self.to_option(self.rx_undersize_frames)
383     }
384 
385     /// The number of frames longer than the maximum length for
386     /// the communications length device
387     #[must_use]
rx_oversize_frames(&self) -> Option<u64>388     pub const fn rx_oversize_frames(&self) -> Option<u64> {
389         self.to_option(self.rx_oversize_frames)
390     }
391 
392     /// The number of valid frames that were dropped because
393     /// the receive buffers were full
394     #[must_use]
rx_dropped_frames(&self) -> Option<u64>395     pub const fn rx_dropped_frames(&self) -> Option<u64> {
396         self.to_option(self.rx_dropped_frames)
397     }
398 
399     /// The number of valid unicast frames received and not dropped
400     #[must_use]
rx_unicast_frames(&self) -> Option<u64>401     pub const fn rx_unicast_frames(&self) -> Option<u64> {
402         self.to_option(self.rx_unicast_frames)
403     }
404 
405     /// The number of valid broadcast frames received and not dropped
406     #[must_use]
rx_broadcast_frames(&self) -> Option<u64>407     pub const fn rx_broadcast_frames(&self) -> Option<u64> {
408         self.to_option(self.rx_broadcast_frames)
409     }
410 
411     /// The number of valid multicast frames received and not dropped
412     #[must_use]
rx_multicast_frames(&self) -> Option<u64>413     pub const fn rx_multicast_frames(&self) -> Option<u64> {
414         self.to_option(self.rx_multicast_frames)
415     }
416 
417     /// Number of frames with CRC or alignment errors
418     #[must_use]
rx_crc_error_frames(&self) -> Option<u64>419     pub const fn rx_crc_error_frames(&self) -> Option<u64> {
420         self.to_option(self.rx_crc_error_frames)
421     }
422 
423     /// The total number of bytes received including frames with errors
424     /// and dropped frames
425     #[must_use]
rx_total_bytes(&self) -> Option<u64>426     pub const fn rx_total_bytes(&self) -> Option<u64> {
427         self.to_option(self.rx_total_bytes)
428     }
429 
430     /// The total number of frames transmitted including frames
431     /// with errors and dropped frames
432     #[must_use]
tx_total_frames(&self) -> Option<u64>433     pub const fn tx_total_frames(&self) -> Option<u64> {
434         self.to_option(self.tx_total_frames)
435     }
436 
437     /// The total number of valid frames transmitted and copied
438     /// into receive buffers
439     #[must_use]
tx_good_frames(&self) -> Option<u64>440     pub const fn tx_good_frames(&self) -> Option<u64> {
441         self.to_option(self.tx_good_frames)
442     }
443 
444     /// The number of frames below the minimum length for
445     /// the media. This would be less than 64 for Ethernet
446     #[must_use]
tx_undersize_frames(&self) -> Option<u64>447     pub const fn tx_undersize_frames(&self) -> Option<u64> {
448         self.to_option(self.tx_undersize_frames)
449     }
450 
451     /// The number of frames longer than the maximum length for
452     /// the media. This would be 1500 for Ethernet
453     #[must_use]
tx_oversize_frames(&self) -> Option<u64>454     pub const fn tx_oversize_frames(&self) -> Option<u64> {
455         self.to_option(self.tx_oversize_frames)
456     }
457 
458     /// The number of valid frames that were dropped because
459     /// received buffers were full
460     #[must_use]
tx_dropped_frames(&self) -> Option<u64>461     pub const fn tx_dropped_frames(&self) -> Option<u64> {
462         self.to_option(self.tx_dropped_frames)
463     }
464 
465     /// The number of valid unicast frames transmitted and not
466     /// dropped
467     #[must_use]
tx_unicast_frames(&self) -> Option<u64>468     pub const fn tx_unicast_frames(&self) -> Option<u64> {
469         self.to_option(self.tx_unicast_frames)
470     }
471 
472     /// The number of valid broadcast frames transmitted and
473     /// not dropped
474     #[must_use]
tx_broadcast_frames(&self) -> Option<u64>475     pub const fn tx_broadcast_frames(&self) -> Option<u64> {
476         self.to_option(self.tx_broadcast_frames)
477     }
478 
479     /// The number of valid multicast frames transmitted
480     /// and not dropped
481     #[must_use]
tx_multicast_frames(&self) -> Option<u64>482     pub const fn tx_multicast_frames(&self) -> Option<u64> {
483         self.to_option(self.tx_multicast_frames)
484     }
485 
486     /// The number of transmitted frames with CRC or
487     /// alignment errors
488     #[must_use]
tx_crc_error_frames(&self) -> Option<u64>489     pub const fn tx_crc_error_frames(&self) -> Option<u64> {
490         self.to_option(self.tx_crc_error_frames)
491     }
492 
493     /// The total number of bytes transmitted including
494     /// error frames and dropped frames
495     #[must_use]
tx_total_bytes(&self) -> Option<u64>496     pub const fn tx_total_bytes(&self) -> Option<u64> {
497         self.to_option(self.tx_total_bytes)
498     }
499 
500     /// The number of collisions detected on this subnet
501     #[must_use]
collisions(&self) -> Option<u64>502     pub const fn collisions(&self) -> Option<u64> {
503         self.to_option(self.collisions)
504     }
505 
506     /// The number of frames destined for unsupported protocol
507     #[must_use]
unsupported_protocol(&self) -> Option<u64>508     pub const fn unsupported_protocol(&self) -> Option<u64> {
509         self.to_option(self.unsupported_protocol)
510     }
511 
512     /// The number of valid frames received that were duplicated
513     #[must_use]
rx_duplicated_frames(&self) -> Option<u64>514     pub const fn rx_duplicated_frames(&self) -> Option<u64> {
515         self.to_option(self.rx_duplicated_frames)
516     }
517 
518     /// The number of encrypted frames received that failed
519     /// to decrypt
520     #[must_use]
rx_decrypt_error_frames(&self) -> Option<u64>521     pub const fn rx_decrypt_error_frames(&self) -> Option<u64> {
522         self.to_option(self.rx_decrypt_error_frames)
523     }
524 
525     /// The number of frames that failed to transmit after
526     /// exceeding the retry limit
527     #[must_use]
tx_error_frames(&self) -> Option<u64>528     pub const fn tx_error_frames(&self) -> Option<u64> {
529         self.to_option(self.tx_error_frames)
530     }
531 
532     /// The number of frames that transmitted successfully
533     /// after more than one attempt
534     #[must_use]
tx_retry_frames(&self) -> Option<u64>535     pub const fn tx_retry_frames(&self) -> Option<u64> {
536         self.to_option(self.tx_retry_frames)
537     }
538 }
539 
540 /// The Simple Network Mode
541 #[repr(C)]
542 #[derive(Debug)]
543 pub struct NetworkMode {
544     /// Reports the current state of the network interface
545     pub state: NetworkState,
546     /// The size of the network interface's hardware address in bytes
547     pub hw_address_size: u32,
548     /// The size of the network interface's media header in bytes
549     pub media_header_size: u32,
550     /// The maximum size of the packets supported by the network interface in bytes
551     pub max_packet_size: u32,
552     /// The size of the NVRAM device attached to the network interface in bytes
553     pub nv_ram_size: u32,
554     /// The size that must be used for all NVRAM reads and writes
555     pub nv_ram_access_size: u32,
556     /// The multicast receive filter settings supported by the network interface
557     pub receive_filter_mask: u32,
558     /// The current multicast receive filter settings
559     pub receive_filter_setting: u32,
560     /// The maximum number of multicast address receive filters supported by the driver
561     pub max_mcast_filter_count: u32,
562     /// The current number of multicast address receive filters
563     pub mcast_filter_count: u32,
564     /// The array containing the addresses of the current multicast address receive filters
565     pub mcast_filter: [MacAddress; 16],
566     /// The current hardware MAC address for the network interface
567     pub current_address: MacAddress,
568     /// The current hardware MAC address for broadcast packets
569     pub broadcast_address: MacAddress,
570     /// The permanent hardware MAC address for the network interface
571     pub permanent_address: MacAddress,
572     /// The interface type of the network interface
573     pub if_type: u8,
574     /// Tells if the MAC address can be changed
575     pub mac_address_changeable: bool,
576     /// Tells if the network interface can transmit more than one packet at a time
577     pub multiple_tx_supported: bool,
578     /// Tells if the presence of the media can be determined
579     pub media_present_supported: bool,
580     /// Tells if media are connected to the network interface
581     pub media_present: bool,
582 }
583 
584 newtype_enum! {
585     /// The state of a network interface.
586     pub enum NetworkState: u32 => {
587         /// The interface has been stopped
588         STOPPED = 0,
589         /// The interface has been started
590         STARTED = 1,
591         /// The interface has been initialized
592         INITIALIZED = 2,
593         /// No state can have a number higher than this
594         MAX_STATE = 4,
595     }
596 }
597