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};