uefi_raw/protocol/device_path.rs
1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3//! The UEFI device path protocol, i.e., UEFI device paths.
4//!
5//! This module provides (generated) ABI-compatible bindings to all known device
6//! path node types.
7//!
8//! # Terminology: Device Paths, Device Path Instances, and Device Path Nodes
9//! An open UEFI device path [protocol], also called _device path_, is a
10//! flexible and structured sequence of binary nodes that describes a route from
11//! the UEFI root to a particular device, controller, or file.
12//!
13//! An entire device path can be made up of multiple device path instances,
14//! and each instance is made up of multiple device path nodes. A device path
15//! _may_ contain multiple device-path instances separated by [`END_INSTANCE`]
16//! nodes, but typical paths contain only a single instance (in which case no
17//! [`END_INSTANCE`] node is needed). The entire device path is terminated with
18//! an [`END_ENTIRE`] node.
19//!
20//! Each node represents a step in the path: PCI device, partition, filesystem,
21//! file path, etc. Each node represents a step in the path: PCI device,
22//! partition, filesystem, file path, etc.
23//!
24//! Example of what a device path containing two instances (each comprised of
25//! three nodes) might look like:
26//!
27//! ```text
28//! ┌──────┬──────┬──────────────╥───────┬──────────┬────────────┐
29//! │ ACPI │ PCI │ END_INSTANCE ║ CDROM │ FILEPATH │ END_ENTIRE │
30//! └──────┴──────┴──────────────╨───────┴──────────┴────────────┘
31//! ↑ ↑ ↑ ↑ ↑ ↑ ↑
32//! ├─Node─╨─Node─╨─────Node─────╨─Node──╨───Node───╨────Node────┤
33//! ↑ ↑ ↑
34//! ├─── DevicePathInstance ─────╨────── DevicePathInstance ─────┤
35//! │ │
36//! └──────────────────── Entire DevicePath ─────────────────────┘
37//! ```
38//!
39//! [`END_ENTIRE`]: DeviceSubType::END_ENTIRE
40//! [`END_INSTANCE`]: DeviceSubType::END_INSTANCE
41//! [protocol]: crate::protocol
42
43mod device_path_gen;
44
45use crate::{Boolean, Char16, Guid, guid, newtype_enum};
46
47pub use device_path_gen::{acpi, bios_boot_spec, end, hardware, media, messaging};
48
49/// Device path protocol.
50///
51/// Note that the fields in this struct define the fixed header at the start of
52/// each node; a device path is typically larger than these four bytes.
53///
54/// See the [module-level documentation] for more details.
55///
56/// [module-level documentation]: self
57#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
58#[repr(C)]
59pub struct DevicePathProtocol {
60 pub major_type: DeviceType,
61 pub sub_type: DeviceSubType,
62 /// Total length of the type including the fixed header as u16 in LE order.
63 pub length: [u8; 2],
64 // followed by payload (dynamically sized)
65}
66
67impl DevicePathProtocol {
68 pub const GUID: Guid = guid!("09576e91-6d3f-11d2-8e39-00a0c969723b");
69
70 /// Returns the total length of the device path node.
71 #[must_use]
72 pub const fn length(&self) -> u16 {
73 u16::from_le_bytes(self.length)
74 }
75}
76
77newtype_enum! {
78/// Type identifier for a device path node.
79pub enum DeviceType: u8 => {
80 /// Hardware Device Path.
81 ///
82 /// This Device Path defines how a device is attached to the resource domain of a system, where resource domain is
83 /// simply the shared memory, memory mapped I/ O, and I/O space of the system.
84 HARDWARE = 0x01,
85 /// ACPI Device Path.
86 ///
87 /// This Device Path is used to describe devices whose enumeration is not described in an industry-standard fashion.
88 /// These devices must be described using ACPI AML in the ACPI namespace; this Device Path is a linkage to the ACPI
89 /// namespace.
90 ACPI = 0x02,
91 /// Messaging Device Path.
92 ///
93 /// This Device Path is used to describe the connection of devices outside the resource domain of the system. This
94 /// Device Path can describe physical messaging information such as a SCSI ID, or abstract information such as
95 /// networking protocol IP addresses.
96 MESSAGING = 0x03,
97 /// Media Device Path.
98 ///
99 /// This Device Path is used to describe the portion of a medium that is being abstracted by a boot service.
100 /// For example, a Media Device Path could define which partition on a hard drive was being used.
101 MEDIA = 0x04,
102 /// BIOS Boot Specification Device Path.
103 ///
104 /// This Device Path is used to point to boot legacy operating systems; it is based on the BIOS Boot Specification
105 /// Version 1.01.
106 BIOS_BOOT_SPEC = 0x05,
107 /// End of Hardware Device Path.
108 ///
109 /// Depending on the Sub-Type, this Device Path node is used to indicate the end of the Device Path instance or
110 /// Device Path structure.
111 END = 0x7F,
112}}
113
114/// Sub-type identifier for a device path node.
115#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
116#[repr(transparent)]
117pub struct DeviceSubType(pub u8);
118
119impl DeviceSubType {
120 /// PCI Device Path.
121 pub const HARDWARE_PCI: Self = Self(1);
122 /// PCCARD Device Path.
123 pub const HARDWARE_PCCARD: Self = Self(2);
124 /// Memory-mapped Device Path.
125 pub const HARDWARE_MEMORY_MAPPED: Self = Self(3);
126 /// Vendor-Defined Device Path.
127 pub const HARDWARE_VENDOR: Self = Self(4);
128 /// Controller Device Path.
129 pub const HARDWARE_CONTROLLER: Self = Self(5);
130 /// BMC Device Path.
131 pub const HARDWARE_BMC: Self = Self(6);
132
133 /// ACPI Device Path.
134 pub const ACPI: Self = Self(1);
135 /// Expanded ACPI Device Path.
136 pub const ACPI_EXPANDED: Self = Self(2);
137 /// ACPI _ADR Device Path.
138 pub const ACPI_ADR: Self = Self(3);
139 /// NVDIMM Device Path.
140 pub const ACPI_NVDIMM: Self = Self(4);
141
142 /// ATAPI Device Path.
143 pub const MESSAGING_ATAPI: Self = Self(1);
144 /// SCSI Device Path.
145 pub const MESSAGING_SCSI: Self = Self(2);
146 /// Fibre Channel Device Path.
147 pub const MESSAGING_FIBRE_CHANNEL: Self = Self(3);
148 /// 1394 Device Path.
149 pub const MESSAGING_1394: Self = Self(4);
150 /// USB Device Path.
151 pub const MESSAGING_USB: Self = Self(5);
152 /// I2O Device Path.
153 pub const MESSAGING_I2O: Self = Self(6);
154 /// Infiniband Device Path.
155 pub const MESSAGING_INFINIBAND: Self = Self(9);
156 /// Vendor-Defined Device Path.
157 pub const MESSAGING_VENDOR: Self = Self(10);
158 /// MAC Address Device Path.
159 pub const MESSAGING_MAC_ADDRESS: Self = Self(11);
160 /// IPV4 Device Path.
161 pub const MESSAGING_IPV4: Self = Self(12);
162 /// IPV6 Device Path.
163 pub const MESSAGING_IPV6: Self = Self(13);
164 /// UART Device Path.
165 pub const MESSAGING_UART: Self = Self(14);
166 /// USB Class Device Path.
167 pub const MESSAGING_USB_CLASS: Self = Self(15);
168 /// USB WWID Device Path.
169 pub const MESSAGING_USB_WWID: Self = Self(16);
170 /// Device Logical Unit.
171 pub const MESSAGING_DEVICE_LOGICAL_UNIT: Self = Self(17);
172 /// SATA Device Path.
173 pub const MESSAGING_SATA: Self = Self(18);
174 /// iSCSI Device Path node (base information).
175 pub const MESSAGING_ISCSI: Self = Self(19);
176 /// VLAN Device Path node.
177 pub const MESSAGING_VLAN: Self = Self(20);
178 /// Fibre Channel Ex Device Path.
179 pub const MESSAGING_FIBRE_CHANNEL_EX: Self = Self(21);
180 /// Serial Attached SCSI (SAS) Ex Device Path.
181 pub const MESSAGING_SCSI_SAS_EX: Self = Self(22);
182 /// NVM Express Namespace Device Path.
183 pub const MESSAGING_NVME_NAMESPACE: Self = Self(23);
184 /// Uniform Resource Identifiers (URI) Device Path.
185 pub const MESSAGING_URI: Self = Self(24);
186 /// UFS Device Path.
187 pub const MESSAGING_UFS: Self = Self(25);
188 /// SD (Secure Digital) Device Path.
189 pub const MESSAGING_SD: Self = Self(26);
190 /// Bluetooth Device Path.
191 pub const MESSAGING_BLUETOOTH: Self = Self(27);
192 /// Wi-Fi Device Path.
193 pub const MESSAGING_WIFI: Self = Self(28);
194 /// eMMC (Embedded Multi-Media Card) Device Path.
195 pub const MESSAGING_EMMC: Self = Self(29);
196 /// BluetoothLE Device Path.
197 pub const MESSAGING_BLUETOOTH_LE: Self = Self(30);
198 /// DNS Device Path.
199 pub const MESSAGING_DNS: Self = Self(31);
200 /// NVDIMM Namespace Device Path.
201 pub const MESSAGING_NVDIMM_NAMESPACE: Self = Self(32);
202 /// REST Service Device Path.
203 pub const MESSAGING_REST_SERVICE: Self = Self(33);
204 /// NVME over Fabric (NVMe-oF) Namespace Device Path.
205 pub const MESSAGING_NVME_OF_NAMESPACE: Self = Self(34);
206
207 /// Hard Drive Media Device Path.
208 pub const MEDIA_HARD_DRIVE: Self = Self(1);
209 /// CD-ROM Media Device Path.
210 pub const MEDIA_CD_ROM: Self = Self(2);
211 /// Vendor-Defined Media Device Path.
212 pub const MEDIA_VENDOR: Self = Self(3);
213 /// File Path Media Device Path.
214 pub const MEDIA_FILE_PATH: Self = Self(4);
215 /// Media Protocol Device Path.
216 pub const MEDIA_PROTOCOL: Self = Self(5);
217 /// PIWG Firmware File.
218 pub const MEDIA_PIWG_FIRMWARE_FILE: Self = Self(6);
219 /// PIWG Firmware Volume.
220 pub const MEDIA_PIWG_FIRMWARE_VOLUME: Self = Self(7);
221 /// Relative Offset Range.
222 pub const MEDIA_RELATIVE_OFFSET_RANGE: Self = Self(8);
223 /// RAM Disk Device Path.
224 pub const MEDIA_RAM_DISK: Self = Self(9);
225
226 /// BIOS Boot Specification Device Path.
227 pub const BIOS_BOOT_SPECIFICATION: Self = Self(1);
228
229 /// End this instance of a Device Path and start a new one.
230 pub const END_INSTANCE: Self = Self(0x01);
231 /// End entire Device Path.
232 pub const END_ENTIRE: Self = Self(0xff);
233}
234
235#[derive(Debug)]
236#[repr(C)]
237pub struct DevicePathToTextProtocol {
238 pub convert_device_node_to_text: unsafe extern "efiapi" fn(
239 device_node: *const DevicePathProtocol,
240 display_only: Boolean,
241 allow_shortcuts: Boolean,
242 ) -> *const Char16,
243 pub convert_device_path_to_text: unsafe extern "efiapi" fn(
244 device_path: *const DevicePathProtocol,
245 display_only: Boolean,
246 allow_shortcuts: Boolean,
247 ) -> *const Char16,
248}
249
250impl DevicePathToTextProtocol {
251 pub const GUID: Guid = guid!("8b843e20-8132-4852-90cc-551a4e4a7f1c");
252}
253
254#[derive(Debug)]
255#[repr(C)]
256pub struct DevicePathFromTextProtocol {
257 pub convert_text_to_device_node:
258 unsafe extern "efiapi" fn(text_device_node: *const Char16) -> *const DevicePathProtocol,
259 pub convert_text_to_device_path:
260 unsafe extern "efiapi" fn(text_device_path: *const Char16) -> *const DevicePathProtocol,
261}
262
263impl DevicePathFromTextProtocol {
264 pub const GUID: Guid = guid!("05c99a21-c70f-4ad2-8a5f-35df3343f51e");
265}
266
267#[derive(Debug)]
268#[repr(C)]
269pub struct DevicePathUtilitiesProtocol {
270 pub get_device_path_size:
271 unsafe extern "efiapi" fn(device_path: *const DevicePathProtocol) -> usize,
272 pub duplicate_device_path: unsafe extern "efiapi" fn(
273 device_path: *const DevicePathProtocol,
274 ) -> *const DevicePathProtocol,
275 pub append_device_path: unsafe extern "efiapi" fn(
276 src1: *const DevicePathProtocol,
277 src2: *const DevicePathProtocol,
278 ) -> *const DevicePathProtocol,
279 pub append_device_node: unsafe extern "efiapi" fn(
280 device_path: *const DevicePathProtocol,
281 device_node: *const DevicePathProtocol,
282 ) -> *const DevicePathProtocol,
283 pub append_device_path_instance: unsafe extern "efiapi" fn(
284 device_path: *const DevicePathProtocol,
285 device_path_instance: *const DevicePathProtocol,
286 ) -> *const DevicePathProtocol,
287 pub get_next_device_path_instance: unsafe extern "efiapi" fn(
288 device_path_instance: *mut *const DevicePathProtocol,
289 device_path_instance_size: *mut usize,
290 ) -> *const DevicePathProtocol,
291 pub is_device_path_multi_instance:
292 unsafe extern "efiapi" fn(device_path: *const DevicePathProtocol) -> Boolean,
293 pub create_device_node: unsafe extern "efiapi" fn(
294 node_type: DeviceType,
295 node_sub_type: DeviceSubType,
296 node_length: u16,
297 ) -> *const DevicePathProtocol,
298}
299
300impl DevicePathUtilitiesProtocol {
301 pub const GUID: Guid = guid!("0379be4e-d706-437d-b037-edb82fb772a4");
302}
303
304#[cfg(test)]
305mod tests {
306 use super::*;
307
308 /// Test that ensures the struct is packed. Thus, we don't need to
309 /// explicitly specify `packed`.
310 #[test]
311 fn abi() {
312 assert_eq!(size_of::<DevicePathProtocol>(), 4);
313 assert_eq!(align_of::<DevicePathProtocol>(), 1);
314 }
315}