Skip to content

Commit f978a8e

Browse files
committedApr 15, 2025·
uefi-raw: Move EFI_SIMPLE_NETWORK_PROTOCOL
1 parent 35e5ab7 commit f978a8e

File tree

4 files changed

+524
-459
lines changed

4 files changed

+524
-459
lines changed
 

‎uefi-raw/src/protocol/network/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ pub mod http;
55
pub mod ip4;
66
pub mod ip4_config2;
77
pub mod pxe;
8+
pub mod snp;
89
pub mod tls;

‎uefi-raw/src/protocol/network/snp.rs

+408
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,408 @@
1+
// SPDX-License-Identifier: MIT OR Apache-2.0
2+
3+
use core::ffi;
4+
5+
use bitflags::bitflags;
6+
7+
use crate::{guid, Boolean, Event, Guid, IpAddress, MacAddress, Status};
8+
9+
#[derive(Debug)]
10+
#[repr(C)]
11+
pub 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+
82+
impl SimpleNetworkProtocol {
83+
pub const GUID: Guid = guid!("a19832b9-ac25-11d3-9a2d-0090273fc14d");
84+
}
85+
86+
bitflags! {
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+
104+
bitflags! {
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)]
130+
pub 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+
159+
impl 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)]
355+
pub 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+
396+
newtype_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+
}

