Skip to main content

uefi_raw/protocol/network/
pxe.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3use crate::{Boolean, Char8, Guid, IpAddress, MacAddress, Status, guid, newtype_enum};
4use bitflags::bitflags;
5use core::ffi::c_void;
6use core::fmt::{self, Debug, Formatter};
7
8#[derive(Debug)]
9#[repr(C)]
10pub struct PxeBaseCodeProtocol {
11    pub revision: u64,
12    pub start: unsafe extern "efiapi" fn(this: *mut Self, use_ipv6: Boolean) -> Status,
13    pub stop: unsafe extern "efiapi" fn(this: *mut Self) -> Status,
14    pub dhcp: unsafe extern "efiapi" fn(this: *mut Self, sort_offers: Boolean) -> Status,
15    pub discover: unsafe extern "efiapi" fn(
16        this: *mut Self,
17        ty: PxeBaseCodeBootType,
18        layer: *mut u16,
19        use_bis: Boolean,
20        info: *const PxeBaseCodeDiscoverInfo,
21    ) -> Status,
22    pub mtftp: unsafe extern "efiapi" fn(
23        this: *mut Self,
24        operation: PxeBaseCodeTftpOpcode,
25        buffer: *mut c_void,
26        overwrite: Boolean,
27        buffer_size: *mut u64,
28        block_size: *const usize,
29        server_ip: *const IpAddress,
30        filename: *const Char8,
31        info: *const PxeBaseCodeMtftpInfo,
32        dont_use_buffer: Boolean,
33    ) -> Status,
34    pub udp_write: unsafe extern "efiapi" fn(
35        this: *mut Self,
36        op_flags: PxeBaseCodeUdpOpFlags,
37        dest_ip: *const IpAddress,
38        dest_port: *const PxeBaseCodeUdpPort,
39        gateway_ip: *const IpAddress,
40        src_ip: *const IpAddress,
41        src_port: *mut PxeBaseCodeUdpPort,
42        header_size: *const usize,
43        header_ptr: *const c_void,
44        buffer_size: *const usize,
45        buffer_ptr: *const c_void,
46    ) -> Status,
47    pub udp_read: unsafe extern "efiapi" fn(
48        this: *mut Self,
49        op_flags: PxeBaseCodeUdpOpFlags,
50        dest_ip: *mut IpAddress,
51        dest_port: *mut PxeBaseCodeUdpPort,
52        src_ip: *mut IpAddress,
53        src_port: *mut PxeBaseCodeUdpPort,
54        header_size: *const usize,
55        header_ptr: *mut c_void,
56        buffer_size: *mut usize,
57        buffer_ptr: *mut c_void,
58    ) -> Status,
59    pub set_ip_filter: unsafe extern "efiapi" fn(
60        this: *mut Self,
61        new_filter: *const PxeBaseCodeIpFilter,
62    ) -> Status,
63    pub arp: unsafe extern "efiapi" fn(
64        this: *mut Self,
65        ip_addr: *const IpAddress,
66        mac_addr: *mut MacAddress,
67    ) -> Status,
68    pub set_parameters: unsafe extern "efiapi" fn(
69        this: *mut Self,
70        new_auto_arp: *const Boolean,
71        new_send_guid: *const Boolean,
72        new_ttl: *const u8,
73        new_tos: *const u8,
74        new_make_callback: *const Boolean,
75    ) -> Status,
76    pub set_station_ip: unsafe extern "efiapi" fn(
77        this: *mut Self,
78        new_station_ip: *const IpAddress,
79        new_subnet_mask: *const IpAddress,
80    ) -> Status,
81    pub set_packets: unsafe extern "efiapi" fn(
82        this: *mut Self,
83        new_dhcp_discover_valid: *const Boolean,
84        new_dhcp_ack_received: *const Boolean,
85        new_proxy_offer_received: *const Boolean,
86        new_pxe_discover_valid: *const Boolean,
87        new_pxe_reply_received: *const Boolean,
88        new_pxe_bis_reply_received: *const Boolean,
89        new_dhcp_discover: *const PxeBaseCodePacket,
90        new_dhcp_ack: *const PxeBaseCodePacket,
91        new_proxy_offer: *const PxeBaseCodePacket,
92        new_pxe_discover: *const PxeBaseCodePacket,
93        new_pxe_reply: *const PxeBaseCodePacket,
94        new_pxe_bis_reply: *const PxeBaseCodePacket,
95    ) -> Status,
96    pub mode: *const PxeBaseCodeMode,
97}
98
99impl PxeBaseCodeProtocol {
100    pub const GUID: Guid = guid!("03c4e603-ac28-11d3-9a2d-0090273fc14d");
101}
102
103newtype_enum! {
104    pub enum PxeBaseCodeBootType: u16 => {
105        BOOTSTRAP = 0,
106        MS_WINNT_RIS = 1,
107        INTEL_LCM = 2,
108        DOS_UNDI = 3,
109        NEC_ESMPRO = 4,
110        IBM_WSOD = 5,
111        IBM_LCCM = 6,
112        CA_UNICENTER_TNG = 7,
113        HP_OPENVIEW = 8,
114        ALTIRIS_9 = 9,
115        ALTIRIS_10 = 10,
116        ALTIRIS_11 = 11,
117        NOT_USED_12 = 12,
118        REDHAT_INSTALL = 13,
119        REDHAT_BOOT = 14,
120        REMBO = 15,
121        BEOBOOT = 16,
122        //    17..=32767: reserved.
123        // 32768..=65279: reserved for vendor use.
124        // 65280..=65534: reserved.
125        PXETEST = 65535,
126    }
127}
128
129newtype_enum! {
130    pub enum PxeBaseCodeTftpOpcode: i32 => {
131        TFTP_FIRST = 0,
132        TFTP_GET_FILE_SIZE = 1,
133        TFTP_READ_FILE = 2,
134        TFTP_WRITE_FILE = 3,
135        TFTP_READ_DIRECTORY = 4,
136        MTFTP_GET_FILE_SIZE = 5,
137        MTFTP_READ_FILE = 6,
138        MTFTP_READ_DIRECTORY = 7,
139        MTFTP_LAST = 8,
140    }
141}
142
143#[derive(Debug)]
144#[repr(C)]
145pub struct PxeBaseCodeDiscoverInfo {
146    pub use_m_cast: Boolean,
147    pub use_b_cast: Boolean,
148    pub use_u_cast: Boolean,
149    pub must_use_list: Boolean,
150    pub server_m_cast_ip: IpAddress,
151    pub ip_cnt: u16,
152
153    /// Note that this field is actually a variable-length array.
154    pub srv_list: [PxeBaseCodeSrvlist; 0],
155}
156
157#[derive(Clone, Copy, Debug)]
158#[repr(C)]
159pub struct PxeBaseCodeSrvlist {
160    pub server_type: u16,
161    pub accept_any_response: Boolean,
162    pub reserved: u8,
163    pub ip_addr: IpAddress,
164}
165
166pub type PxeBaseCodeUdpPort = u16;
167
168#[derive(Clone, Copy, Debug)]
169#[repr(C)]
170pub struct PxeBaseCodeMtftpInfo {
171    pub m_cast_ip: IpAddress,
172    pub c_port: PxeBaseCodeUdpPort,
173    pub s_port: PxeBaseCodeUdpPort,
174    pub listen_timeout: u16,
175    pub transmit_timeout: u16,
176}
177
178bitflags! {
179    /// Flags for UDP read and write operations.
180    #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
181    #[repr(transparent)]
182    pub struct PxeBaseCodeUdpOpFlags: u16 {
183        /// Receive a packet sent from any IP address in UDP read operations.
184        const ANY_SRC_IP = 0x0001;
185
186        /// Receive a packet sent from any UDP port in UDP read operations. If
187        /// the source port is not specified in UDP write operations, the
188        /// source port will be automatically selected.
189        const ANY_SRC_PORT = 0x0002;
190
191        /// Receive a packet sent to any IP address in UDP read operations.
192        const ANY_DEST_IP = 0x0004;
193
194        /// Receive a packet sent to any UDP port in UDP read operations.
195        const ANY_DEST_PORT = 0x0008;
196
197        /// The software filter is used in UDP read operations.
198        const USE_FILTER = 0x0010;
199
200        /// If required, a UDP write operation may be broken up across multiple packets.
201        const MAY_FRAGMENT = 0x0020;
202    }
203}
204
205#[derive(Clone, Debug)]
206#[repr(C)]
207pub struct PxeBaseCodeMode {
208    pub started: Boolean,
209    pub ipv6_available: Boolean,
210    pub ipv6_supported: Boolean,
211    pub using_ipv6: Boolean,
212    pub bis_supported: Boolean,
213    pub bis_detected: Boolean,
214    pub auto_arp: Boolean,
215    pub send_guid: Boolean,
216    pub dhcp_discover_valid: Boolean,
217    pub dhcp_ack_received: Boolean,
218    pub proxy_offer_received: Boolean,
219    pub pxe_discover_valid: Boolean,
220    pub pxe_reply_received: Boolean,
221    pub pxe_bis_reply_received: Boolean,
222    pub icmp_error_received: Boolean,
223    pub tftp_error_received: Boolean,
224    pub make_callbacks: Boolean,
225    pub ttl: u8,
226    pub tos: u8,
227    pub station_ip: IpAddress,
228    pub subnet_mask: IpAddress,
229    pub dhcp_discover: PxeBaseCodePacket,
230    pub dhcp_ack: PxeBaseCodePacket,
231    pub proxy_offer: PxeBaseCodePacket,
232    pub pxe_discover: PxeBaseCodePacket,
233    pub pxe_reply: PxeBaseCodePacket,
234    pub pxe_bis_reply: PxeBaseCodePacket,
235    pub ip_filter: PxeBaseCodeIpFilter,
236    pub arp_cache_entries: u32,
237    pub arp_cache: [PxeBaseCodeArpEntry; 8],
238    pub route_table_entries: u32,
239    pub route_table: [PxeBaseCodeRouteEntry; 8],
240    pub icmp_error: PxeBaseCodeIcmpError,
241    pub tftp_error: PxeBaseCodeTftpError,
242}
243
244#[derive(Clone, Copy)]
245#[repr(C)]
246pub union PxeBaseCodePacket {
247    pub raw: [u8; 1472],
248    pub dhcpv4: PxeBaseCodeDhcpV4Packet,
249    pub dhcpv6: PxeBaseCodeDhcpV6Packet,
250}
251
252impl Debug for PxeBaseCodePacket {
253    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
254        f.debug_struct("PxeBaseCodePacket").finish()
255    }
256}
257
258#[derive(Clone, Copy, Debug)]
259#[repr(C)]
260pub struct PxeBaseCodeDhcpV4Packet {
261    pub bootp_opcode: u8,
262    pub bootp_hw_type: u8,
263    pub bootp_hw_addr_len: u8,
264    pub bootp_gate_hops: u8,
265    pub bootp_ident: u32,
266    pub bootp_seconds: u16,
267    pub bootp_flags: u16,
268    pub bootp_ci_addr: [u8; 4],
269    pub bootp_yi_addr: [u8; 4],
270    pub bootp_si_addr: [u8; 4],
271    pub bootp_gi_addr: [u8; 4],
272    pub bootp_hw_addr: [u8; 16],
273    pub bootp_srv_name: [u8; 64],
274    pub bootp_boot_file: [u8; 128],
275    pub dhcp_magik: u32,
276    pub dhcp_options: [u8; 56],
277}
278
279#[derive(Clone, Copy, Debug)]
280#[repr(C)]
281pub struct PxeBaseCodeDhcpV6Packet {
282    pub message_type: u8,
283    pub transaction_id: [u8; 3],
284    pub dhcp_options: [u8; 1024],
285}
286
287#[derive(Clone, Copy, Debug)]
288#[repr(C)]
289pub struct PxeBaseCodeIpFilter {
290    pub filters: PxeBaseCodeIpFilterFlags,
291    pub ip_cnt: u8,
292    pub reserved: u16,
293    pub ip_list: [IpAddress; 8],
294}
295
296bitflags! {
297    /// IP receive filters.
298    #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
299    #[repr(transparent)]
300    pub struct PxeBaseCodeIpFilterFlags: u8 {
301        /// Enable the Station IP address.
302        const STATION_IP = 0x01;
303
304        /// Enable IPv4 broadcast addresses.
305        const BROADCAST = 0x02;
306
307        /// Enable all addresses.
308        const PROMISCUOUS = 0x04;
309
310        /// Enable all multicast addresses.
311        const PROMISCUOUS_MULTICAST = 0x08;
312    }
313}
314
315#[derive(Clone, Copy, Debug)]
316#[repr(C)]
317pub struct PxeBaseCodeArpEntry {
318    pub ip_addr: IpAddress,
319    pub mac_addr: MacAddress,
320}
321
322#[derive(Clone, Copy, Debug)]
323#[repr(C)]
324pub struct PxeBaseCodeRouteEntry {
325    pub ip_addr: IpAddress,
326    pub subnet_mask: IpAddress,
327    pub gw_addr: IpAddress,
328}
329
330#[derive(Clone, Debug)]
331#[repr(C)]
332pub struct PxeBaseCodeIcmpError {
333    pub ty: u8,
334    pub code: u8,
335    pub checksum: u16,
336    pub u: PxeBaseCodeIcmpErrorUnion,
337    pub data: [u8; 494],
338}
339
340/// In the C API, this is an anonymous union inside the definition of
341/// `EFI_PXE_BASE_CODE_ICMP_ERROR`.
342#[derive(Clone, Copy)]
343#[repr(C)]
344pub union PxeBaseCodeIcmpErrorUnion {
345    pub reserved: u32,
346    pub mtu: u32,
347    pub pointer: u32,
348    pub echo: PxeBaseCodeIcmpErrorEcho,
349}
350
351impl Debug for PxeBaseCodeIcmpErrorUnion {
352    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
353        f.debug_struct("PxeBaseCodeIcmpErrorUnion").finish()
354    }
355}
356
357/// In the C API, this is an anonymous struct inside the definition of
358/// `EFI_PXE_BASE_CODE_ICMP_ERROR`.
359#[derive(Clone, Copy, Debug)]
360#[repr(C)]
361pub struct PxeBaseCodeIcmpErrorEcho {
362    pub identifier: u16,
363    pub sequence: u16,
364}
365
366#[derive(Clone, Debug)]
367#[repr(C)]
368pub struct PxeBaseCodeTftpError {
369    pub error_code: u8,
370    pub error_string: [Char8; 127],
371}