1const std = @import("std");
2const uefi = std.os.uefi;
3const Event = uefi.Event;
4const Guid = uefi.Guid;
5const Status = uefi.Status;
6const cc = uefi.cc;
7
8pub const SimpleNetwork = extern struct {
9 revision: u64,
10 _start: *const fn (*SimpleNetwork) callconv(cc) Status,
11 _stop: *const fn (*SimpleNetwork) callconv(cc) Status,
12 _initialize: *const fn (*SimpleNetwork, usize, usize) callconv(cc) Status,
13 _reset: *const fn (*SimpleNetwork, bool) callconv(cc) Status,
14 _shutdown: *const fn (*SimpleNetwork) callconv(cc) Status,
15 _receive_filters: *const fn (*SimpleNetwork, ReceiveFilter, ReceiveFilter, bool, usize, ?[*]const MacAddress) callconv(cc) Status,
16 _station_address: *const fn (*SimpleNetwork, bool, ?*const MacAddress) callconv(cc) Status,
17 _statistics: *const fn (*const SimpleNetwork, bool, ?*usize, ?*Statistics) callconv(cc) Status,
18 _mcast_ip_to_mac: *const fn (*SimpleNetwork, bool, *const anyopaque, *MacAddress) callconv(cc) Status,
19 _nvdata: *const fn (*SimpleNetwork, bool, usize, usize, [*]u8) callconv(cc) Status,
20 _get_status: *const fn (*SimpleNetwork, ?*InterruptStatus, ?*?[*]u8) callconv(cc) Status,
21 _transmit: *const fn (*SimpleNetwork, usize, usize, [*]const u8, ?*const MacAddress, ?*const MacAddress, ?*const u16) callconv(cc) Status,
22 _receive: *const fn (*SimpleNetwork, ?*usize, *usize, [*]u8, ?*MacAddress, ?*MacAddress, ?*u16) callconv(cc) Status,
23 wait_for_packet: Event,
24 mode: *Mode,
25
26 pub const StartError = uefi.UnexpectedError || error{
27 AlreadyStarted,
28 InvalidParameter,
29 DeviceError,
30 Unsupported,
31 };
32 pub const StopError = uefi.UnexpectedError || error{
33 NotStarted,
34 InvalidParameter,
35 DeviceError,
36 Unsupported,
37 };
38 pub const InitializeError = uefi.UnexpectedError || error{
39 NotStarted,
40 OutOfResources,
41 InvalidParameter,
42 DeviceError,
43 Unsupported,
44 };
45 pub const ResetError = uefi.UnexpectedError || error{
46 NotStarted,
47 InvalidParameter,
48 DeviceError,
49 Unsupported,
50 };
51 pub const ShutdownError = uefi.UnexpectedError || error{
52 NotStarted,
53 InvalidParameter,
54 DeviceError,
55 };
56 pub const ReceiveFiltersError = uefi.UnexpectedError || error{
57 NotStarted,
58 InvalidParameter,
59 DeviceError,
60 Unsupported,
61 };
62 pub const StationAddressError = uefi.UnexpectedError || error{
63 NotStarted,
64 InvalidParameter,
65 DeviceError,
66 Unsupported,
67 };
68 pub const StatisticsError = uefi.UnexpectedError || error{
69 NotStarted,
70 BufferTooSmall,
71 InvalidParameter,
72 DeviceError,
73 Unsupported,
74 };
75 pub const McastIpToMacError = uefi.UnexpectedError || error{
76 NotStarted,
77 InvalidParameter,
78 DeviceError,
79 Unsupported,
80 };
81 pub const NvDataError = uefi.UnexpectedError || error{
82 NotStarted,
83 InvalidParameter,
84 DeviceError,
85 Unsupported,
86 };
87 pub const GetStatusError = uefi.UnexpectedError || error{
88 NotStarted,
89 InvalidParameter,
90 DeviceError,
91 };
92 pub const TransmitError = uefi.UnexpectedError || error{
93 NotStarted,
94 NotReady,
95 BufferTooSmall,
96 InvalidParameter,
97 DeviceError,
98 Unsupported,
99 };
100 pub const ReceiveError = uefi.UnexpectedError || error{
101 NotStarted,
102 NotReady,
103 BufferTooSmall,
104 InvalidParameter,
105 DeviceError,
106 };
107
108 /// Changes the state of a network interface from "stopped" to "started".
109 pub fn start(self: *SimpleNetwork) StartError!void {
110 switch (self._start(self)) {
111 .success => {},
112 .already_started => return error.AlreadyStarted,
113 .invalid_parameter => return error.InvalidParameter,
114 .device_error => return error.DeviceError,
115 .unsupported => return error.Unsupported,
116 else => |status| return uefi.unexpectedStatus(status),
117 }
118 }
119
120 /// Changes the state of a network interface from "started" to "stopped".
121 pub fn stop(self: *SimpleNetwork) StopError!void {
122 switch (self._stop(self)) {
123 .success => {},
124 .not_started => return error.NotStarted,
125 .invalid_parameter => return error.InvalidParameter,
126 .device_error => return error.DeviceError,
127 .unsupported => return error.Unsupported,
128 else => |status| return uefi.unexpectedStatus(status),
129 }
130 }
131
132 /// Resets a network adapter and allocates the transmit and receive buffers required by the network interface.
133 pub fn initialize(
134 self: *SimpleNetwork,
135 extra_rx_buffer_size: usize,
136 extra_tx_buffer_size: usize,
137 ) InitializeError!void {
138 switch (self._initialize(self, extra_rx_buffer_size, extra_tx_buffer_size)) {
139 .success => {},
140 .not_started => return error.NotStarted,
141 .out_of_resources => return error.OutOfResources,
142 .invalid_parameter => return error.InvalidParameter,
143 .device_error => return error.DeviceError,
144 .unsupported => return error.Unsupported,
145 else => |status| return uefi.unexpectedStatus(status),
146 }
147 }
148
149 /// Resets a network adapter and reinitializes it with the parameters that were provided in the previous call to initialize().
150 pub fn reset(self: *SimpleNetwork, extended_verification: bool) ResetError!void {
151 switch (self._reset(self, extended_verification)) {
152 .success => {},
153 .not_started => return error.NotStarted,
154 .invalid_parameter => return error.InvalidParameter,
155 .device_error => return error.DeviceError,
156 .unsupported => return error.Unsupported,
157 else => |status| return uefi.unexpectedStatus(status),
158 }
159 }
160
161 /// Resets a network adapter and leaves it in a state that is safe for another driver to initialize.
162 pub fn shutdown(self: *SimpleNetwork) ShutdownError!void {
163 switch (self._shutdown(self)) {
164 .success => {},
165 .not_started => return error.NotStarted,
166 .invalid_parameter => return error.InvalidParameter,
167 .device_error => return error.DeviceError,
168 else => |status| return uefi.unexpectedStatus(status),
169 }
170 }
171
172 /// Manages the multicast receive filters of a network interface.
173 pub fn receiveFilters(
174 self: *SimpleNetwork,
175 enable: ReceiveFilter,
176 disable: ReceiveFilter,
177 reset_mcast_filter: bool,
178 mcast_filter: ?[]const MacAddress,
179 ) ReceiveFiltersError!void {
180 const count: usize, const ptr: ?[*]const MacAddress =
181 if (mcast_filter) |f|
182 .{ f.len, f.ptr }
183 else
184 .{ 0, null };
185
186 switch (self._receive_filters(self, enable, disable, reset_mcast_filter, count, ptr)) {
187 .success => {},
188 .not_started => return error.NotStarted,
189 .invalid_parameter => return error.InvalidParameter,
190 .device_error => return error.DeviceError,
191 .unsupported => return error.Unsupported,
192 else => |status| return uefi.unexpectedStatus(status),
193 }
194 }
195
196 /// Modifies or resets the current station address, if supported.
197 pub fn stationAddress(
198 self: *SimpleNetwork,
199 reset_flag: bool,
200 new: ?*const MacAddress,
201 ) StationAddressError!void {
202 switch (self._station_address(self, reset_flag, new)) {
203 .success => {},
204 .not_started => return error.NotStarted,
205 .invalid_parameter => return error.InvalidParameter,
206 .device_error => return error.DeviceError,
207 .unsupported => return error.Unsupported,
208 else => |status| return uefi.unexpectedStatus(status),
209 }
210 }
211
212 pub fn resetStatistics(self: *SimpleNetwork) StatisticsError!void {
213 switch (self._statistics(self, true, null, null)) {
214 .success => {},
215 .not_started => return error.NotStarted,
216 .invalid_parameter => return error.InvalidParameter,
217 .device_error => return error.DeviceError,
218 .unsupported => return error.Unsupported,
219 else => |status| return uefi.unexpectedStatus(status),
220 }
221 }
222
223 /// Resets or collects the statistics on a network interface.
224 pub fn statistics(self: *SimpleNetwork, reset_flag: bool) StatisticsError!Statistics {
225 var stats: Statistics = undefined;
226 var stats_size: usize = @sizeOf(Statistics);
227 switch (self._statistics(self, reset_flag, &stats_size, &stats)) {
228 .success => {},
229 .not_started => return error.NotStarted,
230 .invalid_parameter => return error.InvalidParameter,
231 .device_error => return error.DeviceError,
232 .unsupported => return error.Unsupported,
233 else => |status| return uefi.unexpectedStatus(status),
234 }
235
236 if (stats_size != @sizeOf(Statistics))
237 return error.Unexpected
238 else
239 return stats;
240 }
241
242 /// Converts a multicast IP address to a multicast HW MAC address.
243 pub fn mcastIpToMac(
244 self: *SimpleNetwork,
245 ipv6: bool,
246 ip: *const anyopaque,
247 ) McastIpToMacError!MacAddress {
248 var mac: MacAddress = undefined;
249 switch (self._mcast_ip_to_mac(self, ipv6, ip, &mac)) {
250 .success => return mac,
251 .not_started => return error.NotStarted,
252 .invalid_parameter => return error.InvalidParameter,
253 .device_error => return error.DeviceError,
254 .unsupported => return error.Unsupported,
255 else => |status| return uefi.unexpectedStatus(status),
256 }
257 }
258
259 /// Performs read and write operations on the NVRAM device attached to a network interface.
260 pub fn nvData(
261 self: *SimpleNetwork,
262 read_write: NvDataOperation,
263 offset: usize,
264 buffer: []u8,
265 ) NvDataError!void {
266 switch (self._nvdata(
267 self,
268 // if ReadWrite is TRUE, a read operation is performed
269 read_write == .read,
270 offset,
271 buffer.len,
272 buffer.ptr,
273 )) {
274 .success => {},
275 .not_started => return error.NotStarted,
276 .invalid_parameter => return error.InvalidParameter,
277 .device_error => return error.DeviceError,
278 .unsupported => return error.Unsupported,
279 else => |status| return uefi.unexpectedStatus(status),
280 }
281 }
282
283 /// Reads the current interrupt status and recycled transmit buffer status from a network interface.
284 pub fn getStatus(
285 self: *SimpleNetwork,
286 interrupt_status: ?*InterruptStatus,
287 recycled_tx_buf: ?*?[*]u8,
288 ) GetStatusError!void {
289 switch (self._get_status(self, interrupt_status, recycled_tx_buf)) {
290 .success => {},
291 .not_started => return error.NotStarted,
292 .invalid_parameter => return error.InvalidParameter,
293 .device_error => return error.DeviceError,
294 else => |status| return uefi.unexpectedStatus(status),
295 }
296 }
297
298 /// Places a packet in the transmit queue of a network interface.
299 pub fn transmit(
300 self: *SimpleNetwork,
301 header_size: usize,
302 buffer: []const u8,
303 src_addr: ?*const MacAddress,
304 dest_addr: ?*const MacAddress,
305 protocol: ?*const u16,
306 ) TransmitError!void {
307 switch (self._transmit(
308 self,
309 header_size,
310 buffer.len,
311 buffer.ptr,
312 src_addr,
313 dest_addr,
314 protocol,
315 )) {
316 .success => {},
317 .not_started => return error.NotStarted,
318 .not_ready => return error.NotReady,
319 .buffer_too_small => return error.BufferTooSmall,
320 .invalid_parameter => return error.InvalidParameter,
321 .device_error => return error.DeviceError,
322 .unsupported => return error.Unsupported,
323 else => |status| return uefi.unexpectedStatus(status),
324 }
325 }
326
327 /// Receives a packet from a network interface.
328 pub fn receive(self: *SimpleNetwork, buffer: []u8) ReceiveError!Packet {
329 var packet: Packet = undefined;
330 packet.buffer = buffer;
331
332 switch (self._receive(
333 self,
334 &packet.header_size,
335 &packet.buffer.len,
336 packet.buffer.ptr,
337 &packet.src_addr,
338 &packet.dst_addr,
339 &packet.protocol,
340 )) {
341 .success => return packet,
342 .not_started => return error.NotStarted,
343 .not_ready => return error.NotReady,
344 .buffer_too_small => return error.BufferTooSmall,
345 .invalid_parameter => return error.InvalidParameter,
346 .device_error => return error.DeviceError,
347 else => |status| return uefi.unexpectedStatus(status),
348 }
349 }
350
351 pub const guid align(8) = Guid{
352 .time_low = 0xa19832b9,
353 .time_mid = 0xac25,
354 .time_high_and_version = 0x11d3,
355 .clock_seq_high_and_reserved = 0x9a,
356 .clock_seq_low = 0x2d,
357 .node = [_]u8{ 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d },
358 };
359
360 pub const NvDataOperation = enum {
361 read,
362 write,
363 };
364
365 pub const MacAddress = [32]u8;
366
367 pub const Mode = extern struct {
368 state: State,
369 hw_address_size: u32,
370 media_header_size: u32,
371 max_packet_size: u32,
372 nvram_size: u32,
373 nvram_access_size: u32,
374 receive_filter_mask: ReceiveFilter,
375 receive_filter_setting: ReceiveFilter,
376 max_mcast_filter_count: u32,
377 mcast_filter_count: u32,
378 mcast_filter: [16]MacAddress,
379 current_address: MacAddress,
380 broadcast_address: MacAddress,
381 permanent_address: MacAddress,
382 if_type: u8,
383 mac_address_changeable: bool,
384 multiple_tx_supported: bool,
385 media_present_supported: bool,
386 media_present: bool,
387 };
388
389 pub const ReceiveFilter = packed struct(u32) {
390 receive_unicast: bool,
391 receive_multicast: bool,
392 receive_broadcast: bool,
393 receive_promiscuous: bool,
394 receive_promiscuous_multicast: bool,
395 _pad: u27 = 0,
396 };
397
398 pub const State = enum(u32) {
399 stopped,
400 started,
401 initialized,
402 };
403
404 pub const Statistics = extern struct {
405 rx_total_frames: u64,
406 rx_good_frames: u64,
407 rx_undersize_frames: u64,
408 rx_oversize_frames: u64,
409 rx_dropped_frames: u64,
410 rx_unicast_frames: u64,
411 rx_broadcast_frames: u64,
412 rx_multicast_frames: u64,
413 rx_crc_error_frames: u64,
414 rx_total_bytes: u64,
415 tx_total_frames: u64,
416 tx_good_frames: u64,
417 tx_undersize_frames: u64,
418 tx_oversize_frames: u64,
419 tx_dropped_frames: u64,
420 tx_unicast_frames: u64,
421 tx_broadcast_frames: u64,
422 tx_multicast_frames: u64,
423 tx_crc_error_frames: u64,
424 tx_total_bytes: u64,
425 collisions: u64,
426 unsupported_protocol: u64,
427 rx_duplicated_frames: u64,
428 rx_decryptError_frames: u64,
429 tx_error_frames: u64,
430 tx_retry_frames: u64,
431 };
432
433 pub const InterruptStatus = packed struct(u32) {
434 receive_interrupt: bool,
435 transmit_interrupt: bool,
436 command_interrupt: bool,
437 software_interrupt: bool,
438 _pad: u28 = 0,
439 };
440
441 pub const Packet = struct {
442 header_size: usize,
443 buffer: []u8,
444 src_addr: MacAddress,
445 dst_addr: MacAddress,
446 protocol: u16,
447 };
448};