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