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