master
  1const std = @import("std");
  2const uefi = std.os.uefi;
  3const Guid = uefi.Guid;
  4const Event = uefi.Event;
  5const Status = uefi.Status;
  6const MacAddress = uefi.MacAddress;
  7const ManagedNetworkConfigData = uefi.protocol.ManagedNetwork.Config;
  8const SimpleNetwork = uefi.protocol.SimpleNetwork;
  9const cc = uefi.cc;
 10const Error = Status.Error;
 11
 12pub const Ip6 = extern struct {
 13    _get_mode_data: *const fn (*const Ip6, ?*Mode, ?*ManagedNetworkConfigData, ?*SimpleNetwork) callconv(cc) Status,
 14    _configure: *const fn (*Ip6, ?*const Config) callconv(cc) Status,
 15    _groups: *const fn (*Ip6, bool, ?*const Address) callconv(cc) Status,
 16    _routes: *const fn (*Ip6, bool, ?*const Address, u8, ?*const Address) callconv(cc) Status,
 17    _neighbors: *const fn (*Ip6, bool, *const Address, ?*const MacAddress, u32, bool) callconv(cc) Status,
 18    _transmit: *const fn (*Ip6, *CompletionToken) callconv(cc) Status,
 19    _receive: *const fn (*Ip6, *CompletionToken) callconv(cc) Status,
 20    _cancel: *const fn (*Ip6, ?*CompletionToken) callconv(cc) Status,
 21    _poll: *const fn (*Ip6) callconv(cc) Status,
 22
 23    pub const GetModeDataError = uefi.UnexpectedError || error{
 24        InvalidParameter,
 25        OutOfResources,
 26    };
 27    pub const ConfigureError = uefi.UnexpectedError || error{
 28        InvalidParameter,
 29        OutOfResources,
 30        NoMapping,
 31        AlreadyStarted,
 32        DeviceError,
 33        Unsupported,
 34    };
 35    pub const GroupsError = uefi.UnexpectedError || error{
 36        InvalidParameter,
 37        NotStarted,
 38        OutOfResources,
 39        Unsupported,
 40        AlreadyStarted,
 41        NotFound,
 42        DeviceError,
 43    };
 44    pub const RoutesError = uefi.UnexpectedError || error{
 45        NotStarted,
 46        InvalidParameter,
 47        OutOfResources,
 48        NotFound,
 49        AccessDenied,
 50    };
 51    pub const NeighborsError = uefi.UnexpectedError || error{
 52        NotStarted,
 53        InvalidParameter,
 54        OutOfResources,
 55        NotFound,
 56        AccessDenied,
 57    };
 58    pub const TransmitError = uefi.UnexpectedError || error{
 59        NotStarted,
 60        NoMapping,
 61        InvalidParameter,
 62        AccessDenied,
 63        NotReady,
 64        NotFound,
 65        OutOfResources,
 66        BufferTooSmall,
 67        BadBufferSize,
 68        DeviceError,
 69        NoMedia,
 70    };
 71    pub const ReceiveError = uefi.UnexpectedError || error{
 72        NotStarted,
 73        NoMapping,
 74        InvalidParameter,
 75        OutOfResources,
 76        DeviceError,
 77        AccessDenied,
 78        NotReady,
 79        NoMedia,
 80    };
 81    pub const CancelError = uefi.UnexpectedError || error{
 82        InvalidParameter,
 83        NotStarted,
 84        NotFound,
 85        DeviceError,
 86    };
 87    pub const PollError = uefi.UnexpectedError || error{
 88        NotStarted,
 89        InvalidParameter,
 90        DeviceError,
 91        Timeout,
 92    };
 93
 94    pub const ModeData = struct {
 95        ip6_mode: Mode,
 96        mnp_config: ManagedNetworkConfigData,
 97        snp_mode: SimpleNetwork,
 98    };
 99
100    /// Gets the current operational settings for this instance of the EFI IPv6 Protocol driver.
101    pub fn getModeData(self: *const Ip6) GetModeDataError!ModeData {
102        var data: ModeData = undefined;
103        switch (self._get_mode_data(self, &data.ip6_mode, &data.mnp_config, &data.snp_mode)) {
104            .success => return data,
105            .invalid_parameter => return Error.InvalidParameter,
106            .out_of_resources => return Error.OutOfResources,
107            else => |status| return uefi.unexpectedStatus(status),
108        }
109    }
110
111    /// Assign IPv6 address and other configuration parameter to this EFI IPv6 Protocol driver instance.
112    ///
113    /// To reset the configuration, use `disable` instead.
114    pub fn configure(self: *Ip6, ip6_config_data: *const Config) ConfigureError!void {
115        switch (self._configure(self, ip6_config_data)) {
116            .success => {},
117            .invalid_parameter => return Error.InvalidParameter,
118            .out_of_resources => return Error.OutOfResources,
119            .no_mapping => return Error.NoMapping,
120            .already_started => return Error.AlreadyStarted,
121            .device_error => return Error.DeviceError,
122            .unsupported => return Error.Unsupported,
123            else => |status| return uefi.unexpectedStatus(status),
124        }
125    }
126
127    pub fn disable(self: *Ip6) ConfigureError!void {
128        switch (self._configure(self, null)) {
129            .success => {},
130            .invalid_parameter => return Error.InvalidParameter,
131            .out_of_resources => return Error.OutOfResources,
132            .no_mapping => return Error.NoMapping,
133            .already_started => return Error.AlreadyStarted,
134            .device_error => return Error.DeviceError,
135            .unsupported => return Error.Unsupported,
136            else => |status| return uefi.unexpectedStatus(status),
137        }
138    }
139
140    pub fn leaveAllGroups(self: *Ip6) GroupsError!void {
141        switch (self._groups(self, false, null)) {
142            .success => {},
143            .invalid_parameter => return Error.InvalidParameter,
144            .not_started => return Error.NotStarted,
145            .out_of_resources => return Error.OutOfResources,
146            .unsupported => return Error.Unsupported,
147            .already_started => return Error.AlreadyStarted,
148            .not_found => return Error.NotFound,
149            .device_error => return Error.DeviceError,
150            else => |status| return uefi.unexpectedStatus(status),
151        }
152    }
153
154    /// Joins and leaves multicast groups.
155    ///
156    /// To leave all groups, use `leaveAllGroups` instead.
157    pub fn groups(
158        self: *Ip6,
159        join_flag: JoinFlag,
160        group_address: *const Address,
161    ) GroupsError!void {
162        switch (self._groups(
163            self,
164            // set to TRUE to join the multicast group session and FALSE to leave
165            join_flag == .join,
166            group_address,
167        )) {
168            .success => {},
169            .invalid_parameter => return Error.InvalidParameter,
170            .not_started => return Error.NotStarted,
171            .out_of_resources => return Error.OutOfResources,
172            .unsupported => return Error.Unsupported,
173            .already_started => return Error.AlreadyStarted,
174            .not_found => return Error.NotFound,
175            .device_error => return Error.DeviceError,
176            else => |status| return uefi.unexpectedStatus(status),
177        }
178    }
179
180    /// Adds and deletes routing table entries.
181    pub fn routes(
182        self: *Ip6,
183        delete_route: DeleteFlag,
184        destination: ?*const Address,
185        prefix_length: u8,
186        gateway_address: ?*const Address,
187    ) RoutesError!void {
188        switch (self._routes(
189            self,
190            delete_route == .delete,
191            destination,
192            prefix_length,
193            gateway_address,
194        )) {
195            .success => {},
196            .not_started => return Error.NotStarted,
197            .invalid_parameter => return Error.InvalidParameter,
198            .out_of_resources => return Error.OutOfResources,
199            .not_found => return Error.NotFound,
200            .access_denied => return Error.AccessDenied,
201            else => |status| return uefi.unexpectedStatus(status),
202        }
203    }
204
205    /// Add or delete Neighbor cache entries.
206    pub fn neighbors(
207        self: *Ip6,
208        delete_flag: DeleteFlag,
209        target_ip6_address: *const Address,
210        target_link_address: ?*const MacAddress,
211        timeout: u32,
212        override: bool,
213    ) NeighborsError!void {
214        switch (self._neighbors(
215            self,
216            // set to TRUE to delete this route from the routing table.
217            // set to FALSE to add this route to the routing table.
218            delete_flag == .delete,
219            target_ip6_address,
220            target_link_address,
221            timeout,
222            override,
223        )) {
224            .success => {},
225            .not_started => return Error.NotStarted,
226            .invalid_parameter => return Error.InvalidParameter,
227            .out_of_resources => return Error.OutOfResources,
228            .not_found => return Error.NotFound,
229            .access_denied => return Error.AccessDenied,
230            else => |status| return uefi.unexpectedStatus(status),
231        }
232    }
233
234    /// Places outgoing data packets into the transmit queue.
235    pub fn transmit(self: *Ip6, token: *CompletionToken) TransmitError!void {
236        switch (self._transmit(self, token)) {
237            .success => {},
238            .not_started => return Error.NotStarted,
239            .no_mapping => return Error.NoMapping,
240            .invalid_parameter => return Error.InvalidParameter,
241            .access_denied => return Error.AccessDenied,
242            .not_ready => return Error.NotReady,
243            .not_found => return Error.NotFound,
244            .out_of_resources => return Error.OutOfResources,
245            .buffer_too_small => return Error.BufferTooSmall,
246            .bad_buffer_size => return Error.BadBufferSize,
247            .device_error => return Error.DeviceError,
248            .no_media => return Error.NoMedia,
249            else => |status| return uefi.unexpectedStatus(status),
250        }
251    }
252
253    /// Places a receiving request into the receiving queue.
254    pub fn receive(self: *Ip6, token: *CompletionToken) ReceiveError!void {
255        switch (self._receive(self, token)) {
256            .success => {},
257            .not_started => return Error.NotStarted,
258            .no_mapping => return Error.NoMapping,
259            .invalid_parameter => return Error.InvalidParameter,
260            .out_of_resources => return Error.OutOfResources,
261            .device_error => return Error.DeviceError,
262            .access_denied => return Error.AccessDenied,
263            .not_ready => return Error.NotReady,
264            .no_media => return Error.NoMedia,
265            else => |status| return uefi.unexpectedStatus(status),
266        }
267    }
268
269    /// Abort an asynchronous transmits or receive request.
270    pub fn cancel(self: *Ip6, token: ?*CompletionToken) CancelError!void {
271        switch (self._cancel(self, token)) {
272            .success => {},
273            .invalid_parameter => return Error.InvalidParameter,
274            .not_started => return Error.NotStarted,
275            .not_found => return Error.NotFound,
276            .device_error => return Error.DeviceError,
277            else => |status| return uefi.unexpectedStatus(status),
278        }
279    }
280
281    /// Polls for incoming data packets and processes outgoing data packets.
282    ///
283    /// Returns true if a packet was received or processed.
284    pub fn poll(self: *Ip6) PollError!bool {
285        switch (self._poll(self)) {
286            .success => return true,
287            .not_ready => return false,
288            .not_started => return Error.NotStarted,
289            .invalid_parameter => return Error.InvalidParameter,
290            .device_error => return Error.DeviceError,
291            .timeout => return Error.Timeout,
292            else => |status| return uefi.unexpectedStatus(status),
293        }
294    }
295
296    pub const guid align(8) = Guid{
297        .time_low = 0x2c8759d5,
298        .time_mid = 0x5c2d,
299        .time_high_and_version = 0x66ef,
300        .clock_seq_high_and_reserved = 0x92,
301        .clock_seq_low = 0x5f,
302        .node = [_]u8{ 0xb6, 0x6c, 0x10, 0x19, 0x57, 0xe2 },
303    };
304
305    pub const DeleteFlag = enum {
306        delete,
307        add,
308    };
309
310    pub const JoinFlag = enum {
311        join,
312        leave,
313    };
314
315    pub const Mode = extern struct {
316        is_started: bool,
317        max_packet_size: u32,
318        config_data: Config,
319        is_configured: bool,
320        address_count: u32,
321        address_list: [*]AddressInfo,
322        group_count: u32,
323        group_table: [*]Address,
324        route_count: u32,
325        route_table: [*]RouteTable,
326        neighbor_count: u32,
327        neighbor_cache: [*]NeighborCache,
328        prefix_count: u32,
329        prefix_table: [*]AddressInfo,
330        icmp_type_count: u32,
331        icmp_type_list: [*]IcmpType,
332    };
333
334    pub const Config = extern struct {
335        default_protocol: u8,
336        accept_any_protocol: bool,
337        accept_icmp_errors: bool,
338        accept_promiscuous: bool,
339        destination_address: Address,
340        station_address: Address,
341        traffic_class: u8,
342        hop_limit: u8,
343        flow_label: u32,
344        receive_timeout: u32,
345        transmit_timeout: u32,
346    };
347
348    pub const Address = [16]u8;
349
350    pub const AddressInfo = extern struct {
351        address: Address,
352        prefix_length: u8,
353    };
354
355    pub const RouteTable = extern struct {
356        gateway: Address,
357        destination: Address,
358        prefix_length: u8,
359    };
360
361    pub const NeighborState = enum(u32) {
362        incomplete,
363        reachable,
364        stale,
365        delay,
366        probe,
367    };
368
369    pub const NeighborCache = extern struct {
370        neighbor: Address,
371        link_address: MacAddress,
372        state: NeighborState,
373    };
374
375    pub const IcmpType = extern struct {
376        type: u8,
377        code: u8,
378    };
379
380    pub const CompletionToken = extern struct {
381        event: Event,
382        status: Status,
383        packet: *anyopaque, // union TODO
384    };
385};