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}