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