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