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