1const std = @import("std");
2const uefi = std.os.uefi;
3const Guid = uefi.Guid;
4const Event = uefi.Event;
5const Status = uefi.Status;
6const Time = uefi.Time;
7const Ip6 = uefi.protocol.Ip6;
8const ManagedNetworkConfigData = uefi.protocol.ManagedNetwork.Config;
9const SimpleNetwork = uefi.protocol.SimpleNetwork;
10const cc = uefi.cc;
11
12pub const Udp6 = extern struct {
13 _get_mode_data: *const fn (*const Udp6, ?*Config, ?*Ip6.Mode, ?*ManagedNetworkConfigData, ?*SimpleNetwork) callconv(cc) Status,
14 _configure: *const fn (*const Udp6, ?*const Config) callconv(cc) Status,
15 _groups: *const fn (*const Udp6, bool, ?*const Ip6.Address) callconv(cc) Status,
16 _transmit: *const fn (*const Udp6, *CompletionToken) callconv(cc) Status,
17 _receive: *const fn (*const Udp6, *CompletionToken) callconv(cc) Status,
18 _cancel: *const fn (*const Udp6, ?*CompletionToken) callconv(cc) Status,
19 _poll: *const fn (*const Udp6) callconv(cc) Status,
20
21 pub const GetModeDataError = uefi.UnexpectedError || error{
22 NotStarted,
23 InvalidParameter,
24 };
25 pub const ConfigureError = uefi.UnexpectedError || error{
26 NoMapping,
27 InvalidParameter,
28 AlreadyStarted,
29 AccessDenied,
30 OutOfResources,
31 DeviceError,
32 };
33 pub const GroupsError = uefi.UnexpectedError || error{
34 NotStarted,
35 OutOfResources,
36 InvalidParameter,
37 AlreadyStarted,
38 NotFound,
39 DeviceError,
40 };
41 pub const TransmitError = uefi.UnexpectedError || error{
42 NotStarted,
43 NoMapping,
44 InvalidParameter,
45 AccessDenied,
46 NotReady,
47 OutOfResources,
48 NotFound,
49 BadBufferSize,
50 NoMedia,
51 };
52 pub const ReceiveError = uefi.UnexpectedError || error{
53 NotStarted,
54 NoMapping,
55 InvalidParameter,
56 OutOfResources,
57 DeviceError,
58 AccessDenied,
59 NotReady,
60 NoMedia,
61 };
62 pub const CancelError = uefi.UnexpectedError || error{
63 InvalidParameter,
64 NotStarted,
65 NotFound,
66 };
67 pub const PollError = uefi.UnexpectedError || error{
68 InvalidParameter,
69 DeviceError,
70 Timeout,
71 };
72
73 pub fn getModeData(self: *const Udp6) GetModeDataError!ModeData {
74 var data: ModeData = undefined;
75 switch (self._get_mode_data(
76 self,
77 &data.udp6_config_data,
78 &data.ip6_mode_data,
79 &data.mnp_config_data,
80 &data.snp_mode_data,
81 )) {
82 .success => return data,
83 .not_started => return error.NotStarted,
84 .invalid_parameter => return error.InvalidParameter,
85 else => |status| return uefi.unexpectedStatus(status),
86 }
87 }
88
89 pub fn configure(self: *Udp6, udp6_config_data: ?*const Config) ConfigureError!void {
90 switch (self._configure(self, udp6_config_data)) {
91 .success => {},
92 .no_mapping => return error.NoMapping,
93 .invalid_parameter => return error.InvalidParameter,
94 .already_started => return error.AlreadyStarted,
95 .access_denied => return error.AccessDenied,
96 .out_of_resources => return error.OutOfResources,
97 .device_error => return error.DeviceError,
98 else => |status| return uefi.unexpectedStatus(status),
99 }
100 }
101
102 pub fn groups(
103 self: *Udp6,
104 join_flag: JoinFlag,
105 multicast_address: ?*const Ip6.Address,
106 ) GroupsError!void {
107 switch (self._groups(
108 self,
109 // set to TRUE to join a multicast group
110 join_flag == .join,
111 multicast_address,
112 )) {
113 .success => {},
114 .not_started => return error.NotStarted,
115 .out_of_resources => return error.OutOfResources,
116 .invalid_parameter => return error.InvalidParameter,
117 .already_started => return error.AlreadyStarted,
118 .not_found => return error.NotFound,
119 .device_error => return error.DeviceError,
120 else => |status| return uefi.unexpectedStatus(status),
121 }
122 }
123
124 pub fn transmit(self: *Udp6, token: *CompletionToken) TransmitError!void {
125 switch (self._transmit(self, token)) {
126 .success => {},
127 .not_started => return error.NotStarted,
128 .no_mapping => return error.NoMapping,
129 .invalid_parameter => return error.InvalidParameter,
130 .access_denied => return error.AccessDenied,
131 .not_ready => return error.NotReady,
132 .out_of_resources => return error.OutOfResources,
133 .not_found => return error.NotFound,
134 .bad_buffer_size => return error.BadBufferSize,
135 .no_media => return error.NoMedia,
136 else => |status| return uefi.unexpectedStatus(status),
137 }
138 }
139
140 pub fn receive(self: *Udp6, token: *CompletionToken) ReceiveError!void {
141 switch (self._receive(self, token)) {
142 .success => {},
143 .not_started => return error.NotStarted,
144 .no_mapping => return error.NoMapping,
145 .invalid_parameter => return error.InvalidParameter,
146 .out_of_resources => return error.OutOfResources,
147 .device_error => return error.DeviceError,
148 .access_denied => return error.AccessDenied,
149 .not_ready => return error.NotReady,
150 .no_media => return error.NoMedia,
151 else => |status| return uefi.unexpectedStatus(status),
152 }
153 }
154
155 pub fn cancel(self: *Udp6, token: ?*CompletionToken) CancelError!void {
156 switch (self._cancel(self, token)) {
157 .success => {},
158 .invalid_parameter => return error.InvalidParameter,
159 .not_started => return error.NotStarted,
160 .not_found => return error.NotFound,
161 else => |status| return uefi.unexpectedStatus(status),
162 }
163 }
164
165 pub fn poll(self: *Udp6) PollError!void {
166 switch (self._poll(self)) {
167 .success => {},
168 .invalid_parameter => return error.InvalidParameter,
169 .device_error => return error.DeviceError,
170 .timeout => return error.Timeout,
171 else => |status| return uefi.unexpectedStatus(status),
172 }
173 }
174
175 pub const guid align(8) = uefi.Guid{
176 .time_low = 0x4f948815,
177 .time_mid = 0xb4b9,
178 .time_high_and_version = 0x43cb,
179 .clock_seq_high_and_reserved = 0x8a,
180 .clock_seq_low = 0x33,
181 .node = [_]u8{ 0x90, 0xe0, 0x60, 0xb3, 0x49, 0x55 },
182 };
183
184 pub const JoinFlag = enum {
185 join,
186 leave,
187 };
188
189 pub const ModeData = struct {
190 udp6_config_data: Config,
191 ip6_mode_data: Ip6.Mode,
192 mnp_config_data: ManagedNetworkConfigData,
193 snp_mode_data: SimpleNetwork,
194 };
195
196 pub const Config = extern struct {
197 accept_promiscuous: bool,
198 accept_any_port: bool,
199 allow_duplicate_port: bool,
200 traffic_class: u8,
201 hop_limit: u8,
202 receive_timeout: u32,
203 transmit_timeout: u32,
204 station_address: Ip6.Address,
205 station_port: u16,
206 remote_address: Ip6.Address,
207 remote_port: u16,
208 };
209
210 pub const CompletionToken = extern struct {
211 event: Event,
212 status: usize,
213 packet: extern union {
214 rx_data: *ReceiveData,
215 tx_data: *TransmitData,
216 },
217 };
218
219 pub const ReceiveData = extern struct {
220 timestamp: Time,
221 recycle_signal: Event,
222 udp6_session: SessionData,
223 data_length: u32,
224 fragment_count: u32,
225
226 pub fn getFragments(self: *ReceiveData) []Fragment {
227 return @as([*]Fragment, @ptrCast(@alignCast(@as([*]u8, @ptrCast(self)) + @sizeOf(ReceiveData))))[0..self.fragment_count];
228 }
229 };
230
231 pub const TransmitData = extern struct {
232 udp6_session_data: ?*SessionData,
233 data_length: u32,
234 fragment_count: u32,
235
236 pub fn getFragments(self: *TransmitData) []Fragment {
237 return @as([*]Fragment, @ptrCast(@alignCast(@as([*]u8, @ptrCast(self)) + @sizeOf(TransmitData))))[0..self.fragment_count];
238 }
239 };
240
241 pub const SessionData = extern struct {
242 source_address: Ip6.Address,
243 source_port: u16,
244 destination_address: Ip6.Address,
245 destination_port: u16,
246 };
247
248 pub const Fragment = extern struct {
249 fragment_length: u32,
250 fragment_buffer: [*]u8,
251 };
252};