Skip to main content

uefi_raw/protocol/network/
snp.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3use core::ffi;
4
5use bitflags::bitflags;
6
7use crate::{Boolean, Event, Guid, IpAddress, MacAddress, Status, guid, newtype_enum};
8
9#[derive(Debug)]
10#[repr(C)]
11pub struct SimpleNetworkProtocol {
12    pub revision: u64,
13    pub start: unsafe extern "efiapi" fn(this: *const Self) -> Status,
14    pub stop: unsafe extern "efiapi" fn(this: *const Self) -> Status,
15    pub initialize: unsafe extern "efiapi" fn(
16        this: *const Self,
17        extra_receive_buffer_size: usize,
18        extra_transmit_buffer_size: usize,
19    ) -> Status,
20    pub reset:
21        unsafe extern "efiapi" fn(this: *const Self, extended_verification: Boolean) -> Status,
22    pub shutdown: unsafe extern "efiapi" fn(this: *const Self) -> Status,
23    pub receive_filters: unsafe extern "efiapi" fn(
24        this: *const Self,
25        enable: ReceiveFlags,
26        disable: ReceiveFlags,
27        reset_multicast_filter: Boolean,
28        multicast_filter_count: usize,
29        multicast_filter: *const MacAddress,
30    ) -> Status,
31    pub station_address: unsafe extern "efiapi" fn(
32        this: *const Self,
33        reset: Boolean,
34        new: *const MacAddress,
35    ) -> Status,
36    pub statistics: unsafe extern "efiapi" fn(
37        this: *const Self,
38        reset: Boolean,
39        statistics_size: *mut usize,
40        statistics_table: *mut NetworkStatistics,
41    ) -> Status,
42    pub multicast_ip_to_mac: unsafe extern "efiapi" fn(
43        this: *const Self,
44        ipv6: Boolean,
45        ip: *const IpAddress,
46        mac: *mut MacAddress,
47    ) -> Status,
48    pub non_volatile_data: unsafe extern "efiapi" fn(
49        this: *const Self,
50        read: Boolean,
51        offset: usize,
52        buffer_size: usize,
53        buffer: *mut ffi::c_void,
54    ) -> Status,
55    pub get_status: unsafe extern "efiapi" fn(
56        this: *const Self,
57        interrupt_status: *mut InterruptStatus,
58        transmit_buffer: *mut *mut ffi::c_void,
59    ) -> Status,
60    pub transmit: unsafe extern "efiapi" fn(
61        this: *const Self,
62        header_size: usize,
63        buffer_size: usize,
64        buffer: *const ffi::c_void,
65        source_address: *const MacAddress,
66        dest_address: *const MacAddress,
67        protocol: *const u16,
68    ) -> Status,
69    pub receive: unsafe extern "efiapi" fn(
70        this: *const Self,
71        header_size: *mut usize,
72        buffer_size: *mut usize,
73        buffer: *mut ffi::c_void,
74        source_address: *mut MacAddress,
75        dest_address: *mut MacAddress,
76        protocol: *mut u16,
77    ) -> Status,
78    pub wait_for_packet: Event,
79    pub mode: *mut NetworkMode,
80}
81
82impl SimpleNetworkProtocol {
83    pub const GUID: Guid = guid!("a19832b9-ac25-11d3-9a2d-0090273fc14d");
84}
85
86bitflags! {
87    /// Flags to pass to receive_filters to enable/disable reception of some kinds of packets.
88    #[repr(transparent)]
89    #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
90    pub struct ReceiveFlags: u32 {
91        /// Receive unicast packets.
92        const UNICAST = 0x01;
93        /// Receive multicast packets.
94        const MULTICAST = 0x02;
95        /// Receive broadcast packets.
96        const BROADCAST = 0x04;
97        /// Receive packets in promiscuous mode.
98        const PROMISCUOUS = 0x08;
99        /// Receive packets in promiscuous multicast mode.
100        const PROMISCUOUS_MULTICAST = 0x10;
101    }
102}
103
104bitflags! {
105    /// Flags returned by get_interrupt_status to indicate which interrupts have fired on the
106    /// interface since the last call.
107    #[repr(transparent)]
108    #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
109    pub struct InterruptStatus: u32 {
110        /// Packet received.
111        const RECEIVE = 0x01;
112        /// Packet transmitted.
113        const TRANSMIT = 0x02;
114        /// Command interrupt fired.
115        const COMMAND = 0x04;
116        /// Software interrupt fired.
117        const SOFTWARE = 0x08;
118    }
119}
120
121/// Network Statistics
122///
123/// The description of statistics on the network with the SNP's `statistics` function
124/// is returned in this structure
125///
126/// Any of these statistics may or may not be available on the device. So, all the
127/// retriever functions of the statistics return `None` when a statistic is not supported
128#[repr(C)]
129#[derive(Default, Debug)]
130pub struct NetworkStatistics {
131    pub rx_total_frames: u64,
132    pub rx_good_frames: u64,
133    pub rx_undersize_frames: u64,
134    pub rx_oversize_frames: u64,
135    pub rx_dropped_frames: u64,
136    pub rx_unicast_frames: u64,
137    pub rx_broadcast_frames: u64,
138    pub rx_multicast_frames: u64,
139    pub rx_crc_error_frames: u64,
140    pub rx_total_bytes: u64,
141    pub tx_total_frames: u64,
142    pub tx_good_frames: u64,
143    pub tx_undersize_frames: u64,
144    pub tx_oversize_frames: u64,
145    pub tx_dropped_frames: u64,
146    pub tx_unicast_frames: u64,
147    pub tx_broadcast_frames: u64,
148    pub tx_multicast_frames: u64,
149    pub tx_crc_error_frames: u64,
150    pub tx_total_bytes: u64,
151    pub collisions: u64,
152    pub unsupported_protocol: u64,
153    pub rx_duplicated_frames: u64,
154    pub rx_decrypt_error_frames: u64,
155    pub tx_error_frames: u64,
156    pub tx_retry_frames: u64,
157}
158
159impl NetworkStatistics {
160    /// Any statistic value of -1 is not available
161    const fn available(&self, stat: u64) -> bool {
162        stat as i64 != -1
163    }
164
165    /// Takes a statistic and converts it to an option
166    ///
167    /// When the statistic is not available, `None` is returned
168    const fn to_option(&self, stat: u64) -> Option<u64> {
169        match self.available(stat) {
170            true => Some(stat),
171            false => None,
172        }
173    }
174
175    /// The total number of frames received, including error frames
176    /// and dropped frames
177    #[must_use]
178    pub const fn rx_total_frames(&self) -> Option<u64> {
179        self.to_option(self.rx_total_frames)
180    }
181
182    /// The total number of good frames received and copied
183    /// into receive buffers
184    #[must_use]
185    pub const fn rx_good_frames(&self) -> Option<u64> {
186        self.to_option(self.rx_good_frames)
187    }
188
189    /// The number of frames below the minimum length for the
190    /// communications device
191    #[must_use]
192    pub const fn rx_undersize_frames(&self) -> Option<u64> {
193        self.to_option(self.rx_undersize_frames)
194    }
195
196    /// The number of frames longer than the maximum length for
197    /// the communications length device
198    #[must_use]
199    pub const fn rx_oversize_frames(&self) -> Option<u64> {
200        self.to_option(self.rx_oversize_frames)
201    }
202
203    /// The number of valid frames that were dropped because
204    /// the receive buffers were full
205    #[must_use]
206    pub const fn rx_dropped_frames(&self) -> Option<u64> {
207        self.to_option(self.rx_dropped_frames)
208    }
209
210    /// The number of valid unicast frames received and not dropped
211    #[must_use]
212    pub const fn rx_unicast_frames(&self) -> Option<u64> {
213        self.to_option(self.rx_unicast_frames)
214    }
215
216    /// The number of valid broadcast frames received and not dropped
217    #[must_use]
218    pub const fn rx_broadcast_frames(&self) -> Option<u64> {
219        self.to_option(self.rx_broadcast_frames)
220    }
221
222    /// The number of valid multicast frames received and not dropped
223    #[must_use]
224    pub const fn rx_multicast_frames(&self) -> Option<u64> {
225        self.to_option(self.rx_multicast_frames)
226    }
227
228    /// Number of frames with CRC or alignment errors
229    #[must_use]
230    pub const fn rx_crc_error_frames(&self) -> Option<u64> {
231        self.to_option(self.rx_crc_error_frames)
232    }
233
234    /// The total number of bytes received including frames with errors
235    /// and dropped frames
236    #[must_use]
237    pub const fn rx_total_bytes(&self) -> Option<u64> {
238        self.to_option(self.rx_total_bytes)
239    }
240
241    /// The total number of frames transmitted including frames
242    /// with errors and dropped frames
243    #[must_use]
244    pub const fn tx_total_frames(&self) -> Option<u64> {
245        self.to_option(self.tx_total_frames)
246    }
247
248    /// The total number of valid frames transmitted and copied
249    /// into receive buffers
250    #[must_use]
251    pub const fn tx_good_frames(&self) -> Option<u64> {
252        self.to_option(self.tx_good_frames)
253    }
254
255    /// The number of frames below the minimum length for
256    /// the media. This would be less than 64 for Ethernet
257    #[must_use]
258    pub const fn tx_undersize_frames(&self) -> Option<u64> {
259        self.to_option(self.tx_undersize_frames)
260    }
261
262    /// The number of frames longer than the maximum length for
263    /// the media. This would be 1500 for Ethernet
264    #[must_use]
265    pub const fn tx_oversize_frames(&self) -> Option<u64> {
266        self.to_option(self.tx_oversize_frames)
267    }
268
269    /// The number of valid frames that were dropped because
270    /// received buffers were full
271    #[must_use]
272    pub const fn tx_dropped_frames(&self) -> Option<u64> {
273        self.to_option(self.tx_dropped_frames)
274    }
275
276    /// The number of valid unicast frames transmitted and not
277    /// dropped
278    #[must_use]
279    pub const fn tx_unicast_frames(&self) -> Option<u64> {
280        self.to_option(self.tx_unicast_frames)
281    }
282
283    /// The number of valid broadcast frames transmitted and
284    /// not dropped
285    #[must_use]
286    pub const fn tx_broadcast_frames(&self) -> Option<u64> {
287        self.to_option(self.tx_broadcast_frames)
288    }
289
290    /// The number of valid multicast frames transmitted
291    /// and not dropped
292    #[must_use]
293    pub const fn tx_multicast_frames(&self) -> Option<u64> {
294        self.to_option(self.tx_multicast_frames)
295    }
296
297    /// The number of transmitted frames with CRC or
298    /// alignment errors
299    #[must_use]
300    pub const fn tx_crc_error_frames(&self) -> Option<u64> {
301        self.to_option(self.tx_crc_error_frames)
302    }
303
304    /// The total number of bytes transmitted including
305    /// error frames and dropped frames
306    #[must_use]
307    pub const fn tx_total_bytes(&self) -> Option<u64> {
308        self.to_option(self.tx_total_bytes)
309    }
310
311    /// The number of collisions detected on this subnet
312    #[must_use]
313    pub const fn collisions(&self) -> Option<u64> {
314        self.to_option(self.collisions)
315    }
316
317    /// The number of frames destined for unsupported protocol
318    #[must_use]
319    pub const fn unsupported_protocol(&self) -> Option<u64> {
320        self.to_option(self.unsupported_protocol)
321    }
322
323    /// The number of valid frames received that were duplicated
324    #[must_use]
325    pub const fn rx_duplicated_frames(&self) -> Option<u64> {
326        self.to_option(self.rx_duplicated_frames)
327    }
328
329    /// The number of encrypted frames received that failed
330    /// to decrypt
331    #[must_use]
332    pub const fn rx_decrypt_error_frames(&self) -> Option<u64> {
333        self.to_option(self.rx_decrypt_error_frames)
334    }
335
336    /// The number of frames that failed to transmit after
337    /// exceeding the retry limit
338    #[must_use]
339    pub const fn tx_error_frames(&self) -> Option<u64> {
340        self.to_option(self.tx_error_frames)
341    }
342
343    /// The number of frames that transmitted successfully
344    /// after more than one attempt
345    #[must_use]
346    pub const fn tx_retry_frames(&self) -> Option<u64> {
347        self.to_option(self.tx_retry_frames)
348    }
349}
350
351/// Information about the current configuration of an interface obtained by the
352/// [`SimpleNetworkProtocol`].
353#[repr(C)]
354#[derive(Debug)]
355pub struct NetworkMode {
356    /// Reports the current state of the network interface
357    pub state: NetworkState,
358    /// The size of the network interface's hardware address in bytes
359    pub hw_address_size: u32,
360    /// The size of the network interface's media header in bytes
361    pub media_header_size: u32,
362    /// The maximum size of the packets supported by the network interface in bytes
363    pub max_packet_size: u32,
364    /// The size of the NVRAM device attached to the network interface in bytes
365    pub nv_ram_size: u32,
366    /// The size that must be used for all NVRAM reads and writes
367    pub nv_ram_access_size: u32,
368    /// The multicast receive filter settings supported by the network interface
369    pub receive_filter_mask: u32,
370    /// The current multicast receive filter settings
371    pub receive_filter_setting: u32,
372    /// The maximum number of multicast address receive filters supported by the driver
373    pub max_mcast_filter_count: u32,
374    /// The current number of multicast address receive filters
375    pub mcast_filter_count: u32,
376    /// The array containing the addresses of the current multicast address receive filters
377    pub mcast_filter: [MacAddress; 16],
378    /// The current hardware MAC address for the network interface
379    pub current_address: MacAddress,
380    /// The current hardware MAC address for broadcast packets
381    pub broadcast_address: MacAddress,
382    /// The permanent hardware MAC address for the network interface
383    pub permanent_address: MacAddress,
384    /// The interface type of the network interface
385    pub if_type: u8,
386    /// Tells if the MAC address can be changed
387    pub mac_address_changeable: Boolean,
388    /// Tells if the network interface can transmit more than one packet at a time
389    pub multiple_tx_supported: Boolean,
390    /// Tells if the presence of the media can be determined
391    pub media_present_supported: Boolean,
392    /// Tells if media are connected to the network interface
393    pub media_present: Boolean,
394}
395
396newtype_enum! {
397    /// The state of a network interface.
398    pub enum NetworkState: u32 => {
399        /// The interface has been stopped
400        STOPPED = 0,
401        /// The interface has been started
402        STARTED = 1,
403        /// The interface has been initialized
404        INITIALIZED = 2,
405        /// No state can have a number higher than this
406        MAX_STATE = 4,
407    }
408}