Skip to content

Commit b59cbcd

Browse files
committed
Initial attempt: it seems to be working!
1 parent c1d4772 commit b59cbcd

File tree

5 files changed

+183
-0
lines changed

5 files changed

+183
-0
lines changed

src/proto/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,6 @@ pub mod debug;
3333
pub mod device_path;
3434
pub mod loaded_image;
3535
pub mod media;
36+
pub mod network;
3637
pub mod pi;
3738
pub mod shim;

src/proto/network/mod.rs

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
//! Network access protocols.
2+
//!
3+
//! These protocols can be used to interact with network resources.
4+
5+
pub mod snp;

src/proto/network/snp.rs

+172
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
//! Network I/O protocols.
2+
3+
use crate::proto::Protocol;
4+
use crate::{unsafe_guid, Result, Status};
5+
6+
/// The SNP protocol.
7+
#[repr(C)]
8+
#[unsafe_guid("a19832b9-ac25-11d3-9a2d-0090273fc14d")]
9+
#[derive(Protocol)]
10+
pub struct SNP {
11+
pub revision: u64,
12+
start : extern "efiapi" fn(this: &SNP) -> Status,
13+
stop : extern "efiapi" fn(this: &SNP) -> Status,
14+
initialize : extern "efiapi" fn(this: &SNP, extra_rx_buffer_size: usize, extra_tx_buffer_size: usize) -> Status,
15+
reset : extern "efiapi" fn(this: &SNP, extended_verification: bool) -> Status,
16+
shutdown : extern "efiapi" fn(this: &SNP) -> Status,
17+
receive_filters : extern "efiapi" fn(this: &SNP, enable: u32, disable: u32, reset_mcast_filter: bool, mcast_filter_count: usize, mcast_filter: *const MacAddress) -> Status,
18+
station_address : extern "efiapi" fn(this: &SNP, reset: bool, new: *const MacAddress) -> Status,
19+
statistics : extern "efiapi" fn(this: &SNP, reset: bool, statistics_size: *mut usize, statistics_table: *mut NetworkStatistics) -> Status,
20+
mcast_ip_to_mac : extern "efiapi" fn(this: &SNP, ipv6: bool, ip: *const IpAddress) -> Status,
21+
nv_data : extern "efiapi" fn(this: &SNP, read_write: bool, offset: usize, buffer_size: usize, buffer: *mut u8) -> Status,
22+
get_status : extern "efiapi" fn(this: &SNP, interrupt_status: *mut u32, tx_buf: *mut *mut u8) -> Status,
23+
transmit : extern "efiapi" fn(this: &SNP, header_size: usize, buffer_size: usize, buffer: *const u8, src_addr: *const MacAddress, dest_addr: *const MacAddress, protocol: u16) -> Status,
24+
receive : extern "efiapi" fn(this: &SNP, header_size: *const usize, buffer_size: *mut usize, buffer: *mut u8, src_addr: *mut MacAddress, dest_addr: *mut MacAddress, protocol: *mut u16) -> Status,
25+
wait_for_packet : usize,
26+
mode: *const NetworkMode,
27+
}
28+
29+
impl SNP {
30+
31+
/// Changes the state of a network interface from “stopped” to “started”.
32+
///
33+
/// # Errors
34+
/// * `uefi::Status::ALREADY_STARTED` The network interface is already in the started state.
35+
/// * `uefi::Status::INVALID_PARAMETER` This parameter was NULL or did not point to a valid EFI_SIMPLE_NETWORK_PROTOCOL structure
36+
/// * `uefi::Status::DEVICE_ERROR` The command could not be sent to the network interface.
37+
/// * `uefi::Status::DEVICE_ERROR` This function is not supported by the network interface.
38+
pub fn start(&self) -> Result {
39+
(self.start)(self).into()
40+
}
41+
42+
/// Changes the state of a network interface from “started” to “stopped”.
43+
///
44+
/// # Errors
45+
/// * `uefi::Status::NOT_STARTED` The network interface has not been started.
46+
/// * `uefi::Status::INVALID_PARAMETER` This parameter was NULL or did not point to a valid EFI_SIMPLE_NETWORK_PROTOCOL structure
47+
/// * `uefi::Status::DEVICE_ERROR` The command could not be sent to the network interface.
48+
/// * `uefi::Status::DEVICE_ERROR` This function is not supported by the network interface.
49+
pub fn stop(&mut self) -> Result {
50+
(self.stop)(self).into()
51+
}
52+
53+
/// Resets a network adapter and allocates the transmit and receive buffers.
54+
///
55+
/// # Errors
56+
/// * `uefi::Status::NOT_STARTED` The network interface has not been started.
57+
/// * `uefi::Status::EFI_OUT_OF_RESOURCES` There was not enough memory for the transmit and receive buffers
58+
/// * `uefi::Status::INVALID_PARAMETER` This parameter was NULL or did not point to a valid EFI_SIMPLE_NETWORK_PROTOCOL structure
59+
/// * `uefi::Status::DEVICE_ERROR` The command could not be sent to the network interface.
60+
/// * `uefi::Status::UNSUPPORTED` The increased buffer size feature is not supported.
61+
pub fn initialize(&self, extra_rx_buffer_size: usize, extra_tx_buffer_size: usize) -> Result {
62+
(self.initialize)(self, extra_rx_buffer_size, extra_tx_buffer_size).into()
63+
}
64+
65+
/// Resets or collects the statistics on a network interface.
66+
///
67+
/// # Errors
68+
pub fn statistics(&self, reset: bool, statistics_size: *mut usize, statistics_table: *mut NetworkStatistics) -> Result {
69+
(self.statistics)(self, reset, statistics_size, statistics_table).into()
70+
}
71+
72+
/// Places a packet in the transmit queue of a network interface.
73+
///
74+
/// # Errors
75+
/// * `uefi::Status::NOT_STARTED` The network interface has not been started.
76+
/// * `uefi::Status::EFI_OUT_OF_RESOURCES` There was not enough memory for the transmit and receive buffers
77+
/// * `uefi::Status::INVALID_PARAMETER` This parameter was NULL or did not point to a valid EFI_SIMPLE_NETWORK_PROTOCOL structure
78+
/// * `uefi::Status::DEVICE_ERROR` The command could not be sent to the network interface.
79+
/// * `uefi::Status::UNSUPPORTED` The increased buffer size feature is not supported.
80+
pub fn transmit(&self, header_size: usize, buffer: &[u8], src_addr: *const MacAddress, dest_addr: *const MacAddress, protocol: u16) -> Result {
81+
(self.transmit)(self, header_size, buffer.len(), buffer.as_ptr(), src_addr, dest_addr, protocol).into()
82+
}
83+
84+
/// Pointer for network mode.
85+
pub fn mode(&self) -> &NetworkMode {
86+
unsafe { &*self.mode }
87+
}
88+
}
89+
90+
/// Network statistics structure
91+
#[repr(C)]
92+
#[derive(Debug)]
93+
pub struct NetworkStatistics {
94+
rx_total_frames: u64,
95+
rx_good_frames: u64,
96+
rx_undersize_frames: u64,
97+
rx_oversize_frames: u64,
98+
rx_dropped_frames: u64,
99+
rx_unicast_frames: u64,
100+
rx_broadcast_frames: u64,
101+
rx_multicast_frames: u64,
102+
rx_crc_error_frames: u64,
103+
rx_total_bytes: u64,
104+
tx_total_frames: u64,
105+
tx_good_frames: u64,
106+
tx_undersize_frames: u64,
107+
tx_oversize_frames: u64,
108+
tx_dropped_frames: u64,
109+
tx_unicast_frames: u64,
110+
tx_broadcast_frames: u64,
111+
tx_multicast_frames: u64,
112+
tx_crc_error_frames: u64,
113+
tx_total_bytes: u64,
114+
collisions: u64,
115+
unsupported_protocol: u64,
116+
rx_duplicated_frames: u64,
117+
rx_decrypt_error_frames: u64,
118+
tx_error_frames: u64,
119+
tx_retry_frames: u64,
120+
}
121+
122+
/// EFI_MAC_ADDRESS
123+
#[repr(C)]
124+
#[derive(Debug)]
125+
pub struct MacAddress {
126+
pub addr: [u8; 32],
127+
}
128+
129+
/// EFI_IP_ADDRESS
130+
#[repr(C)]
131+
#[derive(Debug)]
132+
pub struct IpAddress {
133+
addr: [u8; 4],
134+
}
135+
136+
/// Network mode structure
137+
#[repr(C)]
138+
#[derive(Debug)]
139+
pub struct NetworkMode {
140+
state: u32,
141+
hw_address_size: u32,
142+
media_header_size: u32,
143+
max_packet_size: u32,
144+
nv_ram_size: u32,
145+
nv_ram_access_size: u32,
146+
receive_filter_mask: u32,
147+
receive_filter_setting: u32,
148+
max_mcast_filter_count: u32,
149+
mcast_filter_count: u32,
150+
mcast_filter: [MacAddress; 16],
151+
current_address: MacAddress,
152+
broadcast_address: MacAddress,
153+
permanent_address: MacAddress,
154+
if_type: u8,
155+
mac_address_changeable: bool,
156+
multiple_tx_supported: bool,
157+
media_present_supported: bool,
158+
media_present: bool,
159+
}
160+
161+
impl NetworkMode {
162+
163+
///
164+
pub fn current_address(&self) -> &MacAddress {
165+
&self.current_address
166+
}
167+
168+
///
169+
pub fn if_type(&self) -> u8 {
170+
self.if_type
171+
}
172+
}

uefi-test-runner/build.py

+3
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,9 @@ def run_qemu():
277277

278278
# Map the QEMU monitor to a pair of named pipes
279279
'-qmp', f'pipe:{qemu_monitor_pipe}',
280+
281+
# Add network interface
282+
'-nic', 'model=rtl8139',
280283
])
281284

282285
# For now these only work on x86_64

uefi-test-runner/src/proto/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ pub fn test(image: Handle, st: &mut SystemTable<Boot>) {
1515
debug::test(bt);
1616
device_path::test(image, bt);
1717
media::test(bt);
18+
network::test(bt);
1819
pi::test(bt);
1920

2021
#[cfg(any(
@@ -57,6 +58,7 @@ mod console;
5758
mod debug;
5859
mod device_path;
5960
mod media;
61+
mod network;
6062
mod pi;
6163
#[cfg(any(
6264
target_arch = "i386",

0 commit comments

Comments
 (0)