‎uefi-test-runner/src/proto/network/snp.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,9 @@ pub fn test() {
5353
.expect("Failed to set receive filters");
5454

5555
// Check media
56-
if !simple_network.mode().media_present_supported || !simple_network.mode().media_present {
56+
if !bool::from(simple_network.mode().media_present_supported)
57+
|| !bool::from(simple_network.mode().media_present)
58+
{
5759
continue;
5860
}
5961

‎uefi/src/proto/network/snp.rs

+112-458
Original file line numberDiff line numberDiff line change
@@ -12,108 +12,52 @@
1212
use super::{IpAddress, MacAddress};
1313
use crate::data_types::Event;
1414
use crate::proto::unsafe_protocol;
15-
use crate::{Result, Status, StatusExt};
16-
use bitflags::bitflags;
15+
use crate::{Result, StatusExt};
1716
use core::ffi::c_void;
1817
use core::ptr;
1918
use core::ptr::NonNull;
19+
use uefi_raw::protocol::network::snp::SimpleNetworkProtocol;
20+
use uefi_raw::Boolean;
21+
22+
pub use uefi_raw::protocol::network::snp::{
23+
InterruptStatus, NetworkMode, NetworkState, NetworkStatistics, ReceiveFlags,
24+
};
2025

2126
/// The Simple Network Protocol
2227
#[derive(Debug)]
23-
#[repr(C)]
24-
#[unsafe_protocol("a19832b9-ac25-11d3-9a2d-0090273fc14d")]
25-
pub struct SimpleNetwork {
26-
revision: u64,
27-
start: extern "efiapi" fn(this: &Self) -> Status,
28-
stop: extern "efiapi" fn(this: &Self) -> Status,
29-
initialize: extern "efiapi" fn(
30-
this: &Self,
31-
extra_recv_buffer_size: usize,
32-
extra_transmit_buffer_size: usize,
33-
) -> Status,
34-
reset: extern "efiapi" fn(this: &Self, extended_verification: bool) -> Status,
35-
shutdown: extern "efiapi" fn(this: &Self) -> Status,
36-
receive_filters: extern "efiapi" fn(
37-
this: &Self,
38-
enable: u32,
39-
disable: u32,
40-
reset_mcast_filter: bool,
41-
mcast_filter_count: usize,
42-
mcast_filter: Option<NonNull<MacAddress>>,
43-
) -> Status,
44-
station_address:
45-
extern "efiapi" fn(this: &Self, reset: bool, new: Option<&MacAddress>) -> Status,
46-
statistics: extern "efiapi" fn(
47-
this: &Self,
48-
reset: bool,
49-
stats_size: Option<&mut usize>,
50-
stats_table: Option<&mut NetworkStats>,
51-
) -> Status,
52-
mcast_ip_to_mac:
53-
extern "efiapi" fn(this: &Self, ipv6: bool, ip: &IpAddress, mac: &mut MacAddress) -> Status,
54-
nv_data: extern "efiapi" fn(
55-
this: &Self,
56-
read_write: bool,
57-
offset: usize,
58-
buffer_size: usize,
59-
buffer: *mut c_void,
60-
) -> Status,
61-
get_status: extern "efiapi" fn(
62-
this: &Self,
63-
interrupt_status: Option<&mut InterruptStatus>,
64-
tx_buf: Option<&mut *mut c_void>,
65-
) -> Status,
66-
transmit: extern "efiapi" fn(
67-
this: &Self,
68-
header_size: usize,
69-
buffer_size: usize,
70-
buffer: *const c_void,
71-
src_addr: Option<&MacAddress>,
72-
dest_addr: Option<&MacAddress>,
73-
protocol: Option<&u16>,
74-
) -> Status,
75-
receive: extern "efiapi" fn(
76-
this: &Self,
77-
header_size: Option<&mut usize>,
78-
buffer_size: &mut usize,
79-
buffer: *mut c_void,
80-
src_addr: Option<&mut MacAddress>,
81-
dest_addr: Option<&mut MacAddress>,
82-
protocol: Option<&mut u16>,
83-
) -> Status,
84-
// On QEMU, this event seems to never fire.
85-
wait_for_packet: Event,
86-
mode: *const NetworkMode,
87-
}
28+
#[repr(transparent)]
29+
#[unsafe_protocol(SimpleNetworkProtocol::GUID)]
30+
pub struct SimpleNetwork(SimpleNetworkProtocol);
8831

8932
impl SimpleNetwork {
9033
/// Change the state of a network from "Stopped" to "Started".
9134
pub fn start(&self) -> Result {
92-
(self.start)(self).to_result()
35+
unsafe { (self.0.start)(&self.0) }.to_result()
9336
}
9437

9538
/// Change the state of a network interface from "Started" to "Stopped".
9639
pub fn stop(&self) -> Result {
97-
(self.stop)(self).to_result()
40+
unsafe { (self.0.stop)(&self.0) }.to_result()
9841
}
9942

10043
/// Reset a network adapter and allocate the transmit and receive buffers
10144
/// required by the network interface; optionally, also request allocation of
10245
/// additional transmit and receive buffers.
10346
pub fn initialize(&self, extra_rx_buffer_size: usize, extra_tx_buffer_size: usize) -> Result {
104-
(self.initialize)(self, extra_rx_buffer_size, extra_tx_buffer_size).to_result()
47+
unsafe { (self.0.initialize)(&self.0, extra_rx_buffer_size, extra_tx_buffer_size) }
48+
.to_result()
10549
}
10650

10751
/// Reset a network adapter and reinitialize it with the parameters that were
10852
/// provided in the previous call to `initialize`.
10953
pub fn reset(&self, extended_verification: bool) -> Result {
110-
(self.reset)(self, extended_verification).to_result()
54+
unsafe { (self.0.reset)(&self.0, Boolean::from(extended_verification)) }.to_result()
11155
}
11256

11357
/// Reset a network adapter, leaving it in a state that is safe
11458
/// for another driver to initialize
11559
pub fn shutdown(&self) -> Result {
116-
(self.shutdown)(self).to_result()
60+
unsafe { (self.0.shutdown)(&self.0) }.to_result()
11761
}
11862

11963
/// Manage the multicast receive filters of a network.
@@ -124,92 +68,121 @@ impl SimpleNetwork {
12468
reset_mcast_filter: bool,
12569
mcast_filter: Option<&[MacAddress]>,
12670
) -> Result {
127-
if let Some(mcast_filter) = mcast_filter {
128-
(self.receive_filters)(
129-
self,
130-
enable.bits(),
131-
disable.bits(),
132-
reset_mcast_filter,
133-
mcast_filter.len(),
134-
NonNull::new(mcast_filter.as_ptr() as *mut _),
135-
)
136-
.to_result()
137-
} else {
138-
(self.receive_filters)(
139-
self,
140-
enable.bits(),
141-
disable.bits(),
142-
reset_mcast_filter,
143-
0,
144-
None,
71+
let filter_count = mcast_filter.map(|filters| filters.len()).unwrap_or(0);
72+
let filters = mcast_filter
73+
.map(|filters| filters.as_ptr())
74+
.unwrap_or(core::ptr::null_mut());
75+
76+
unsafe {
77+
(self.0.receive_filters)(
78+
&self.0,
79+
enable,
80+
disable,
81+
Boolean::from(reset_mcast_filter),
82+
filter_count,
83+
filters,
14584
)
146-
.to_result()
14785
}
86+
.to_result()
14887
}
14988

15089
/// Modify or reset the current station address, if supported.
15190
pub fn station_address(&self, reset: bool, new: Option<&MacAddress>) -> Result {
152-
(self.station_address)(self, reset, new).to_result()
91+
unsafe {
92+
(self.0.station_address)(
93+
&self.0,
94+
Boolean::from(reset),
95+
new.map(ptr::from_ref).unwrap_or(ptr::null()),
96+
)
97+
}
98+
.to_result()
15399
}
154100

155101
/// Reset statistics on a network interface.
156102
pub fn reset_statistics(&self) -> Result {
157-
(self.statistics)(self, true, None, None).to_result()
103+
unsafe {
104+
(self.0.statistics)(
105+
&self.0,
106+
Boolean::from(true),
107+
ptr::null_mut(),
108+
ptr::null_mut(),
109+
)
110+
}
111+
.to_result()
158112
}
159113

160114
/// Collect statistics on a network interface.
161-
pub fn collect_statistics(&self) -> Result<NetworkStats> {
162-
let mut stats_table: NetworkStats = Default::default();
163-
let mut stats_size = size_of::<NetworkStats>();
164-
let status = (self.statistics)(self, false, Some(&mut stats_size), Some(&mut stats_table));
115+
pub fn collect_statistics(&self) -> Result<NetworkStatistics> {
116+
let mut stats_table: NetworkStatistics = Default::default();
117+
let mut stats_size = size_of::<NetworkStatistics>();
118+
let status = unsafe {
119+
(self.0.statistics)(
120+
&self.0,
121+
Boolean::from(false),
122+
&mut stats_size,
123+
&mut stats_table,
124+
)
125+
};
165126
status.to_result_with_val(|| stats_table)
166127
}
167128

168129
/// Convert a multicast IP address to a multicast HW MAC Address.
169130
pub fn mcast_ip_to_mac(&self, ipv6: bool, ip: IpAddress) -> Result<MacAddress> {
170131
let mut mac_address = MacAddress([0; 32]);
171-
let status = (self.mcast_ip_to_mac)(self, ipv6, &ip, &mut mac_address);
132+
let status = unsafe {
133+
(self.0.multicast_ip_to_mac)(
134+
&self.0,
135+
Boolean::from(ipv6),
136+
ip.as_raw_ptr(),
137+
&mut mac_address,
138+
)
139+
};
172140
status.to_result_with_val(|| mac_address)
173141
}
174142

175143
/// Perform read operations on the NVRAM device attached to
176144
/// a network interface.
177145
pub fn read_nv_data(&self, offset: usize, buffer: &[u8]) -> Result {
178-
(self.nv_data)(
179-
self,
180-
true,
181-
offset,
182-
buffer.len(),
183-
buffer.as_ptr() as *mut c_void,
184-
)
146+
unsafe {
147+
(self.0.non_volatile_data)(
148+
&self.0,
149+
Boolean::from(true),
150+
offset,
151+
buffer.len(),
152+
buffer.as_ptr() as *mut c_void,
153+
)
154+
}
185155
.to_result()
186156
}
187157

188158
/// Perform write operations on the NVRAM device attached to a network interface.
189159
pub fn write_nv_data(&self, offset: usize, buffer: &mut [u8]) -> Result {
190-
(self.nv_data)(
191-
self,
192-
false,
193-
offset,
194-
buffer.len(),
195-
buffer.as_mut_ptr().cast(),
196-
)
160+
unsafe {
161+
(self.0.non_volatile_data)(
162+
&self.0,
163+
Boolean::from(false),
164+
offset,
165+
buffer.len(),
166+
buffer.as_mut_ptr().cast(),
167+
)
168+
}
197169
.to_result()
198170
}
199171

200172
/// Read the current interrupt status and recycled transmit buffer
201173
/// status from a network interface.
202174
pub fn get_interrupt_status(&self) -> Result<InterruptStatus> {
203175
let mut interrupt_status = InterruptStatus::empty();
204-
let status = (self.get_status)(self, Some(&mut interrupt_status), None);
176+
let status =
177+
unsafe { (self.0.get_status)(&self.0, &mut interrupt_status, ptr::null_mut()) };
205178
status.to_result_with_val(|| interrupt_status)
206179
}
207180

208181
/// Read the current recycled transmit buffer status from a
209182
/// network interface.
210183
pub fn get_recycled_transmit_buffer_status(&self) -> Result<Option<NonNull<u8>>> {
211184
let mut tx_buf: *mut c_void = ptr::null_mut();
212-
let status = (self.get_status)(self, None, Some(&mut tx_buf));
185+
let status = unsafe { (self.0.get_status)(&self.0, ptr::null_mut(), &mut tx_buf) };
213186
status.to_result_with_val(|| NonNull::new(tx_buf.cast()))
214187
}
215188

@@ -222,15 +195,17 @@ impl SimpleNetwork {
222195
dest_addr: Option<MacAddress>,
223196
protocol: Option<u16>,
224197
) -> Result {
225-
(self.transmit)(
226-
self,
227-
header_size,
228-
buffer.len(),
229-
buffer.as_ptr().cast(),
230-
src_addr.as_ref(),
231-
dest_addr.as_ref(),
232-
protocol.as_ref(),
233-
)
198+
unsafe {
199+
(self.0.transmit)(
200+
&self.0,
201+
header_size,
202+
buffer.len(),
203+
buffer.as_ptr().cast(),
204+
src_addr.as_ref().map(ptr::from_ref).unwrap_or(ptr::null()),
205+
dest_addr.as_ref().map(ptr::from_ref).unwrap_or(ptr::null()),
206+
protocol.as_ref().map(ptr::from_ref).unwrap_or(ptr::null()),
207+
)
208+
}
234209
.to_result()
235210
}
236211

@@ -246,15 +221,17 @@ impl SimpleNetwork {
246221
protocol: Option<&mut u16>,
247222
) -> Result<usize> {
248223
let mut buffer_size = buffer.len();
249-
let status = (self.receive)(
250-
self,
251-
header_size,
252-
&mut buffer_size,
253-
buffer.as_mut_ptr().cast(),
254-
src_addr,
255-
dest_addr,
256-
protocol,
257-
);
224+
let status = unsafe {
225+
(self.0.receive)(
226+
&self.0,
227+
header_size.map(ptr::from_mut).unwrap_or(ptr::null_mut()),
228+
&mut buffer_size,
229+
buffer.as_mut_ptr().cast(),
230+
src_addr.map(ptr::from_mut).unwrap_or(ptr::null_mut()),
231+
dest_addr.map(ptr::from_mut).unwrap_or(ptr::null_mut()),
232+
protocol.map(ptr::from_mut).unwrap_or(ptr::null_mut()),
233+
)
234+
};
258235
status.to_result_with_val(|| buffer_size)
259236
}
260237

@@ -264,335 +241,12 @@ impl SimpleNetwork {
264241
/// of UEFI properly implements this event before using it.
265242
#[must_use]
266243
pub const fn wait_for_packet(&self) -> &Event {
267-
&self.wait_for_packet
244+
unsafe { &*(ptr::from_ref(&self.0.wait_for_packet).cast::<Event>()) }
268245
}
269246

270247
/// Returns a reference to the Simple Network mode.
271248
#[must_use]
272-
pub const fn mode(&self) -> &NetworkMode {
273-
unsafe { &*self.mode }
274-
}
275-
}
276-
277-
bitflags! {
278-
/// Flags to pass to receive_filters to enable/disable reception of some kinds of packets.
279-
#[repr(transparent)]
280-
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
281-
pub struct ReceiveFlags : u32 {
282-
/// Receive unicast packets.
283-
const UNICAST = 0x01;
284-
/// Receive multicast packets.
285-
const MULTICAST = 0x02;
286-
/// Receive broadcast packets.
287-
const BROADCAST = 0x04;
288-
/// Receive packets in promiscuous mode.
289-
const PROMISCUOUS = 0x08;
290-
/// Receive packets in promiscuous multicast mode.
291-
const PROMISCUOUS_MULTICAST = 0x10;
292-
}
293-
}
294-
295-
bitflags! {
296-
/// Flags returned by get_interrupt_status to indicate which interrupts have fired on the
297-
/// interface since the last call.
298-
#[repr(transparent)]
299-
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
300-
pub struct InterruptStatus : u32 {
301-
/// Packet received.
302-
const RECEIVE = 0x01;
303-
/// Packet transmitted.
304-
const TRANSMIT = 0x02;
305-
/// Command interrupt fired.
306-
const COMMAND = 0x04;
307-
/// Software interrupt fired.
308-
const SOFTWARE = 0x08;
309-
}
310-
}
311-
312-
/// Network Statistics
313-
///
314-
/// The description of statistics on the network with the SNP's `statistics` function
315-
/// is returned in this structure
316-
///
317-
/// Any of these statistics may or may not be available on the device. So, all the
318-
/// retriever functions of the statistics return `None` when a statistic is not supported
319-
#[repr(C)]
320-
#[derive(Default, Debug)]
321-
pub struct NetworkStats {
322-
rx_total_frames: u64,
323-
rx_good_frames: u64,
324-
rx_undersize_frames: u64,
325-
rx_oversize_frames: u64,
326-
rx_dropped_frames: u64,
327-
rx_unicast_frames: u64,
328-
rx_broadcast_frames: u64,
329-
rx_multicast_frames: u64,
330-
rx_crc_error_frames: u64,
331-
rx_total_bytes: u64,
332-
tx_total_frames: u64,
333-
tx_good_frames: u64,
334-
tx_undersize_frames: u64,
335-
tx_oversize_frames: u64,
336-
tx_dropped_frames: u64,
337-
tx_unicast_frames: u64,
338-
tx_broadcast_frames: u64,
339-
tx_multicast_frames: u64,
340-
tx_crc_error_frames: u64,
341-
tx_total_bytes: u64,
342-
collisions: u64,
343-
unsupported_protocol: u64,
344-
rx_duplicated_frames: u64,
345-
rx_decrypt_error_frames: u64,
346-
tx_error_frames: u64,
347-
tx_retry_frames: u64,
348-
}
349-
350-
impl NetworkStats {
351-
/// Any statistic value of -1 is not available
352-
const fn available(&self, stat: u64) -> bool {
353-
stat as i64 != -1
354-
}
355-
356-
/// Takes a statistic and converts it to an option
357-
///
358-
/// When the statistic is not available, `None` is returned
359-
const fn to_option(&self, stat: u64) -> Option<u64> {
360-
match self.available(stat) {
361-
true => Some(stat),
362-
false => None,
363-
}
364-
}
365-
366-
/// The total number of frames received, including error frames
367-
/// and dropped frames
368-
#[must_use]
369-
pub const fn rx_total_frames(&self) -> Option<u64> {
370-
self.to_option(self.rx_total_frames)
371-
}
372-
373-
/// The total number of good frames received and copied
374-
/// into receive buffers
375-
#[must_use]
376-
pub const fn rx_good_frames(&self) -> Option<u64> {
377-
self.to_option(self.rx_good_frames)
378-
}
379-
380-
/// The number of frames below the minimum length for the
381-
/// communications device
382-
#[must_use]
383-
pub const fn rx_undersize_frames(&self) -> Option<u64> {
384-
self.to_option(self.rx_undersize_frames)
385-
}
386-
387-
/// The number of frames longer than the maximum length for
388-
/// the communications length device
389-
#[must_use]
390-
pub const fn rx_oversize_frames(&self) -> Option<u64> {
391-
self.to_option(self.rx_oversize_frames)
392-
}
393-
394-
/// The number of valid frames that were dropped because
395-
/// the receive buffers were full
396-
#[must_use]
397-
pub const fn rx_dropped_frames(&self) -> Option<u64> {
398-
self.to_option(self.rx_dropped_frames)
399-
}
400-
401-
/// The number of valid unicast frames received and not dropped
402-
#[must_use]
403-
pub const fn rx_unicast_frames(&self) -> Option<u64> {
404-
self.to_option(self.rx_unicast_frames)
405-
}
406-
407-
/// The number of valid broadcast frames received and not dropped
408-
#[must_use]
409-
pub const fn rx_broadcast_frames(&self) -> Option<u64> {
410-
self.to_option(self.rx_broadcast_frames)
411-
}
412-
413-
/// The number of valid multicast frames received and not dropped
414-
#[must_use]
415-
pub const fn rx_multicast_frames(&self) -> Option<u64> {
416-
self.to_option(self.rx_multicast_frames)
417-
}
418-
419-
/// Number of frames with CRC or alignment errors
420-
#[must_use]
421-
pub const fn rx_crc_error_frames(&self) -> Option<u64> {
422-
self.to_option(self.rx_crc_error_frames)
423-
}
424-
425-
/// The total number of bytes received including frames with errors
426-
/// and dropped frames
427-
#[must_use]
428-
pub const fn rx_total_bytes(&self) -> Option<u64> {
429-
self.to_option(self.rx_total_bytes)
430-
}
431-
432-
/// The total number of frames transmitted including frames
433-
/// with errors and dropped frames
434-
#[must_use]
435-
pub const fn tx_total_frames(&self) -> Option<u64> {
436-
self.to_option(self.tx_total_frames)
437-
}
438-
439-
/// The total number of valid frames transmitted and copied
440-
/// into receive buffers
441-
#[must_use]
442-
pub const fn tx_good_frames(&self) -> Option<u64> {
443-
self.to_option(self.tx_good_frames)
444-
}
445-
446-
/// The number of frames below the minimum length for
447-
/// the media. This would be less than 64 for Ethernet
448-
#[must_use]
449-
pub const fn tx_undersize_frames(&self) -> Option<u64> {
450-
self.to_option(self.tx_undersize_frames)
451-
}
452-
453-
/// The number of frames longer than the maximum length for
454-
/// the media. This would be 1500 for Ethernet
455-
#[must_use]
456-
pub const fn tx_oversize_frames(&self) -> Option<u64> {
457-
self.to_option(self.tx_oversize_frames)
458-
}
459-
460-
/// The number of valid frames that were dropped because
461-
/// received buffers were full
462-
#[must_use]
463-
pub const fn tx_dropped_frames(&self) -> Option<u64> {
464-
self.to_option(self.tx_dropped_frames)
465-
}
466-
467-
/// The number of valid unicast frames transmitted and not
468-
/// dropped
469-
#[must_use]
470-
pub const fn tx_unicast_frames(&self) -> Option<u64> {
471-
self.to_option(self.tx_unicast_frames)
472-
}
473-
474-
/// The number of valid broadcast frames transmitted and
475-
/// not dropped
476-
#[must_use]
477-
pub const fn tx_broadcast_frames(&self) -> Option<u64> {
478-
self.to_option(self.tx_broadcast_frames)
479-
}
480-
481-
/// The number of valid multicast frames transmitted
482-
/// and not dropped
483-
#[must_use]
484-
pub const fn tx_multicast_frames(&self) -> Option<u64> {
485-
self.to_option(self.tx_multicast_frames)
486-
}
487-
488-
/// The number of transmitted frames with CRC or
489-
/// alignment errors
490-
#[must_use]
491-
pub const fn tx_crc_error_frames(&self) -> Option<u64> {
492-
self.to_option(self.tx_crc_error_frames)
493-
}
494-
495-
/// The total number of bytes transmitted including
496-
/// error frames and dropped frames
497-
#[must_use]
498-
pub const fn tx_total_bytes(&self) -> Option<u64> {
499-
self.to_option(self.tx_total_bytes)
500-
}
501-
502-
/// The number of collisions detected on this subnet
503-
#[must_use]
504-
pub const fn collisions(&self) -> Option<u64> {
505-
self.to_option(self.collisions)
506-
}
507-
508-
/// The number of frames destined for unsupported protocol
509-
#[must_use]
510-
pub const fn unsupported_protocol(&self) -> Option<u64> {
511-
self.to_option(self.unsupported_protocol)
512-
}
513-
514-
/// The number of valid frames received that were duplicated
515-
#[must_use]
516-
pub const fn rx_duplicated_frames(&self) -> Option<u64> {
517-
self.to_option(self.rx_duplicated_frames)
518-
}
519-
520-
/// The number of encrypted frames received that failed
521-
/// to decrypt
522-
#[must_use]
523-
pub const fn rx_decrypt_error_frames(&self) -> Option<u64> {
524-
self.to_option(self.rx_decrypt_error_frames)
525-
}
526-
527-
/// The number of frames that failed to transmit after
528-
/// exceeding the retry limit
529-
#[must_use]
530-
pub const fn tx_error_frames(&self) -> Option<u64> {
531-
self.to_option(self.tx_error_frames)
532-
}
533-
534-
/// The number of frames that transmitted successfully
535-
/// after more than one attempt
536-
#[must_use]
537-
pub const fn tx_retry_frames(&self) -> Option<u64> {
538-
self.to_option(self.tx_retry_frames)
539-
}
540-
}
541-
542-
/// The Simple Network Mode
543-
#[repr(C)]
544-
#[derive(Debug)]
545-
pub struct NetworkMode {
546-
/// Reports the current state of the network interface
547-
pub state: NetworkState,
548-
/// The size of the network interface's hardware address in bytes
549-
pub hw_address_size: u32,
550-
/// The size of the network interface's media header in bytes
551-
pub media_header_size: u32,
552-
/// The maximum size of the packets supported by the network interface in bytes
553-
pub max_packet_size: u32,
554-
/// The size of the NVRAM device attached to the network interface in bytes
555-
pub nv_ram_size: u32,
556-
/// The size that must be used for all NVRAM reads and writes
557-
pub nv_ram_access_size: u32,
558-
/// The multicast receive filter settings supported by the network interface
559-
pub receive_filter_mask: u32,
560-
/// The current multicast receive filter settings
561-
pub receive_filter_setting: u32,
562-
/// The maximum number of multicast address receive filters supported by the driver
563-
pub max_mcast_filter_count: u32,
564-
/// The current number of multicast address receive filters
565-
pub mcast_filter_count: u32,
566-
/// The array containing the addresses of the current multicast address receive filters
567-
pub mcast_filter: [MacAddress; 16],
568-
/// The current hardware MAC address for the network interface
569-
pub current_address: MacAddress,
570-
/// The current hardware MAC address for broadcast packets
571-
pub broadcast_address: MacAddress,
572-
/// The permanent hardware MAC address for the network interface
573-
pub permanent_address: MacAddress,
574-
/// The interface type of the network interface
575-
pub if_type: u8,
576-
/// Tells if the MAC address can be changed
577-
pub mac_address_changeable: bool,
578-
/// Tells if the network interface can transmit more than one packet at a time
579-
pub multiple_tx_supported: bool,
580-
/// Tells if the presence of the media can be determined
581-
pub media_present_supported: bool,
582-
/// Tells if media are connected to the network interface
583-
pub media_present: bool,
584-
}
585-
586-
newtype_enum! {
587-
/// The state of a network interface.
588-
pub enum NetworkState: u32 => {
589-
/// The interface has been stopped
590-
STOPPED = 0,
591-
/// The interface has been started
592-
STARTED = 1,
593-
/// The interface has been initialized
594-
INITIALIZED = 2,
595-
/// No state can have a number higher than this
596-
MAX_STATE = 4,
249+
pub fn mode(&self) -> &NetworkMode {
250+
unsafe { &*self.0.mode }
597251
}
598252
}

0 commit comments

Comments
 (0)
Please sign in to comment.