• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // DO NOT EDIT
2 //
3 // This file was automatically generated with:
4 // `cargo xtask gen-code`
5 //
6 // See `/xtask/src/device_path/README.md` for more details.
7 #![allow(clippy::missing_const_for_fn)]
8 
9 use crate::data_types::UnalignedSlice;
10 use crate::mem::memory_map::MemoryType;
11 use crate::polyfill::maybe_uninit_slice_as_mut_ptr;
12 use crate::proto::device_path::{
13     self, DevicePathHeader, DevicePathNode, DeviceSubType, DeviceType, NodeConversionError,
14 };
15 use crate::proto::network::IpAddress;
16 use crate::{guid, Guid};
17 use bitflags::bitflags;
18 use core::mem::{size_of, size_of_val};
19 use core::ptr::addr_of;
20 use core::{fmt, slice};
21 use ptr_meta::{Pointee, PtrExt};
22 /// Device path nodes for [`DeviceType::END`].
23 pub mod end {
24     use super::*;
25     /// Node that terminates a [`DevicePathInstance`].
26     ///
27     /// [`DevicePathInstance`]: device_path::DevicePathInstance
28     #[repr(C, packed)]
29     pub struct Instance {
30         pub(super) header: DevicePathHeader,
31     }
32 
33     impl Instance {}
34 
35     impl fmt::Debug for Instance {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result36         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37             f.debug_struct("Instance").finish()
38         }
39     }
40 
41     impl TryFrom<&DevicePathNode> for &Instance {
42         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>43         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
44             if size_of_val(node) != size_of::<Instance>() {
45                 return Err(NodeConversionError::InvalidLength);
46             }
47 
48             let node: *const DevicePathNode = node;
49             let node: *const Instance = node.cast();
50             Ok(unsafe { &*node })
51         }
52     }
53 
54     /// Node that terminates an entire [`DevicePath`].
55     ///
56     /// [`DevicePath`]: device_path::DevicePath
57     #[repr(C, packed)]
58     pub struct Entire {
59         pub(super) header: DevicePathHeader,
60     }
61 
62     impl Entire {}
63 
64     impl fmt::Debug for Entire {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result65         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66             f.debug_struct("Entire").finish()
67         }
68     }
69 
70     impl TryFrom<&DevicePathNode> for &Entire {
71         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>72         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
73             if size_of_val(node) != size_of::<Entire>() {
74                 return Err(NodeConversionError::InvalidLength);
75             }
76 
77             let node: *const DevicePathNode = node;
78             let node: *const Entire = node.cast();
79             Ok(unsafe { &*node })
80         }
81     }
82 }
83 
84 /// Device path nodes for [`DeviceType::HARDWARE`].
85 pub mod hardware {
86     use super::*;
87     /// PCI hardware device path node.
88     #[repr(C, packed)]
89     pub struct Pci {
90         pub(super) header: DevicePathHeader,
91         pub(super) function: u8,
92         pub(super) device: u8,
93     }
94 
95     impl Pci {
96         /// PCI function number.
97         #[must_use]
function(&self) -> u898         pub fn function(&self) -> u8 {
99             self.function
100         }
101 
102         /// PCI device number.
103         #[must_use]
device(&self) -> u8104         pub fn device(&self) -> u8 {
105             self.device
106         }
107     }
108 
109     impl fmt::Debug for Pci {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result110         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
111             f.debug_struct("Pci")
112                 .field("function", &{ self.function })
113                 .field("device", &{ self.device })
114                 .finish()
115         }
116     }
117 
118     impl TryFrom<&DevicePathNode> for &Pci {
119         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>120         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
121             if size_of_val(node) != size_of::<Pci>() {
122                 return Err(NodeConversionError::InvalidLength);
123             }
124 
125             let node: *const DevicePathNode = node;
126             let node: *const Pci = node.cast();
127             Ok(unsafe { &*node })
128         }
129     }
130 
131     /// PCCARD hardware device path node.
132     #[repr(C, packed)]
133     pub struct Pccard {
134         pub(super) header: DevicePathHeader,
135         pub(super) function: u8,
136     }
137 
138     impl Pccard {
139         /// Function number starting from 0.
140         #[must_use]
function(&self) -> u8141         pub fn function(&self) -> u8 {
142             self.function
143         }
144     }
145 
146     impl fmt::Debug for Pccard {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result147         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
148             f.debug_struct("Pccard")
149                 .field("function", &{ self.function })
150                 .finish()
151         }
152     }
153 
154     impl TryFrom<&DevicePathNode> for &Pccard {
155         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>156         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
157             if size_of_val(node) != size_of::<Pccard>() {
158                 return Err(NodeConversionError::InvalidLength);
159             }
160 
161             let node: *const DevicePathNode = node;
162             let node: *const Pccard = node.cast();
163             Ok(unsafe { &*node })
164         }
165     }
166 
167     /// Memory mapped hardware device path node.
168     #[repr(C, packed)]
169     pub struct MemoryMapped {
170         pub(super) header: DevicePathHeader,
171         pub(super) memory_type: MemoryType,
172         pub(super) start_address: u64,
173         pub(super) end_address: u64,
174     }
175 
176     impl MemoryMapped {
177         /// Memory type.
178         #[must_use]
memory_type(&self) -> MemoryType179         pub fn memory_type(&self) -> MemoryType {
180             self.memory_type
181         }
182 
183         /// Starting memory address.
184         #[must_use]
start_address(&self) -> u64185         pub fn start_address(&self) -> u64 {
186             self.start_address
187         }
188 
189         /// Ending memory address.
190         #[must_use]
end_address(&self) -> u64191         pub fn end_address(&self) -> u64 {
192             self.end_address
193         }
194     }
195 
196     impl fmt::Debug for MemoryMapped {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result197         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
198             f.debug_struct("MemoryMapped")
199                 .field("memory_type", &{ self.memory_type })
200                 .field("start_address", &{ self.start_address })
201                 .field("end_address", &{ self.end_address })
202                 .finish()
203         }
204     }
205 
206     impl TryFrom<&DevicePathNode> for &MemoryMapped {
207         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>208         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
209             if size_of_val(node) != size_of::<MemoryMapped>() {
210                 return Err(NodeConversionError::InvalidLength);
211             }
212 
213             let node: *const DevicePathNode = node;
214             let node: *const MemoryMapped = node.cast();
215             Ok(unsafe { &*node })
216         }
217     }
218 
219     /// Vendor-defined hardware device path node.
220     #[repr(C, packed)]
221     #[derive(Pointee)]
222     pub struct Vendor {
223         pub(super) header: DevicePathHeader,
224         pub(super) vendor_guid: Guid,
225         pub(super) vendor_defined_data: [u8],
226     }
227 
228     impl Vendor {
229         /// Vendor-assigned GUID that defines the data that follows.
230         #[must_use]
vendor_guid(&self) -> Guid231         pub fn vendor_guid(&self) -> Guid {
232             self.vendor_guid
233         }
234 
235         /// Vendor-defined data.
236         #[must_use]
vendor_defined_data(&self) -> &[u8]237         pub fn vendor_defined_data(&self) -> &[u8] {
238             &self.vendor_defined_data
239         }
240     }
241 
242     impl fmt::Debug for Vendor {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result243         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
244             f.debug_struct("Vendor")
245                 .field("vendor_guid", &{ self.vendor_guid })
246                 .field("vendor_defined_data", {
247                     let ptr = addr_of!(self.vendor_defined_data);
248                     let (ptr, len) = PtrExt::to_raw_parts(ptr);
249                     let byte_len = size_of::<u8>() * len;
250                     unsafe { &slice::from_raw_parts(ptr.cast::<u8>(), byte_len) }
251                 })
252                 .finish()
253         }
254     }
255 
256     impl TryFrom<&DevicePathNode> for &Vendor {
257         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>258         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
259             let static_size = 20usize;
260             let dst_size = size_of_val(node)
261                 .checked_sub(static_size)
262                 .ok_or(NodeConversionError::InvalidLength)?;
263             let elem_size = size_of::<u8>();
264             if dst_size % elem_size != 0 {
265                 return Err(NodeConversionError::InvalidLength);
266             }
267 
268             let node: *const DevicePathNode = node;
269             let node: *const Vendor = ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size);
270             Ok(unsafe { &*node })
271         }
272     }
273 
274     /// Controller hardware device path node.
275     #[repr(C, packed)]
276     pub struct Controller {
277         pub(super) header: DevicePathHeader,
278         pub(super) controller_number: u32,
279     }
280 
281     impl Controller {
282         /// Controller number.
283         #[must_use]
controller_number(&self) -> u32284         pub fn controller_number(&self) -> u32 {
285             self.controller_number
286         }
287     }
288 
289     impl fmt::Debug for Controller {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result290         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
291             f.debug_struct("Controller")
292                 .field("controller_number", &{ self.controller_number })
293                 .finish()
294         }
295     }
296 
297     impl TryFrom<&DevicePathNode> for &Controller {
298         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>299         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
300             if size_of_val(node) != size_of::<Controller>() {
301                 return Err(NodeConversionError::InvalidLength);
302             }
303 
304             let node: *const DevicePathNode = node;
305             let node: *const Controller = node.cast();
306             Ok(unsafe { &*node })
307         }
308     }
309 
310     /// Baseboard Management Controller (BMC) host interface hardware
311     /// device path node.
312     #[repr(C, packed)]
313     pub struct Bmc {
314         pub(super) header: DevicePathHeader,
315         pub(super) interface_type: device_path::hardware::BmcInterfaceType,
316         pub(super) base_address: u64,
317     }
318 
319     impl Bmc {
320         /// Host interface type.
321         #[must_use]
interface_type(&self) -> device_path::hardware::BmcInterfaceType322         pub fn interface_type(&self) -> device_path::hardware::BmcInterfaceType {
323             self.interface_type
324         }
325 
326         /// Base address of the BMC. If the least-significant bit of the
327         /// field is a 1 then the address is in I/O space, otherwise the
328         /// address is memory-mapped.
329         #[must_use]
base_address(&self) -> u64330         pub fn base_address(&self) -> u64 {
331             self.base_address
332         }
333     }
334 
335     impl fmt::Debug for Bmc {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result336         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
337             f.debug_struct("Bmc")
338                 .field("interface_type", &{ self.interface_type })
339                 .field("base_address", &{ self.base_address })
340                 .finish()
341         }
342     }
343 
344     impl TryFrom<&DevicePathNode> for &Bmc {
345         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>346         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
347             if size_of_val(node) != size_of::<Bmc>() {
348                 return Err(NodeConversionError::InvalidLength);
349             }
350 
351             let node: *const DevicePathNode = node;
352             let node: *const Bmc = node.cast();
353             Ok(unsafe { &*node })
354         }
355     }
356 
357     newtype_enum! { # [doc = " Baseboard Management Controller (BMC) host interface type."] pub enum BmcInterfaceType : u8 => { # [doc = " Unknown."] UNKNOWN = 0x00 , # [doc = " Keyboard controller style."] KEYBOARD_CONTROLLER_STYLE = 0x01 , # [doc = " Server management interface chip."] SERVER_MANAGEMENT_INTERFACE_CHIP = 0x02 , # [doc = " Block transfer."] BLOCK_TRANSFER = 0x03 , }
358 
359     }
360 }
361 
362 /// Device path nodes for [`DeviceType::ACPI`].
363 pub mod acpi {
364     use super::*;
365     /// ACPI device path node.
366     #[repr(C, packed)]
367     pub struct Acpi {
368         pub(super) header: DevicePathHeader,
369         pub(super) hid: u32,
370         pub(super) uid: u32,
371     }
372 
373     impl Acpi {
374         /// Device's PnP hardware ID stored in a numeric 32-bit
375         /// compressed EISA-type ID.
376         #[must_use]
hid(&self) -> u32377         pub fn hid(&self) -> u32 {
378             self.hid
379         }
380 
381         /// Unique ID that is required by ACPI if two devices have the
382         /// same HID.
383         #[must_use]
uid(&self) -> u32384         pub fn uid(&self) -> u32 {
385             self.uid
386         }
387     }
388 
389     impl fmt::Debug for Acpi {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result390         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
391             f.debug_struct("Acpi")
392                 .field("hid", &{ self.hid })
393                 .field("uid", &{ self.uid })
394                 .finish()
395         }
396     }
397 
398     impl TryFrom<&DevicePathNode> for &Acpi {
399         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>400         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
401             if size_of_val(node) != size_of::<Acpi>() {
402                 return Err(NodeConversionError::InvalidLength);
403             }
404 
405             let node: *const DevicePathNode = node;
406             let node: *const Acpi = node.cast();
407             Ok(unsafe { &*node })
408         }
409     }
410 
411     /// Expanded ACPI device path node.
412     #[repr(C, packed)]
413     #[derive(Pointee)]
414     pub struct Expanded {
415         pub(super) header: DevicePathHeader,
416         pub(super) hid: u32,
417         pub(super) uid: u32,
418         pub(super) cid: u32,
419         pub(super) data: [u8],
420     }
421 
422     impl Expanded {
423         /// Device's PnP hardware ID stored in a numeric 32-bit compressed
424         /// EISA-type ID.
425         #[must_use]
hid(&self) -> u32426         pub fn hid(&self) -> u32 {
427             self.hid
428         }
429 
430         /// Unique ID that is required by ACPI if two devices have the
431         /// same HID.
432         #[must_use]
uid(&self) -> u32433         pub fn uid(&self) -> u32 {
434             self.uid
435         }
436 
437         /// Device's compatible PnP hardware ID stored in a numeric 32-bit
438         /// compressed EISA-type ID.
439         #[must_use]
cid(&self) -> u32440         pub fn cid(&self) -> u32 {
441             self.cid
442         }
443 
444         /// Device's PnP hardware ID stored as a null-terminated ASCII
445         /// string. This value must match the corresponding HID in the
446         /// ACPI name space. If the length of this string not including
447         /// the null-terminator is 0, then the numeric HID is used.
448         #[must_use]
hid_str(&self) -> &[u8]449         pub fn hid_str(&self) -> &[u8] {
450             self.get_hid_str()
451         }
452 
453         /// Unique ID that is required by ACPI if two devices have the
454         /// same HID. This value is stored as a null-terminated ASCII
455         /// string. If the length of this string not including the
456         /// null-terminator is 0, then the numeric UID is used.
457         #[must_use]
uid_str(&self) -> &[u8]458         pub fn uid_str(&self) -> &[u8] {
459             self.get_uid_str()
460         }
461 
462         /// Device's compatible PnP hardware ID stored as a
463         /// null-terminated ASCII string. If the length of this string
464         /// not including the null-terminator is 0, then the numeric CID
465         /// is used.
466         #[must_use]
cid_str(&self) -> &[u8]467         pub fn cid_str(&self) -> &[u8] {
468             self.get_cid_str()
469         }
470     }
471 
472     impl fmt::Debug for Expanded {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result473         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
474             f.debug_struct("Expanded")
475                 .field("hid", &{ self.hid })
476                 .field("uid", &{ self.uid })
477                 .field("cid", &{ self.cid })
478                 .field("data", &&self.data)
479                 .finish()
480         }
481     }
482 
483     impl TryFrom<&DevicePathNode> for &Expanded {
484         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>485         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
486             let static_size = 16usize;
487             let dst_size = size_of_val(node)
488                 .checked_sub(static_size)
489                 .ok_or(NodeConversionError::InvalidLength)?;
490             let elem_size = size_of::<u8>();
491             if dst_size % elem_size != 0 {
492                 return Err(NodeConversionError::InvalidLength);
493             }
494 
495             let node: *const DevicePathNode = node;
496             let node: *const Expanded = ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size);
497             Ok(unsafe { &*node })
498         }
499     }
500 
501     /// ADR ACPI device path node.
502     #[repr(C, packed)]
503     #[derive(Pointee)]
504     pub struct Adr {
505         pub(super) header: DevicePathHeader,
506         pub(super) adr: [u32],
507     }
508 
509     impl Adr {
510         /// ADR values. For video output devices the value of this field
511         /// comes from Table B-2 ACPI 3.0 specification. At least one
512         /// ADR value is required.
513         #[must_use]
adr(&self) -> UnalignedSlice<u32>514         pub fn adr(&self) -> UnalignedSlice<u32> {
515             let ptr: *const [u32] = addr_of!(self.adr);
516             let (ptr, len): (*const (), usize) = PtrExt::to_raw_parts(ptr);
517             unsafe { UnalignedSlice::new(ptr.cast::<u32>(), len) }
518         }
519     }
520 
521     impl fmt::Debug for Adr {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result522         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
523             f.debug_struct("Adr")
524                 .field("adr", {
525                     let ptr = addr_of!(self.adr);
526                     let (ptr, len) = PtrExt::to_raw_parts(ptr);
527                     let byte_len = size_of::<u32>() * len;
528                     unsafe { &slice::from_raw_parts(ptr.cast::<u8>(), byte_len) }
529                 })
530                 .finish()
531         }
532     }
533 
534     impl TryFrom<&DevicePathNode> for &Adr {
535         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>536         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
537             let static_size = 4usize;
538             let dst_size = size_of_val(node)
539                 .checked_sub(static_size)
540                 .ok_or(NodeConversionError::InvalidLength)?;
541             let elem_size = size_of::<u32>();
542             if dst_size % elem_size != 0 {
543                 return Err(NodeConversionError::InvalidLength);
544             }
545 
546             let node: *const DevicePathNode = node;
547             let node: *const Adr = ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size);
548             Ok(unsafe { &*node })
549         }
550     }
551 
552     /// NVDIMM ACPI device path node.
553     #[repr(C, packed)]
554     pub struct Nvdimm {
555         pub(super) header: DevicePathHeader,
556         pub(super) nfit_device_handle: u32,
557     }
558 
559     impl Nvdimm {
560         /// NFIT device handle.
561         #[must_use]
nfit_device_handle(&self) -> u32562         pub fn nfit_device_handle(&self) -> u32 {
563             self.nfit_device_handle
564         }
565     }
566 
567     impl fmt::Debug for Nvdimm {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result568         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
569             f.debug_struct("Nvdimm")
570                 .field("nfit_device_handle", &{ self.nfit_device_handle })
571                 .finish()
572         }
573     }
574 
575     impl TryFrom<&DevicePathNode> for &Nvdimm {
576         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>577         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
578             if size_of_val(node) != size_of::<Nvdimm>() {
579                 return Err(NodeConversionError::InvalidLength);
580             }
581 
582             let node: *const DevicePathNode = node;
583             let node: *const Nvdimm = node.cast();
584             Ok(unsafe { &*node })
585         }
586     }
587 
588     impl Expanded {
get_hid_str(&self) -> &[u8]589         fn get_hid_str(&self) -> &[u8] {
590             get_acpi_expanded_substr(&self.data, 0)
591         }
592 
get_uid_str(&self) -> &[u8]593         fn get_uid_str(&self) -> &[u8] {
594             get_acpi_expanded_substr(&self.data, 1)
595         }
596 
get_cid_str(&self) -> &[u8]597         fn get_cid_str(&self) -> &[u8] {
598             get_acpi_expanded_substr(&self.data, 2)
599         }
600     }
601 
602     /// Get the indices of the three nulls in the combined hid/uid/cid
603     /// string. This never fails; if some nulls are missing then `None`
604     /// is returned for those indices. If more than three nulls are
605     /// present then the extra ones are ignored.
acpi_expanded_null_indices(data: &[u8]) -> [Option<usize>; 3]606     fn acpi_expanded_null_indices(data: &[u8]) -> [Option<usize>; 3] {
607         let mut iter = data
608             .iter()
609             .copied()
610             .enumerate()
611             .filter_map(|(index, byte)| if byte == 0 { Some(index) } else { None })
612             .fuse();
613         [iter.next(), iter.next(), iter.next()]
614     }
615 
616     /// Get the hid, uid, or cid string from the combined string. The
617     /// returned string includes the trailing null if possible; if the
618     /// substring was not properly null terminated then it ends at the
619     /// end of `data`.
620     ///
621     /// This never fails; if there aren't enough nulls in the input
622     /// string then an empty slice may be returned.
get_acpi_expanded_substr(data: &[u8], string_index: usize) -> &[u8]623     fn get_acpi_expanded_substr(data: &[u8], string_index: usize) -> &[u8] {
624         let [n0, n1, n2] = acpi_expanded_null_indices(data);
625         let mut start = data.len();
626         let mut end = start;
627         match string_index {
628             0 => {
629                 start = 0;
630                 if let Some(n0) = n0 {
631                     end = n0 + 1;
632                 }
633             }
634 
635             1 => {
636                 if let Some(n0) = n0 {
637                     start = n0 + 1;
638                     if let Some(n1) = n1 {
639                         end = n1 + 1;
640                     }
641                 }
642             }
643 
644             2 => {
645                 if let Some(n1) = n1 {
646                     start = n1 + 1;
647                     if let Some(n2) = n2 {
648                         end = n2 + 1;
649                     }
650                 }
651             }
652 
653             _ => {
654                 unreachable!("invalid string index")
655             }
656         }
657 
658         data.get(start..end).unwrap_or(&[])
659     }
660 
661     #[cfg(test)]
662     mod tests {
663         use super::*;
664         #[test]
test_get_acpi_expanded_substr()665         fn test_get_acpi_expanded_substr() {
666             let s = b"ab\0cd\0ef\0";
667             assert_eq!(get_acpi_expanded_substr(s, 0), b"ab\0");
668             assert_eq!(get_acpi_expanded_substr(s, 1), b"cd\0");
669             assert_eq!(get_acpi_expanded_substr(s, 2), b"ef\0");
670             let s = b"\0\0\0";
671             assert_eq!(get_acpi_expanded_substr(s, 0), b"\0");
672             assert_eq!(get_acpi_expanded_substr(s, 1), b"\0");
673             assert_eq!(get_acpi_expanded_substr(s, 2), b"\0");
674             let s = b"ab\0cd\0";
675             assert_eq!(get_acpi_expanded_substr(s, 0), b"ab\0");
676             assert_eq!(get_acpi_expanded_substr(s, 1), b"cd\0");
677             assert_eq!(get_acpi_expanded_substr(s, 2), b"");
678             let s = b"ab\0";
679             assert_eq!(get_acpi_expanded_substr(s, 0), b"ab\0");
680             assert_eq!(get_acpi_expanded_substr(s, 1), b"");
681             assert_eq!(get_acpi_expanded_substr(s, 2), b"");
682             let s = b"ab\0cd\0ef";
683             assert_eq!(get_acpi_expanded_substr(s, 0), b"ab\0");
684             assert_eq!(get_acpi_expanded_substr(s, 1), b"cd\0");
685             assert_eq!(get_acpi_expanded_substr(s, 2), b"ef");
686             let s = b"ab\0cd";
687             assert_eq!(get_acpi_expanded_substr(s, 0), b"ab\0");
688             assert_eq!(get_acpi_expanded_substr(s, 1), b"cd");
689             assert_eq!(get_acpi_expanded_substr(s, 2), b"");
690             let s = b"ab";
691             assert_eq!(get_acpi_expanded_substr(s, 0), b"ab");
692             assert_eq!(get_acpi_expanded_substr(s, 1), b"");
693             assert_eq!(get_acpi_expanded_substr(s, 2), b"");
694             let s = b"";
695             assert_eq!(get_acpi_expanded_substr(s, 0), b"");
696             assert_eq!(get_acpi_expanded_substr(s, 1), b"");
697             assert_eq!(get_acpi_expanded_substr(s, 2), b"");
698         }
699     }
700 }
701 
702 /// Device path nodes for [`DeviceType::MESSAGING`].
703 pub mod messaging {
704     use super::*;
705     /// ATAPI messaging device path node.
706     #[repr(C, packed)]
707     pub struct Atapi {
708         pub(super) header: DevicePathHeader,
709         pub(super) primary_secondary: device_path::messaging::PrimarySecondary,
710         pub(super) master_slave: device_path::messaging::MasterSlave,
711         pub(super) logical_unit_number: u16,
712     }
713 
714     impl Atapi {
715         /// Whether the ATAPI device is primary or secondary.
716         #[must_use]
primary_secondary(&self) -> device_path::messaging::PrimarySecondary717         pub fn primary_secondary(&self) -> device_path::messaging::PrimarySecondary {
718             self.primary_secondary
719         }
720 
721         /// Whether the ATAPI device is master or slave.
722         #[must_use]
master_slave(&self) -> device_path::messaging::MasterSlave723         pub fn master_slave(&self) -> device_path::messaging::MasterSlave {
724             self.master_slave
725         }
726 
727         /// Logical Unit Number (LUN).
728         #[must_use]
logical_unit_number(&self) -> u16729         pub fn logical_unit_number(&self) -> u16 {
730             self.logical_unit_number
731         }
732     }
733 
734     impl fmt::Debug for Atapi {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result735         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
736             f.debug_struct("Atapi")
737                 .field("primary_secondary", &{ self.primary_secondary })
738                 .field("master_slave", &{ self.master_slave })
739                 .field("logical_unit_number", &{ self.logical_unit_number })
740                 .finish()
741         }
742     }
743 
744     impl TryFrom<&DevicePathNode> for &Atapi {
745         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>746         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
747             if size_of_val(node) != size_of::<Atapi>() {
748                 return Err(NodeConversionError::InvalidLength);
749             }
750 
751             let node: *const DevicePathNode = node;
752             let node: *const Atapi = node.cast();
753             Ok(unsafe { &*node })
754         }
755     }
756 
757     /// SCSI messaging device path node.
758     #[repr(C, packed)]
759     pub struct Scsi {
760         pub(super) header: DevicePathHeader,
761         pub(super) target_id: u16,
762         pub(super) logical_unit_number: u16,
763     }
764 
765     impl Scsi {
766         /// Target ID on the SCSI bus.
767         #[must_use]
target_id(&self) -> u16768         pub fn target_id(&self) -> u16 {
769             self.target_id
770         }
771 
772         /// Logical Unit Number.
773         #[must_use]
logical_unit_number(&self) -> u16774         pub fn logical_unit_number(&self) -> u16 {
775             self.logical_unit_number
776         }
777     }
778 
779     impl fmt::Debug for Scsi {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result780         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
781             f.debug_struct("Scsi")
782                 .field("target_id", &{ self.target_id })
783                 .field("logical_unit_number", &{ self.logical_unit_number })
784                 .finish()
785         }
786     }
787 
788     impl TryFrom<&DevicePathNode> for &Scsi {
789         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>790         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
791             if size_of_val(node) != size_of::<Scsi>() {
792                 return Err(NodeConversionError::InvalidLength);
793             }
794 
795             let node: *const DevicePathNode = node;
796             let node: *const Scsi = node.cast();
797             Ok(unsafe { &*node })
798         }
799     }
800 
801     /// Fibre channel messaging device path node.
802     #[repr(C, packed)]
803     pub struct FibreChannel {
804         pub(super) header: DevicePathHeader,
805         pub(super) _reserved: u32,
806         pub(super) world_wide_name: u64,
807         pub(super) logical_unit_number: u64,
808     }
809 
810     impl FibreChannel {
811         /// Fibre Channel World Wide Name.
812         #[must_use]
world_wide_name(&self) -> u64813         pub fn world_wide_name(&self) -> u64 {
814             self.world_wide_name
815         }
816 
817         /// Fibre Channel Logical Unit Number.
818         #[must_use]
logical_unit_number(&self) -> u64819         pub fn logical_unit_number(&self) -> u64 {
820             self.logical_unit_number
821         }
822     }
823 
824     impl fmt::Debug for FibreChannel {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result825         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
826             f.debug_struct("FibreChannel")
827                 .field("_reserved", &{ self._reserved })
828                 .field("world_wide_name", &{ self.world_wide_name })
829                 .field("logical_unit_number", &{ self.logical_unit_number })
830                 .finish()
831         }
832     }
833 
834     impl TryFrom<&DevicePathNode> for &FibreChannel {
835         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>836         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
837             if size_of_val(node) != size_of::<FibreChannel>() {
838                 return Err(NodeConversionError::InvalidLength);
839             }
840 
841             let node: *const DevicePathNode = node;
842             let node: *const FibreChannel = node.cast();
843             Ok(unsafe { &*node })
844         }
845     }
846 
847     /// Fibre channel extended messaging device path node.
848     #[repr(C, packed)]
849     pub struct FibreChannelEx {
850         pub(super) header: DevicePathHeader,
851         pub(super) _reserved: u32,
852         pub(super) world_wide_name: [u8; 8usize],
853         pub(super) logical_unit_number: [u8; 8usize],
854     }
855 
856     impl FibreChannelEx {
857         /// Fibre Channel end device port name (aka World Wide Name).
858         #[must_use]
world_wide_name(&self) -> [u8; 8usize]859         pub fn world_wide_name(&self) -> [u8; 8usize] {
860             self.world_wide_name
861         }
862 
863         /// Fibre Channel Logical Unit Number.
864         #[must_use]
logical_unit_number(&self) -> [u8; 8usize]865         pub fn logical_unit_number(&self) -> [u8; 8usize] {
866             self.logical_unit_number
867         }
868     }
869 
870     impl fmt::Debug for FibreChannelEx {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result871         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
872             f.debug_struct("FibreChannelEx")
873                 .field("_reserved", &{ self._reserved })
874                 .field("world_wide_name", &{ self.world_wide_name })
875                 .field("logical_unit_number", &{ self.logical_unit_number })
876                 .finish()
877         }
878     }
879 
880     impl TryFrom<&DevicePathNode> for &FibreChannelEx {
881         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>882         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
883             if size_of_val(node) != size_of::<FibreChannelEx>() {
884                 return Err(NodeConversionError::InvalidLength);
885             }
886 
887             let node: *const DevicePathNode = node;
888             let node: *const FibreChannelEx = node.cast();
889             Ok(unsafe { &*node })
890         }
891     }
892 
893     /// 1394 messaging device path node.
894     #[repr(C, packed)]
895     pub struct Ieee1394 {
896         pub(super) header: DevicePathHeader,
897         pub(super) _reserved: u32,
898         pub(super) guid: [u8; 8usize],
899     }
900 
901     impl Ieee1394 {
902         /// 1394 Global Unique ID. Note that this is not the same as a
903         /// UEFI GUID.
904         #[must_use]
guid(&self) -> [u8; 8usize]905         pub fn guid(&self) -> [u8; 8usize] {
906             self.guid
907         }
908     }
909 
910     impl fmt::Debug for Ieee1394 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result911         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
912             f.debug_struct("Ieee1394")
913                 .field("_reserved", &{ self._reserved })
914                 .field("guid", &{ self.guid })
915                 .finish()
916         }
917     }
918 
919     impl TryFrom<&DevicePathNode> for &Ieee1394 {
920         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>921         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
922             if size_of_val(node) != size_of::<Ieee1394>() {
923                 return Err(NodeConversionError::InvalidLength);
924             }
925 
926             let node: *const DevicePathNode = node;
927             let node: *const Ieee1394 = node.cast();
928             Ok(unsafe { &*node })
929         }
930     }
931 
932     /// USB messaging device path node.
933     #[repr(C, packed)]
934     pub struct Usb {
935         pub(super) header: DevicePathHeader,
936         pub(super) parent_port_number: u8,
937         pub(super) interface: u8,
938     }
939 
940     impl Usb {
941         /// USB parent port number.
942         #[must_use]
parent_port_number(&self) -> u8943         pub fn parent_port_number(&self) -> u8 {
944             self.parent_port_number
945         }
946 
947         /// USB interface number.
948         #[must_use]
interface(&self) -> u8949         pub fn interface(&self) -> u8 {
950             self.interface
951         }
952     }
953 
954     impl fmt::Debug for Usb {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result955         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
956             f.debug_struct("Usb")
957                 .field("parent_port_number", &{ self.parent_port_number })
958                 .field("interface", &{ self.interface })
959                 .finish()
960         }
961     }
962 
963     impl TryFrom<&DevicePathNode> for &Usb {
964         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>965         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
966             if size_of_val(node) != size_of::<Usb>() {
967                 return Err(NodeConversionError::InvalidLength);
968             }
969 
970             let node: *const DevicePathNode = node;
971             let node: *const Usb = node.cast();
972             Ok(unsafe { &*node })
973         }
974     }
975 
976     /// SATA messaging device path node.
977     #[repr(C, packed)]
978     pub struct Sata {
979         pub(super) header: DevicePathHeader,
980         pub(super) hba_port_number: u16,
981         pub(super) port_multiplier_port_number: u16,
982         pub(super) logical_unit_number: u16,
983     }
984 
985     impl Sata {
986         /// The HBA port number that facilitates the connection to the
987         /// device or a port multiplier. The value 0xffff is reserved.
988         #[must_use]
hba_port_number(&self) -> u16989         pub fn hba_port_number(&self) -> u16 {
990             self.hba_port_number
991         }
992 
993         /// the port multiplier port number that facilitates the
994         /// connection to the device. Must be set to 0xffff if the
995         /// device is directly connected to the HBA.
996         #[must_use]
port_multiplier_port_number(&self) -> u16997         pub fn port_multiplier_port_number(&self) -> u16 {
998             self.port_multiplier_port_number
999         }
1000 
1001         /// Logical unit number.
1002         #[must_use]
logical_unit_number(&self) -> u161003         pub fn logical_unit_number(&self) -> u16 {
1004             self.logical_unit_number
1005         }
1006     }
1007 
1008     impl fmt::Debug for Sata {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1009         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1010             f.debug_struct("Sata")
1011                 .field("hba_port_number", &{ self.hba_port_number })
1012                 .field("port_multiplier_port_number", &{
1013                     self.port_multiplier_port_number
1014                 })
1015                 .field("logical_unit_number", &{ self.logical_unit_number })
1016                 .finish()
1017         }
1018     }
1019 
1020     impl TryFrom<&DevicePathNode> for &Sata {
1021         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>1022         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
1023             if size_of_val(node) != size_of::<Sata>() {
1024                 return Err(NodeConversionError::InvalidLength);
1025             }
1026 
1027             let node: *const DevicePathNode = node;
1028             let node: *const Sata = node.cast();
1029             Ok(unsafe { &*node })
1030         }
1031     }
1032 
1033     /// USB World Wide ID (WWID) messaging device path node.
1034     #[repr(C, packed)]
1035     #[derive(Pointee)]
1036     pub struct UsbWwid {
1037         pub(super) header: DevicePathHeader,
1038         pub(super) interface_number: u16,
1039         pub(super) device_vendor_id: u16,
1040         pub(super) device_product_id: u16,
1041         pub(super) serial_number: [u16],
1042     }
1043 
1044     impl UsbWwid {
1045         /// USB interface number.
1046         #[must_use]
interface_number(&self) -> u161047         pub fn interface_number(&self) -> u16 {
1048             self.interface_number
1049         }
1050 
1051         /// USB vendor ID.
1052         #[must_use]
device_vendor_id(&self) -> u161053         pub fn device_vendor_id(&self) -> u16 {
1054             self.device_vendor_id
1055         }
1056 
1057         /// USB product ID.
1058         #[must_use]
device_product_id(&self) -> u161059         pub fn device_product_id(&self) -> u16 {
1060             self.device_product_id
1061         }
1062 
1063         /// Last 64 (or fewer) characters of the USB Serial number.
1064         #[must_use]
serial_number(&self) -> UnalignedSlice<u16>1065         pub fn serial_number(&self) -> UnalignedSlice<u16> {
1066             let ptr: *const [u16] = addr_of!(self.serial_number);
1067             let (ptr, len): (*const (), usize) = PtrExt::to_raw_parts(ptr);
1068             unsafe { UnalignedSlice::new(ptr.cast::<u16>(), len) }
1069         }
1070     }
1071 
1072     impl fmt::Debug for UsbWwid {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1073         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1074             f.debug_struct("UsbWwid")
1075                 .field("interface_number", &{ self.interface_number })
1076                 .field("device_vendor_id", &{ self.device_vendor_id })
1077                 .field("device_product_id", &{ self.device_product_id })
1078                 .field("serial_number", {
1079                     let ptr = addr_of!(self.serial_number);
1080                     let (ptr, len) = PtrExt::to_raw_parts(ptr);
1081                     let byte_len = size_of::<u16>() * len;
1082                     unsafe { &slice::from_raw_parts(ptr.cast::<u8>(), byte_len) }
1083                 })
1084                 .finish()
1085         }
1086     }
1087 
1088     impl TryFrom<&DevicePathNode> for &UsbWwid {
1089         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>1090         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
1091             let static_size = 10usize;
1092             let dst_size = size_of_val(node)
1093                 .checked_sub(static_size)
1094                 .ok_or(NodeConversionError::InvalidLength)?;
1095             let elem_size = size_of::<u16>();
1096             if dst_size % elem_size != 0 {
1097                 return Err(NodeConversionError::InvalidLength);
1098             }
1099 
1100             let node: *const DevicePathNode = node;
1101             let node: *const UsbWwid = ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size);
1102             Ok(unsafe { &*node })
1103         }
1104     }
1105 
1106     /// Device logical unit messaging device path node.
1107     #[repr(C, packed)]
1108     pub struct DeviceLogicalUnit {
1109         pub(super) header: DevicePathHeader,
1110         pub(super) logical_unit_number: u8,
1111     }
1112 
1113     impl DeviceLogicalUnit {
1114         /// Logical Unit Number.
1115         #[must_use]
logical_unit_number(&self) -> u81116         pub fn logical_unit_number(&self) -> u8 {
1117             self.logical_unit_number
1118         }
1119     }
1120 
1121     impl fmt::Debug for DeviceLogicalUnit {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1122         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1123             f.debug_struct("DeviceLogicalUnit")
1124                 .field("logical_unit_number", &{ self.logical_unit_number })
1125                 .finish()
1126         }
1127     }
1128 
1129     impl TryFrom<&DevicePathNode> for &DeviceLogicalUnit {
1130         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>1131         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
1132             if size_of_val(node) != size_of::<DeviceLogicalUnit>() {
1133                 return Err(NodeConversionError::InvalidLength);
1134             }
1135 
1136             let node: *const DevicePathNode = node;
1137             let node: *const DeviceLogicalUnit = node.cast();
1138             Ok(unsafe { &*node })
1139         }
1140     }
1141 
1142     /// USB class messaging device path node.
1143     #[repr(C, packed)]
1144     pub struct UsbClass {
1145         pub(super) header: DevicePathHeader,
1146         pub(super) vendor_id: u16,
1147         pub(super) product_id: u16,
1148         pub(super) device_class: u8,
1149         pub(super) device_subclass: u8,
1150         pub(super) device_protocol: u8,
1151     }
1152 
1153     impl UsbClass {
1154         /// USB vendor ID.
1155         #[must_use]
vendor_id(&self) -> u161156         pub fn vendor_id(&self) -> u16 {
1157             self.vendor_id
1158         }
1159 
1160         /// USB product ID.
1161         #[must_use]
product_id(&self) -> u161162         pub fn product_id(&self) -> u16 {
1163             self.product_id
1164         }
1165 
1166         /// USB device class.
1167         #[must_use]
device_class(&self) -> u81168         pub fn device_class(&self) -> u8 {
1169             self.device_class
1170         }
1171 
1172         /// USB device subclass.
1173         #[must_use]
device_subclass(&self) -> u81174         pub fn device_subclass(&self) -> u8 {
1175             self.device_subclass
1176         }
1177 
1178         /// USB device protocol.
1179         #[must_use]
device_protocol(&self) -> u81180         pub fn device_protocol(&self) -> u8 {
1181             self.device_protocol
1182         }
1183     }
1184 
1185     impl fmt::Debug for UsbClass {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1186         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1187             f.debug_struct("UsbClass")
1188                 .field("vendor_id", &{ self.vendor_id })
1189                 .field("product_id", &{ self.product_id })
1190                 .field("device_class", &{ self.device_class })
1191                 .field("device_subclass", &{ self.device_subclass })
1192                 .field("device_protocol", &{ self.device_protocol })
1193                 .finish()
1194         }
1195     }
1196 
1197     impl TryFrom<&DevicePathNode> for &UsbClass {
1198         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>1199         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
1200             if size_of_val(node) != size_of::<UsbClass>() {
1201                 return Err(NodeConversionError::InvalidLength);
1202             }
1203 
1204             let node: *const DevicePathNode = node;
1205             let node: *const UsbClass = node.cast();
1206             Ok(unsafe { &*node })
1207         }
1208     }
1209 
1210     /// I2O messaging device path node.
1211     #[repr(C, packed)]
1212     pub struct I2o {
1213         pub(super) header: DevicePathHeader,
1214         pub(super) target_id: u32,
1215     }
1216 
1217     impl I2o {
1218         /// Target ID (TID).
1219         #[must_use]
target_id(&self) -> u321220         pub fn target_id(&self) -> u32 {
1221             self.target_id
1222         }
1223     }
1224 
1225     impl fmt::Debug for I2o {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1226         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1227             f.debug_struct("I2o")
1228                 .field("target_id", &{ self.target_id })
1229                 .finish()
1230         }
1231     }
1232 
1233     impl TryFrom<&DevicePathNode> for &I2o {
1234         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>1235         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
1236             if size_of_val(node) != size_of::<I2o>() {
1237                 return Err(NodeConversionError::InvalidLength);
1238             }
1239 
1240             let node: *const DevicePathNode = node;
1241             let node: *const I2o = node.cast();
1242             Ok(unsafe { &*node })
1243         }
1244     }
1245 
1246     /// MAC address messaging device path node.
1247     #[repr(C, packed)]
1248     pub struct MacAddress {
1249         pub(super) header: DevicePathHeader,
1250         pub(super) mac_address: [u8; 32usize],
1251         pub(super) interface_type: u8,
1252     }
1253 
1254     impl MacAddress {
1255         /// MAC address for a network interface, padded with zeros.
1256         #[must_use]
mac_address(&self) -> [u8; 32usize]1257         pub fn mac_address(&self) -> [u8; 32usize] {
1258             self.mac_address
1259         }
1260 
1261         /// Network interface type. See
1262         /// <https://www.iana.org/assignments/smi-numbers/smi-numbers.xhtml#smi-numbers-5>
1263         #[must_use]
interface_type(&self) -> u81264         pub fn interface_type(&self) -> u8 {
1265             self.interface_type
1266         }
1267     }
1268 
1269     impl fmt::Debug for MacAddress {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1270         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1271             f.debug_struct("MacAddress")
1272                 .field("mac_address", &{ self.mac_address })
1273                 .field("interface_type", &{ self.interface_type })
1274                 .finish()
1275         }
1276     }
1277 
1278     impl TryFrom<&DevicePathNode> for &MacAddress {
1279         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>1280         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
1281             if size_of_val(node) != size_of::<MacAddress>() {
1282                 return Err(NodeConversionError::InvalidLength);
1283             }
1284 
1285             let node: *const DevicePathNode = node;
1286             let node: *const MacAddress = node.cast();
1287             Ok(unsafe { &*node })
1288         }
1289     }
1290 
1291     /// IPv4 messaging device path node.
1292     #[repr(C, packed)]
1293     pub struct Ipv4 {
1294         pub(super) header: DevicePathHeader,
1295         pub(super) local_ip_address: [u8; 4usize],
1296         pub(super) remote_ip_address: [u8; 4usize],
1297         pub(super) local_port: u16,
1298         pub(super) remote_port: u16,
1299         pub(super) protocol: u16,
1300         pub(super) ip_address_origin: device_path::messaging::Ipv4AddressOrigin,
1301         pub(super) gateway_ip_address: [u8; 4usize],
1302         pub(super) subnet_mask: [u8; 4usize],
1303     }
1304 
1305     impl Ipv4 {
1306         /// Local IPv4 address.
1307         #[must_use]
local_ip_address(&self) -> [u8; 4usize]1308         pub fn local_ip_address(&self) -> [u8; 4usize] {
1309             self.local_ip_address
1310         }
1311 
1312         /// Remote IPv4 address.
1313         #[must_use]
remote_ip_address(&self) -> [u8; 4usize]1314         pub fn remote_ip_address(&self) -> [u8; 4usize] {
1315             self.remote_ip_address
1316         }
1317 
1318         /// Local port number.
1319         #[must_use]
local_port(&self) -> u161320         pub fn local_port(&self) -> u16 {
1321             self.local_port
1322         }
1323 
1324         /// Remote port number.
1325         #[must_use]
remote_port(&self) -> u161326         pub fn remote_port(&self) -> u16 {
1327             self.remote_port
1328         }
1329 
1330         /// Network protocol. See
1331         /// <https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml>
1332         #[must_use]
protocol(&self) -> u161333         pub fn protocol(&self) -> u16 {
1334             self.protocol
1335         }
1336 
1337         /// Whether the source IP address is static or assigned via DHCP.
1338         #[must_use]
ip_address_origin(&self) -> device_path::messaging::Ipv4AddressOrigin1339         pub fn ip_address_origin(&self) -> device_path::messaging::Ipv4AddressOrigin {
1340             self.ip_address_origin
1341         }
1342 
1343         /// Gateway IP address.
1344         #[must_use]
gateway_ip_address(&self) -> [u8; 4usize]1345         pub fn gateway_ip_address(&self) -> [u8; 4usize] {
1346             self.gateway_ip_address
1347         }
1348 
1349         /// Subnet mask.
1350         #[must_use]
subnet_mask(&self) -> [u8; 4usize]1351         pub fn subnet_mask(&self) -> [u8; 4usize] {
1352             self.subnet_mask
1353         }
1354     }
1355 
1356     impl fmt::Debug for Ipv4 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1357         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1358             f.debug_struct("Ipv4")
1359                 .field("local_ip_address", &{ self.local_ip_address })
1360                 .field("remote_ip_address", &{ self.remote_ip_address })
1361                 .field("local_port", &{ self.local_port })
1362                 .field("remote_port", &{ self.remote_port })
1363                 .field("protocol", &{ self.protocol })
1364                 .field("ip_address_origin", &{ self.ip_address_origin })
1365                 .field("gateway_ip_address", &{ self.gateway_ip_address })
1366                 .field("subnet_mask", &{ self.subnet_mask })
1367                 .finish()
1368         }
1369     }
1370 
1371     impl TryFrom<&DevicePathNode> for &Ipv4 {
1372         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>1373         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
1374             if size_of_val(node) != size_of::<Ipv4>() {
1375                 return Err(NodeConversionError::InvalidLength);
1376             }
1377 
1378             let node: *const DevicePathNode = node;
1379             let node: *const Ipv4 = node.cast();
1380             Ok(unsafe { &*node })
1381         }
1382     }
1383 
1384     /// IPv6 messaging device path node.
1385     #[repr(C, packed)]
1386     pub struct Ipv6 {
1387         pub(super) header: DevicePathHeader,
1388         pub(super) local_ip_address: [u8; 16usize],
1389         pub(super) remote_ip_address: [u8; 16usize],
1390         pub(super) local_port: u16,
1391         pub(super) remote_port: u16,
1392         pub(super) protocol: u16,
1393         pub(super) ip_address_origin: device_path::messaging::Ipv6AddressOrigin,
1394         pub(super) prefix_length: u8,
1395         pub(super) gateway_ip_address: [u8; 16usize],
1396     }
1397 
1398     impl Ipv6 {
1399         /// Local Ipv6 address.
1400         #[must_use]
local_ip_address(&self) -> [u8; 16usize]1401         pub fn local_ip_address(&self) -> [u8; 16usize] {
1402             self.local_ip_address
1403         }
1404 
1405         /// Remote Ipv6 address.
1406         #[must_use]
remote_ip_address(&self) -> [u8; 16usize]1407         pub fn remote_ip_address(&self) -> [u8; 16usize] {
1408             self.remote_ip_address
1409         }
1410 
1411         /// Local port number.
1412         #[must_use]
local_port(&self) -> u161413         pub fn local_port(&self) -> u16 {
1414             self.local_port
1415         }
1416 
1417         /// Remote port number.
1418         #[must_use]
remote_port(&self) -> u161419         pub fn remote_port(&self) -> u16 {
1420             self.remote_port
1421         }
1422 
1423         /// Network protocol. See
1424         /// <https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml>
1425         #[must_use]
protocol(&self) -> u161426         pub fn protocol(&self) -> u16 {
1427             self.protocol
1428         }
1429 
1430         /// Origin of the local IP address.
1431         #[must_use]
ip_address_origin(&self) -> device_path::messaging::Ipv6AddressOrigin1432         pub fn ip_address_origin(&self) -> device_path::messaging::Ipv6AddressOrigin {
1433             self.ip_address_origin
1434         }
1435 
1436         /// Prefix length.
1437         #[must_use]
prefix_length(&self) -> u81438         pub fn prefix_length(&self) -> u8 {
1439             self.prefix_length
1440         }
1441 
1442         /// Gateway IP address.
1443         #[must_use]
gateway_ip_address(&self) -> [u8; 16usize]1444         pub fn gateway_ip_address(&self) -> [u8; 16usize] {
1445             self.gateway_ip_address
1446         }
1447     }
1448 
1449     impl fmt::Debug for Ipv6 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1450         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1451             f.debug_struct("Ipv6")
1452                 .field("local_ip_address", &{ self.local_ip_address })
1453                 .field("remote_ip_address", &{ self.remote_ip_address })
1454                 .field("local_port", &{ self.local_port })
1455                 .field("remote_port", &{ self.remote_port })
1456                 .field("protocol", &{ self.protocol })
1457                 .field("ip_address_origin", &{ self.ip_address_origin })
1458                 .field("prefix_length", &{ self.prefix_length })
1459                 .field("gateway_ip_address", &{ self.gateway_ip_address })
1460                 .finish()
1461         }
1462     }
1463 
1464     impl TryFrom<&DevicePathNode> for &Ipv6 {
1465         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>1466         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
1467             if size_of_val(node) != size_of::<Ipv6>() {
1468                 return Err(NodeConversionError::InvalidLength);
1469             }
1470 
1471             let node: *const DevicePathNode = node;
1472             let node: *const Ipv6 = node.cast();
1473             Ok(unsafe { &*node })
1474         }
1475     }
1476 
1477     /// VLAN messaging device path node.
1478     #[repr(C, packed)]
1479     pub struct Vlan {
1480         pub(super) header: DevicePathHeader,
1481         pub(super) vlan_id: u16,
1482     }
1483 
1484     impl Vlan {
1485         /// VLAN identifier (0-4094).
1486         #[must_use]
vlan_id(&self) -> u161487         pub fn vlan_id(&self) -> u16 {
1488             self.vlan_id
1489         }
1490     }
1491 
1492     impl fmt::Debug for Vlan {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1493         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1494             f.debug_struct("Vlan")
1495                 .field("vlan_id", &{ self.vlan_id })
1496                 .finish()
1497         }
1498     }
1499 
1500     impl TryFrom<&DevicePathNode> for &Vlan {
1501         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>1502         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
1503             if size_of_val(node) != size_of::<Vlan>() {
1504                 return Err(NodeConversionError::InvalidLength);
1505             }
1506 
1507             let node: *const DevicePathNode = node;
1508             let node: *const Vlan = node.cast();
1509             Ok(unsafe { &*node })
1510         }
1511     }
1512 
1513     /// InfiniBand messaging device path node.
1514     #[repr(C, packed)]
1515     pub struct Infiniband {
1516         pub(super) header: DevicePathHeader,
1517         pub(super) resource_flags: device_path::messaging::InfinibandResourceFlags,
1518         pub(super) port_gid: [u8; 16usize],
1519         pub(super) ioc_guid_or_service_id: u64,
1520         pub(super) target_port_id: u64,
1521         pub(super) device_id: u64,
1522     }
1523 
1524     impl Infiniband {
1525         /// Flags to identify/manage InfiniBand elements.
1526         #[must_use]
resource_flags(&self) -> device_path::messaging::InfinibandResourceFlags1527         pub fn resource_flags(&self) -> device_path::messaging::InfinibandResourceFlags {
1528             self.resource_flags
1529         }
1530 
1531         /// 128-bit Global Identifier for remote fabric port. Note that
1532         /// this is not the same as a UEFI GUID.
1533         #[must_use]
port_gid(&self) -> [u8; 16usize]1534         pub fn port_gid(&self) -> [u8; 16usize] {
1535             self.port_gid
1536         }
1537 
1538         /// IOC GUID if bit 0 of `resource_flags` is unset, or Service
1539         /// ID if bit 0 of `resource_flags` is set.
1540         #[must_use]
ioc_guid_or_service_id(&self) -> u641541         pub fn ioc_guid_or_service_id(&self) -> u64 {
1542             self.ioc_guid_or_service_id
1543         }
1544 
1545         /// 64-bit persistent ID of remote IOC port.
1546         #[must_use]
target_port_id(&self) -> u641547         pub fn target_port_id(&self) -> u64 {
1548             self.target_port_id
1549         }
1550 
1551         /// 64-bit persistent ID of remote device..
1552         #[must_use]
device_id(&self) -> u641553         pub fn device_id(&self) -> u64 {
1554             self.device_id
1555         }
1556     }
1557 
1558     impl fmt::Debug for Infiniband {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1559         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1560             f.debug_struct("Infiniband")
1561                 .field("resource_flags", &{ self.resource_flags })
1562                 .field("port_gid", &{ self.port_gid })
1563                 .field("ioc_guid_or_service_id", &{ self.ioc_guid_or_service_id })
1564                 .field("target_port_id", &{ self.target_port_id })
1565                 .field("device_id", &{ self.device_id })
1566                 .finish()
1567         }
1568     }
1569 
1570     impl TryFrom<&DevicePathNode> for &Infiniband {
1571         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>1572         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
1573             if size_of_val(node) != size_of::<Infiniband>() {
1574                 return Err(NodeConversionError::InvalidLength);
1575             }
1576 
1577             let node: *const DevicePathNode = node;
1578             let node: *const Infiniband = node.cast();
1579             Ok(unsafe { &*node })
1580         }
1581     }
1582 
1583     /// UART messaging device path node.
1584     #[repr(C, packed)]
1585     pub struct Uart {
1586         pub(super) header: DevicePathHeader,
1587         pub(super) _reserved: u32,
1588         pub(super) baud_rate: u64,
1589         pub(super) data_bits: u8,
1590         pub(super) parity: device_path::messaging::Parity,
1591         pub(super) stop_bits: device_path::messaging::StopBits,
1592     }
1593 
1594     impl Uart {
1595         /// Baud rate setting, or 0 to use the device's default.
1596         #[must_use]
baud_rate(&self) -> u641597         pub fn baud_rate(&self) -> u64 {
1598             self.baud_rate
1599         }
1600 
1601         /// Number of data bits, or 0 to use the device's default.
1602         #[must_use]
data_bits(&self) -> u81603         pub fn data_bits(&self) -> u8 {
1604             self.data_bits
1605         }
1606 
1607         /// Parity setting.
1608         #[must_use]
parity(&self) -> device_path::messaging::Parity1609         pub fn parity(&self) -> device_path::messaging::Parity {
1610             self.parity
1611         }
1612 
1613         /// Number of stop bits.
1614         #[must_use]
stop_bits(&self) -> device_path::messaging::StopBits1615         pub fn stop_bits(&self) -> device_path::messaging::StopBits {
1616             self.stop_bits
1617         }
1618     }
1619 
1620     impl fmt::Debug for Uart {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1621         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1622             f.debug_struct("Uart")
1623                 .field("_reserved", &{ self._reserved })
1624                 .field("baud_rate", &{ self.baud_rate })
1625                 .field("data_bits", &{ self.data_bits })
1626                 .field("parity", &{ self.parity })
1627                 .field("stop_bits", &{ self.stop_bits })
1628                 .finish()
1629         }
1630     }
1631 
1632     impl TryFrom<&DevicePathNode> for &Uart {
1633         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>1634         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
1635             if size_of_val(node) != size_of::<Uart>() {
1636                 return Err(NodeConversionError::InvalidLength);
1637             }
1638 
1639             let node: *const DevicePathNode = node;
1640             let node: *const Uart = node.cast();
1641             Ok(unsafe { &*node })
1642         }
1643     }
1644 
1645     /// Vendor-defined messaging device path node.
1646     #[repr(C, packed)]
1647     #[derive(Pointee)]
1648     pub struct Vendor {
1649         pub(super) header: DevicePathHeader,
1650         pub(super) vendor_guid: Guid,
1651         pub(super) vendor_defined_data: [u8],
1652     }
1653 
1654     impl Vendor {
1655         /// Vendor-assigned GUID that defines the data that follows.
1656         #[must_use]
vendor_guid(&self) -> Guid1657         pub fn vendor_guid(&self) -> Guid {
1658             self.vendor_guid
1659         }
1660 
1661         /// Vendor-defined data.
1662         #[must_use]
vendor_defined_data(&self) -> &[u8]1663         pub fn vendor_defined_data(&self) -> &[u8] {
1664             &self.vendor_defined_data
1665         }
1666     }
1667 
1668     impl fmt::Debug for Vendor {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1669         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1670             f.debug_struct("Vendor")
1671                 .field("vendor_guid", &{ self.vendor_guid })
1672                 .field("vendor_defined_data", {
1673                     let ptr = addr_of!(self.vendor_defined_data);
1674                     let (ptr, len) = PtrExt::to_raw_parts(ptr);
1675                     let byte_len = size_of::<u8>() * len;
1676                     unsafe { &slice::from_raw_parts(ptr.cast::<u8>(), byte_len) }
1677                 })
1678                 .finish()
1679         }
1680     }
1681 
1682     impl TryFrom<&DevicePathNode> for &Vendor {
1683         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>1684         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
1685             let static_size = 20usize;
1686             let dst_size = size_of_val(node)
1687                 .checked_sub(static_size)
1688                 .ok_or(NodeConversionError::InvalidLength)?;
1689             let elem_size = size_of::<u8>();
1690             if dst_size % elem_size != 0 {
1691                 return Err(NodeConversionError::InvalidLength);
1692             }
1693 
1694             let node: *const DevicePathNode = node;
1695             let node: *const Vendor = ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size);
1696             Ok(unsafe { &*node })
1697         }
1698     }
1699 
1700     /// Serial Attached SCSI (SAS) extended messaging device path node.
1701     #[repr(C, packed)]
1702     pub struct SasEx {
1703         pub(super) header: DevicePathHeader,
1704         pub(super) sas_address: [u8; 8usize],
1705         pub(super) logical_unit_number: [u8; 8usize],
1706         pub(super) info: u16,
1707         pub(super) relative_target_port: u16,
1708     }
1709 
1710     impl SasEx {
1711         /// SAS address.
1712         #[must_use]
sas_address(&self) -> [u8; 8usize]1713         pub fn sas_address(&self) -> [u8; 8usize] {
1714             self.sas_address
1715         }
1716 
1717         /// Logical Unit Number.
1718         #[must_use]
logical_unit_number(&self) -> [u8; 8usize]1719         pub fn logical_unit_number(&self) -> [u8; 8usize] {
1720             self.logical_unit_number
1721         }
1722 
1723         /// Information about the device and its interconnect.
1724         #[must_use]
info(&self) -> u161725         pub fn info(&self) -> u16 {
1726             self.info
1727         }
1728 
1729         /// Relative Target Port (RTP).
1730         #[must_use]
relative_target_port(&self) -> u161731         pub fn relative_target_port(&self) -> u16 {
1732             self.relative_target_port
1733         }
1734     }
1735 
1736     impl fmt::Debug for SasEx {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1737         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1738             f.debug_struct("SasEx")
1739                 .field("sas_address", &{ self.sas_address })
1740                 .field("logical_unit_number", &{ self.logical_unit_number })
1741                 .field("info", &{ self.info })
1742                 .field("relative_target_port", &{ self.relative_target_port })
1743                 .finish()
1744         }
1745     }
1746 
1747     impl TryFrom<&DevicePathNode> for &SasEx {
1748         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>1749         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
1750             if size_of_val(node) != size_of::<SasEx>() {
1751                 return Err(NodeConversionError::InvalidLength);
1752             }
1753 
1754             let node: *const DevicePathNode = node;
1755             let node: *const SasEx = node.cast();
1756             Ok(unsafe { &*node })
1757         }
1758     }
1759 
1760     /// iSCSI messaging device path node.
1761     #[repr(C, packed)]
1762     #[derive(Pointee)]
1763     pub struct Iscsi {
1764         pub(super) header: DevicePathHeader,
1765         pub(super) protocol: device_path::messaging::IscsiProtocol,
1766         pub(super) options: device_path::messaging::IscsiLoginOptions,
1767         pub(super) logical_unit_number: [u8; 8usize],
1768         pub(super) target_portal_group_tag: u16,
1769         pub(super) iscsi_target_name: [u8],
1770     }
1771 
1772     impl Iscsi {
1773         /// Network protocol.
1774         #[must_use]
protocol(&self) -> device_path::messaging::IscsiProtocol1775         pub fn protocol(&self) -> device_path::messaging::IscsiProtocol {
1776             self.protocol
1777         }
1778 
1779         /// iSCSI login options (bitfield).
1780         #[must_use]
options(&self) -> device_path::messaging::IscsiLoginOptions1781         pub fn options(&self) -> device_path::messaging::IscsiLoginOptions {
1782             self.options
1783         }
1784 
1785         /// iSCSI Logical Unit Number.
1786         #[must_use]
logical_unit_number(&self) -> [u8; 8usize]1787         pub fn logical_unit_number(&self) -> [u8; 8usize] {
1788             self.logical_unit_number
1789         }
1790 
1791         /// iSCSI Target Portal group tag the initiator intends to
1792         /// establish a session with.
1793         #[must_use]
target_portal_group_tag(&self) -> u161794         pub fn target_portal_group_tag(&self) -> u16 {
1795             self.target_portal_group_tag
1796         }
1797 
1798         /// iSCSI Node Target name.
1799         ///
1800         /// The UEFI Specification does not specify how the string is
1801         /// encoded, but gives one example that appears to be
1802         /// null-terminated ASCII.
1803         #[must_use]
iscsi_target_name(&self) -> &[u8]1804         pub fn iscsi_target_name(&self) -> &[u8] {
1805             &self.iscsi_target_name
1806         }
1807     }
1808 
1809     impl fmt::Debug for Iscsi {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1810         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1811             f.debug_struct("Iscsi")
1812                 .field("protocol", &{ self.protocol })
1813                 .field("options", &{ self.options })
1814                 .field("logical_unit_number", &{ self.logical_unit_number })
1815                 .field("target_portal_group_tag", &{ self.target_portal_group_tag })
1816                 .field("iscsi_target_name", {
1817                     let ptr = addr_of!(self.iscsi_target_name);
1818                     let (ptr, len) = PtrExt::to_raw_parts(ptr);
1819                     let byte_len = size_of::<u8>() * len;
1820                     unsafe { &slice::from_raw_parts(ptr.cast::<u8>(), byte_len) }
1821                 })
1822                 .finish()
1823         }
1824     }
1825 
1826     impl TryFrom<&DevicePathNode> for &Iscsi {
1827         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>1828         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
1829             let static_size = 18usize;
1830             let dst_size = size_of_val(node)
1831                 .checked_sub(static_size)
1832                 .ok_or(NodeConversionError::InvalidLength)?;
1833             let elem_size = size_of::<u8>();
1834             if dst_size % elem_size != 0 {
1835                 return Err(NodeConversionError::InvalidLength);
1836             }
1837 
1838             let node: *const DevicePathNode = node;
1839             let node: *const Iscsi = ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size);
1840             Ok(unsafe { &*node })
1841         }
1842     }
1843 
1844     /// NVM Express namespace messaging device path node.
1845     #[repr(C, packed)]
1846     pub struct NvmeNamespace {
1847         pub(super) header: DevicePathHeader,
1848         pub(super) namespace_identifier: u32,
1849         pub(super) ieee_extended_unique_identifier: u64,
1850     }
1851 
1852     impl NvmeNamespace {
1853         /// Namespace identifier (NSID). The values 0 and 0xffff_ffff
1854         /// are invalid.
1855         #[must_use]
namespace_identifier(&self) -> u321856         pub fn namespace_identifier(&self) -> u32 {
1857             self.namespace_identifier
1858         }
1859 
1860         /// IEEE Extended Unique Identifier (EUI-64), or 0 if the device
1861         /// does not have a EUI-64.
1862         #[must_use]
ieee_extended_unique_identifier(&self) -> u641863         pub fn ieee_extended_unique_identifier(&self) -> u64 {
1864             self.ieee_extended_unique_identifier
1865         }
1866     }
1867 
1868     impl fmt::Debug for NvmeNamespace {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1869         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1870             f.debug_struct("NvmeNamespace")
1871                 .field("namespace_identifier", &{ self.namespace_identifier })
1872                 .field("ieee_extended_unique_identifier", &{
1873                     self.ieee_extended_unique_identifier
1874                 })
1875                 .finish()
1876         }
1877     }
1878 
1879     impl TryFrom<&DevicePathNode> for &NvmeNamespace {
1880         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>1881         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
1882             if size_of_val(node) != size_of::<NvmeNamespace>() {
1883                 return Err(NodeConversionError::InvalidLength);
1884             }
1885 
1886             let node: *const DevicePathNode = node;
1887             let node: *const NvmeNamespace = node.cast();
1888             Ok(unsafe { &*node })
1889         }
1890     }
1891 
1892     /// Uniform Resource Identifier (URI) messaging device path node.
1893     #[repr(C, packed)]
1894     #[derive(Pointee)]
1895     pub struct Uri {
1896         pub(super) header: DevicePathHeader,
1897         pub(super) value: [u8],
1898     }
1899 
1900     impl Uri {
1901         /// URI as defined by [RFC 3986](https://www.rfc-editor.org/rfc/rfc3986).
1902         #[must_use]
value(&self) -> &[u8]1903         pub fn value(&self) -> &[u8] {
1904             &self.value
1905         }
1906     }
1907 
1908     impl fmt::Debug for Uri {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1909         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1910             f.debug_struct("Uri")
1911                 .field("value", {
1912                     let ptr = addr_of!(self.value);
1913                     let (ptr, len) = PtrExt::to_raw_parts(ptr);
1914                     let byte_len = size_of::<u8>() * len;
1915                     unsafe { &slice::from_raw_parts(ptr.cast::<u8>(), byte_len) }
1916                 })
1917                 .finish()
1918         }
1919     }
1920 
1921     impl TryFrom<&DevicePathNode> for &Uri {
1922         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>1923         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
1924             let static_size = 4usize;
1925             let dst_size = size_of_val(node)
1926                 .checked_sub(static_size)
1927                 .ok_or(NodeConversionError::InvalidLength)?;
1928             let elem_size = size_of::<u8>();
1929             if dst_size % elem_size != 0 {
1930                 return Err(NodeConversionError::InvalidLength);
1931             }
1932 
1933             let node: *const DevicePathNode = node;
1934             let node: *const Uri = ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size);
1935             Ok(unsafe { &*node })
1936         }
1937     }
1938 
1939     /// Universal Flash Storage (UFS) messaging device path node.
1940     #[repr(C, packed)]
1941     pub struct Ufs {
1942         pub(super) header: DevicePathHeader,
1943         pub(super) target_id: u8,
1944         pub(super) logical_unit_number: u8,
1945     }
1946 
1947     impl Ufs {
1948         /// Target ID on the UFS interface (PUN).
1949         #[must_use]
target_id(&self) -> u81950         pub fn target_id(&self) -> u8 {
1951             self.target_id
1952         }
1953 
1954         /// Logical Unit Number (LUN).
1955         #[must_use]
logical_unit_number(&self) -> u81956         pub fn logical_unit_number(&self) -> u8 {
1957             self.logical_unit_number
1958         }
1959     }
1960 
1961     impl fmt::Debug for Ufs {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1962         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1963             f.debug_struct("Ufs")
1964                 .field("target_id", &{ self.target_id })
1965                 .field("logical_unit_number", &{ self.logical_unit_number })
1966                 .finish()
1967         }
1968     }
1969 
1970     impl TryFrom<&DevicePathNode> for &Ufs {
1971         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>1972         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
1973             if size_of_val(node) != size_of::<Ufs>() {
1974                 return Err(NodeConversionError::InvalidLength);
1975             }
1976 
1977             let node: *const DevicePathNode = node;
1978             let node: *const Ufs = node.cast();
1979             Ok(unsafe { &*node })
1980         }
1981     }
1982 
1983     /// Secure Digital (SD) messaging device path node.
1984     #[repr(C, packed)]
1985     pub struct Sd {
1986         pub(super) header: DevicePathHeader,
1987         pub(super) slot_number: u8,
1988     }
1989 
1990     impl Sd {
1991         /// Slot number.
1992         #[must_use]
slot_number(&self) -> u81993         pub fn slot_number(&self) -> u8 {
1994             self.slot_number
1995         }
1996     }
1997 
1998     impl fmt::Debug for Sd {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1999         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2000             f.debug_struct("Sd")
2001                 .field("slot_number", &{ self.slot_number })
2002                 .finish()
2003         }
2004     }
2005 
2006     impl TryFrom<&DevicePathNode> for &Sd {
2007         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>2008         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
2009             if size_of_val(node) != size_of::<Sd>() {
2010                 return Err(NodeConversionError::InvalidLength);
2011             }
2012 
2013             let node: *const DevicePathNode = node;
2014             let node: *const Sd = node.cast();
2015             Ok(unsafe { &*node })
2016         }
2017     }
2018 
2019     /// Bluetooth messaging device path node.
2020     #[repr(C, packed)]
2021     pub struct Bluetooth {
2022         pub(super) header: DevicePathHeader,
2023         pub(super) device_address: [u8; 6usize],
2024     }
2025 
2026     impl Bluetooth {
2027         /// 48-bit bluetooth device address.
2028         #[must_use]
device_address(&self) -> [u8; 6usize]2029         pub fn device_address(&self) -> [u8; 6usize] {
2030             self.device_address
2031         }
2032     }
2033 
2034     impl fmt::Debug for Bluetooth {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result2035         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2036             f.debug_struct("Bluetooth")
2037                 .field("device_address", &{ self.device_address })
2038                 .finish()
2039         }
2040     }
2041 
2042     impl TryFrom<&DevicePathNode> for &Bluetooth {
2043         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>2044         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
2045             if size_of_val(node) != size_of::<Bluetooth>() {
2046                 return Err(NodeConversionError::InvalidLength);
2047             }
2048 
2049             let node: *const DevicePathNode = node;
2050             let node: *const Bluetooth = node.cast();
2051             Ok(unsafe { &*node })
2052         }
2053     }
2054 
2055     /// Wi-Fi messaging device path node.
2056     #[repr(C, packed)]
2057     pub struct Wifi {
2058         pub(super) header: DevicePathHeader,
2059         pub(super) ssid: [u8; 32usize],
2060     }
2061 
2062     impl Wifi {
2063         /// Service set identifier (SSID).
2064         #[must_use]
ssid(&self) -> [u8; 32usize]2065         pub fn ssid(&self) -> [u8; 32usize] {
2066             self.ssid
2067         }
2068     }
2069 
2070     impl fmt::Debug for Wifi {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result2071         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2072             f.debug_struct("Wifi")
2073                 .field("ssid", &{ self.ssid })
2074                 .finish()
2075         }
2076     }
2077 
2078     impl TryFrom<&DevicePathNode> for &Wifi {
2079         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>2080         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
2081             if size_of_val(node) != size_of::<Wifi>() {
2082                 return Err(NodeConversionError::InvalidLength);
2083             }
2084 
2085             let node: *const DevicePathNode = node;
2086             let node: *const Wifi = node.cast();
2087             Ok(unsafe { &*node })
2088         }
2089     }
2090 
2091     /// Embedded Multi-Media Card (eMMC) messaging device path node.
2092     #[repr(C, packed)]
2093     pub struct Emmc {
2094         pub(super) header: DevicePathHeader,
2095         pub(super) slot_number: u8,
2096     }
2097 
2098     impl Emmc {
2099         /// Slot number.
2100         #[must_use]
slot_number(&self) -> u82101         pub fn slot_number(&self) -> u8 {
2102             self.slot_number
2103         }
2104     }
2105 
2106     impl fmt::Debug for Emmc {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result2107         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2108             f.debug_struct("Emmc")
2109                 .field("slot_number", &{ self.slot_number })
2110                 .finish()
2111         }
2112     }
2113 
2114     impl TryFrom<&DevicePathNode> for &Emmc {
2115         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>2116         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
2117             if size_of_val(node) != size_of::<Emmc>() {
2118                 return Err(NodeConversionError::InvalidLength);
2119             }
2120 
2121             let node: *const DevicePathNode = node;
2122             let node: *const Emmc = node.cast();
2123             Ok(unsafe { &*node })
2124         }
2125     }
2126 
2127     /// BluetoothLE messaging device path node.
2128     #[repr(C, packed)]
2129     pub struct BluetoothLe {
2130         pub(super) header: DevicePathHeader,
2131         pub(super) device_address: [u8; 6usize],
2132         pub(super) address_type: device_path::messaging::BluetoothLeAddressType,
2133     }
2134 
2135     impl BluetoothLe {
2136         /// 48-bit bluetooth device address.
2137         #[must_use]
device_address(&self) -> [u8; 6usize]2138         pub fn device_address(&self) -> [u8; 6usize] {
2139             self.device_address
2140         }
2141 
2142         /// Address type.
2143         #[must_use]
address_type(&self) -> device_path::messaging::BluetoothLeAddressType2144         pub fn address_type(&self) -> device_path::messaging::BluetoothLeAddressType {
2145             self.address_type
2146         }
2147     }
2148 
2149     impl fmt::Debug for BluetoothLe {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result2150         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2151             f.debug_struct("BluetoothLe")
2152                 .field("device_address", &{ self.device_address })
2153                 .field("address_type", &{ self.address_type })
2154                 .finish()
2155         }
2156     }
2157 
2158     impl TryFrom<&DevicePathNode> for &BluetoothLe {
2159         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>2160         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
2161             if size_of_val(node) != size_of::<BluetoothLe>() {
2162                 return Err(NodeConversionError::InvalidLength);
2163             }
2164 
2165             let node: *const DevicePathNode = node;
2166             let node: *const BluetoothLe = node.cast();
2167             Ok(unsafe { &*node })
2168         }
2169     }
2170 
2171     /// DNS messaging device path node.
2172     #[repr(C, packed)]
2173     #[derive(Pointee)]
2174     pub struct Dns {
2175         pub(super) header: DevicePathHeader,
2176         pub(super) address_type: device_path::messaging::DnsAddressType,
2177         pub(super) addresses: [IpAddress],
2178     }
2179 
2180     impl Dns {
2181         /// Whether the addresses are IPv4 or IPv6.
2182         #[must_use]
address_type(&self) -> device_path::messaging::DnsAddressType2183         pub fn address_type(&self) -> device_path::messaging::DnsAddressType {
2184             self.address_type
2185         }
2186 
2187         /// One or more instances of the DNS server address.
2188         #[must_use]
addresses(&self) -> UnalignedSlice<IpAddress>2189         pub fn addresses(&self) -> UnalignedSlice<IpAddress> {
2190             let ptr: *const [IpAddress] = addr_of!(self.addresses);
2191             let (ptr, len): (*const (), usize) = PtrExt::to_raw_parts(ptr);
2192             unsafe { UnalignedSlice::new(ptr.cast::<IpAddress>(), len) }
2193         }
2194     }
2195 
2196     impl fmt::Debug for Dns {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result2197         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2198             f.debug_struct("Dns")
2199                 .field("address_type", &{ self.address_type })
2200                 .field("addresses", {
2201                     let ptr = addr_of!(self.addresses);
2202                     let (ptr, len) = PtrExt::to_raw_parts(ptr);
2203                     let byte_len = size_of::<IpAddress>() * len;
2204                     unsafe { &slice::from_raw_parts(ptr.cast::<u8>(), byte_len) }
2205                 })
2206                 .finish()
2207         }
2208     }
2209 
2210     impl TryFrom<&DevicePathNode> for &Dns {
2211         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>2212         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
2213             let static_size = 5usize;
2214             let dst_size = size_of_val(node)
2215                 .checked_sub(static_size)
2216                 .ok_or(NodeConversionError::InvalidLength)?;
2217             let elem_size = size_of::<IpAddress>();
2218             if dst_size % elem_size != 0 {
2219                 return Err(NodeConversionError::InvalidLength);
2220             }
2221 
2222             let node: *const DevicePathNode = node;
2223             let node: *const Dns = ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size);
2224             Ok(unsafe { &*node })
2225         }
2226     }
2227 
2228     /// NVDIMM namespace messaging device path node.
2229     #[repr(C, packed)]
2230     pub struct NvdimmNamespace {
2231         pub(super) header: DevicePathHeader,
2232         pub(super) uuid: [u8; 16usize],
2233     }
2234 
2235     impl NvdimmNamespace {
2236         /// Namespace unique label identifier.
2237         #[must_use]
uuid(&self) -> [u8; 16usize]2238         pub fn uuid(&self) -> [u8; 16usize] {
2239             self.uuid
2240         }
2241     }
2242 
2243     impl fmt::Debug for NvdimmNamespace {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result2244         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2245             f.debug_struct("NvdimmNamespace")
2246                 .field("uuid", &{ self.uuid })
2247                 .finish()
2248         }
2249     }
2250 
2251     impl TryFrom<&DevicePathNode> for &NvdimmNamespace {
2252         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>2253         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
2254             if size_of_val(node) != size_of::<NvdimmNamespace>() {
2255                 return Err(NodeConversionError::InvalidLength);
2256             }
2257 
2258             let node: *const DevicePathNode = node;
2259             let node: *const NvdimmNamespace = node.cast();
2260             Ok(unsafe { &*node })
2261         }
2262     }
2263 
2264     /// REST service messaging device path node.
2265     #[repr(C, packed)]
2266     #[derive(Pointee)]
2267     pub struct RestService {
2268         pub(super) header: DevicePathHeader,
2269         pub(super) service_type: device_path::messaging::RestServiceType,
2270         pub(super) access_mode: device_path::messaging::RestServiceAccessMode,
2271         pub(super) vendor_guid_and_data: [u8],
2272     }
2273 
2274     impl RestService {
2275         /// Type of REST service.
2276         #[must_use]
service_type(&self) -> device_path::messaging::RestServiceType2277         pub fn service_type(&self) -> device_path::messaging::RestServiceType {
2278             self.service_type
2279         }
2280 
2281         /// Whether the service is in-band or out-of-band.
2282         #[must_use]
access_mode(&self) -> device_path::messaging::RestServiceAccessMode2283         pub fn access_mode(&self) -> device_path::messaging::RestServiceAccessMode {
2284             self.access_mode
2285         }
2286     }
2287 
2288     impl fmt::Debug for RestService {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result2289         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2290             f.debug_struct("RestService")
2291                 .field("service_type", &{ self.service_type })
2292                 .field("access_mode", &{ self.access_mode })
2293                 .field("vendor_guid_and_data", {
2294                     let ptr = addr_of!(self.vendor_guid_and_data);
2295                     let (ptr, len) = PtrExt::to_raw_parts(ptr);
2296                     let byte_len = size_of::<u8>() * len;
2297                     unsafe { &slice::from_raw_parts(ptr.cast::<u8>(), byte_len) }
2298                 })
2299                 .finish()
2300         }
2301     }
2302 
2303     impl TryFrom<&DevicePathNode> for &RestService {
2304         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>2305         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
2306             let static_size = 6usize;
2307             let dst_size = size_of_val(node)
2308                 .checked_sub(static_size)
2309                 .ok_or(NodeConversionError::InvalidLength)?;
2310             let elem_size = size_of::<u8>();
2311             if dst_size % elem_size != 0 {
2312                 return Err(NodeConversionError::InvalidLength);
2313             }
2314 
2315             let node: *const DevicePathNode = node;
2316             let node: *const RestService =
2317                 ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size);
2318             Ok(unsafe { &*node })
2319         }
2320     }
2321 
2322     /// NVME over Fabric (NVMe-oF) namespace messaging device path node.
2323     #[repr(C, packed)]
2324     #[derive(Pointee)]
2325     pub struct NvmeOfNamespace {
2326         pub(super) header: DevicePathHeader,
2327         pub(super) nidt: u8,
2328         pub(super) nid: [u8; 16usize],
2329         pub(super) subsystem_nqn: [u8],
2330     }
2331 
2332     impl NvmeOfNamespace {
2333         /// Namespace Identifier Type (NIDT).
2334         #[must_use]
nidt(&self) -> u82335         pub fn nidt(&self) -> u8 {
2336             self.nidt
2337         }
2338 
2339         /// Namespace Identifier (NID).
2340         #[must_use]
nid(&self) -> [u8; 16usize]2341         pub fn nid(&self) -> [u8; 16usize] {
2342             self.nid
2343         }
2344 
2345         /// Unique identifier of an NVM subsystem stored as a
2346         /// null-terminated UTF-8 string. Maximum length of 224 bytes.
2347         #[must_use]
subsystem_nqn(&self) -> &[u8]2348         pub fn subsystem_nqn(&self) -> &[u8] {
2349             &self.subsystem_nqn
2350         }
2351     }
2352 
2353     impl fmt::Debug for NvmeOfNamespace {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result2354         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2355             f.debug_struct("NvmeOfNamespace")
2356                 .field("nidt", &{ self.nidt })
2357                 .field("nid", &{ self.nid })
2358                 .field("subsystem_nqn", {
2359                     let ptr = addr_of!(self.subsystem_nqn);
2360                     let (ptr, len) = PtrExt::to_raw_parts(ptr);
2361                     let byte_len = size_of::<u8>() * len;
2362                     unsafe { &slice::from_raw_parts(ptr.cast::<u8>(), byte_len) }
2363                 })
2364                 .finish()
2365         }
2366     }
2367 
2368     impl TryFrom<&DevicePathNode> for &NvmeOfNamespace {
2369         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>2370         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
2371             let static_size = 21usize;
2372             let dst_size = size_of_val(node)
2373                 .checked_sub(static_size)
2374                 .ok_or(NodeConversionError::InvalidLength)?;
2375             let elem_size = size_of::<u8>();
2376             if dst_size % elem_size != 0 {
2377                 return Err(NodeConversionError::InvalidLength);
2378             }
2379 
2380             let node: *const DevicePathNode = node;
2381             let node: *const NvmeOfNamespace =
2382                 ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size);
2383             Ok(unsafe { &*node })
2384         }
2385     }
2386 
2387     newtype_enum! { # [doc = " Whether the ATAPI device is primary or secondary."] pub enum PrimarySecondary : u8 => { # [doc = " Primary."] PRIMARY = 0x00 , # [doc = " Secondary."] SECONDARY = 0x01 , }
2388 
2389     }
2390 
2391     newtype_enum! { # [doc = " Whether the ATAPI device is master or slave."] pub enum MasterSlave : u8 => { # [doc = " Master mode."] MASTER = 0x00 , # [doc = " Slave mode."] SLAVE = 0x01 , }
2392 
2393     }
2394 
2395     newtype_enum! { # [doc = " Origin of the source IP address."] pub enum Ipv4AddressOrigin : u8 => { # [doc = " Source IP address was assigned through DHCP."] DHCP = 0x00 , # [doc = " Source IP address is statically bound."] STATIC = 0x01 , }
2396 
2397     }
2398 
2399     newtype_enum! { # [doc = " Origin of the local IP address."] pub enum Ipv6AddressOrigin : u8 => { # [doc = " Local IP address was manually configured."] MANUAL = 0x00 , # [doc = " Local IP address assigned through IPv6 stateless"] # [doc = " auto-configuration."] STATELESS_AUTO_CONFIGURATION = 0x01 , # [doc = " Local IP address assigned through IPv6 stateful"] # [doc = " configuration."] STATEFUL_CONFIGURATION = 0x02 , }
2400 
2401     }
2402 
2403     bitflags! { # [doc = " Flags to identify/manage InfiniBand elements."] # [derive (Clone , Copy , Debug , Default , PartialEq , Eq , PartialOrd , Ord)] # [repr (transparent)] pub struct InfinibandResourceFlags : u32 { # [doc = " Set = service, unset = IOC."] const SERVICE = 0x0000_0001 ; # [doc = " Extended boot environment."] const EXTENDED_BOOT_ENVIRONMENT = 0x0000_0002 ; # [doc = " Console protocol."] const CONSOLE_PROTOCOL = 0x0000_0004 ; # [doc = " Storage protocol."] const STORAGE_PROTOCOL = 0x0000_0008 ; # [doc = " Network protocol."] const NETWORK_PROTOCOL = 0x0000_0010 ; }
2404 
2405     }
2406 
2407     newtype_enum! { # [doc = " UART parity setting."] pub enum Parity : u8 => { # [doc = " Default parity."] DEFAULT = 0x00 , # [doc = " No parity."] NO = 0x01 , # [doc = " Even parity."] EVEN = 0x02 , # [doc = " Odd parity."] ODD = 0x03 , # [doc = " Mark parity."] MARK = 0x04 , # [doc = " Space parity."] SPACE = 0x05 , }
2408 
2409     }
2410 
2411     newtype_enum! { # [doc = " UART number of stop bits."] pub enum StopBits : u8 => { # [doc = " Default number of stop bits."] DEFAULT = 0x00 , # [doc = " 1 stop bit."] ONE = 0x01 , # [doc = " 1.5 stop bits."] ONE_POINT_FIVE = 0x02 , # [doc = " 2 stop bits."] TWO = 0x03 , }
2412 
2413     }
2414 
2415     impl Vendor {
2416         /// PC-ANSI terminal GUID.
2417         pub const PC_ANSI: Guid = guid!("e0c14753-f9be-11d2-9a0c-0090273fc14d");
2418         /// VT-100 terminal GUID.
2419         pub const VT_100: Guid = guid!("dfa66065-b419-11d3-9a2d-0090273fc14d");
2420         /// VT-100+ terminal GUID.
2421         pub const VT_100_PLUS: Guid = guid!("7baec70b-57e0-4c76-8e87-2f9e28088343");
2422         /// VT-UTF8 terminal GUID.
2423         pub const VT_UTF8: Guid = guid!("ad15a0d6-8bec-4acf-a073-d01de77e2d88");
2424     }
2425 
2426     newtype_enum! { # [doc = " iSCSI network protocol."] pub enum IscsiProtocol : u16 => { # [doc = " TCP."] TCP = 0x0000 , }
2427 
2428     }
2429 
2430     bitflags! { # [doc = " iSCSI login options."] # [derive (Clone , Copy , Debug , Default , PartialEq , Eq , PartialOrd , Ord)] # [repr (transparent)] pub struct IscsiLoginOptions : u16 { # [doc = " Header digest using CRC32. If not set, no header digest."] const HEADER_DIGEST_USING_CRC32 = 0x0002 ; # [doc = " Data digest using CRC32. If not set, no data digest."] const DATA_DIGEST_USING_CRC32 = 0x0008 ; # [doc = " Auth method none. If not set, auth method CHAP."] const AUTH_METHOD_NONE = 0x0800 ; # [doc = " CHAP UNI. If not set, CHAP BI."] const CHAP_UNI = 0x1000 ; }
2431 
2432     }
2433 
2434     newtype_enum! { # [doc = " BluetoothLE address type."] pub enum BluetoothLeAddressType : u8 => { # [doc = " Public device address."] PUBLIC = 0x00 , # [doc = " Random device address."] RANDOM = 0x01 , }
2435 
2436     }
2437 
2438     newtype_enum! { # [doc = " Whether the address is IPv4 or IPv6."] pub enum DnsAddressType : u8 => { # [doc = " DNS server address is IPv4."] IPV4 = 0x00 , # [doc = " DNS server address is IPv6."] IPV6 = 0x01 , }
2439 
2440     }
2441 
2442     impl RestService {
2443         /// Get the vendor GUID and vendor data. Only used if the
2444         /// service type is [`VENDOR`], otherwise returns None.
2445         ///
2446         /// [`VENDOR`]: uefi::proto::device_path::messaging::RestServiceType
2447         #[must_use]
vendor_guid_and_data(&self) -> Option<(Guid, &[u8])>2448         pub fn vendor_guid_and_data(&self) -> Option<(Guid, &[u8])> {
2449             if self.service_type == RestServiceType::VENDOR
2450                 && self.vendor_guid_and_data.len() >= size_of::<Guid>()
2451             {
2452                 let (guid, data) = self.vendor_guid_and_data.split_at(size_of::<Guid>());
2453                 let guid: [u8; 16] = guid.try_into().unwrap();
2454                 Some((Guid::from_bytes(guid), data))
2455             } else {
2456                 None
2457             }
2458         }
2459     }
2460 
2461     newtype_enum! { # [doc = " Type of REST service."] pub enum RestServiceType : u8 => { # [doc = " Redfish REST service."] REDFISH = 0x01 , # [doc = " OData REST service."] ODATA = 0x02 , # [doc = " Vendor-specific REST service."] VENDOR = 0xff , }
2462 
2463     }
2464 
2465     newtype_enum! { # [doc = " Whether the service is in-band or out-of-band."] pub enum RestServiceAccessMode : u8 => { # [doc = " In-band REST service."] IN_BAND = 0x01 , # [doc = " Out-of-band REST service."] OUT_OF_BAND = 0x02 , }
2466 
2467     }
2468 }
2469 
2470 /// Device path nodes for [`DeviceType::MEDIA`].
2471 pub mod media {
2472     use super::*;
2473     /// Hard drive media device path node.
2474     #[repr(C, packed)]
2475     pub struct HardDrive {
2476         pub(super) header: DevicePathHeader,
2477         pub(super) partition_number: u32,
2478         pub(super) partition_start: u64,
2479         pub(super) partition_size: u64,
2480         pub(super) partition_signature: [u8; 16usize],
2481         pub(super) partition_format: device_path::media::PartitionFormat,
2482         pub(super) signature_type: u8,
2483     }
2484 
2485     impl HardDrive {
2486         /// Index of the partition, starting from 1.
2487         #[must_use]
partition_number(&self) -> u322488         pub fn partition_number(&self) -> u32 {
2489             self.partition_number
2490         }
2491 
2492         /// Starting LBA (logical block address) of the partition.
2493         #[must_use]
partition_start(&self) -> u642494         pub fn partition_start(&self) -> u64 {
2495             self.partition_start
2496         }
2497 
2498         /// Size of the partition in blocks.
2499         #[must_use]
partition_size(&self) -> u642500         pub fn partition_size(&self) -> u64 {
2501             self.partition_size
2502         }
2503 
2504         /// Partition format.
2505         #[must_use]
partition_format(&self) -> device_path::media::PartitionFormat2506         pub fn partition_format(&self) -> device_path::media::PartitionFormat {
2507             self.partition_format
2508         }
2509     }
2510 
2511     impl fmt::Debug for HardDrive {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result2512         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2513             f.debug_struct("HardDrive")
2514                 .field("partition_number", &{ self.partition_number })
2515                 .field("partition_start", &{ self.partition_start })
2516                 .field("partition_size", &{ self.partition_size })
2517                 .field("partition_signature", &{ self.partition_signature })
2518                 .field("partition_format", &{ self.partition_format })
2519                 .field("signature_type", &{ self.signature_type })
2520                 .finish()
2521         }
2522     }
2523 
2524     impl TryFrom<&DevicePathNode> for &HardDrive {
2525         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>2526         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
2527             if size_of_val(node) != size_of::<HardDrive>() {
2528                 return Err(NodeConversionError::InvalidLength);
2529             }
2530 
2531             let node: *const DevicePathNode = node;
2532             let node: *const HardDrive = node.cast();
2533             Ok(unsafe { &*node })
2534         }
2535     }
2536 
2537     /// CD-ROM media device path node.
2538     #[repr(C, packed)]
2539     pub struct CdRom {
2540         pub(super) header: DevicePathHeader,
2541         pub(super) boot_entry: u32,
2542         pub(super) partition_start: u64,
2543         pub(super) partition_size: u64,
2544     }
2545 
2546     impl CdRom {
2547         /// Boot entry number from the boot catalog, or 0 for the
2548         /// default entry.
2549         #[must_use]
boot_entry(&self) -> u322550         pub fn boot_entry(&self) -> u32 {
2551             self.boot_entry
2552         }
2553 
2554         /// Starting RBA (Relative logical Block Address).
2555         #[must_use]
partition_start(&self) -> u642556         pub fn partition_start(&self) -> u64 {
2557             self.partition_start
2558         }
2559 
2560         /// Size of the partition in blocks.
2561         #[must_use]
partition_size(&self) -> u642562         pub fn partition_size(&self) -> u64 {
2563             self.partition_size
2564         }
2565     }
2566 
2567     impl fmt::Debug for CdRom {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result2568         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2569             f.debug_struct("CdRom")
2570                 .field("boot_entry", &{ self.boot_entry })
2571                 .field("partition_start", &{ self.partition_start })
2572                 .field("partition_size", &{ self.partition_size })
2573                 .finish()
2574         }
2575     }
2576 
2577     impl TryFrom<&DevicePathNode> for &CdRom {
2578         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>2579         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
2580             if size_of_val(node) != size_of::<CdRom>() {
2581                 return Err(NodeConversionError::InvalidLength);
2582             }
2583 
2584             let node: *const DevicePathNode = node;
2585             let node: *const CdRom = node.cast();
2586             Ok(unsafe { &*node })
2587         }
2588     }
2589 
2590     /// Vendor-defined media device path node.
2591     #[repr(C, packed)]
2592     #[derive(Pointee)]
2593     pub struct Vendor {
2594         pub(super) header: DevicePathHeader,
2595         pub(super) vendor_guid: Guid,
2596         pub(super) vendor_defined_data: [u8],
2597     }
2598 
2599     impl Vendor {
2600         /// Vendor-assigned GUID that defines the data that follows.
2601         #[must_use]
vendor_guid(&self) -> Guid2602         pub fn vendor_guid(&self) -> Guid {
2603             self.vendor_guid
2604         }
2605 
2606         /// Vendor-defined data.
2607         #[must_use]
vendor_defined_data(&self) -> &[u8]2608         pub fn vendor_defined_data(&self) -> &[u8] {
2609             &self.vendor_defined_data
2610         }
2611     }
2612 
2613     impl fmt::Debug for Vendor {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result2614         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2615             f.debug_struct("Vendor")
2616                 .field("vendor_guid", &{ self.vendor_guid })
2617                 .field("vendor_defined_data", {
2618                     let ptr = addr_of!(self.vendor_defined_data);
2619                     let (ptr, len) = PtrExt::to_raw_parts(ptr);
2620                     let byte_len = size_of::<u8>() * len;
2621                     unsafe { &slice::from_raw_parts(ptr.cast::<u8>(), byte_len) }
2622                 })
2623                 .finish()
2624         }
2625     }
2626 
2627     impl TryFrom<&DevicePathNode> for &Vendor {
2628         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>2629         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
2630             let static_size = 20usize;
2631             let dst_size = size_of_val(node)
2632                 .checked_sub(static_size)
2633                 .ok_or(NodeConversionError::InvalidLength)?;
2634             let elem_size = size_of::<u8>();
2635             if dst_size % elem_size != 0 {
2636                 return Err(NodeConversionError::InvalidLength);
2637             }
2638 
2639             let node: *const DevicePathNode = node;
2640             let node: *const Vendor = ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size);
2641             Ok(unsafe { &*node })
2642         }
2643     }
2644 
2645     /// File path media device path node.
2646     #[repr(C, packed)]
2647     #[derive(Pointee)]
2648     pub struct FilePath {
2649         pub(super) header: DevicePathHeader,
2650         pub(super) path_name: [u16],
2651     }
2652 
2653     impl FilePath {
2654         /// Null-terminated path.
2655         #[must_use]
path_name(&self) -> UnalignedSlice<u16>2656         pub fn path_name(&self) -> UnalignedSlice<u16> {
2657             let ptr: *const [u16] = addr_of!(self.path_name);
2658             let (ptr, len): (*const (), usize) = PtrExt::to_raw_parts(ptr);
2659             unsafe { UnalignedSlice::new(ptr.cast::<u16>(), len) }
2660         }
2661     }
2662 
2663     impl fmt::Debug for FilePath {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result2664         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2665             f.debug_struct("FilePath")
2666                 .field("path_name", {
2667                     let ptr = addr_of!(self.path_name);
2668                     let (ptr, len) = PtrExt::to_raw_parts(ptr);
2669                     let byte_len = size_of::<u16>() * len;
2670                     unsafe { &slice::from_raw_parts(ptr.cast::<u8>(), byte_len) }
2671                 })
2672                 .finish()
2673         }
2674     }
2675 
2676     impl TryFrom<&DevicePathNode> for &FilePath {
2677         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>2678         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
2679             let static_size = 4usize;
2680             let dst_size = size_of_val(node)
2681                 .checked_sub(static_size)
2682                 .ok_or(NodeConversionError::InvalidLength)?;
2683             let elem_size = size_of::<u16>();
2684             if dst_size % elem_size != 0 {
2685                 return Err(NodeConversionError::InvalidLength);
2686             }
2687 
2688             let node: *const DevicePathNode = node;
2689             let node: *const FilePath = ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size);
2690             Ok(unsafe { &*node })
2691         }
2692     }
2693 
2694     /// Media protocol media device path node.
2695     #[repr(C, packed)]
2696     pub struct Protocol {
2697         pub(super) header: DevicePathHeader,
2698         pub(super) protocol_guid: Guid,
2699     }
2700 
2701     impl Protocol {
2702         /// The ID of the protocol.
2703         #[must_use]
protocol_guid(&self) -> Guid2704         pub fn protocol_guid(&self) -> Guid {
2705             self.protocol_guid
2706         }
2707     }
2708 
2709     impl fmt::Debug for Protocol {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result2710         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2711             f.debug_struct("Protocol")
2712                 .field("protocol_guid", &{ self.protocol_guid })
2713                 .finish()
2714         }
2715     }
2716 
2717     impl TryFrom<&DevicePathNode> for &Protocol {
2718         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>2719         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
2720             if size_of_val(node) != size_of::<Protocol>() {
2721                 return Err(NodeConversionError::InvalidLength);
2722             }
2723 
2724             let node: *const DevicePathNode = node;
2725             let node: *const Protocol = node.cast();
2726             Ok(unsafe { &*node })
2727         }
2728     }
2729 
2730     /// PIWG firmware file media device path node.
2731     #[repr(C, packed)]
2732     #[derive(Pointee)]
2733     pub struct PiwgFirmwareFile {
2734         pub(super) header: DevicePathHeader,
2735         pub(super) data: [u8],
2736     }
2737 
2738     impl PiwgFirmwareFile {
2739         /// Contents are defined in the UEFI PI Specification.
2740         #[must_use]
data(&self) -> &[u8]2741         pub fn data(&self) -> &[u8] {
2742             &self.data
2743         }
2744     }
2745 
2746     impl fmt::Debug for PiwgFirmwareFile {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result2747         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2748             f.debug_struct("PiwgFirmwareFile")
2749                 .field("data", {
2750                     let ptr = addr_of!(self.data);
2751                     let (ptr, len) = PtrExt::to_raw_parts(ptr);
2752                     let byte_len = size_of::<u8>() * len;
2753                     unsafe { &slice::from_raw_parts(ptr.cast::<u8>(), byte_len) }
2754                 })
2755                 .finish()
2756         }
2757     }
2758 
2759     impl TryFrom<&DevicePathNode> for &PiwgFirmwareFile {
2760         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>2761         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
2762             let static_size = 4usize;
2763             let dst_size = size_of_val(node)
2764                 .checked_sub(static_size)
2765                 .ok_or(NodeConversionError::InvalidLength)?;
2766             let elem_size = size_of::<u8>();
2767             if dst_size % elem_size != 0 {
2768                 return Err(NodeConversionError::InvalidLength);
2769             }
2770 
2771             let node: *const DevicePathNode = node;
2772             let node: *const PiwgFirmwareFile =
2773                 ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size);
2774             Ok(unsafe { &*node })
2775         }
2776     }
2777 
2778     /// PIWG firmware volume media device path node.
2779     #[repr(C, packed)]
2780     #[derive(Pointee)]
2781     pub struct PiwgFirmwareVolume {
2782         pub(super) header: DevicePathHeader,
2783         pub(super) data: [u8],
2784     }
2785 
2786     impl PiwgFirmwareVolume {
2787         /// Contents are defined in the UEFI PI Specification.
2788         #[must_use]
data(&self) -> &[u8]2789         pub fn data(&self) -> &[u8] {
2790             &self.data
2791         }
2792     }
2793 
2794     impl fmt::Debug for PiwgFirmwareVolume {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result2795         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2796             f.debug_struct("PiwgFirmwareVolume")
2797                 .field("data", {
2798                     let ptr = addr_of!(self.data);
2799                     let (ptr, len) = PtrExt::to_raw_parts(ptr);
2800                     let byte_len = size_of::<u8>() * len;
2801                     unsafe { &slice::from_raw_parts(ptr.cast::<u8>(), byte_len) }
2802                 })
2803                 .finish()
2804         }
2805     }
2806 
2807     impl TryFrom<&DevicePathNode> for &PiwgFirmwareVolume {
2808         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>2809         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
2810             let static_size = 4usize;
2811             let dst_size = size_of_val(node)
2812                 .checked_sub(static_size)
2813                 .ok_or(NodeConversionError::InvalidLength)?;
2814             let elem_size = size_of::<u8>();
2815             if dst_size % elem_size != 0 {
2816                 return Err(NodeConversionError::InvalidLength);
2817             }
2818 
2819             let node: *const DevicePathNode = node;
2820             let node: *const PiwgFirmwareVolume =
2821                 ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size);
2822             Ok(unsafe { &*node })
2823         }
2824     }
2825 
2826     /// Relative offset range media device path node.
2827     #[repr(C, packed)]
2828     pub struct RelativeOffsetRange {
2829         pub(super) header: DevicePathHeader,
2830         pub(super) _reserved: u32,
2831         pub(super) starting_offset: u64,
2832         pub(super) ending_offset: u64,
2833     }
2834 
2835     impl RelativeOffsetRange {
2836         /// Offset of the first byte, relative to the parent device node.
2837         #[must_use]
starting_offset(&self) -> u642838         pub fn starting_offset(&self) -> u64 {
2839             self.starting_offset
2840         }
2841 
2842         /// Offset of the last byte, relative to the parent device node.
2843         #[must_use]
ending_offset(&self) -> u642844         pub fn ending_offset(&self) -> u64 {
2845             self.ending_offset
2846         }
2847     }
2848 
2849     impl fmt::Debug for RelativeOffsetRange {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result2850         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2851             f.debug_struct("RelativeOffsetRange")
2852                 .field("_reserved", &{ self._reserved })
2853                 .field("starting_offset", &{ self.starting_offset })
2854                 .field("ending_offset", &{ self.ending_offset })
2855                 .finish()
2856         }
2857     }
2858 
2859     impl TryFrom<&DevicePathNode> for &RelativeOffsetRange {
2860         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>2861         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
2862             if size_of_val(node) != size_of::<RelativeOffsetRange>() {
2863                 return Err(NodeConversionError::InvalidLength);
2864             }
2865 
2866             let node: *const DevicePathNode = node;
2867             let node: *const RelativeOffsetRange = node.cast();
2868             Ok(unsafe { &*node })
2869         }
2870     }
2871 
2872     /// RAM disk media device path node.
2873     #[repr(C, packed)]
2874     pub struct RamDisk {
2875         pub(super) header: DevicePathHeader,
2876         pub(super) starting_address: u64,
2877         pub(super) ending_address: u64,
2878         pub(super) disk_type: device_path::media::RamDiskType,
2879         pub(super) disk_instance: u16,
2880     }
2881 
2882     impl RamDisk {
2883         /// Starting memory address.
2884         #[must_use]
starting_address(&self) -> u642885         pub fn starting_address(&self) -> u64 {
2886             self.starting_address
2887         }
2888 
2889         /// Ending memory address.
2890         #[must_use]
ending_address(&self) -> u642891         pub fn ending_address(&self) -> u64 {
2892             self.ending_address
2893         }
2894 
2895         /// Type of RAM disk.
2896         #[must_use]
disk_type(&self) -> device_path::media::RamDiskType2897         pub fn disk_type(&self) -> device_path::media::RamDiskType {
2898             self.disk_type
2899         }
2900 
2901         /// RAM disk instance number if supported, otherwise 0.
2902         #[must_use]
disk_instance(&self) -> u162903         pub fn disk_instance(&self) -> u16 {
2904             self.disk_instance
2905         }
2906     }
2907 
2908     impl fmt::Debug for RamDisk {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result2909         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2910             f.debug_struct("RamDisk")
2911                 .field("starting_address", &{ self.starting_address })
2912                 .field("ending_address", &{ self.ending_address })
2913                 .field("disk_type", &{ self.disk_type })
2914                 .field("disk_instance", &{ self.disk_instance })
2915                 .finish()
2916         }
2917     }
2918 
2919     impl TryFrom<&DevicePathNode> for &RamDisk {
2920         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>2921         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
2922             if size_of_val(node) != size_of::<RamDisk>() {
2923                 return Err(NodeConversionError::InvalidLength);
2924             }
2925 
2926             let node: *const DevicePathNode = node;
2927             let node: *const RamDisk = node.cast();
2928             Ok(unsafe { &*node })
2929         }
2930     }
2931 
2932     impl HardDrive {
2933         /// Signature unique to this partition.
2934         #[must_use]
partition_signature(&self) -> PartitionSignature2935         pub fn partition_signature(&self) -> PartitionSignature {
2936             match self.signature_type {
2937                 0 => PartitionSignature::None,
2938                 1 => PartitionSignature::Mbr([
2939                     self.partition_signature[0],
2940                     self.partition_signature[1],
2941                     self.partition_signature[2],
2942                     self.partition_signature[3],
2943                 ]),
2944                 2 => PartitionSignature::Guid(Guid::from_bytes(self.partition_signature)),
2945                 unknown => PartitionSignature::Unknown {
2946                     signature_type: unknown,
2947                     signature: self.partition_signature,
2948                 },
2949             }
2950         }
2951     }
2952 
2953     /// Hard drive partition signature.
2954     #[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
2955     pub enum PartitionSignature {
2956         /// No disk signature.
2957         None,
2958         /// 32-bit MBR partition signature.
2959         Mbr([u8; 4]),
2960         /// 128-bit GUID partition signature.
2961         Guid(Guid),
2962         /// Unknown signature type not listed in the UEFI Specification.
2963         Unknown {
2964             /// Signature type.
2965             signature_type: u8,
2966             /// Signature data.
2967             signature: [u8; 16],
2968         },
2969     }
2970 
2971     newtype_enum! { # [doc = " Hard drive partition format."] pub enum PartitionFormat : u8 => { # [doc = " MBR (PC-AT compatible Master Boot Record) format."] MBR = 0x01 , # [doc = " GPT (GUID Partition Table) format."] GPT = 0x02 , }
2972 
2973     }
2974 
2975     newtype_enum! { # [doc = " RAM disk type."] pub enum RamDiskType : Guid => { # [doc = " RAM disk with a raw disk format in volatile memory."] VIRTUAL_DISK = guid ! ("77ab535a-45fc-624b-5560-f7b281d1f96e") , # [doc = " RAM disk of an ISO image in volatile memory."] VIRTUAL_CD = guid ! ("3d5abd30-4175-87ce-6d64-d2ade523c4bb") , # [doc = " RAM disk with a raw disk format in persistent memory."] PERSISTENT_VIRTUAL_DISK = guid ! ("5cea02c9-4d07-69d3-269f-4496fbe096f9") , # [doc = " RAM disk of an ISO image in persistent memory."] PERSISTENT_VIRTUAL_CD = guid ! ("08018188-42cd-bb48-100f-5387d53ded3d") , }
2976 
2977     }
2978 }
2979 
2980 /// Device path nodes for [`DeviceType::BIOS_BOOT_SPEC`].
2981 pub mod bios_boot_spec {
2982     use super::*;
2983     /// BIOS Boot Specification device path node.
2984     #[repr(C, packed)]
2985     #[derive(Pointee)]
2986     pub struct BootSpecification {
2987         pub(super) header: DevicePathHeader,
2988         pub(super) device_type: u16,
2989         pub(super) status_flag: u16,
2990         pub(super) description_string: [u8],
2991     }
2992 
2993     impl BootSpecification {
2994         /// Device type as defined by the BIOS Boot Specification.
2995         #[must_use]
device_type(&self) -> u162996         pub fn device_type(&self) -> u16 {
2997             self.device_type
2998         }
2999 
3000         /// Status flags as defined by the BIOS Boot Specification.
3001         #[must_use]
status_flag(&self) -> u163002         pub fn status_flag(&self) -> u16 {
3003             self.status_flag
3004         }
3005 
3006         /// Description of the boot device encoded as a null-terminated
3007         /// ASCII string.
3008         #[must_use]
description_string(&self) -> &[u8]3009         pub fn description_string(&self) -> &[u8] {
3010             &self.description_string
3011         }
3012     }
3013 
3014     impl fmt::Debug for BootSpecification {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result3015         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3016             f.debug_struct("BootSpecification")
3017                 .field("device_type", &{ self.device_type })
3018                 .field("status_flag", &{ self.status_flag })
3019                 .field("description_string", {
3020                     let ptr = addr_of!(self.description_string);
3021                     let (ptr, len) = PtrExt::to_raw_parts(ptr);
3022                     let byte_len = size_of::<u8>() * len;
3023                     unsafe { &slice::from_raw_parts(ptr.cast::<u8>(), byte_len) }
3024                 })
3025                 .finish()
3026         }
3027     }
3028 
3029     impl TryFrom<&DevicePathNode> for &BootSpecification {
3030         type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>3031         fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
3032             let static_size = 8usize;
3033             let dst_size = size_of_val(node)
3034                 .checked_sub(static_size)
3035                 .ok_or(NodeConversionError::InvalidLength)?;
3036             let elem_size = size_of::<u8>();
3037             if dst_size % elem_size != 0 {
3038                 return Err(NodeConversionError::InvalidLength);
3039             }
3040 
3041             let node: *const DevicePathNode = node;
3042             let node: *const BootSpecification =
3043                 ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size);
3044             Ok(unsafe { &*node })
3045         }
3046     }
3047 }
3048 
3049 /// Enum of references to all the different device path node
3050 /// types. Return type of [`DevicePathNode::as_enum`].
3051 #[derive(Debug)]
3052 pub enum DevicePathNodeEnum<'a> {
3053     /// Node that terminates a [`DevicePathInstance`].
3054     ///
3055     /// [`DevicePathInstance`]: device_path::DevicePathInstance
3056     EndInstance(&'a end::Instance),
3057     /// Node that terminates an entire [`DevicePath`].
3058     ///
3059     /// [`DevicePath`]: device_path::DevicePath
3060     EndEntire(&'a end::Entire),
3061     /// PCI hardware device path node.
3062     HardwarePci(&'a hardware::Pci),
3063     /// PCCARD hardware device path node.
3064     HardwarePccard(&'a hardware::Pccard),
3065     /// Memory mapped hardware device path node.
3066     HardwareMemoryMapped(&'a hardware::MemoryMapped),
3067     /// Vendor-defined hardware device path node.
3068     HardwareVendor(&'a hardware::Vendor),
3069     /// Controller hardware device path node.
3070     HardwareController(&'a hardware::Controller),
3071     /// Baseboard Management Controller (BMC) host interface hardware
3072     /// device path node.
3073     HardwareBmc(&'a hardware::Bmc),
3074     /// ACPI device path node.
3075     AcpiAcpi(&'a acpi::Acpi),
3076     /// Expanded ACPI device path node.
3077     AcpiExpanded(&'a acpi::Expanded),
3078     /// ADR ACPI device path node.
3079     AcpiAdr(&'a acpi::Adr),
3080     /// NVDIMM ACPI device path node.
3081     AcpiNvdimm(&'a acpi::Nvdimm),
3082     /// ATAPI messaging device path node.
3083     MessagingAtapi(&'a messaging::Atapi),
3084     /// SCSI messaging device path node.
3085     MessagingScsi(&'a messaging::Scsi),
3086     /// Fibre channel messaging device path node.
3087     MessagingFibreChannel(&'a messaging::FibreChannel),
3088     /// Fibre channel extended messaging device path node.
3089     MessagingFibreChannelEx(&'a messaging::FibreChannelEx),
3090     /// 1394 messaging device path node.
3091     MessagingIeee1394(&'a messaging::Ieee1394),
3092     /// USB messaging device path node.
3093     MessagingUsb(&'a messaging::Usb),
3094     /// SATA messaging device path node.
3095     MessagingSata(&'a messaging::Sata),
3096     /// USB World Wide ID (WWID) messaging device path node.
3097     MessagingUsbWwid(&'a messaging::UsbWwid),
3098     /// Device logical unit messaging device path node.
3099     MessagingDeviceLogicalUnit(&'a messaging::DeviceLogicalUnit),
3100     /// USB class messaging device path node.
3101     MessagingUsbClass(&'a messaging::UsbClass),
3102     /// I2O messaging device path node.
3103     MessagingI2o(&'a messaging::I2o),
3104     /// MAC address messaging device path node.
3105     MessagingMacAddress(&'a messaging::MacAddress),
3106     /// IPv4 messaging device path node.
3107     MessagingIpv4(&'a messaging::Ipv4),
3108     /// IPv6 messaging device path node.
3109     MessagingIpv6(&'a messaging::Ipv6),
3110     /// VLAN messaging device path node.
3111     MessagingVlan(&'a messaging::Vlan),
3112     /// InfiniBand messaging device path node.
3113     MessagingInfiniband(&'a messaging::Infiniband),
3114     /// UART messaging device path node.
3115     MessagingUart(&'a messaging::Uart),
3116     /// Vendor-defined messaging device path node.
3117     MessagingVendor(&'a messaging::Vendor),
3118     /// Serial Attached SCSI (SAS) extended messaging device path node.
3119     MessagingSasEx(&'a messaging::SasEx),
3120     /// iSCSI messaging device path node.
3121     MessagingIscsi(&'a messaging::Iscsi),
3122     /// NVM Express namespace messaging device path node.
3123     MessagingNvmeNamespace(&'a messaging::NvmeNamespace),
3124     /// Uniform Resource Identifier (URI) messaging device path node.
3125     MessagingUri(&'a messaging::Uri),
3126     /// Universal Flash Storage (UFS) messaging device path node.
3127     MessagingUfs(&'a messaging::Ufs),
3128     /// Secure Digital (SD) messaging device path node.
3129     MessagingSd(&'a messaging::Sd),
3130     /// Bluetooth messaging device path node.
3131     MessagingBluetooth(&'a messaging::Bluetooth),
3132     /// Wi-Fi messaging device path node.
3133     MessagingWifi(&'a messaging::Wifi),
3134     /// Embedded Multi-Media Card (eMMC) messaging device path node.
3135     MessagingEmmc(&'a messaging::Emmc),
3136     /// BluetoothLE messaging device path node.
3137     MessagingBluetoothLe(&'a messaging::BluetoothLe),
3138     /// DNS messaging device path node.
3139     MessagingDns(&'a messaging::Dns),
3140     /// NVDIMM namespace messaging device path node.
3141     MessagingNvdimmNamespace(&'a messaging::NvdimmNamespace),
3142     /// REST service messaging device path node.
3143     MessagingRestService(&'a messaging::RestService),
3144     /// NVME over Fabric (NVMe-oF) namespace messaging device path node.
3145     MessagingNvmeOfNamespace(&'a messaging::NvmeOfNamespace),
3146     /// Hard drive media device path node.
3147     MediaHardDrive(&'a media::HardDrive),
3148     /// CD-ROM media device path node.
3149     MediaCdRom(&'a media::CdRom),
3150     /// Vendor-defined media device path node.
3151     MediaVendor(&'a media::Vendor),
3152     /// File path media device path node.
3153     MediaFilePath(&'a media::FilePath),
3154     /// Media protocol media device path node.
3155     MediaProtocol(&'a media::Protocol),
3156     /// PIWG firmware file media device path node.
3157     MediaPiwgFirmwareFile(&'a media::PiwgFirmwareFile),
3158     /// PIWG firmware volume media device path node.
3159     MediaPiwgFirmwareVolume(&'a media::PiwgFirmwareVolume),
3160     /// Relative offset range media device path node.
3161     MediaRelativeOffsetRange(&'a media::RelativeOffsetRange),
3162     /// RAM disk media device path node.
3163     MediaRamDisk(&'a media::RamDisk),
3164     /// BIOS Boot Specification device path node.
3165     BiosBootSpecBootSpecification(&'a bios_boot_spec::BootSpecification),
3166 }
3167 
3168 impl<'a> TryFrom<&DevicePathNode> for DevicePathNodeEnum<'a> {
3169     type Error = NodeConversionError;
try_from(node: &DevicePathNode) -> Result<Self, Self::Error>3170     fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
3171         Ok(match node.full_type() {
3172             (DeviceType::END, DeviceSubType::END_INSTANCE) => Self::EndInstance(node.try_into()?),
3173             (DeviceType::END, DeviceSubType::END_ENTIRE) => Self::EndEntire(node.try_into()?),
3174             (DeviceType::HARDWARE, DeviceSubType::HARDWARE_PCI) => {
3175                 Self::HardwarePci(node.try_into()?)
3176             }
3177             (DeviceType::HARDWARE, DeviceSubType::HARDWARE_PCCARD) => {
3178                 Self::HardwarePccard(node.try_into()?)
3179             }
3180             (DeviceType::HARDWARE, DeviceSubType::HARDWARE_MEMORY_MAPPED) => {
3181                 Self::HardwareMemoryMapped(node.try_into()?)
3182             }
3183             (DeviceType::HARDWARE, DeviceSubType::HARDWARE_VENDOR) => {
3184                 Self::HardwareVendor(node.try_into()?)
3185             }
3186             (DeviceType::HARDWARE, DeviceSubType::HARDWARE_CONTROLLER) => {
3187                 Self::HardwareController(node.try_into()?)
3188             }
3189             (DeviceType::HARDWARE, DeviceSubType::HARDWARE_BMC) => {
3190                 Self::HardwareBmc(node.try_into()?)
3191             }
3192             (DeviceType::ACPI, DeviceSubType::ACPI) => Self::AcpiAcpi(node.try_into()?),
3193             (DeviceType::ACPI, DeviceSubType::ACPI_EXPANDED) => {
3194                 Self::AcpiExpanded(node.try_into()?)
3195             }
3196             (DeviceType::ACPI, DeviceSubType::ACPI_ADR) => Self::AcpiAdr(node.try_into()?),
3197             (DeviceType::ACPI, DeviceSubType::ACPI_NVDIMM) => Self::AcpiNvdimm(node.try_into()?),
3198             (DeviceType::MESSAGING, DeviceSubType::MESSAGING_ATAPI) => {
3199                 Self::MessagingAtapi(node.try_into()?)
3200             }
3201             (DeviceType::MESSAGING, DeviceSubType::MESSAGING_SCSI) => {
3202                 Self::MessagingScsi(node.try_into()?)
3203             }
3204             (DeviceType::MESSAGING, DeviceSubType::MESSAGING_FIBRE_CHANNEL) => {
3205                 Self::MessagingFibreChannel(node.try_into()?)
3206             }
3207             (DeviceType::MESSAGING, DeviceSubType::MESSAGING_FIBRE_CHANNEL_EX) => {
3208                 Self::MessagingFibreChannelEx(node.try_into()?)
3209             }
3210             (DeviceType::MESSAGING, DeviceSubType::MESSAGING_1394) => {
3211                 Self::MessagingIeee1394(node.try_into()?)
3212             }
3213             (DeviceType::MESSAGING, DeviceSubType::MESSAGING_USB) => {
3214                 Self::MessagingUsb(node.try_into()?)
3215             }
3216             (DeviceType::MESSAGING, DeviceSubType::MESSAGING_SATA) => {
3217                 Self::MessagingSata(node.try_into()?)
3218             }
3219             (DeviceType::MESSAGING, DeviceSubType::MESSAGING_USB_WWID) => {
3220                 Self::MessagingUsbWwid(node.try_into()?)
3221             }
3222             (DeviceType::MESSAGING, DeviceSubType::MESSAGING_DEVICE_LOGICAL_UNIT) => {
3223                 Self::MessagingDeviceLogicalUnit(node.try_into()?)
3224             }
3225             (DeviceType::MESSAGING, DeviceSubType::MESSAGING_USB_CLASS) => {
3226                 Self::MessagingUsbClass(node.try_into()?)
3227             }
3228             (DeviceType::MESSAGING, DeviceSubType::MESSAGING_I2O) => {
3229                 Self::MessagingI2o(node.try_into()?)
3230             }
3231             (DeviceType::MESSAGING, DeviceSubType::MESSAGING_MAC_ADDRESS) => {
3232                 Self::MessagingMacAddress(node.try_into()?)
3233             }
3234             (DeviceType::MESSAGING, DeviceSubType::MESSAGING_IPV4) => {
3235                 Self::MessagingIpv4(node.try_into()?)
3236             }
3237             (DeviceType::MESSAGING, DeviceSubType::MESSAGING_IPV6) => {
3238                 Self::MessagingIpv6(node.try_into()?)
3239             }
3240             (DeviceType::MESSAGING, DeviceSubType::MESSAGING_VLAN) => {
3241                 Self::MessagingVlan(node.try_into()?)
3242             }
3243             (DeviceType::MESSAGING, DeviceSubType::MESSAGING_INFINIBAND) => {
3244                 Self::MessagingInfiniband(node.try_into()?)
3245             }
3246             (DeviceType::MESSAGING, DeviceSubType::MESSAGING_UART) => {
3247                 Self::MessagingUart(node.try_into()?)
3248             }
3249             (DeviceType::MESSAGING, DeviceSubType::MESSAGING_VENDOR) => {
3250                 Self::MessagingVendor(node.try_into()?)
3251             }
3252             (DeviceType::MESSAGING, DeviceSubType::MESSAGING_SCSI_SAS_EX) => {
3253                 Self::MessagingSasEx(node.try_into()?)
3254             }
3255             (DeviceType::MESSAGING, DeviceSubType::MESSAGING_ISCSI) => {
3256                 Self::MessagingIscsi(node.try_into()?)
3257             }
3258             (DeviceType::MESSAGING, DeviceSubType::MESSAGING_NVME_NAMESPACE) => {
3259                 Self::MessagingNvmeNamespace(node.try_into()?)
3260             }
3261             (DeviceType::MESSAGING, DeviceSubType::MESSAGING_URI) => {
3262                 Self::MessagingUri(node.try_into()?)
3263             }
3264             (DeviceType::MESSAGING, DeviceSubType::MESSAGING_UFS) => {
3265                 Self::MessagingUfs(node.try_into()?)
3266             }
3267             (DeviceType::MESSAGING, DeviceSubType::MESSAGING_SD) => {
3268                 Self::MessagingSd(node.try_into()?)
3269             }
3270             (DeviceType::MESSAGING, DeviceSubType::MESSAGING_BLUETOOTH) => {
3271                 Self::MessagingBluetooth(node.try_into()?)
3272             }
3273             (DeviceType::MESSAGING, DeviceSubType::MESSAGING_WIFI) => {
3274                 Self::MessagingWifi(node.try_into()?)
3275             }
3276             (DeviceType::MESSAGING, DeviceSubType::MESSAGING_EMMC) => {
3277                 Self::MessagingEmmc(node.try_into()?)
3278             }
3279             (DeviceType::MESSAGING, DeviceSubType::MESSAGING_BLUETOOTH_LE) => {
3280                 Self::MessagingBluetoothLe(node.try_into()?)
3281             }
3282             (DeviceType::MESSAGING, DeviceSubType::MESSAGING_DNS) => {
3283                 Self::MessagingDns(node.try_into()?)
3284             }
3285             (DeviceType::MESSAGING, DeviceSubType::MESSAGING_NVDIMM_NAMESPACE) => {
3286                 Self::MessagingNvdimmNamespace(node.try_into()?)
3287             }
3288             (DeviceType::MESSAGING, DeviceSubType::MESSAGING_REST_SERVICE) => {
3289                 Self::MessagingRestService(node.try_into()?)
3290             }
3291             (DeviceType::MESSAGING, DeviceSubType::MESSAGING_NVME_OF_NAMESPACE) => {
3292                 Self::MessagingNvmeOfNamespace(node.try_into()?)
3293             }
3294             (DeviceType::MEDIA, DeviceSubType::MEDIA_HARD_DRIVE) => {
3295                 Self::MediaHardDrive(node.try_into()?)
3296             }
3297             (DeviceType::MEDIA, DeviceSubType::MEDIA_CD_ROM) => Self::MediaCdRom(node.try_into()?),
3298             (DeviceType::MEDIA, DeviceSubType::MEDIA_VENDOR) => Self::MediaVendor(node.try_into()?),
3299             (DeviceType::MEDIA, DeviceSubType::MEDIA_FILE_PATH) => {
3300                 Self::MediaFilePath(node.try_into()?)
3301             }
3302             (DeviceType::MEDIA, DeviceSubType::MEDIA_PROTOCOL) => {
3303                 Self::MediaProtocol(node.try_into()?)
3304             }
3305             (DeviceType::MEDIA, DeviceSubType::MEDIA_PIWG_FIRMWARE_FILE) => {
3306                 Self::MediaPiwgFirmwareFile(node.try_into()?)
3307             }
3308             (DeviceType::MEDIA, DeviceSubType::MEDIA_PIWG_FIRMWARE_VOLUME) => {
3309                 Self::MediaPiwgFirmwareVolume(node.try_into()?)
3310             }
3311             (DeviceType::MEDIA, DeviceSubType::MEDIA_RELATIVE_OFFSET_RANGE) => {
3312                 Self::MediaRelativeOffsetRange(node.try_into()?)
3313             }
3314             (DeviceType::MEDIA, DeviceSubType::MEDIA_RAM_DISK) => {
3315                 Self::MediaRamDisk(node.try_into()?)
3316             }
3317             (DeviceType::BIOS_BOOT_SPEC, DeviceSubType::BIOS_BOOT_SPECIFICATION) => {
3318                 Self::BiosBootSpecBootSpecification(node.try_into()?)
3319             }
3320             _ => return Err(NodeConversionError::UnsupportedType),
3321         })
3322     }
3323 }
3324 
3325 /// Build device paths from their component nodes.
3326 pub mod build {
3327     use super::*;
3328     use crate::proto::device_path::build::{BuildError, BuildNode};
3329     use crate::proto::device_path::{DeviceSubType, DeviceType};
3330     use crate::CStr16;
3331     use core::mem::{size_of_val, MaybeUninit};
3332     /// Device path build nodes for [`DeviceType::END`].
3333     pub mod end {
3334         use super::*;
3335         /// Node that terminates a [`DevicePathInstance`].
3336         ///
3337         /// [`DevicePathInstance`]: device_path::DevicePathInstance
3338         #[derive(Debug)]
3339         pub struct Instance;
3340         unsafe impl BuildNode for Instance {
size_in_bytes(&self) -> Result<u16, BuildError>3341             fn size_in_bytes(&self) -> Result<u16, BuildError> {
3342                 let size = 4usize;
3343                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
3344             }
3345 
write_data(&self, out: &mut [MaybeUninit<u8>])3346             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
3347                 let size = usize::from(self.size_in_bytes().unwrap());
3348                 assert_eq!(size, out.len());
3349                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
3350                 unsafe {
3351                     out_ptr
3352                         .cast::<DevicePathHeader>()
3353                         .write_unaligned(DevicePathHeader {
3354                             device_type: DeviceType::END,
3355                             sub_type: DeviceSubType::END_INSTANCE,
3356                             length: u16::try_from(size).unwrap(),
3357                         });
3358                 }
3359             }
3360         }
3361 
3362         /// Node that terminates an entire [`DevicePath`].
3363         ///
3364         /// [`DevicePath`]: device_path::DevicePath
3365         #[derive(Debug)]
3366         pub struct Entire;
3367         unsafe impl BuildNode for Entire {
size_in_bytes(&self) -> Result<u16, BuildError>3368             fn size_in_bytes(&self) -> Result<u16, BuildError> {
3369                 let size = 4usize;
3370                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
3371             }
3372 
write_data(&self, out: &mut [MaybeUninit<u8>])3373             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
3374                 let size = usize::from(self.size_in_bytes().unwrap());
3375                 assert_eq!(size, out.len());
3376                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
3377                 unsafe {
3378                     out_ptr
3379                         .cast::<DevicePathHeader>()
3380                         .write_unaligned(DevicePathHeader {
3381                             device_type: DeviceType::END,
3382                             sub_type: DeviceSubType::END_ENTIRE,
3383                             length: u16::try_from(size).unwrap(),
3384                         });
3385                 }
3386             }
3387         }
3388     }
3389 
3390     /// Device path build nodes for [`DeviceType::HARDWARE`].
3391     pub mod hardware {
3392         use super::*;
3393         /// PCI hardware device path node.
3394         #[derive(Debug)]
3395         pub struct Pci {
3396             /// PCI function number.
3397             pub function: u8,
3398             /// PCI device number.
3399             pub device: u8,
3400         }
3401 
3402         unsafe impl BuildNode for Pci {
size_in_bytes(&self) -> Result<u16, BuildError>3403             fn size_in_bytes(&self) -> Result<u16, BuildError> {
3404                 let size = 6usize;
3405                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
3406             }
3407 
write_data(&self, out: &mut [MaybeUninit<u8>])3408             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
3409                 let size = usize::from(self.size_in_bytes().unwrap());
3410                 assert_eq!(size, out.len());
3411                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
3412                 unsafe {
3413                     out_ptr
3414                         .cast::<DevicePathHeader>()
3415                         .write_unaligned(DevicePathHeader {
3416                             device_type: DeviceType::HARDWARE,
3417                             sub_type: DeviceSubType::HARDWARE_PCI,
3418                             length: u16::try_from(size).unwrap(),
3419                         });
3420                     out_ptr
3421                         .add(4usize)
3422                         .cast::<u8>()
3423                         .write_unaligned(self.function);
3424                     out_ptr
3425                         .add(5usize)
3426                         .cast::<u8>()
3427                         .write_unaligned(self.device);
3428                 }
3429             }
3430         }
3431 
3432         /// PCCARD hardware device path node.
3433         #[derive(Debug)]
3434         pub struct Pccard {
3435             /// Function number starting from 0.
3436             pub function: u8,
3437         }
3438 
3439         unsafe impl BuildNode for Pccard {
size_in_bytes(&self) -> Result<u16, BuildError>3440             fn size_in_bytes(&self) -> Result<u16, BuildError> {
3441                 let size = 5usize;
3442                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
3443             }
3444 
write_data(&self, out: &mut [MaybeUninit<u8>])3445             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
3446                 let size = usize::from(self.size_in_bytes().unwrap());
3447                 assert_eq!(size, out.len());
3448                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
3449                 unsafe {
3450                     out_ptr
3451                         .cast::<DevicePathHeader>()
3452                         .write_unaligned(DevicePathHeader {
3453                             device_type: DeviceType::HARDWARE,
3454                             sub_type: DeviceSubType::HARDWARE_PCCARD,
3455                             length: u16::try_from(size).unwrap(),
3456                         });
3457                     out_ptr
3458                         .add(4usize)
3459                         .cast::<u8>()
3460                         .write_unaligned(self.function);
3461                 }
3462             }
3463         }
3464 
3465         /// Memory mapped hardware device path node.
3466         #[derive(Debug)]
3467         pub struct MemoryMapped {
3468             /// Memory type.
3469             pub memory_type: MemoryType,
3470             /// Starting memory address.
3471             pub start_address: u64,
3472             /// Ending memory address.
3473             pub end_address: u64,
3474         }
3475 
3476         unsafe impl BuildNode for MemoryMapped {
size_in_bytes(&self) -> Result<u16, BuildError>3477             fn size_in_bytes(&self) -> Result<u16, BuildError> {
3478                 let size = 24usize;
3479                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
3480             }
3481 
write_data(&self, out: &mut [MaybeUninit<u8>])3482             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
3483                 let size = usize::from(self.size_in_bytes().unwrap());
3484                 assert_eq!(size, out.len());
3485                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
3486                 unsafe {
3487                     out_ptr
3488                         .cast::<DevicePathHeader>()
3489                         .write_unaligned(DevicePathHeader {
3490                             device_type: DeviceType::HARDWARE,
3491                             sub_type: DeviceSubType::HARDWARE_MEMORY_MAPPED,
3492                             length: u16::try_from(size).unwrap(),
3493                         });
3494                     out_ptr
3495                         .add(4usize)
3496                         .cast::<MemoryType>()
3497                         .write_unaligned(self.memory_type);
3498                     out_ptr
3499                         .add(8usize)
3500                         .cast::<u64>()
3501                         .write_unaligned(self.start_address);
3502                     out_ptr
3503                         .add(16usize)
3504                         .cast::<u64>()
3505                         .write_unaligned(self.end_address);
3506                 }
3507             }
3508         }
3509 
3510         /// Vendor-defined hardware device path node.
3511         #[derive(Debug)]
3512         pub struct Vendor<'a> {
3513             /// Vendor-assigned GUID that defines the data that follows.
3514             pub vendor_guid: Guid,
3515             /// Vendor-defined data.
3516             pub vendor_defined_data: &'a [u8],
3517         }
3518 
3519         unsafe impl<'a> BuildNode for Vendor<'a> {
size_in_bytes(&self) -> Result<u16, BuildError>3520             fn size_in_bytes(&self) -> Result<u16, BuildError> {
3521                 let size = 20usize + size_of_val(self.vendor_defined_data);
3522                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
3523             }
3524 
write_data(&self, out: &mut [MaybeUninit<u8>])3525             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
3526                 let size = usize::from(self.size_in_bytes().unwrap());
3527                 assert_eq!(size, out.len());
3528                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
3529                 unsafe {
3530                     out_ptr
3531                         .cast::<DevicePathHeader>()
3532                         .write_unaligned(DevicePathHeader {
3533                             device_type: DeviceType::HARDWARE,
3534                             sub_type: DeviceSubType::HARDWARE_VENDOR,
3535                             length: u16::try_from(size).unwrap(),
3536                         });
3537                     out_ptr
3538                         .add(4usize)
3539                         .cast::<Guid>()
3540                         .write_unaligned(self.vendor_guid);
3541                     self.vendor_defined_data
3542                         .as_ptr()
3543                         .cast::<u8>()
3544                         .copy_to_nonoverlapping(
3545                             out_ptr.add(20usize),
3546                             size_of_val(self.vendor_defined_data),
3547                         );
3548                 }
3549             }
3550         }
3551 
3552         /// Controller hardware device path node.
3553         #[derive(Debug)]
3554         pub struct Controller {
3555             /// Controller number.
3556             pub controller_number: u32,
3557         }
3558 
3559         unsafe impl BuildNode for Controller {
size_in_bytes(&self) -> Result<u16, BuildError>3560             fn size_in_bytes(&self) -> Result<u16, BuildError> {
3561                 let size = 8usize;
3562                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
3563             }
3564 
write_data(&self, out: &mut [MaybeUninit<u8>])3565             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
3566                 let size = usize::from(self.size_in_bytes().unwrap());
3567                 assert_eq!(size, out.len());
3568                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
3569                 unsafe {
3570                     out_ptr
3571                         .cast::<DevicePathHeader>()
3572                         .write_unaligned(DevicePathHeader {
3573                             device_type: DeviceType::HARDWARE,
3574                             sub_type: DeviceSubType::HARDWARE_CONTROLLER,
3575                             length: u16::try_from(size).unwrap(),
3576                         });
3577                     out_ptr
3578                         .add(4usize)
3579                         .cast::<u32>()
3580                         .write_unaligned(self.controller_number);
3581                 }
3582             }
3583         }
3584 
3585         /// Baseboard Management Controller (BMC) host interface hardware
3586         /// device path node.
3587         #[derive(Debug)]
3588         pub struct Bmc {
3589             /// Host interface type.
3590             pub interface_type: device_path::hardware::BmcInterfaceType,
3591             /// Base address of the BMC. If the least-significant bit of the
3592             /// field is a 1 then the address is in I/O space, otherwise the
3593             /// address is memory-mapped.
3594             pub base_address: u64,
3595         }
3596 
3597         unsafe impl BuildNode for Bmc {
size_in_bytes(&self) -> Result<u16, BuildError>3598             fn size_in_bytes(&self) -> Result<u16, BuildError> {
3599                 let size = 13usize;
3600                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
3601             }
3602 
write_data(&self, out: &mut [MaybeUninit<u8>])3603             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
3604                 let size = usize::from(self.size_in_bytes().unwrap());
3605                 assert_eq!(size, out.len());
3606                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
3607                 unsafe {
3608                     out_ptr
3609                         .cast::<DevicePathHeader>()
3610                         .write_unaligned(DevicePathHeader {
3611                             device_type: DeviceType::HARDWARE,
3612                             sub_type: DeviceSubType::HARDWARE_BMC,
3613                             length: u16::try_from(size).unwrap(),
3614                         });
3615                     out_ptr
3616                         .add(4usize)
3617                         .cast::<device_path::hardware::BmcInterfaceType>()
3618                         .write_unaligned(self.interface_type);
3619                     out_ptr
3620                         .add(5usize)
3621                         .cast::<u64>()
3622                         .write_unaligned(self.base_address);
3623                 }
3624             }
3625         }
3626     }
3627 
3628     /// Device path build nodes for [`DeviceType::ACPI`].
3629     pub mod acpi {
3630         use super::*;
3631         /// ACPI device path node.
3632         #[derive(Debug)]
3633         pub struct Acpi {
3634             /// Device's PnP hardware ID stored in a numeric 32-bit
3635             /// compressed EISA-type ID.
3636             pub hid: u32,
3637             /// Unique ID that is required by ACPI if two devices have the
3638             /// same HID.
3639             pub uid: u32,
3640         }
3641 
3642         unsafe impl BuildNode for Acpi {
size_in_bytes(&self) -> Result<u16, BuildError>3643             fn size_in_bytes(&self) -> Result<u16, BuildError> {
3644                 let size = 12usize;
3645                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
3646             }
3647 
write_data(&self, out: &mut [MaybeUninit<u8>])3648             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
3649                 let size = usize::from(self.size_in_bytes().unwrap());
3650                 assert_eq!(size, out.len());
3651                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
3652                 unsafe {
3653                     out_ptr
3654                         .cast::<DevicePathHeader>()
3655                         .write_unaligned(DevicePathHeader {
3656                             device_type: DeviceType::ACPI,
3657                             sub_type: DeviceSubType::ACPI,
3658                             length: u16::try_from(size).unwrap(),
3659                         });
3660                     out_ptr.add(4usize).cast::<u32>().write_unaligned(self.hid);
3661                     out_ptr.add(8usize).cast::<u32>().write_unaligned(self.uid);
3662                 }
3663             }
3664         }
3665 
3666         /// Expanded ACPI device path node.
3667         #[derive(Debug)]
3668         pub struct Expanded<'a> {
3669             /// Device's PnP hardware ID stored in a numeric 32-bit compressed
3670             /// EISA-type ID.
3671             pub hid: u32,
3672             /// Unique ID that is required by ACPI if two devices have the
3673             /// same HID.
3674             pub uid: u32,
3675             /// Device's compatible PnP hardware ID stored in a numeric 32-bit
3676             /// compressed EISA-type ID.
3677             pub cid: u32,
3678             /// Device's PnP hardware ID stored as a null-terminated ASCII
3679             /// string. This value must match the corresponding HID in the
3680             /// ACPI name space. If the length of this string not including
3681             /// the null-terminator is 0, then the numeric HID is used.
3682             pub hid_str: &'a [u8],
3683             /// Unique ID that is required by ACPI if two devices have the
3684             /// same HID. This value is stored as a null-terminated ASCII
3685             /// string. If the length of this string not including the
3686             /// null-terminator is 0, then the numeric UID is used.
3687             pub uid_str: &'a [u8],
3688             /// Device's compatible PnP hardware ID stored as a
3689             /// null-terminated ASCII string. If the length of this string
3690             /// not including the null-terminator is 0, then the numeric CID
3691             /// is used.
3692             pub cid_str: &'a [u8],
3693         }
3694 
3695         unsafe impl<'a> BuildNode for Expanded<'a> {
size_in_bytes(&self) -> Result<u16, BuildError>3696             fn size_in_bytes(&self) -> Result<u16, BuildError> {
3697                 let size = 16usize
3698                     + size_of_val(self.hid_str)
3699                     + size_of_val(self.uid_str)
3700                     + size_of_val(self.cid_str);
3701                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
3702             }
3703 
write_data(&self, out: &mut [MaybeUninit<u8>])3704             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
3705                 let size = usize::from(self.size_in_bytes().unwrap());
3706                 assert_eq!(size, out.len());
3707                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
3708                 unsafe {
3709                     out_ptr
3710                         .cast::<DevicePathHeader>()
3711                         .write_unaligned(DevicePathHeader {
3712                             device_type: DeviceType::ACPI,
3713                             sub_type: DeviceSubType::ACPI_EXPANDED,
3714                             length: u16::try_from(size).unwrap(),
3715                         });
3716                     let mut dst_group_offset = 0;
3717                     out_ptr.add(4usize).cast::<u32>().write_unaligned(self.hid);
3718                     out_ptr.add(8usize).cast::<u32>().write_unaligned(self.uid);
3719                     out_ptr.add(12usize).cast::<u32>().write_unaligned(self.cid);
3720                     self.hid_str.as_ptr().cast::<u8>().copy_to_nonoverlapping(
3721                         out_ptr.add(16usize + dst_group_offset),
3722                         size_of_val(self.hid_str),
3723                     );
3724                     dst_group_offset += size_of_val(self.hid_str);
3725                     self.uid_str.as_ptr().cast::<u8>().copy_to_nonoverlapping(
3726                         out_ptr.add(16usize + dst_group_offset),
3727                         size_of_val(self.uid_str),
3728                     );
3729                     dst_group_offset += size_of_val(self.uid_str);
3730                     self.cid_str.as_ptr().cast::<u8>().copy_to_nonoverlapping(
3731                         out_ptr.add(16usize + dst_group_offset),
3732                         size_of_val(self.cid_str),
3733                     );
3734                 }
3735             }
3736         }
3737 
3738         /// ADR ACPI device path node.
3739         #[derive(Debug)]
3740         pub struct Adr<'a> {
3741             /// ADR values. For video output devices the value of this field
3742             /// comes from Table B-2 ACPI 3.0 specification. At least one
3743             /// ADR value is required.
3744             pub adr: &'a AdrSlice,
3745         }
3746 
3747         unsafe impl<'a> BuildNode for Adr<'a> {
size_in_bytes(&self) -> Result<u16, BuildError>3748             fn size_in_bytes(&self) -> Result<u16, BuildError> {
3749                 let size = 4usize + size_of_val(self.adr);
3750                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
3751             }
3752 
write_data(&self, out: &mut [MaybeUninit<u8>])3753             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
3754                 let size = usize::from(self.size_in_bytes().unwrap());
3755                 assert_eq!(size, out.len());
3756                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
3757                 unsafe {
3758                     out_ptr
3759                         .cast::<DevicePathHeader>()
3760                         .write_unaligned(DevicePathHeader {
3761                             device_type: DeviceType::ACPI,
3762                             sub_type: DeviceSubType::ACPI_ADR,
3763                             length: u16::try_from(size).unwrap(),
3764                         });
3765                     self.adr
3766                         .as_ptr()
3767                         .cast::<u8>()
3768                         .copy_to_nonoverlapping(out_ptr.add(4usize), size_of_val(self.adr));
3769                 }
3770             }
3771         }
3772 
3773         /// NVDIMM ACPI device path node.
3774         #[derive(Debug)]
3775         pub struct Nvdimm {
3776             /// NFIT device handle.
3777             pub nfit_device_handle: u32,
3778         }
3779 
3780         unsafe impl BuildNode for Nvdimm {
size_in_bytes(&self) -> Result<u16, BuildError>3781             fn size_in_bytes(&self) -> Result<u16, BuildError> {
3782                 let size = 8usize;
3783                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
3784             }
3785 
write_data(&self, out: &mut [MaybeUninit<u8>])3786             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
3787                 let size = usize::from(self.size_in_bytes().unwrap());
3788                 assert_eq!(size, out.len());
3789                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
3790                 unsafe {
3791                     out_ptr
3792                         .cast::<DevicePathHeader>()
3793                         .write_unaligned(DevicePathHeader {
3794                             device_type: DeviceType::ACPI,
3795                             sub_type: DeviceSubType::ACPI_NVDIMM,
3796                             length: u16::try_from(size).unwrap(),
3797                         });
3798                     out_ptr
3799                         .add(4usize)
3800                         .cast::<u32>()
3801                         .write_unaligned(self.nfit_device_handle);
3802                 }
3803             }
3804         }
3805 
3806         /// Wrapper for [`u32`] ADR values that enforces at least one
3807         /// element is present.
3808         #[repr(transparent)]
3809         #[derive(Debug)]
3810         pub struct AdrSlice([u32]);
3811         impl AdrSlice {
3812             /// Create a new `AdrSlice`. Returns `None` if the input slice
3813             /// is empty.
3814             #[must_use]
new(slice: &[u32]) -> Option<&Self>3815             pub fn new(slice: &[u32]) -> Option<&Self> {
3816                 if slice.is_empty() {
3817                     None
3818                 } else {
3819                     let adr_slice: &Self = unsafe { core::mem::transmute(slice) };
3820                     Some(adr_slice)
3821                 }
3822             }
3823 
as_ptr(&self) -> *const u323824             fn as_ptr(&self) -> *const u32 {
3825                 self.0.as_ptr()
3826             }
3827         }
3828     }
3829 
3830     /// Device path build nodes for [`DeviceType::MESSAGING`].
3831     pub mod messaging {
3832         use super::*;
3833         /// ATAPI messaging device path node.
3834         #[derive(Debug)]
3835         pub struct Atapi {
3836             /// Whether the ATAPI device is primary or secondary.
3837             pub primary_secondary: device_path::messaging::PrimarySecondary,
3838             /// Whether the ATAPI device is master or slave.
3839             pub master_slave: device_path::messaging::MasterSlave,
3840             /// Logical Unit Number (LUN).
3841             pub logical_unit_number: u16,
3842         }
3843 
3844         unsafe impl BuildNode for Atapi {
size_in_bytes(&self) -> Result<u16, BuildError>3845             fn size_in_bytes(&self) -> Result<u16, BuildError> {
3846                 let size = 8usize;
3847                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
3848             }
3849 
write_data(&self, out: &mut [MaybeUninit<u8>])3850             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
3851                 let size = usize::from(self.size_in_bytes().unwrap());
3852                 assert_eq!(size, out.len());
3853                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
3854                 unsafe {
3855                     out_ptr
3856                         .cast::<DevicePathHeader>()
3857                         .write_unaligned(DevicePathHeader {
3858                             device_type: DeviceType::MESSAGING,
3859                             sub_type: DeviceSubType::MESSAGING_ATAPI,
3860                             length: u16::try_from(size).unwrap(),
3861                         });
3862                     out_ptr
3863                         .add(4usize)
3864                         .cast::<device_path::messaging::PrimarySecondary>()
3865                         .write_unaligned(self.primary_secondary);
3866                     out_ptr
3867                         .add(5usize)
3868                         .cast::<device_path::messaging::MasterSlave>()
3869                         .write_unaligned(self.master_slave);
3870                     out_ptr
3871                         .add(6usize)
3872                         .cast::<u16>()
3873                         .write_unaligned(self.logical_unit_number);
3874                 }
3875             }
3876         }
3877 
3878         /// SCSI messaging device path node.
3879         #[derive(Debug)]
3880         pub struct Scsi {
3881             /// Target ID on the SCSI bus.
3882             pub target_id: u16,
3883             /// Logical Unit Number.
3884             pub logical_unit_number: u16,
3885         }
3886 
3887         unsafe impl BuildNode for Scsi {
size_in_bytes(&self) -> Result<u16, BuildError>3888             fn size_in_bytes(&self) -> Result<u16, BuildError> {
3889                 let size = 8usize;
3890                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
3891             }
3892 
write_data(&self, out: &mut [MaybeUninit<u8>])3893             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
3894                 let size = usize::from(self.size_in_bytes().unwrap());
3895                 assert_eq!(size, out.len());
3896                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
3897                 unsafe {
3898                     out_ptr
3899                         .cast::<DevicePathHeader>()
3900                         .write_unaligned(DevicePathHeader {
3901                             device_type: DeviceType::MESSAGING,
3902                             sub_type: DeviceSubType::MESSAGING_SCSI,
3903                             length: u16::try_from(size).unwrap(),
3904                         });
3905                     out_ptr
3906                         .add(4usize)
3907                         .cast::<u16>()
3908                         .write_unaligned(self.target_id);
3909                     out_ptr
3910                         .add(6usize)
3911                         .cast::<u16>()
3912                         .write_unaligned(self.logical_unit_number);
3913                 }
3914             }
3915         }
3916 
3917         /// Fibre channel messaging device path node.
3918         #[derive(Debug)]
3919         pub struct FibreChannel {
3920             /// Fibre Channel World Wide Name.
3921             pub world_wide_name: u64,
3922             /// Fibre Channel Logical Unit Number.
3923             pub logical_unit_number: u64,
3924         }
3925 
3926         unsafe impl BuildNode for FibreChannel {
size_in_bytes(&self) -> Result<u16, BuildError>3927             fn size_in_bytes(&self) -> Result<u16, BuildError> {
3928                 let size = 24usize;
3929                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
3930             }
3931 
write_data(&self, out: &mut [MaybeUninit<u8>])3932             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
3933                 let size = usize::from(self.size_in_bytes().unwrap());
3934                 assert_eq!(size, out.len());
3935                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
3936                 unsafe {
3937                     out_ptr
3938                         .cast::<DevicePathHeader>()
3939                         .write_unaligned(DevicePathHeader {
3940                             device_type: DeviceType::MESSAGING,
3941                             sub_type: DeviceSubType::MESSAGING_FIBRE_CHANNEL,
3942                             length: u16::try_from(size).unwrap(),
3943                         });
3944                     out_ptr.add(4usize).write_bytes(0, size_of::<u32>());
3945                     out_ptr
3946                         .add(8usize)
3947                         .cast::<u64>()
3948                         .write_unaligned(self.world_wide_name);
3949                     out_ptr
3950                         .add(16usize)
3951                         .cast::<u64>()
3952                         .write_unaligned(self.logical_unit_number);
3953                 }
3954             }
3955         }
3956 
3957         /// Fibre channel extended messaging device path node.
3958         #[derive(Debug)]
3959         pub struct FibreChannelEx {
3960             /// Fibre Channel end device port name (aka World Wide Name).
3961             pub world_wide_name: [u8; 8usize],
3962             /// Fibre Channel Logical Unit Number.
3963             pub logical_unit_number: [u8; 8usize],
3964         }
3965 
3966         unsafe impl BuildNode for FibreChannelEx {
size_in_bytes(&self) -> Result<u16, BuildError>3967             fn size_in_bytes(&self) -> Result<u16, BuildError> {
3968                 let size = 24usize;
3969                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
3970             }
3971 
write_data(&self, out: &mut [MaybeUninit<u8>])3972             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
3973                 let size = usize::from(self.size_in_bytes().unwrap());
3974                 assert_eq!(size, out.len());
3975                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
3976                 unsafe {
3977                     out_ptr
3978                         .cast::<DevicePathHeader>()
3979                         .write_unaligned(DevicePathHeader {
3980                             device_type: DeviceType::MESSAGING,
3981                             sub_type: DeviceSubType::MESSAGING_FIBRE_CHANNEL_EX,
3982                             length: u16::try_from(size).unwrap(),
3983                         });
3984                     out_ptr.add(4usize).write_bytes(0, size_of::<u32>());
3985                     out_ptr
3986                         .add(8usize)
3987                         .cast::<[u8; 8usize]>()
3988                         .write_unaligned(self.world_wide_name);
3989                     out_ptr
3990                         .add(16usize)
3991                         .cast::<[u8; 8usize]>()
3992                         .write_unaligned(self.logical_unit_number);
3993                 }
3994             }
3995         }
3996 
3997         /// 1394 messaging device path node.
3998         #[derive(Debug)]
3999         pub struct Ieee1394 {
4000             /// 1394 Global Unique ID. Note that this is not the same as a
4001             /// UEFI GUID.
4002             pub guid: [u8; 8usize],
4003         }
4004 
4005         unsafe impl BuildNode for Ieee1394 {
size_in_bytes(&self) -> Result<u16, BuildError>4006             fn size_in_bytes(&self) -> Result<u16, BuildError> {
4007                 let size = 16usize;
4008                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
4009             }
4010 
write_data(&self, out: &mut [MaybeUninit<u8>])4011             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
4012                 let size = usize::from(self.size_in_bytes().unwrap());
4013                 assert_eq!(size, out.len());
4014                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
4015                 unsafe {
4016                     out_ptr
4017                         .cast::<DevicePathHeader>()
4018                         .write_unaligned(DevicePathHeader {
4019                             device_type: DeviceType::MESSAGING,
4020                             sub_type: DeviceSubType::MESSAGING_1394,
4021                             length: u16::try_from(size).unwrap(),
4022                         });
4023                     out_ptr.add(4usize).write_bytes(0, size_of::<u32>());
4024                     out_ptr
4025                         .add(8usize)
4026                         .cast::<[u8; 8usize]>()
4027                         .write_unaligned(self.guid);
4028                 }
4029             }
4030         }
4031 
4032         /// USB messaging device path node.
4033         #[derive(Debug)]
4034         pub struct Usb {
4035             /// USB parent port number.
4036             pub parent_port_number: u8,
4037             /// USB interface number.
4038             pub interface: u8,
4039         }
4040 
4041         unsafe impl BuildNode for Usb {
size_in_bytes(&self) -> Result<u16, BuildError>4042             fn size_in_bytes(&self) -> Result<u16, BuildError> {
4043                 let size = 6usize;
4044                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
4045             }
4046 
write_data(&self, out: &mut [MaybeUninit<u8>])4047             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
4048                 let size = usize::from(self.size_in_bytes().unwrap());
4049                 assert_eq!(size, out.len());
4050                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
4051                 unsafe {
4052                     out_ptr
4053                         .cast::<DevicePathHeader>()
4054                         .write_unaligned(DevicePathHeader {
4055                             device_type: DeviceType::MESSAGING,
4056                             sub_type: DeviceSubType::MESSAGING_USB,
4057                             length: u16::try_from(size).unwrap(),
4058                         });
4059                     out_ptr
4060                         .add(4usize)
4061                         .cast::<u8>()
4062                         .write_unaligned(self.parent_port_number);
4063                     out_ptr
4064                         .add(5usize)
4065                         .cast::<u8>()
4066                         .write_unaligned(self.interface);
4067                 }
4068             }
4069         }
4070 
4071         /// SATA messaging device path node.
4072         #[derive(Debug)]
4073         pub struct Sata {
4074             /// The HBA port number that facilitates the connection to the
4075             /// device or a port multiplier. The value 0xffff is reserved.
4076             pub hba_port_number: u16,
4077             /// the port multiplier port number that facilitates the
4078             /// connection to the device. Must be set to 0xffff if the
4079             /// device is directly connected to the HBA.
4080             pub port_multiplier_port_number: u16,
4081             /// Logical unit number.
4082             pub logical_unit_number: u16,
4083         }
4084 
4085         unsafe impl BuildNode for Sata {
size_in_bytes(&self) -> Result<u16, BuildError>4086             fn size_in_bytes(&self) -> Result<u16, BuildError> {
4087                 let size = 10usize;
4088                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
4089             }
4090 
write_data(&self, out: &mut [MaybeUninit<u8>])4091             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
4092                 let size = usize::from(self.size_in_bytes().unwrap());
4093                 assert_eq!(size, out.len());
4094                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
4095                 unsafe {
4096                     out_ptr
4097                         .cast::<DevicePathHeader>()
4098                         .write_unaligned(DevicePathHeader {
4099                             device_type: DeviceType::MESSAGING,
4100                             sub_type: DeviceSubType::MESSAGING_SATA,
4101                             length: u16::try_from(size).unwrap(),
4102                         });
4103                     out_ptr
4104                         .add(4usize)
4105                         .cast::<u16>()
4106                         .write_unaligned(self.hba_port_number);
4107                     out_ptr
4108                         .add(6usize)
4109                         .cast::<u16>()
4110                         .write_unaligned(self.port_multiplier_port_number);
4111                     out_ptr
4112                         .add(8usize)
4113                         .cast::<u16>()
4114                         .write_unaligned(self.logical_unit_number);
4115                 }
4116             }
4117         }
4118 
4119         /// USB World Wide ID (WWID) messaging device path node.
4120         #[derive(Debug)]
4121         pub struct UsbWwid<'a> {
4122             /// USB interface number.
4123             pub interface_number: u16,
4124             /// USB vendor ID.
4125             pub device_vendor_id: u16,
4126             /// USB product ID.
4127             pub device_product_id: u16,
4128             /// Last 64 (or fewer) characters of the USB Serial number.
4129             pub serial_number: &'a [u16],
4130         }
4131 
4132         unsafe impl<'a> BuildNode for UsbWwid<'a> {
size_in_bytes(&self) -> Result<u16, BuildError>4133             fn size_in_bytes(&self) -> Result<u16, BuildError> {
4134                 let size = 10usize + size_of_val(self.serial_number);
4135                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
4136             }
4137 
write_data(&self, out: &mut [MaybeUninit<u8>])4138             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
4139                 let size = usize::from(self.size_in_bytes().unwrap());
4140                 assert_eq!(size, out.len());
4141                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
4142                 unsafe {
4143                     out_ptr
4144                         .cast::<DevicePathHeader>()
4145                         .write_unaligned(DevicePathHeader {
4146                             device_type: DeviceType::MESSAGING,
4147                             sub_type: DeviceSubType::MESSAGING_USB_WWID,
4148                             length: u16::try_from(size).unwrap(),
4149                         });
4150                     out_ptr
4151                         .add(4usize)
4152                         .cast::<u16>()
4153                         .write_unaligned(self.interface_number);
4154                     out_ptr
4155                         .add(6usize)
4156                         .cast::<u16>()
4157                         .write_unaligned(self.device_vendor_id);
4158                     out_ptr
4159                         .add(8usize)
4160                         .cast::<u16>()
4161                         .write_unaligned(self.device_product_id);
4162                     self.serial_number
4163                         .as_ptr()
4164                         .cast::<u8>()
4165                         .copy_to_nonoverlapping(
4166                             out_ptr.add(10usize),
4167                             size_of_val(self.serial_number),
4168                         );
4169                 }
4170             }
4171         }
4172 
4173         /// Device logical unit messaging device path node.
4174         #[derive(Debug)]
4175         pub struct DeviceLogicalUnit {
4176             /// Logical Unit Number.
4177             pub logical_unit_number: u8,
4178         }
4179 
4180         unsafe impl BuildNode for DeviceLogicalUnit {
size_in_bytes(&self) -> Result<u16, BuildError>4181             fn size_in_bytes(&self) -> Result<u16, BuildError> {
4182                 let size = 5usize;
4183                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
4184             }
4185 
write_data(&self, out: &mut [MaybeUninit<u8>])4186             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
4187                 let size = usize::from(self.size_in_bytes().unwrap());
4188                 assert_eq!(size, out.len());
4189                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
4190                 unsafe {
4191                     out_ptr
4192                         .cast::<DevicePathHeader>()
4193                         .write_unaligned(DevicePathHeader {
4194                             device_type: DeviceType::MESSAGING,
4195                             sub_type: DeviceSubType::MESSAGING_DEVICE_LOGICAL_UNIT,
4196                             length: u16::try_from(size).unwrap(),
4197                         });
4198                     out_ptr
4199                         .add(4usize)
4200                         .cast::<u8>()
4201                         .write_unaligned(self.logical_unit_number);
4202                 }
4203             }
4204         }
4205 
4206         /// USB class messaging device path node.
4207         #[derive(Debug)]
4208         pub struct UsbClass {
4209             /// USB vendor ID.
4210             pub vendor_id: u16,
4211             /// USB product ID.
4212             pub product_id: u16,
4213             /// USB device class.
4214             pub device_class: u8,
4215             /// USB device subclass.
4216             pub device_subclass: u8,
4217             /// USB device protocol.
4218             pub device_protocol: u8,
4219         }
4220 
4221         unsafe impl BuildNode for UsbClass {
size_in_bytes(&self) -> Result<u16, BuildError>4222             fn size_in_bytes(&self) -> Result<u16, BuildError> {
4223                 let size = 11usize;
4224                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
4225             }
4226 
write_data(&self, out: &mut [MaybeUninit<u8>])4227             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
4228                 let size = usize::from(self.size_in_bytes().unwrap());
4229                 assert_eq!(size, out.len());
4230                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
4231                 unsafe {
4232                     out_ptr
4233                         .cast::<DevicePathHeader>()
4234                         .write_unaligned(DevicePathHeader {
4235                             device_type: DeviceType::MESSAGING,
4236                             sub_type: DeviceSubType::MESSAGING_USB_CLASS,
4237                             length: u16::try_from(size).unwrap(),
4238                         });
4239                     out_ptr
4240                         .add(4usize)
4241                         .cast::<u16>()
4242                         .write_unaligned(self.vendor_id);
4243                     out_ptr
4244                         .add(6usize)
4245                         .cast::<u16>()
4246                         .write_unaligned(self.product_id);
4247                     out_ptr
4248                         .add(8usize)
4249                         .cast::<u8>()
4250                         .write_unaligned(self.device_class);
4251                     out_ptr
4252                         .add(9usize)
4253                         .cast::<u8>()
4254                         .write_unaligned(self.device_subclass);
4255                     out_ptr
4256                         .add(10usize)
4257                         .cast::<u8>()
4258                         .write_unaligned(self.device_protocol);
4259                 }
4260             }
4261         }
4262 
4263         /// I2O messaging device path node.
4264         #[derive(Debug)]
4265         pub struct I2o {
4266             /// Target ID (TID).
4267             pub target_id: u32,
4268         }
4269 
4270         unsafe impl BuildNode for I2o {
size_in_bytes(&self) -> Result<u16, BuildError>4271             fn size_in_bytes(&self) -> Result<u16, BuildError> {
4272                 let size = 8usize;
4273                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
4274             }
4275 
write_data(&self, out: &mut [MaybeUninit<u8>])4276             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
4277                 let size = usize::from(self.size_in_bytes().unwrap());
4278                 assert_eq!(size, out.len());
4279                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
4280                 unsafe {
4281                     out_ptr
4282                         .cast::<DevicePathHeader>()
4283                         .write_unaligned(DevicePathHeader {
4284                             device_type: DeviceType::MESSAGING,
4285                             sub_type: DeviceSubType::MESSAGING_I2O,
4286                             length: u16::try_from(size).unwrap(),
4287                         });
4288                     out_ptr
4289                         .add(4usize)
4290                         .cast::<u32>()
4291                         .write_unaligned(self.target_id);
4292                 }
4293             }
4294         }
4295 
4296         /// MAC address messaging device path node.
4297         #[derive(Debug)]
4298         pub struct MacAddress {
4299             /// MAC address for a network interface, padded with zeros.
4300             pub mac_address: [u8; 32usize],
4301             /// Network interface type. See
4302             /// <https://www.iana.org/assignments/smi-numbers/smi-numbers.xhtml#smi-numbers-5>
4303             pub interface_type: u8,
4304         }
4305 
4306         unsafe impl BuildNode for MacAddress {
size_in_bytes(&self) -> Result<u16, BuildError>4307             fn size_in_bytes(&self) -> Result<u16, BuildError> {
4308                 let size = 37usize;
4309                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
4310             }
4311 
write_data(&self, out: &mut [MaybeUninit<u8>])4312             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
4313                 let size = usize::from(self.size_in_bytes().unwrap());
4314                 assert_eq!(size, out.len());
4315                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
4316                 unsafe {
4317                     out_ptr
4318                         .cast::<DevicePathHeader>()
4319                         .write_unaligned(DevicePathHeader {
4320                             device_type: DeviceType::MESSAGING,
4321                             sub_type: DeviceSubType::MESSAGING_MAC_ADDRESS,
4322                             length: u16::try_from(size).unwrap(),
4323                         });
4324                     out_ptr
4325                         .add(4usize)
4326                         .cast::<[u8; 32usize]>()
4327                         .write_unaligned(self.mac_address);
4328                     out_ptr
4329                         .add(36usize)
4330                         .cast::<u8>()
4331                         .write_unaligned(self.interface_type);
4332                 }
4333             }
4334         }
4335 
4336         /// IPv4 messaging device path node.
4337         #[derive(Debug)]
4338         pub struct Ipv4 {
4339             /// Local IPv4 address.
4340             pub local_ip_address: [u8; 4usize],
4341             /// Remote IPv4 address.
4342             pub remote_ip_address: [u8; 4usize],
4343             /// Local port number.
4344             pub local_port: u16,
4345             /// Remote port number.
4346             pub remote_port: u16,
4347             /// Network protocol. See
4348             /// <https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml>
4349             pub protocol: u16,
4350             /// Whether the source IP address is static or assigned via DHCP.
4351             pub ip_address_origin: device_path::messaging::Ipv4AddressOrigin,
4352             /// Gateway IP address.
4353             pub gateway_ip_address: [u8; 4usize],
4354             /// Subnet mask.
4355             pub subnet_mask: [u8; 4usize],
4356         }
4357 
4358         unsafe impl BuildNode for Ipv4 {
size_in_bytes(&self) -> Result<u16, BuildError>4359             fn size_in_bytes(&self) -> Result<u16, BuildError> {
4360                 let size = 27usize;
4361                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
4362             }
4363 
write_data(&self, out: &mut [MaybeUninit<u8>])4364             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
4365                 let size = usize::from(self.size_in_bytes().unwrap());
4366                 assert_eq!(size, out.len());
4367                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
4368                 unsafe {
4369                     out_ptr
4370                         .cast::<DevicePathHeader>()
4371                         .write_unaligned(DevicePathHeader {
4372                             device_type: DeviceType::MESSAGING,
4373                             sub_type: DeviceSubType::MESSAGING_IPV4,
4374                             length: u16::try_from(size).unwrap(),
4375                         });
4376                     out_ptr
4377                         .add(4usize)
4378                         .cast::<[u8; 4usize]>()
4379                         .write_unaligned(self.local_ip_address);
4380                     out_ptr
4381                         .add(8usize)
4382                         .cast::<[u8; 4usize]>()
4383                         .write_unaligned(self.remote_ip_address);
4384                     out_ptr
4385                         .add(12usize)
4386                         .cast::<u16>()
4387                         .write_unaligned(self.local_port);
4388                     out_ptr
4389                         .add(14usize)
4390                         .cast::<u16>()
4391                         .write_unaligned(self.remote_port);
4392                     out_ptr
4393                         .add(16usize)
4394                         .cast::<u16>()
4395                         .write_unaligned(self.protocol);
4396                     out_ptr
4397                         .add(18usize)
4398                         .cast::<device_path::messaging::Ipv4AddressOrigin>()
4399                         .write_unaligned(self.ip_address_origin);
4400                     out_ptr
4401                         .add(19usize)
4402                         .cast::<[u8; 4usize]>()
4403                         .write_unaligned(self.gateway_ip_address);
4404                     out_ptr
4405                         .add(23usize)
4406                         .cast::<[u8; 4usize]>()
4407                         .write_unaligned(self.subnet_mask);
4408                 }
4409             }
4410         }
4411 
4412         /// IPv6 messaging device path node.
4413         #[derive(Debug)]
4414         pub struct Ipv6 {
4415             /// Local Ipv6 address.
4416             pub local_ip_address: [u8; 16usize],
4417             /// Remote Ipv6 address.
4418             pub remote_ip_address: [u8; 16usize],
4419             /// Local port number.
4420             pub local_port: u16,
4421             /// Remote port number.
4422             pub remote_port: u16,
4423             /// Network protocol. See
4424             /// <https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml>
4425             pub protocol: u16,
4426             /// Origin of the local IP address.
4427             pub ip_address_origin: device_path::messaging::Ipv6AddressOrigin,
4428             /// Prefix length.
4429             pub prefix_length: u8,
4430             /// Gateway IP address.
4431             pub gateway_ip_address: [u8; 16usize],
4432         }
4433 
4434         unsafe impl BuildNode for Ipv6 {
size_in_bytes(&self) -> Result<u16, BuildError>4435             fn size_in_bytes(&self) -> Result<u16, BuildError> {
4436                 let size = 60usize;
4437                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
4438             }
4439 
write_data(&self, out: &mut [MaybeUninit<u8>])4440             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
4441                 let size = usize::from(self.size_in_bytes().unwrap());
4442                 assert_eq!(size, out.len());
4443                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
4444                 unsafe {
4445                     out_ptr
4446                         .cast::<DevicePathHeader>()
4447                         .write_unaligned(DevicePathHeader {
4448                             device_type: DeviceType::MESSAGING,
4449                             sub_type: DeviceSubType::MESSAGING_IPV6,
4450                             length: u16::try_from(size).unwrap(),
4451                         });
4452                     out_ptr
4453                         .add(4usize)
4454                         .cast::<[u8; 16usize]>()
4455                         .write_unaligned(self.local_ip_address);
4456                     out_ptr
4457                         .add(20usize)
4458                         .cast::<[u8; 16usize]>()
4459                         .write_unaligned(self.remote_ip_address);
4460                     out_ptr
4461                         .add(36usize)
4462                         .cast::<u16>()
4463                         .write_unaligned(self.local_port);
4464                     out_ptr
4465                         .add(38usize)
4466                         .cast::<u16>()
4467                         .write_unaligned(self.remote_port);
4468                     out_ptr
4469                         .add(40usize)
4470                         .cast::<u16>()
4471                         .write_unaligned(self.protocol);
4472                     out_ptr
4473                         .add(42usize)
4474                         .cast::<device_path::messaging::Ipv6AddressOrigin>()
4475                         .write_unaligned(self.ip_address_origin);
4476                     out_ptr
4477                         .add(43usize)
4478                         .cast::<u8>()
4479                         .write_unaligned(self.prefix_length);
4480                     out_ptr
4481                         .add(44usize)
4482                         .cast::<[u8; 16usize]>()
4483                         .write_unaligned(self.gateway_ip_address);
4484                 }
4485             }
4486         }
4487 
4488         /// VLAN messaging device path node.
4489         #[derive(Debug)]
4490         pub struct Vlan {
4491             /// VLAN identifier (0-4094).
4492             pub vlan_id: u16,
4493         }
4494 
4495         unsafe impl BuildNode for Vlan {
size_in_bytes(&self) -> Result<u16, BuildError>4496             fn size_in_bytes(&self) -> Result<u16, BuildError> {
4497                 let size = 6usize;
4498                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
4499             }
4500 
write_data(&self, out: &mut [MaybeUninit<u8>])4501             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
4502                 let size = usize::from(self.size_in_bytes().unwrap());
4503                 assert_eq!(size, out.len());
4504                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
4505                 unsafe {
4506                     out_ptr
4507                         .cast::<DevicePathHeader>()
4508                         .write_unaligned(DevicePathHeader {
4509                             device_type: DeviceType::MESSAGING,
4510                             sub_type: DeviceSubType::MESSAGING_VLAN,
4511                             length: u16::try_from(size).unwrap(),
4512                         });
4513                     out_ptr
4514                         .add(4usize)
4515                         .cast::<u16>()
4516                         .write_unaligned(self.vlan_id);
4517                 }
4518             }
4519         }
4520 
4521         /// InfiniBand messaging device path node.
4522         #[derive(Debug)]
4523         pub struct Infiniband {
4524             /// Flags to identify/manage InfiniBand elements.
4525             pub resource_flags: device_path::messaging::InfinibandResourceFlags,
4526             /// 128-bit Global Identifier for remote fabric port. Note that
4527             /// this is not the same as a UEFI GUID.
4528             pub port_gid: [u8; 16usize],
4529             /// IOC GUID if bit 0 of `resource_flags` is unset, or Service
4530             /// ID if bit 0 of `resource_flags` is set.
4531             pub ioc_guid_or_service_id: u64,
4532             /// 64-bit persistent ID of remote IOC port.
4533             pub target_port_id: u64,
4534             /// 64-bit persistent ID of remote device..
4535             pub device_id: u64,
4536         }
4537 
4538         unsafe impl BuildNode for Infiniband {
size_in_bytes(&self) -> Result<u16, BuildError>4539             fn size_in_bytes(&self) -> Result<u16, BuildError> {
4540                 let size = 48usize;
4541                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
4542             }
4543 
write_data(&self, out: &mut [MaybeUninit<u8>])4544             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
4545                 let size = usize::from(self.size_in_bytes().unwrap());
4546                 assert_eq!(size, out.len());
4547                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
4548                 unsafe {
4549                     out_ptr
4550                         .cast::<DevicePathHeader>()
4551                         .write_unaligned(DevicePathHeader {
4552                             device_type: DeviceType::MESSAGING,
4553                             sub_type: DeviceSubType::MESSAGING_INFINIBAND,
4554                             length: u16::try_from(size).unwrap(),
4555                         });
4556                     out_ptr
4557                         .add(4usize)
4558                         .cast::<device_path::messaging::InfinibandResourceFlags>()
4559                         .write_unaligned(self.resource_flags);
4560                     out_ptr
4561                         .add(8usize)
4562                         .cast::<[u8; 16usize]>()
4563                         .write_unaligned(self.port_gid);
4564                     out_ptr
4565                         .add(24usize)
4566                         .cast::<u64>()
4567                         .write_unaligned(self.ioc_guid_or_service_id);
4568                     out_ptr
4569                         .add(32usize)
4570                         .cast::<u64>()
4571                         .write_unaligned(self.target_port_id);
4572                     out_ptr
4573                         .add(40usize)
4574                         .cast::<u64>()
4575                         .write_unaligned(self.device_id);
4576                 }
4577             }
4578         }
4579 
4580         /// UART messaging device path node.
4581         #[derive(Debug)]
4582         pub struct Uart {
4583             /// Baud rate setting, or 0 to use the device's default.
4584             pub baud_rate: u64,
4585             /// Number of data bits, or 0 to use the device's default.
4586             pub data_bits: u8,
4587             /// Parity setting.
4588             pub parity: device_path::messaging::Parity,
4589             /// Number of stop bits.
4590             pub stop_bits: device_path::messaging::StopBits,
4591         }
4592 
4593         unsafe impl BuildNode for Uart {
size_in_bytes(&self) -> Result<u16, BuildError>4594             fn size_in_bytes(&self) -> Result<u16, BuildError> {
4595                 let size = 19usize;
4596                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
4597             }
4598 
write_data(&self, out: &mut [MaybeUninit<u8>])4599             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
4600                 let size = usize::from(self.size_in_bytes().unwrap());
4601                 assert_eq!(size, out.len());
4602                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
4603                 unsafe {
4604                     out_ptr
4605                         .cast::<DevicePathHeader>()
4606                         .write_unaligned(DevicePathHeader {
4607                             device_type: DeviceType::MESSAGING,
4608                             sub_type: DeviceSubType::MESSAGING_UART,
4609                             length: u16::try_from(size).unwrap(),
4610                         });
4611                     out_ptr.add(4usize).write_bytes(0, size_of::<u32>());
4612                     out_ptr
4613                         .add(8usize)
4614                         .cast::<u64>()
4615                         .write_unaligned(self.baud_rate);
4616                     out_ptr
4617                         .add(16usize)
4618                         .cast::<u8>()
4619                         .write_unaligned(self.data_bits);
4620                     out_ptr
4621                         .add(17usize)
4622                         .cast::<device_path::messaging::Parity>()
4623                         .write_unaligned(self.parity);
4624                     out_ptr
4625                         .add(18usize)
4626                         .cast::<device_path::messaging::StopBits>()
4627                         .write_unaligned(self.stop_bits);
4628                 }
4629             }
4630         }
4631 
4632         /// Vendor-defined messaging device path node.
4633         #[derive(Debug)]
4634         pub struct Vendor<'a> {
4635             /// Vendor-assigned GUID that defines the data that follows.
4636             pub vendor_guid: Guid,
4637             /// Vendor-defined data.
4638             pub vendor_defined_data: &'a [u8],
4639         }
4640 
4641         unsafe impl<'a> BuildNode for Vendor<'a> {
size_in_bytes(&self) -> Result<u16, BuildError>4642             fn size_in_bytes(&self) -> Result<u16, BuildError> {
4643                 let size = 20usize + size_of_val(self.vendor_defined_data);
4644                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
4645             }
4646 
write_data(&self, out: &mut [MaybeUninit<u8>])4647             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
4648                 let size = usize::from(self.size_in_bytes().unwrap());
4649                 assert_eq!(size, out.len());
4650                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
4651                 unsafe {
4652                     out_ptr
4653                         .cast::<DevicePathHeader>()
4654                         .write_unaligned(DevicePathHeader {
4655                             device_type: DeviceType::MESSAGING,
4656                             sub_type: DeviceSubType::MESSAGING_VENDOR,
4657                             length: u16::try_from(size).unwrap(),
4658                         });
4659                     out_ptr
4660                         .add(4usize)
4661                         .cast::<Guid>()
4662                         .write_unaligned(self.vendor_guid);
4663                     self.vendor_defined_data
4664                         .as_ptr()
4665                         .cast::<u8>()
4666                         .copy_to_nonoverlapping(
4667                             out_ptr.add(20usize),
4668                             size_of_val(self.vendor_defined_data),
4669                         );
4670                 }
4671             }
4672         }
4673 
4674         /// Serial Attached SCSI (SAS) extended messaging device path node.
4675         #[derive(Debug)]
4676         pub struct SasEx {
4677             /// SAS address.
4678             pub sas_address: [u8; 8usize],
4679             /// Logical Unit Number.
4680             pub logical_unit_number: [u8; 8usize],
4681             /// Information about the device and its interconnect.
4682             pub info: u16,
4683             /// Relative Target Port (RTP).
4684             pub relative_target_port: u16,
4685         }
4686 
4687         unsafe impl BuildNode for SasEx {
size_in_bytes(&self) -> Result<u16, BuildError>4688             fn size_in_bytes(&self) -> Result<u16, BuildError> {
4689                 let size = 24usize;
4690                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
4691             }
4692 
write_data(&self, out: &mut [MaybeUninit<u8>])4693             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
4694                 let size = usize::from(self.size_in_bytes().unwrap());
4695                 assert_eq!(size, out.len());
4696                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
4697                 unsafe {
4698                     out_ptr
4699                         .cast::<DevicePathHeader>()
4700                         .write_unaligned(DevicePathHeader {
4701                             device_type: DeviceType::MESSAGING,
4702                             sub_type: DeviceSubType::MESSAGING_SCSI_SAS_EX,
4703                             length: u16::try_from(size).unwrap(),
4704                         });
4705                     out_ptr
4706                         .add(4usize)
4707                         .cast::<[u8; 8usize]>()
4708                         .write_unaligned(self.sas_address);
4709                     out_ptr
4710                         .add(12usize)
4711                         .cast::<[u8; 8usize]>()
4712                         .write_unaligned(self.logical_unit_number);
4713                     out_ptr
4714                         .add(20usize)
4715                         .cast::<u16>()
4716                         .write_unaligned(self.info);
4717                     out_ptr
4718                         .add(22usize)
4719                         .cast::<u16>()
4720                         .write_unaligned(self.relative_target_port);
4721                 }
4722             }
4723         }
4724 
4725         /// iSCSI messaging device path node.
4726         #[derive(Debug)]
4727         pub struct Iscsi<'a> {
4728             /// Network protocol.
4729             pub protocol: device_path::messaging::IscsiProtocol,
4730             /// iSCSI login options (bitfield).
4731             pub options: device_path::messaging::IscsiLoginOptions,
4732             /// iSCSI Logical Unit Number.
4733             pub logical_unit_number: [u8; 8usize],
4734             /// iSCSI Target Portal group tag the initiator intends to
4735             /// establish a session with.
4736             pub target_portal_group_tag: u16,
4737             /// iSCSI Node Target name.
4738             ///
4739             /// The UEFI Specification does not specify how the string is
4740             /// encoded, but gives one example that appears to be
4741             /// null-terminated ASCII.
4742             pub iscsi_target_name: &'a [u8],
4743         }
4744 
4745         unsafe impl<'a> BuildNode for Iscsi<'a> {
size_in_bytes(&self) -> Result<u16, BuildError>4746             fn size_in_bytes(&self) -> Result<u16, BuildError> {
4747                 let size = 18usize + size_of_val(self.iscsi_target_name);
4748                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
4749             }
4750 
write_data(&self, out: &mut [MaybeUninit<u8>])4751             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
4752                 let size = usize::from(self.size_in_bytes().unwrap());
4753                 assert_eq!(size, out.len());
4754                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
4755                 unsafe {
4756                     out_ptr
4757                         .cast::<DevicePathHeader>()
4758                         .write_unaligned(DevicePathHeader {
4759                             device_type: DeviceType::MESSAGING,
4760                             sub_type: DeviceSubType::MESSAGING_ISCSI,
4761                             length: u16::try_from(size).unwrap(),
4762                         });
4763                     out_ptr
4764                         .add(4usize)
4765                         .cast::<device_path::messaging::IscsiProtocol>()
4766                         .write_unaligned(self.protocol);
4767                     out_ptr
4768                         .add(6usize)
4769                         .cast::<device_path::messaging::IscsiLoginOptions>()
4770                         .write_unaligned(self.options);
4771                     out_ptr
4772                         .add(8usize)
4773                         .cast::<[u8; 8usize]>()
4774                         .write_unaligned(self.logical_unit_number);
4775                     out_ptr
4776                         .add(16usize)
4777                         .cast::<u16>()
4778                         .write_unaligned(self.target_portal_group_tag);
4779                     self.iscsi_target_name
4780                         .as_ptr()
4781                         .cast::<u8>()
4782                         .copy_to_nonoverlapping(
4783                             out_ptr.add(18usize),
4784                             size_of_val(self.iscsi_target_name),
4785                         );
4786                 }
4787             }
4788         }
4789 
4790         /// NVM Express namespace messaging device path node.
4791         #[derive(Debug)]
4792         pub struct NvmeNamespace {
4793             /// Namespace identifier (NSID). The values 0 and 0xffff_ffff
4794             /// are invalid.
4795             pub namespace_identifier: u32,
4796             /// IEEE Extended Unique Identifier (EUI-64), or 0 if the device
4797             /// does not have a EUI-64.
4798             pub ieee_extended_unique_identifier: u64,
4799         }
4800 
4801         unsafe impl BuildNode for NvmeNamespace {
size_in_bytes(&self) -> Result<u16, BuildError>4802             fn size_in_bytes(&self) -> Result<u16, BuildError> {
4803                 let size = 16usize;
4804                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
4805             }
4806 
write_data(&self, out: &mut [MaybeUninit<u8>])4807             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
4808                 let size = usize::from(self.size_in_bytes().unwrap());
4809                 assert_eq!(size, out.len());
4810                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
4811                 unsafe {
4812                     out_ptr
4813                         .cast::<DevicePathHeader>()
4814                         .write_unaligned(DevicePathHeader {
4815                             device_type: DeviceType::MESSAGING,
4816                             sub_type: DeviceSubType::MESSAGING_NVME_NAMESPACE,
4817                             length: u16::try_from(size).unwrap(),
4818                         });
4819                     out_ptr
4820                         .add(4usize)
4821                         .cast::<u32>()
4822                         .write_unaligned(self.namespace_identifier);
4823                     out_ptr
4824                         .add(8usize)
4825                         .cast::<u64>()
4826                         .write_unaligned(self.ieee_extended_unique_identifier);
4827                 }
4828             }
4829         }
4830 
4831         /// Uniform Resource Identifier (URI) messaging device path node.
4832         #[derive(Debug)]
4833         pub struct Uri<'a> {
4834             /// URI as defined by [RFC 3986](https://www.rfc-editor.org/rfc/rfc3986).
4835             pub value: &'a [u8],
4836         }
4837 
4838         unsafe impl<'a> BuildNode for Uri<'a> {
size_in_bytes(&self) -> Result<u16, BuildError>4839             fn size_in_bytes(&self) -> Result<u16, BuildError> {
4840                 let size = 4usize + size_of_val(self.value);
4841                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
4842             }
4843 
write_data(&self, out: &mut [MaybeUninit<u8>])4844             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
4845                 let size = usize::from(self.size_in_bytes().unwrap());
4846                 assert_eq!(size, out.len());
4847                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
4848                 unsafe {
4849                     out_ptr
4850                         .cast::<DevicePathHeader>()
4851                         .write_unaligned(DevicePathHeader {
4852                             device_type: DeviceType::MESSAGING,
4853                             sub_type: DeviceSubType::MESSAGING_URI,
4854                             length: u16::try_from(size).unwrap(),
4855                         });
4856                     self.value
4857                         .as_ptr()
4858                         .cast::<u8>()
4859                         .copy_to_nonoverlapping(out_ptr.add(4usize), size_of_val(self.value));
4860                 }
4861             }
4862         }
4863 
4864         /// Universal Flash Storage (UFS) messaging device path node.
4865         #[derive(Debug)]
4866         pub struct Ufs {
4867             /// Target ID on the UFS interface (PUN).
4868             pub target_id: u8,
4869             /// Logical Unit Number (LUN).
4870             pub logical_unit_number: u8,
4871         }
4872 
4873         unsafe impl BuildNode for Ufs {
size_in_bytes(&self) -> Result<u16, BuildError>4874             fn size_in_bytes(&self) -> Result<u16, BuildError> {
4875                 let size = 6usize;
4876                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
4877             }
4878 
write_data(&self, out: &mut [MaybeUninit<u8>])4879             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
4880                 let size = usize::from(self.size_in_bytes().unwrap());
4881                 assert_eq!(size, out.len());
4882                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
4883                 unsafe {
4884                     out_ptr
4885                         .cast::<DevicePathHeader>()
4886                         .write_unaligned(DevicePathHeader {
4887                             device_type: DeviceType::MESSAGING,
4888                             sub_type: DeviceSubType::MESSAGING_UFS,
4889                             length: u16::try_from(size).unwrap(),
4890                         });
4891                     out_ptr
4892                         .add(4usize)
4893                         .cast::<u8>()
4894                         .write_unaligned(self.target_id);
4895                     out_ptr
4896                         .add(5usize)
4897                         .cast::<u8>()
4898                         .write_unaligned(self.logical_unit_number);
4899                 }
4900             }
4901         }
4902 
4903         /// Secure Digital (SD) messaging device path node.
4904         #[derive(Debug)]
4905         pub struct Sd {
4906             /// Slot number.
4907             pub slot_number: u8,
4908         }
4909 
4910         unsafe impl BuildNode for Sd {
size_in_bytes(&self) -> Result<u16, BuildError>4911             fn size_in_bytes(&self) -> Result<u16, BuildError> {
4912                 let size = 5usize;
4913                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
4914             }
4915 
write_data(&self, out: &mut [MaybeUninit<u8>])4916             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
4917                 let size = usize::from(self.size_in_bytes().unwrap());
4918                 assert_eq!(size, out.len());
4919                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
4920                 unsafe {
4921                     out_ptr
4922                         .cast::<DevicePathHeader>()
4923                         .write_unaligned(DevicePathHeader {
4924                             device_type: DeviceType::MESSAGING,
4925                             sub_type: DeviceSubType::MESSAGING_SD,
4926                             length: u16::try_from(size).unwrap(),
4927                         });
4928                     out_ptr
4929                         .add(4usize)
4930                         .cast::<u8>()
4931                         .write_unaligned(self.slot_number);
4932                 }
4933             }
4934         }
4935 
4936         /// Bluetooth messaging device path node.
4937         #[derive(Debug)]
4938         pub struct Bluetooth {
4939             /// 48-bit bluetooth device address.
4940             pub device_address: [u8; 6usize],
4941         }
4942 
4943         unsafe impl BuildNode for Bluetooth {
size_in_bytes(&self) -> Result<u16, BuildError>4944             fn size_in_bytes(&self) -> Result<u16, BuildError> {
4945                 let size = 10usize;
4946                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
4947             }
4948 
write_data(&self, out: &mut [MaybeUninit<u8>])4949             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
4950                 let size = usize::from(self.size_in_bytes().unwrap());
4951                 assert_eq!(size, out.len());
4952                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
4953                 unsafe {
4954                     out_ptr
4955                         .cast::<DevicePathHeader>()
4956                         .write_unaligned(DevicePathHeader {
4957                             device_type: DeviceType::MESSAGING,
4958                             sub_type: DeviceSubType::MESSAGING_BLUETOOTH,
4959                             length: u16::try_from(size).unwrap(),
4960                         });
4961                     out_ptr
4962                         .add(4usize)
4963                         .cast::<[u8; 6usize]>()
4964                         .write_unaligned(self.device_address);
4965                 }
4966             }
4967         }
4968 
4969         /// Wi-Fi messaging device path node.
4970         #[derive(Debug)]
4971         pub struct Wifi {
4972             /// Service set identifier (SSID).
4973             pub ssid: [u8; 32usize],
4974         }
4975 
4976         unsafe impl BuildNode for Wifi {
size_in_bytes(&self) -> Result<u16, BuildError>4977             fn size_in_bytes(&self) -> Result<u16, BuildError> {
4978                 let size = 36usize;
4979                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
4980             }
4981 
write_data(&self, out: &mut [MaybeUninit<u8>])4982             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
4983                 let size = usize::from(self.size_in_bytes().unwrap());
4984                 assert_eq!(size, out.len());
4985                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
4986                 unsafe {
4987                     out_ptr
4988                         .cast::<DevicePathHeader>()
4989                         .write_unaligned(DevicePathHeader {
4990                             device_type: DeviceType::MESSAGING,
4991                             sub_type: DeviceSubType::MESSAGING_WIFI,
4992                             length: u16::try_from(size).unwrap(),
4993                         });
4994                     out_ptr
4995                         .add(4usize)
4996                         .cast::<[u8; 32usize]>()
4997                         .write_unaligned(self.ssid);
4998                 }
4999             }
5000         }
5001 
5002         /// Embedded Multi-Media Card (eMMC) messaging device path node.
5003         #[derive(Debug)]
5004         pub struct Emmc {
5005             /// Slot number.
5006             pub slot_number: u8,
5007         }
5008 
5009         unsafe impl BuildNode for Emmc {
size_in_bytes(&self) -> Result<u16, BuildError>5010             fn size_in_bytes(&self) -> Result<u16, BuildError> {
5011                 let size = 5usize;
5012                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
5013             }
5014 
write_data(&self, out: &mut [MaybeUninit<u8>])5015             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
5016                 let size = usize::from(self.size_in_bytes().unwrap());
5017                 assert_eq!(size, out.len());
5018                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
5019                 unsafe {
5020                     out_ptr
5021                         .cast::<DevicePathHeader>()
5022                         .write_unaligned(DevicePathHeader {
5023                             device_type: DeviceType::MESSAGING,
5024                             sub_type: DeviceSubType::MESSAGING_EMMC,
5025                             length: u16::try_from(size).unwrap(),
5026                         });
5027                     out_ptr
5028                         .add(4usize)
5029                         .cast::<u8>()
5030                         .write_unaligned(self.slot_number);
5031                 }
5032             }
5033         }
5034 
5035         /// BluetoothLE messaging device path node.
5036         #[derive(Debug)]
5037         pub struct BluetoothLe {
5038             /// 48-bit bluetooth device address.
5039             pub device_address: [u8; 6usize],
5040             /// Address type.
5041             pub address_type: device_path::messaging::BluetoothLeAddressType,
5042         }
5043 
5044         unsafe impl BuildNode for BluetoothLe {
size_in_bytes(&self) -> Result<u16, BuildError>5045             fn size_in_bytes(&self) -> Result<u16, BuildError> {
5046                 let size = 11usize;
5047                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
5048             }
5049 
write_data(&self, out: &mut [MaybeUninit<u8>])5050             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
5051                 let size = usize::from(self.size_in_bytes().unwrap());
5052                 assert_eq!(size, out.len());
5053                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
5054                 unsafe {
5055                     out_ptr
5056                         .cast::<DevicePathHeader>()
5057                         .write_unaligned(DevicePathHeader {
5058                             device_type: DeviceType::MESSAGING,
5059                             sub_type: DeviceSubType::MESSAGING_BLUETOOTH_LE,
5060                             length: u16::try_from(size).unwrap(),
5061                         });
5062                     out_ptr
5063                         .add(4usize)
5064                         .cast::<[u8; 6usize]>()
5065                         .write_unaligned(self.device_address);
5066                     out_ptr
5067                         .add(10usize)
5068                         .cast::<device_path::messaging::BluetoothLeAddressType>()
5069                         .write_unaligned(self.address_type);
5070                 }
5071             }
5072         }
5073 
5074         /// DNS messaging device path node.
5075         #[derive(Debug)]
5076         pub struct Dns<'a> {
5077             /// Whether the addresses are IPv4 or IPv6.
5078             pub address_type: device_path::messaging::DnsAddressType,
5079             /// One or more instances of the DNS server address.
5080             pub addresses: &'a [IpAddress],
5081         }
5082 
5083         unsafe impl<'a> BuildNode for Dns<'a> {
size_in_bytes(&self) -> Result<u16, BuildError>5084             fn size_in_bytes(&self) -> Result<u16, BuildError> {
5085                 let size = 5usize + size_of_val(self.addresses);
5086                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
5087             }
5088 
write_data(&self, out: &mut [MaybeUninit<u8>])5089             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
5090                 let size = usize::from(self.size_in_bytes().unwrap());
5091                 assert_eq!(size, out.len());
5092                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
5093                 unsafe {
5094                     out_ptr
5095                         .cast::<DevicePathHeader>()
5096                         .write_unaligned(DevicePathHeader {
5097                             device_type: DeviceType::MESSAGING,
5098                             sub_type: DeviceSubType::MESSAGING_DNS,
5099                             length: u16::try_from(size).unwrap(),
5100                         });
5101                     out_ptr
5102                         .add(4usize)
5103                         .cast::<device_path::messaging::DnsAddressType>()
5104                         .write_unaligned(self.address_type);
5105                     self.addresses
5106                         .as_ptr()
5107                         .cast::<u8>()
5108                         .copy_to_nonoverlapping(out_ptr.add(5usize), size_of_val(self.addresses));
5109                 }
5110             }
5111         }
5112 
5113         /// NVDIMM namespace messaging device path node.
5114         #[derive(Debug)]
5115         pub struct NvdimmNamespace {
5116             /// Namespace unique label identifier.
5117             pub uuid: [u8; 16usize],
5118         }
5119 
5120         unsafe impl BuildNode for NvdimmNamespace {
size_in_bytes(&self) -> Result<u16, BuildError>5121             fn size_in_bytes(&self) -> Result<u16, BuildError> {
5122                 let size = 20usize;
5123                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
5124             }
5125 
write_data(&self, out: &mut [MaybeUninit<u8>])5126             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
5127                 let size = usize::from(self.size_in_bytes().unwrap());
5128                 assert_eq!(size, out.len());
5129                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
5130                 unsafe {
5131                     out_ptr
5132                         .cast::<DevicePathHeader>()
5133                         .write_unaligned(DevicePathHeader {
5134                             device_type: DeviceType::MESSAGING,
5135                             sub_type: DeviceSubType::MESSAGING_NVDIMM_NAMESPACE,
5136                             length: u16::try_from(size).unwrap(),
5137                         });
5138                     out_ptr
5139                         .add(4usize)
5140                         .cast::<[u8; 16usize]>()
5141                         .write_unaligned(self.uuid);
5142                 }
5143             }
5144         }
5145 
5146         /// REST service messaging device path node.
5147         #[derive(Debug)]
5148         pub struct RestService<'a> {
5149             /// Type of REST service.
5150             pub service_type: device_path::messaging::RestServiceType,
5151             /// Whether the service is in-band or out-of-band.
5152             pub access_mode: device_path::messaging::RestServiceAccessMode,
5153             /// Vendor-specific data. Only used if the service type is [`VENDOR`].
5154             ///
5155             /// [`VENDOR`]: uefi::proto::device_path::messaging::RestServiceType
5156             pub vendor_guid_and_data: Option<RestServiceVendorData<'a>>,
5157         }
5158 
5159         unsafe impl<'a> BuildNode for RestService<'a> {
size_in_bytes(&self) -> Result<u16, BuildError>5160             fn size_in_bytes(&self) -> Result<u16, BuildError> {
5161                 let size = 6usize + self.build_size_vendor_guid_and_data();
5162                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
5163             }
5164 
write_data(&self, out: &mut [MaybeUninit<u8>])5165             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
5166                 let size = usize::from(self.size_in_bytes().unwrap());
5167                 assert_eq!(size, out.len());
5168                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
5169                 unsafe {
5170                     out_ptr
5171                         .cast::<DevicePathHeader>()
5172                         .write_unaligned(DevicePathHeader {
5173                             device_type: DeviceType::MESSAGING,
5174                             sub_type: DeviceSubType::MESSAGING_REST_SERVICE,
5175                             length: u16::try_from(size).unwrap(),
5176                         });
5177                     out_ptr
5178                         .add(4usize)
5179                         .cast::<device_path::messaging::RestServiceType>()
5180                         .write_unaligned(self.service_type);
5181                     out_ptr
5182                         .add(5usize)
5183                         .cast::<device_path::messaging::RestServiceAccessMode>()
5184                         .write_unaligned(self.access_mode);
5185                     self.build_vendor_guid_and_data(&mut out[6usize..])
5186                 }
5187             }
5188         }
5189 
5190         /// NVME over Fabric (NVMe-oF) namespace messaging device path node.
5191         #[derive(Debug)]
5192         pub struct NvmeOfNamespace<'a> {
5193             /// Namespace Identifier Type (NIDT).
5194             pub nidt: u8,
5195             /// Namespace Identifier (NID).
5196             pub nid: [u8; 16usize],
5197             /// Unique identifier of an NVM subsystem stored as a
5198             /// null-terminated UTF-8 string. Maximum length of 224 bytes.
5199             pub subsystem_nqn: &'a [u8],
5200         }
5201 
5202         unsafe impl<'a> BuildNode for NvmeOfNamespace<'a> {
size_in_bytes(&self) -> Result<u16, BuildError>5203             fn size_in_bytes(&self) -> Result<u16, BuildError> {
5204                 let size = 21usize + size_of_val(self.subsystem_nqn);
5205                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
5206             }
5207 
write_data(&self, out: &mut [MaybeUninit<u8>])5208             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
5209                 let size = usize::from(self.size_in_bytes().unwrap());
5210                 assert_eq!(size, out.len());
5211                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
5212                 unsafe {
5213                     out_ptr
5214                         .cast::<DevicePathHeader>()
5215                         .write_unaligned(DevicePathHeader {
5216                             device_type: DeviceType::MESSAGING,
5217                             sub_type: DeviceSubType::MESSAGING_NVME_OF_NAMESPACE,
5218                             length: u16::try_from(size).unwrap(),
5219                         });
5220                     out_ptr.add(4usize).cast::<u8>().write_unaligned(self.nidt);
5221                     out_ptr
5222                         .add(5usize)
5223                         .cast::<[u8; 16usize]>()
5224                         .write_unaligned(self.nid);
5225                     self.subsystem_nqn
5226                         .as_ptr()
5227                         .cast::<u8>()
5228                         .copy_to_nonoverlapping(
5229                             out_ptr.add(21usize),
5230                             size_of_val(self.subsystem_nqn),
5231                         );
5232                 }
5233             }
5234         }
5235 
5236         /// Vendor-specific REST service data. Only used for service type [`VENDOR`].
5237         ///
5238         /// [`VENDOR`]: uefi::proto::device_path::messaging::RestServiceType
5239         #[derive(Debug)]
5240         pub struct RestServiceVendorData<'a> {
5241             /// Vendor GUID.
5242             pub vendor_guid: Guid,
5243             /// Vendor-defined data.
5244             pub vendor_defined_data: &'a [u8],
5245         }
5246 
5247         impl<'a> RestService<'a> {
build_size_vendor_guid_and_data(&self) -> usize5248             fn build_size_vendor_guid_and_data(&self) -> usize {
5249                 if let Some(src) = &self.vendor_guid_and_data {
5250                     assert!(self.service_type == device_path::messaging::RestServiceType::VENDOR);
5251                     size_of::<Guid>() + size_of_val(src.vendor_defined_data)
5252                 } else {
5253                     0
5254                 }
5255             }
5256 
build_vendor_guid_and_data(&self, out: &mut [MaybeUninit<u8>])5257             fn build_vendor_guid_and_data(&self, out: &mut [MaybeUninit<u8>]) {
5258                 if let Some(src) = &self.vendor_guid_and_data {
5259                     assert!(self.service_type == device_path::messaging::RestServiceType::VENDOR);
5260                     let (guid_out, data_out) = out.split_at_mut(size_of::<Guid>());
5261                     let guid_out_ptr: *mut Guid = maybe_uninit_slice_as_mut_ptr(guid_out).cast();
5262                     unsafe {
5263                         guid_out_ptr.write_unaligned(src.vendor_guid);
5264                     }
5265 
5266                     let data_out_ptr = maybe_uninit_slice_as_mut_ptr(data_out);
5267                     unsafe {
5268                         src.vendor_defined_data
5269                             .as_ptr()
5270                             .copy_to_nonoverlapping(data_out_ptr, data_out.len());
5271                     }
5272                 }
5273             }
5274         }
5275     }
5276 
5277     /// Device path build nodes for [`DeviceType::MEDIA`].
5278     pub mod media {
5279         use super::*;
5280         /// Hard drive media device path node.
5281         #[derive(Debug)]
5282         pub struct HardDrive {
5283             /// Index of the partition, starting from 1.
5284             pub partition_number: u32,
5285             /// Starting LBA (logical block address) of the partition.
5286             pub partition_start: u64,
5287             /// Size of the partition in blocks.
5288             pub partition_size: u64,
5289             /// Partition signature.
5290             pub partition_signature: device_path::media::PartitionSignature,
5291             /// Partition format.
5292             pub partition_format: device_path::media::PartitionFormat,
5293         }
5294 
5295         unsafe impl BuildNode for HardDrive {
size_in_bytes(&self) -> Result<u16, BuildError>5296             fn size_in_bytes(&self) -> Result<u16, BuildError> {
5297                 let size = 42usize;
5298                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
5299             }
5300 
write_data(&self, out: &mut [MaybeUninit<u8>])5301             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
5302                 let size = usize::from(self.size_in_bytes().unwrap());
5303                 assert_eq!(size, out.len());
5304                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
5305                 unsafe {
5306                     out_ptr
5307                         .cast::<DevicePathHeader>()
5308                         .write_unaligned(DevicePathHeader {
5309                             device_type: DeviceType::MEDIA,
5310                             sub_type: DeviceSubType::MEDIA_HARD_DRIVE,
5311                             length: u16::try_from(size).unwrap(),
5312                         });
5313                     out_ptr
5314                         .add(4usize)
5315                         .cast::<u32>()
5316                         .write_unaligned(self.partition_number);
5317                     out_ptr
5318                         .add(8usize)
5319                         .cast::<u64>()
5320                         .write_unaligned(self.partition_start);
5321                     out_ptr
5322                         .add(16usize)
5323                         .cast::<u64>()
5324                         .write_unaligned(self.partition_size);
5325                     out_ptr
5326                         .add(24usize)
5327                         .cast::<[u8; 16usize]>()
5328                         .write_unaligned(self.build_partition_signature());
5329                     out_ptr
5330                         .add(40usize)
5331                         .cast::<device_path::media::PartitionFormat>()
5332                         .write_unaligned(self.partition_format);
5333                     out_ptr
5334                         .add(41usize)
5335                         .cast::<u8>()
5336                         .write_unaligned(self.build_signature_type());
5337                 }
5338             }
5339         }
5340 
5341         /// CD-ROM media device path node.
5342         #[derive(Debug)]
5343         pub struct CdRom {
5344             /// Boot entry number from the boot catalog, or 0 for the
5345             /// default entry.
5346             pub boot_entry: u32,
5347             /// Starting RBA (Relative logical Block Address).
5348             pub partition_start: u64,
5349             /// Size of the partition in blocks.
5350             pub partition_size: u64,
5351         }
5352 
5353         unsafe impl BuildNode for CdRom {
size_in_bytes(&self) -> Result<u16, BuildError>5354             fn size_in_bytes(&self) -> Result<u16, BuildError> {
5355                 let size = 24usize;
5356                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
5357             }
5358 
write_data(&self, out: &mut [MaybeUninit<u8>])5359             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
5360                 let size = usize::from(self.size_in_bytes().unwrap());
5361                 assert_eq!(size, out.len());
5362                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
5363                 unsafe {
5364                     out_ptr
5365                         .cast::<DevicePathHeader>()
5366                         .write_unaligned(DevicePathHeader {
5367                             device_type: DeviceType::MEDIA,
5368                             sub_type: DeviceSubType::MEDIA_CD_ROM,
5369                             length: u16::try_from(size).unwrap(),
5370                         });
5371                     out_ptr
5372                         .add(4usize)
5373                         .cast::<u32>()
5374                         .write_unaligned(self.boot_entry);
5375                     out_ptr
5376                         .add(8usize)
5377                         .cast::<u64>()
5378                         .write_unaligned(self.partition_start);
5379                     out_ptr
5380                         .add(16usize)
5381                         .cast::<u64>()
5382                         .write_unaligned(self.partition_size);
5383                 }
5384             }
5385         }
5386 
5387         /// Vendor-defined media device path node.
5388         #[derive(Debug)]
5389         pub struct Vendor<'a> {
5390             /// Vendor-assigned GUID that defines the data that follows.
5391             pub vendor_guid: Guid,
5392             /// Vendor-defined data.
5393             pub vendor_defined_data: &'a [u8],
5394         }
5395 
5396         unsafe impl<'a> BuildNode for Vendor<'a> {
size_in_bytes(&self) -> Result<u16, BuildError>5397             fn size_in_bytes(&self) -> Result<u16, BuildError> {
5398                 let size = 20usize + size_of_val(self.vendor_defined_data);
5399                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
5400             }
5401 
write_data(&self, out: &mut [MaybeUninit<u8>])5402             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
5403                 let size = usize::from(self.size_in_bytes().unwrap());
5404                 assert_eq!(size, out.len());
5405                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
5406                 unsafe {
5407                     out_ptr
5408                         .cast::<DevicePathHeader>()
5409                         .write_unaligned(DevicePathHeader {
5410                             device_type: DeviceType::MEDIA,
5411                             sub_type: DeviceSubType::MEDIA_VENDOR,
5412                             length: u16::try_from(size).unwrap(),
5413                         });
5414                     out_ptr
5415                         .add(4usize)
5416                         .cast::<Guid>()
5417                         .write_unaligned(self.vendor_guid);
5418                     self.vendor_defined_data
5419                         .as_ptr()
5420                         .cast::<u8>()
5421                         .copy_to_nonoverlapping(
5422                             out_ptr.add(20usize),
5423                             size_of_val(self.vendor_defined_data),
5424                         );
5425                 }
5426             }
5427         }
5428 
5429         /// File path media device path node.
5430         #[derive(Debug)]
5431         pub struct FilePath<'a> {
5432             /// Null-terminated path.
5433             pub path_name: &'a CStr16,
5434         }
5435 
5436         unsafe impl<'a> BuildNode for FilePath<'a> {
size_in_bytes(&self) -> Result<u16, BuildError>5437             fn size_in_bytes(&self) -> Result<u16, BuildError> {
5438                 let size = 4usize + size_of_val(self.path_name);
5439                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
5440             }
5441 
write_data(&self, out: &mut [MaybeUninit<u8>])5442             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
5443                 let size = usize::from(self.size_in_bytes().unwrap());
5444                 assert_eq!(size, out.len());
5445                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
5446                 unsafe {
5447                     out_ptr
5448                         .cast::<DevicePathHeader>()
5449                         .write_unaligned(DevicePathHeader {
5450                             device_type: DeviceType::MEDIA,
5451                             sub_type: DeviceSubType::MEDIA_FILE_PATH,
5452                             length: u16::try_from(size).unwrap(),
5453                         });
5454                     self.path_name
5455                         .as_ptr()
5456                         .cast::<u8>()
5457                         .copy_to_nonoverlapping(out_ptr.add(4usize), size_of_val(self.path_name));
5458                 }
5459             }
5460         }
5461 
5462         /// Media protocol media device path node.
5463         #[derive(Debug)]
5464         pub struct Protocol {
5465             /// The ID of the protocol.
5466             pub protocol_guid: Guid,
5467         }
5468 
5469         unsafe impl BuildNode for Protocol {
size_in_bytes(&self) -> Result<u16, BuildError>5470             fn size_in_bytes(&self) -> Result<u16, BuildError> {
5471                 let size = 20usize;
5472                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
5473             }
5474 
write_data(&self, out: &mut [MaybeUninit<u8>])5475             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
5476                 let size = usize::from(self.size_in_bytes().unwrap());
5477                 assert_eq!(size, out.len());
5478                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
5479                 unsafe {
5480                     out_ptr
5481                         .cast::<DevicePathHeader>()
5482                         .write_unaligned(DevicePathHeader {
5483                             device_type: DeviceType::MEDIA,
5484                             sub_type: DeviceSubType::MEDIA_PROTOCOL,
5485                             length: u16::try_from(size).unwrap(),
5486                         });
5487                     out_ptr
5488                         .add(4usize)
5489                         .cast::<Guid>()
5490                         .write_unaligned(self.protocol_guid);
5491                 }
5492             }
5493         }
5494 
5495         /// PIWG firmware file media device path node.
5496         #[derive(Debug)]
5497         pub struct PiwgFirmwareFile<'a> {
5498             /// Contents are defined in the UEFI PI Specification.
5499             pub data: &'a [u8],
5500         }
5501 
5502         unsafe impl<'a> BuildNode for PiwgFirmwareFile<'a> {
size_in_bytes(&self) -> Result<u16, BuildError>5503             fn size_in_bytes(&self) -> Result<u16, BuildError> {
5504                 let size = 4usize + size_of_val(self.data);
5505                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
5506             }
5507 
write_data(&self, out: &mut [MaybeUninit<u8>])5508             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
5509                 let size = usize::from(self.size_in_bytes().unwrap());
5510                 assert_eq!(size, out.len());
5511                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
5512                 unsafe {
5513                     out_ptr
5514                         .cast::<DevicePathHeader>()
5515                         .write_unaligned(DevicePathHeader {
5516                             device_type: DeviceType::MEDIA,
5517                             sub_type: DeviceSubType::MEDIA_PIWG_FIRMWARE_FILE,
5518                             length: u16::try_from(size).unwrap(),
5519                         });
5520                     self.data
5521                         .as_ptr()
5522                         .cast::<u8>()
5523                         .copy_to_nonoverlapping(out_ptr.add(4usize), size_of_val(self.data));
5524                 }
5525             }
5526         }
5527 
5528         /// PIWG firmware volume media device path node.
5529         #[derive(Debug)]
5530         pub struct PiwgFirmwareVolume<'a> {
5531             /// Contents are defined in the UEFI PI Specification.
5532             pub data: &'a [u8],
5533         }
5534 
5535         unsafe impl<'a> BuildNode for PiwgFirmwareVolume<'a> {
size_in_bytes(&self) -> Result<u16, BuildError>5536             fn size_in_bytes(&self) -> Result<u16, BuildError> {
5537                 let size = 4usize + size_of_val(self.data);
5538                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
5539             }
5540 
write_data(&self, out: &mut [MaybeUninit<u8>])5541             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
5542                 let size = usize::from(self.size_in_bytes().unwrap());
5543                 assert_eq!(size, out.len());
5544                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
5545                 unsafe {
5546                     out_ptr
5547                         .cast::<DevicePathHeader>()
5548                         .write_unaligned(DevicePathHeader {
5549                             device_type: DeviceType::MEDIA,
5550                             sub_type: DeviceSubType::MEDIA_PIWG_FIRMWARE_VOLUME,
5551                             length: u16::try_from(size).unwrap(),
5552                         });
5553                     self.data
5554                         .as_ptr()
5555                         .cast::<u8>()
5556                         .copy_to_nonoverlapping(out_ptr.add(4usize), size_of_val(self.data));
5557                 }
5558             }
5559         }
5560 
5561         /// Relative offset range media device path node.
5562         #[derive(Debug)]
5563         pub struct RelativeOffsetRange {
5564             /// Offset of the first byte, relative to the parent device node.
5565             pub starting_offset: u64,
5566             /// Offset of the last byte, relative to the parent device node.
5567             pub ending_offset: u64,
5568         }
5569 
5570         unsafe impl BuildNode for RelativeOffsetRange {
size_in_bytes(&self) -> Result<u16, BuildError>5571             fn size_in_bytes(&self) -> Result<u16, BuildError> {
5572                 let size = 24usize;
5573                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
5574             }
5575 
write_data(&self, out: &mut [MaybeUninit<u8>])5576             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
5577                 let size = usize::from(self.size_in_bytes().unwrap());
5578                 assert_eq!(size, out.len());
5579                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
5580                 unsafe {
5581                     out_ptr
5582                         .cast::<DevicePathHeader>()
5583                         .write_unaligned(DevicePathHeader {
5584                             device_type: DeviceType::MEDIA,
5585                             sub_type: DeviceSubType::MEDIA_RELATIVE_OFFSET_RANGE,
5586                             length: u16::try_from(size).unwrap(),
5587                         });
5588                     out_ptr.add(4usize).write_bytes(0, size_of::<u32>());
5589                     out_ptr
5590                         .add(8usize)
5591                         .cast::<u64>()
5592                         .write_unaligned(self.starting_offset);
5593                     out_ptr
5594                         .add(16usize)
5595                         .cast::<u64>()
5596                         .write_unaligned(self.ending_offset);
5597                 }
5598             }
5599         }
5600 
5601         /// RAM disk media device path node.
5602         #[derive(Debug)]
5603         pub struct RamDisk {
5604             /// Starting memory address.
5605             pub starting_address: u64,
5606             /// Ending memory address.
5607             pub ending_address: u64,
5608             /// Type of RAM disk.
5609             pub disk_type: device_path::media::RamDiskType,
5610             /// RAM disk instance number if supported, otherwise 0.
5611             pub disk_instance: u16,
5612         }
5613 
5614         unsafe impl BuildNode for RamDisk {
size_in_bytes(&self) -> Result<u16, BuildError>5615             fn size_in_bytes(&self) -> Result<u16, BuildError> {
5616                 let size = 38usize;
5617                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
5618             }
5619 
write_data(&self, out: &mut [MaybeUninit<u8>])5620             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
5621                 let size = usize::from(self.size_in_bytes().unwrap());
5622                 assert_eq!(size, out.len());
5623                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
5624                 unsafe {
5625                     out_ptr
5626                         .cast::<DevicePathHeader>()
5627                         .write_unaligned(DevicePathHeader {
5628                             device_type: DeviceType::MEDIA,
5629                             sub_type: DeviceSubType::MEDIA_RAM_DISK,
5630                             length: u16::try_from(size).unwrap(),
5631                         });
5632                     out_ptr
5633                         .add(4usize)
5634                         .cast::<u64>()
5635                         .write_unaligned(self.starting_address);
5636                     out_ptr
5637                         .add(12usize)
5638                         .cast::<u64>()
5639                         .write_unaligned(self.ending_address);
5640                     out_ptr
5641                         .add(20usize)
5642                         .cast::<device_path::media::RamDiskType>()
5643                         .write_unaligned(self.disk_type);
5644                     out_ptr
5645                         .add(36usize)
5646                         .cast::<u16>()
5647                         .write_unaligned(self.disk_instance);
5648                 }
5649             }
5650         }
5651 
5652         impl HardDrive {
build_partition_signature(&self) -> [u8; 16]5653             fn build_partition_signature(&self) -> [u8; 16] {
5654                 use device_path::media::PartitionSignature::*;
5655                 match self.partition_signature {
5656                     None => [0u8; 16],
5657                     Mbr(mbr) => {
5658                         let mut sig = [0u8; 16];
5659                         sig[0..4].copy_from_slice(&mbr);
5660                         sig
5661                     }
5662 
5663                     Guid(guid) => guid.to_bytes(),
5664                     Unknown { signature, .. } => signature,
5665                 }
5666             }
5667 
build_signature_type(&self) -> u85668             fn build_signature_type(&self) -> u8 {
5669                 use device_path::media::PartitionSignature::*;
5670                 match self.partition_signature {
5671                     None => 0,
5672                     Mbr(_) => 1,
5673                     Guid(_) => 2,
5674                     Unknown { signature_type, .. } => signature_type,
5675                 }
5676             }
5677         }
5678     }
5679 
5680     /// Device path build nodes for [`DeviceType::BIOS_BOOT_SPEC`].
5681     pub mod bios_boot_spec {
5682         use super::*;
5683         /// BIOS Boot Specification device path node.
5684         #[derive(Debug)]
5685         pub struct BootSpecification<'a> {
5686             /// Device type as defined by the BIOS Boot Specification.
5687             pub device_type: u16,
5688             /// Status flags as defined by the BIOS Boot Specification.
5689             pub status_flag: u16,
5690             /// Description of the boot device encoded as a null-terminated
5691             /// ASCII string.
5692             pub description_string: &'a [u8],
5693         }
5694 
5695         unsafe impl<'a> BuildNode for BootSpecification<'a> {
size_in_bytes(&self) -> Result<u16, BuildError>5696             fn size_in_bytes(&self) -> Result<u16, BuildError> {
5697                 let size = 8usize + size_of_val(self.description_string);
5698                 u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
5699             }
5700 
write_data(&self, out: &mut [MaybeUninit<u8>])5701             fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
5702                 let size = usize::from(self.size_in_bytes().unwrap());
5703                 assert_eq!(size, out.len());
5704                 let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
5705                 unsafe {
5706                     out_ptr
5707                         .cast::<DevicePathHeader>()
5708                         .write_unaligned(DevicePathHeader {
5709                             device_type: DeviceType::BIOS_BOOT_SPEC,
5710                             sub_type: DeviceSubType::BIOS_BOOT_SPECIFICATION,
5711                             length: u16::try_from(size).unwrap(),
5712                         });
5713                     out_ptr
5714                         .add(4usize)
5715                         .cast::<u16>()
5716                         .write_unaligned(self.device_type);
5717                     out_ptr
5718                         .add(6usize)
5719                         .cast::<u16>()
5720                         .write_unaligned(self.status_flag);
5721                     self.description_string
5722                         .as_ptr()
5723                         .cast::<u8>()
5724                         .copy_to_nonoverlapping(
5725                             out_ptr.add(8usize),
5726                             size_of_val(self.description_string),
5727                         );
5728                 }
5729             }
5730         }
5731     }
5732 }
5733