use crate::data_types::UnalignedSlice;
use crate::polyfill::maybe_uninit_slice_as_mut_ptr;
use crate::proto::device_path::{
DevicePathHeader, DevicePathNode, DeviceSubType, DeviceType, NodeConversionError,
};
use crate::proto::network::IpAddress;
use crate::table::boot::MemoryType;
use crate::{guid, Guid};
use bitflags::bitflags;
use core::mem::{size_of, size_of_val};
use core::ptr::addr_of;
use core::{fmt, slice};
use ptr_meta::{Pointee, PtrExt};
pub mod end {
use super::*;
#[repr(C, packed)]
pub struct Instance {
pub(super) header: DevicePathHeader,
}
impl Instance {}
impl fmt::Debug for Instance {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Instance").finish()
}
}
impl TryFrom<&DevicePathNode> for &Instance {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
if size_of_val(node) != size_of::<Instance>() {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const Instance = node.cast();
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
pub struct Entire {
pub(super) header: DevicePathHeader,
}
impl Entire {}
impl fmt::Debug for Entire {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Entire").finish()
}
}
impl TryFrom<&DevicePathNode> for &Entire {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
if size_of_val(node) != size_of::<Entire>() {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const Entire = node.cast();
Ok(unsafe { &*node })
}
}
}
pub mod hardware {
use super::*;
#[repr(C, packed)]
pub struct Pci {
pub(super) header: DevicePathHeader,
pub(super) function: u8,
pub(super) device: u8,
}
impl Pci {
#[must_use]
pub fn function(&self) -> u8 {
self.function
}
#[must_use]
pub fn device(&self) -> u8 {
self.device
}
}
impl fmt::Debug for Pci {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Pci")
.field("function", &{ self.function })
.field("device", &{ self.device })
.finish()
}
}
impl TryFrom<&DevicePathNode> for &Pci {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
if size_of_val(node) != size_of::<Pci>() {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const Pci = node.cast();
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
pub struct Pccard {
pub(super) header: DevicePathHeader,
pub(super) function: u8,
}
impl Pccard {
#[must_use]
pub fn function(&self) -> u8 {
self.function
}
}
impl fmt::Debug for Pccard {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Pccard")
.field("function", &{ self.function })
.finish()
}
}
impl TryFrom<&DevicePathNode> for &Pccard {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
if size_of_val(node) != size_of::<Pccard>() {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const Pccard = node.cast();
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
pub struct MemoryMapped {
pub(super) header: DevicePathHeader,
pub(super) memory_type: MemoryType,
pub(super) start_address: u64,
pub(super) end_address: u64,
}
impl MemoryMapped {
#[must_use]
pub fn memory_type(&self) -> MemoryType {
self.memory_type
}
#[must_use]
pub fn start_address(&self) -> u64 {
self.start_address
}
#[must_use]
pub fn end_address(&self) -> u64 {
self.end_address
}
}
impl fmt::Debug for MemoryMapped {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("MemoryMapped")
.field("memory_type", &{ self.memory_type })
.field("start_address", &{ self.start_address })
.field("end_address", &{ self.end_address })
.finish()
}
}
impl TryFrom<&DevicePathNode> for &MemoryMapped {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
if size_of_val(node) != size_of::<MemoryMapped>() {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const MemoryMapped = node.cast();
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
#[derive(Pointee)]
pub struct Vendor {
pub(super) header: DevicePathHeader,
pub(super) vendor_guid: Guid,
pub(super) vendor_defined_data: [u8],
}
impl Vendor {
#[must_use]
pub fn vendor_guid(&self) -> Guid {
self.vendor_guid
}
#[must_use]
pub fn vendor_defined_data(&self) -> &[u8] {
&self.vendor_defined_data
}
}
impl fmt::Debug for Vendor {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Vendor")
.field("vendor_guid", &{ self.vendor_guid })
.field("vendor_defined_data", {
let ptr = addr_of!(self.vendor_defined_data);
let (ptr, len) = PtrExt::to_raw_parts(ptr);
let byte_len = size_of::<u8>() * len;
unsafe { &slice::from_raw_parts(ptr.cast::<u8>(), byte_len) }
})
.finish()
}
}
impl TryFrom<&DevicePathNode> for &Vendor {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
let static_size = 20usize;
let dst_size = size_of_val(node)
.checked_sub(static_size)
.ok_or(NodeConversionError::InvalidLength)?;
let elem_size = size_of::<u8>();
if dst_size % elem_size != 0 {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const Vendor = ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size);
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
pub struct Controller {
pub(super) header: DevicePathHeader,
pub(super) controller_number: u32,
}
impl Controller {
#[must_use]
pub fn controller_number(&self) -> u32 {
self.controller_number
}
}
impl fmt::Debug for Controller {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Controller")
.field("controller_number", &{ self.controller_number })
.finish()
}
}
impl TryFrom<&DevicePathNode> for &Controller {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
if size_of_val(node) != size_of::<Controller>() {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const Controller = node.cast();
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
pub struct Bmc {
pub(super) header: DevicePathHeader,
pub(super) interface_type: crate::proto::device_path::hardware::BmcInterfaceType,
pub(super) base_address: u64,
}
impl Bmc {
#[must_use]
pub fn interface_type(&self) -> crate::proto::device_path::hardware::BmcInterfaceType {
self.interface_type
}
#[must_use]
pub fn base_address(&self) -> u64 {
self.base_address
}
}
impl fmt::Debug for Bmc {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Bmc")
.field("interface_type", &{ self.interface_type })
.field("base_address", &{ self.base_address })
.finish()
}
}
impl TryFrom<&DevicePathNode> for &Bmc {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
if size_of_val(node) != size_of::<Bmc>() {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const Bmc = node.cast();
Ok(unsafe { &*node })
}
}
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 , }
}
}
pub mod acpi {
use super::*;
#[repr(C, packed)]
pub struct Acpi {
pub(super) header: DevicePathHeader,
pub(super) hid: u32,
pub(super) uid: u32,
}
impl Acpi {
#[must_use]
pub fn hid(&self) -> u32 {
self.hid
}
#[must_use]
pub fn uid(&self) -> u32 {
self.uid
}
}
impl fmt::Debug for Acpi {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Acpi")
.field("hid", &{ self.hid })
.field("uid", &{ self.uid })
.finish()
}
}
impl TryFrom<&DevicePathNode> for &Acpi {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
if size_of_val(node) != size_of::<Acpi>() {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const Acpi = node.cast();
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
#[derive(Pointee)]
pub struct Expanded {
pub(super) header: DevicePathHeader,
pub(super) hid: u32,
pub(super) uid: u32,
pub(super) cid: u32,
pub(super) data: [u8],
}
impl Expanded {
#[must_use]
pub fn hid(&self) -> u32 {
self.hid
}
#[must_use]
pub fn uid(&self) -> u32 {
self.uid
}
#[must_use]
pub fn cid(&self) -> u32 {
self.cid
}
#[must_use]
pub fn hid_str(&self) -> &[u8] {
self.get_hid_str()
}
#[must_use]
pub fn uid_str(&self) -> &[u8] {
self.get_uid_str()
}
#[must_use]
pub fn cid_str(&self) -> &[u8] {
self.get_cid_str()
}
}
impl fmt::Debug for Expanded {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Expanded")
.field("hid", &{ self.hid })
.field("uid", &{ self.uid })
.field("cid", &{ self.cid })
.field("data", &&self.data)
.finish()
}
}
impl TryFrom<&DevicePathNode> for &Expanded {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
let static_size = 16usize;
let dst_size = size_of_val(node)
.checked_sub(static_size)
.ok_or(NodeConversionError::InvalidLength)?;
let elem_size = size_of::<u8>();
if dst_size % elem_size != 0 {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const Expanded = ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size);
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
#[derive(Pointee)]
pub struct Adr {
pub(super) header: DevicePathHeader,
pub(super) adr: [u32],
}
impl Adr {
#[must_use]
pub fn adr(&self) -> UnalignedSlice<u32> {
let ptr: *const [u32] = addr_of!(self.adr);
let (ptr, len): (*const (), usize) = PtrExt::to_raw_parts(ptr);
unsafe { UnalignedSlice::new(ptr.cast::<u32>(), len) }
}
}
impl fmt::Debug for Adr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Adr")
.field("adr", {
let ptr = addr_of!(self.adr);
let (ptr, len) = PtrExt::to_raw_parts(ptr);
let byte_len = size_of::<u32>() * len;
unsafe { &slice::from_raw_parts(ptr.cast::<u8>(), byte_len) }
})
.finish()
}
}
impl TryFrom<&DevicePathNode> for &Adr {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
let static_size = 4usize;
let dst_size = size_of_val(node)
.checked_sub(static_size)
.ok_or(NodeConversionError::InvalidLength)?;
let elem_size = size_of::<u32>();
if dst_size % elem_size != 0 {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const Adr = ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size);
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
pub struct Nvdimm {
pub(super) header: DevicePathHeader,
pub(super) nfit_device_handle: u32,
}
impl Nvdimm {
#[must_use]
pub fn nfit_device_handle(&self) -> u32 {
self.nfit_device_handle
}
}
impl fmt::Debug for Nvdimm {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Nvdimm")
.field("nfit_device_handle", &{ self.nfit_device_handle })
.finish()
}
}
impl TryFrom<&DevicePathNode> for &Nvdimm {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
if size_of_val(node) != size_of::<Nvdimm>() {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const Nvdimm = node.cast();
Ok(unsafe { &*node })
}
}
impl Expanded {
fn get_hid_str(&self) -> &[u8] {
get_acpi_expanded_substr(&self.data, 0)
}
fn get_uid_str(&self) -> &[u8] {
get_acpi_expanded_substr(&self.data, 1)
}
fn get_cid_str(&self) -> &[u8] {
get_acpi_expanded_substr(&self.data, 2)
}
}
fn acpi_expanded_null_indices(data: &[u8]) -> [Option<usize>; 3] {
let mut iter = data
.iter()
.copied()
.enumerate()
.filter_map(|(index, byte)| if byte == 0 { Some(index) } else { None })
.fuse();
[iter.next(), iter.next(), iter.next()]
}
fn get_acpi_expanded_substr(data: &[u8], string_index: usize) -> &[u8] {
let [n0, n1, n2] = acpi_expanded_null_indices(data);
let mut start = data.len();
let mut end = start;
match string_index {
0 => {
start = 0;
if let Some(n0) = n0 {
end = n0 + 1;
}
}
1 => {
if let Some(n0) = n0 {
start = n0 + 1;
if let Some(n1) = n1 {
end = n1 + 1;
}
}
}
2 => {
if let Some(n1) = n1 {
start = n1 + 1;
if let Some(n2) = n2 {
end = n2 + 1;
}
}
}
_ => {
unreachable!("invalid string index")
}
}
data.get(start..end).unwrap_or(&[])
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_get_acpi_expanded_substr() {
let s = b"ab\0cd\0ef\0";
assert_eq!(get_acpi_expanded_substr(s, 0), b"ab\0");
assert_eq!(get_acpi_expanded_substr(s, 1), b"cd\0");
assert_eq!(get_acpi_expanded_substr(s, 2), b"ef\0");
let s = b"\0\0\0";
assert_eq!(get_acpi_expanded_substr(s, 0), b"\0");
assert_eq!(get_acpi_expanded_substr(s, 1), b"\0");
assert_eq!(get_acpi_expanded_substr(s, 2), b"\0");
let s = b"ab\0cd\0";
assert_eq!(get_acpi_expanded_substr(s, 0), b"ab\0");
assert_eq!(get_acpi_expanded_substr(s, 1), b"cd\0");
assert_eq!(get_acpi_expanded_substr(s, 2), b"");
let s = b"ab\0";
assert_eq!(get_acpi_expanded_substr(s, 0), b"ab\0");
assert_eq!(get_acpi_expanded_substr(s, 1), b"");
assert_eq!(get_acpi_expanded_substr(s, 2), b"");
let s = b"ab\0cd\0ef";
assert_eq!(get_acpi_expanded_substr(s, 0), b"ab\0");
assert_eq!(get_acpi_expanded_substr(s, 1), b"cd\0");
assert_eq!(get_acpi_expanded_substr(s, 2), b"ef");
let s = b"ab\0cd";
assert_eq!(get_acpi_expanded_substr(s, 0), b"ab\0");
assert_eq!(get_acpi_expanded_substr(s, 1), b"cd");
assert_eq!(get_acpi_expanded_substr(s, 2), b"");
let s = b"ab";
assert_eq!(get_acpi_expanded_substr(s, 0), b"ab");
assert_eq!(get_acpi_expanded_substr(s, 1), b"");
assert_eq!(get_acpi_expanded_substr(s, 2), b"");
let s = b"";
assert_eq!(get_acpi_expanded_substr(s, 0), b"");
assert_eq!(get_acpi_expanded_substr(s, 1), b"");
assert_eq!(get_acpi_expanded_substr(s, 2), b"");
}
}
}
pub mod messaging {
use super::*;
#[repr(C, packed)]
pub struct Atapi {
pub(super) header: DevicePathHeader,
pub(super) primary_secondary: crate::proto::device_path::messaging::PrimarySecondary,
pub(super) master_slave: crate::proto::device_path::messaging::MasterSlave,
pub(super) logical_unit_number: u16,
}
impl Atapi {
#[must_use]
pub fn primary_secondary(&self) -> crate::proto::device_path::messaging::PrimarySecondary {
self.primary_secondary
}
#[must_use]
pub fn master_slave(&self) -> crate::proto::device_path::messaging::MasterSlave {
self.master_slave
}
#[must_use]
pub fn logical_unit_number(&self) -> u16 {
self.logical_unit_number
}
}
impl fmt::Debug for Atapi {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Atapi")
.field("primary_secondary", &{ self.primary_secondary })
.field("master_slave", &{ self.master_slave })
.field("logical_unit_number", &{ self.logical_unit_number })
.finish()
}
}
impl TryFrom<&DevicePathNode> for &Atapi {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
if size_of_val(node) != size_of::<Atapi>() {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const Atapi = node.cast();
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
pub struct Scsi {
pub(super) header: DevicePathHeader,
pub(super) target_id: u16,
pub(super) logical_unit_number: u16,
}
impl Scsi {
#[must_use]
pub fn target_id(&self) -> u16 {
self.target_id
}
#[must_use]
pub fn logical_unit_number(&self) -> u16 {
self.logical_unit_number
}
}
impl fmt::Debug for Scsi {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Scsi")
.field("target_id", &{ self.target_id })
.field("logical_unit_number", &{ self.logical_unit_number })
.finish()
}
}
impl TryFrom<&DevicePathNode> for &Scsi {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
if size_of_val(node) != size_of::<Scsi>() {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const Scsi = node.cast();
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
pub struct FibreChannel {
pub(super) header: DevicePathHeader,
pub(super) _reserved: u32,
pub(super) world_wide_name: u64,
pub(super) logical_unit_number: u64,
}
impl FibreChannel {
#[must_use]
pub fn world_wide_name(&self) -> u64 {
self.world_wide_name
}
#[must_use]
pub fn logical_unit_number(&self) -> u64 {
self.logical_unit_number
}
}
impl fmt::Debug for FibreChannel {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("FibreChannel")
.field("_reserved", &{ self._reserved })
.field("world_wide_name", &{ self.world_wide_name })
.field("logical_unit_number", &{ self.logical_unit_number })
.finish()
}
}
impl TryFrom<&DevicePathNode> for &FibreChannel {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
if size_of_val(node) != size_of::<FibreChannel>() {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const FibreChannel = node.cast();
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
pub struct FibreChannelEx {
pub(super) header: DevicePathHeader,
pub(super) _reserved: u32,
pub(super) world_wide_name: [u8; 8usize],
pub(super) logical_unit_number: [u8; 8usize],
}
impl FibreChannelEx {
#[must_use]
pub fn world_wide_name(&self) -> [u8; 8usize] {
self.world_wide_name
}
#[must_use]
pub fn logical_unit_number(&self) -> [u8; 8usize] {
self.logical_unit_number
}
}
impl fmt::Debug for FibreChannelEx {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("FibreChannelEx")
.field("_reserved", &{ self._reserved })
.field("world_wide_name", &{ self.world_wide_name })
.field("logical_unit_number", &{ self.logical_unit_number })
.finish()
}
}
impl TryFrom<&DevicePathNode> for &FibreChannelEx {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
if size_of_val(node) != size_of::<FibreChannelEx>() {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const FibreChannelEx = node.cast();
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
pub struct Ieee1394 {
pub(super) header: DevicePathHeader,
pub(super) _reserved: u32,
pub(super) guid: [u8; 8usize],
}
impl Ieee1394 {
#[must_use]
pub fn guid(&self) -> [u8; 8usize] {
self.guid
}
}
impl fmt::Debug for Ieee1394 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Ieee1394")
.field("_reserved", &{ self._reserved })
.field("guid", &{ self.guid })
.finish()
}
}
impl TryFrom<&DevicePathNode> for &Ieee1394 {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
if size_of_val(node) != size_of::<Ieee1394>() {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const Ieee1394 = node.cast();
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
pub struct Usb {
pub(super) header: DevicePathHeader,
pub(super) parent_port_number: u8,
pub(super) interface: u8,
}
impl Usb {
#[must_use]
pub fn parent_port_number(&self) -> u8 {
self.parent_port_number
}
#[must_use]
pub fn interface(&self) -> u8 {
self.interface
}
}
impl fmt::Debug for Usb {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Usb")
.field("parent_port_number", &{ self.parent_port_number })
.field("interface", &{ self.interface })
.finish()
}
}
impl TryFrom<&DevicePathNode> for &Usb {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
if size_of_val(node) != size_of::<Usb>() {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const Usb = node.cast();
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
pub struct Sata {
pub(super) header: DevicePathHeader,
pub(super) hba_port_number: u16,
pub(super) port_multiplier_port_number: u16,
pub(super) logical_unit_number: u16,
}
impl Sata {
#[must_use]
pub fn hba_port_number(&self) -> u16 {
self.hba_port_number
}
#[must_use]
pub fn port_multiplier_port_number(&self) -> u16 {
self.port_multiplier_port_number
}
#[must_use]
pub fn logical_unit_number(&self) -> u16 {
self.logical_unit_number
}
}
impl fmt::Debug for Sata {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Sata")
.field("hba_port_number", &{ self.hba_port_number })
.field("port_multiplier_port_number", &{
self.port_multiplier_port_number
})
.field("logical_unit_number", &{ self.logical_unit_number })
.finish()
}
}
impl TryFrom<&DevicePathNode> for &Sata {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
if size_of_val(node) != size_of::<Sata>() {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const Sata = node.cast();
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
#[derive(Pointee)]
pub struct UsbWwid {
pub(super) header: DevicePathHeader,
pub(super) interface_number: u16,
pub(super) device_vendor_id: u16,
pub(super) device_product_id: u16,
pub(super) serial_number: [u16],
}
impl UsbWwid {
#[must_use]
pub fn interface_number(&self) -> u16 {
self.interface_number
}
#[must_use]
pub fn device_vendor_id(&self) -> u16 {
self.device_vendor_id
}
#[must_use]
pub fn device_product_id(&self) -> u16 {
self.device_product_id
}
#[must_use]
pub fn serial_number(&self) -> UnalignedSlice<u16> {
let ptr: *const [u16] = addr_of!(self.serial_number);
let (ptr, len): (*const (), usize) = PtrExt::to_raw_parts(ptr);
unsafe { UnalignedSlice::new(ptr.cast::<u16>(), len) }
}
}
impl fmt::Debug for UsbWwid {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("UsbWwid")
.field("interface_number", &{ self.interface_number })
.field("device_vendor_id", &{ self.device_vendor_id })
.field("device_product_id", &{ self.device_product_id })
.field("serial_number", {
let ptr = addr_of!(self.serial_number);
let (ptr, len) = PtrExt::to_raw_parts(ptr);
let byte_len = size_of::<u16>() * len;
unsafe { &slice::from_raw_parts(ptr.cast::<u8>(), byte_len) }
})
.finish()
}
}
impl TryFrom<&DevicePathNode> for &UsbWwid {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
let static_size = 10usize;
let dst_size = size_of_val(node)
.checked_sub(static_size)
.ok_or(NodeConversionError::InvalidLength)?;
let elem_size = size_of::<u16>();
if dst_size % elem_size != 0 {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const UsbWwid = ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size);
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
pub struct DeviceLogicalUnit {
pub(super) header: DevicePathHeader,
pub(super) logical_unit_number: u8,
}
impl DeviceLogicalUnit {
#[must_use]
pub fn logical_unit_number(&self) -> u8 {
self.logical_unit_number
}
}
impl fmt::Debug for DeviceLogicalUnit {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("DeviceLogicalUnit")
.field("logical_unit_number", &{ self.logical_unit_number })
.finish()
}
}
impl TryFrom<&DevicePathNode> for &DeviceLogicalUnit {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
if size_of_val(node) != size_of::<DeviceLogicalUnit>() {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const DeviceLogicalUnit = node.cast();
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
pub struct UsbClass {
pub(super) header: DevicePathHeader,
pub(super) vendor_id: u16,
pub(super) product_id: u16,
pub(super) device_class: u8,
pub(super) device_subclass: u8,
pub(super) device_protocol: u8,
}
impl UsbClass {
#[must_use]
pub fn vendor_id(&self) -> u16 {
self.vendor_id
}
#[must_use]
pub fn product_id(&self) -> u16 {
self.product_id
}
#[must_use]
pub fn device_class(&self) -> u8 {
self.device_class
}
#[must_use]
pub fn device_subclass(&self) -> u8 {
self.device_subclass
}
#[must_use]
pub fn device_protocol(&self) -> u8 {
self.device_protocol
}
}
impl fmt::Debug for UsbClass {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("UsbClass")
.field("vendor_id", &{ self.vendor_id })
.field("product_id", &{ self.product_id })
.field("device_class", &{ self.device_class })
.field("device_subclass", &{ self.device_subclass })
.field("device_protocol", &{ self.device_protocol })
.finish()
}
}
impl TryFrom<&DevicePathNode> for &UsbClass {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
if size_of_val(node) != size_of::<UsbClass>() {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const UsbClass = node.cast();
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
pub struct I2o {
pub(super) header: DevicePathHeader,
pub(super) target_id: u32,
}
impl I2o {
#[must_use]
pub fn target_id(&self) -> u32 {
self.target_id
}
}
impl fmt::Debug for I2o {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("I2o")
.field("target_id", &{ self.target_id })
.finish()
}
}
impl TryFrom<&DevicePathNode> for &I2o {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
if size_of_val(node) != size_of::<I2o>() {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const I2o = node.cast();
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
pub struct MacAddress {
pub(super) header: DevicePathHeader,
pub(super) mac_address: [u8; 32usize],
pub(super) interface_type: u8,
}
impl MacAddress {
#[must_use]
pub fn mac_address(&self) -> [u8; 32usize] {
self.mac_address
}
#[must_use]
pub fn interface_type(&self) -> u8 {
self.interface_type
}
}
impl fmt::Debug for MacAddress {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("MacAddress")
.field("mac_address", &{ self.mac_address })
.field("interface_type", &{ self.interface_type })
.finish()
}
}
impl TryFrom<&DevicePathNode> for &MacAddress {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
if size_of_val(node) != size_of::<MacAddress>() {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const MacAddress = node.cast();
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
pub struct Ipv4 {
pub(super) header: DevicePathHeader,
pub(super) local_ip_address: [u8; 4usize],
pub(super) remote_ip_address: [u8; 4usize],
pub(super) local_port: u16,
pub(super) remote_port: u16,
pub(super) protocol: u16,
pub(super) ip_address_origin: crate::proto::device_path::messaging::Ipv4AddressOrigin,
pub(super) gateway_ip_address: [u8; 4usize],
pub(super) subnet_mask: [u8; 4usize],
}
impl Ipv4 {
#[must_use]
pub fn local_ip_address(&self) -> [u8; 4usize] {
self.local_ip_address
}
#[must_use]
pub fn remote_ip_address(&self) -> [u8; 4usize] {
self.remote_ip_address
}
#[must_use]
pub fn local_port(&self) -> u16 {
self.local_port
}
#[must_use]
pub fn remote_port(&self) -> u16 {
self.remote_port
}
#[must_use]
pub fn protocol(&self) -> u16 {
self.protocol
}
#[must_use]
pub fn ip_address_origin(&self) -> crate::proto::device_path::messaging::Ipv4AddressOrigin {
self.ip_address_origin
}
#[must_use]
pub fn gateway_ip_address(&self) -> [u8; 4usize] {
self.gateway_ip_address
}
#[must_use]
pub fn subnet_mask(&self) -> [u8; 4usize] {
self.subnet_mask
}
}
impl fmt::Debug for Ipv4 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Ipv4")
.field("local_ip_address", &{ self.local_ip_address })
.field("remote_ip_address", &{ self.remote_ip_address })
.field("local_port", &{ self.local_port })
.field("remote_port", &{ self.remote_port })
.field("protocol", &{ self.protocol })
.field("ip_address_origin", &{ self.ip_address_origin })
.field("gateway_ip_address", &{ self.gateway_ip_address })
.field("subnet_mask", &{ self.subnet_mask })
.finish()
}
}
impl TryFrom<&DevicePathNode> for &Ipv4 {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
if size_of_val(node) != size_of::<Ipv4>() {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const Ipv4 = node.cast();
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
pub struct Ipv6 {
pub(super) header: DevicePathHeader,
pub(super) local_ip_address: [u8; 16usize],
pub(super) remote_ip_address: [u8; 16usize],
pub(super) local_port: u16,
pub(super) remote_port: u16,
pub(super) protocol: u16,
pub(super) ip_address_origin: crate::proto::device_path::messaging::Ipv6AddressOrigin,
pub(super) prefix_length: u8,
pub(super) gateway_ip_address: [u8; 16usize],
}
impl Ipv6 {
#[must_use]
pub fn local_ip_address(&self) -> [u8; 16usize] {
self.local_ip_address
}
#[must_use]
pub fn remote_ip_address(&self) -> [u8; 16usize] {
self.remote_ip_address
}
#[must_use]
pub fn local_port(&self) -> u16 {
self.local_port
}
#[must_use]
pub fn remote_port(&self) -> u16 {
self.remote_port
}
#[must_use]
pub fn protocol(&self) -> u16 {
self.protocol
}
#[must_use]
pub fn ip_address_origin(&self) -> crate::proto::device_path::messaging::Ipv6AddressOrigin {
self.ip_address_origin
}
#[must_use]
pub fn prefix_length(&self) -> u8 {
self.prefix_length
}
#[must_use]
pub fn gateway_ip_address(&self) -> [u8; 16usize] {
self.gateway_ip_address
}
}
impl fmt::Debug for Ipv6 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Ipv6")
.field("local_ip_address", &{ self.local_ip_address })
.field("remote_ip_address", &{ self.remote_ip_address })
.field("local_port", &{ self.local_port })
.field("remote_port", &{ self.remote_port })
.field("protocol", &{ self.protocol })
.field("ip_address_origin", &{ self.ip_address_origin })
.field("prefix_length", &{ self.prefix_length })
.field("gateway_ip_address", &{ self.gateway_ip_address })
.finish()
}
}
impl TryFrom<&DevicePathNode> for &Ipv6 {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
if size_of_val(node) != size_of::<Ipv6>() {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const Ipv6 = node.cast();
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
pub struct Vlan {
pub(super) header: DevicePathHeader,
pub(super) vlan_id: u16,
}
impl Vlan {
#[must_use]
pub fn vlan_id(&self) -> u16 {
self.vlan_id
}
}
impl fmt::Debug for Vlan {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Vlan")
.field("vlan_id", &{ self.vlan_id })
.finish()
}
}
impl TryFrom<&DevicePathNode> for &Vlan {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
if size_of_val(node) != size_of::<Vlan>() {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const Vlan = node.cast();
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
pub struct Infiniband {
pub(super) header: DevicePathHeader,
pub(super) resource_flags: crate::proto::device_path::messaging::InfinibandResourceFlags,
pub(super) port_gid: [u8; 16usize],
pub(super) ioc_guid_or_service_id: u64,
pub(super) target_port_id: u64,
pub(super) device_id: u64,
}
impl Infiniband {
#[must_use]
pub fn resource_flags(
&self,
) -> crate::proto::device_path::messaging::InfinibandResourceFlags {
self.resource_flags
}
#[must_use]
pub fn port_gid(&self) -> [u8; 16usize] {
self.port_gid
}
#[must_use]
pub fn ioc_guid_or_service_id(&self) -> u64 {
self.ioc_guid_or_service_id
}
#[must_use]
pub fn target_port_id(&self) -> u64 {
self.target_port_id
}
#[must_use]
pub fn device_id(&self) -> u64 {
self.device_id
}
}
impl fmt::Debug for Infiniband {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Infiniband")
.field("resource_flags", &{ self.resource_flags })
.field("port_gid", &{ self.port_gid })
.field("ioc_guid_or_service_id", &{ self.ioc_guid_or_service_id })
.field("target_port_id", &{ self.target_port_id })
.field("device_id", &{ self.device_id })
.finish()
}
}
impl TryFrom<&DevicePathNode> for &Infiniband {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
if size_of_val(node) != size_of::<Infiniband>() {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const Infiniband = node.cast();
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
pub struct Uart {
pub(super) header: DevicePathHeader,
pub(super) _reserved: u32,
pub(super) baud_rate: u64,
pub(super) data_bits: u8,
pub(super) parity: crate::proto::device_path::messaging::Parity,
pub(super) stop_bits: crate::proto::device_path::messaging::StopBits,
}
impl Uart {
#[must_use]
pub fn baud_rate(&self) -> u64 {
self.baud_rate
}
#[must_use]
pub fn data_bits(&self) -> u8 {
self.data_bits
}
#[must_use]
pub fn parity(&self) -> crate::proto::device_path::messaging::Parity {
self.parity
}
#[must_use]
pub fn stop_bits(&self) -> crate::proto::device_path::messaging::StopBits {
self.stop_bits
}
}
impl fmt::Debug for Uart {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Uart")
.field("_reserved", &{ self._reserved })
.field("baud_rate", &{ self.baud_rate })
.field("data_bits", &{ self.data_bits })
.field("parity", &{ self.parity })
.field("stop_bits", &{ self.stop_bits })
.finish()
}
}
impl TryFrom<&DevicePathNode> for &Uart {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
if size_of_val(node) != size_of::<Uart>() {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const Uart = node.cast();
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
#[derive(Pointee)]
pub struct Vendor {
pub(super) header: DevicePathHeader,
pub(super) vendor_guid: Guid,
pub(super) vendor_defined_data: [u8],
}
impl Vendor {
#[must_use]
pub fn vendor_guid(&self) -> Guid {
self.vendor_guid
}
#[must_use]
pub fn vendor_defined_data(&self) -> &[u8] {
&self.vendor_defined_data
}
}
impl fmt::Debug for Vendor {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Vendor")
.field("vendor_guid", &{ self.vendor_guid })
.field("vendor_defined_data", {
let ptr = addr_of!(self.vendor_defined_data);
let (ptr, len) = PtrExt::to_raw_parts(ptr);
let byte_len = size_of::<u8>() * len;
unsafe { &slice::from_raw_parts(ptr.cast::<u8>(), byte_len) }
})
.finish()
}
}
impl TryFrom<&DevicePathNode> for &Vendor {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
let static_size = 20usize;
let dst_size = size_of_val(node)
.checked_sub(static_size)
.ok_or(NodeConversionError::InvalidLength)?;
let elem_size = size_of::<u8>();
if dst_size % elem_size != 0 {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const Vendor = ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size);
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
pub struct SasEx {
pub(super) header: DevicePathHeader,
pub(super) sas_address: [u8; 8usize],
pub(super) logical_unit_number: [u8; 8usize],
pub(super) info: u16,
pub(super) relative_target_port: u16,
}
impl SasEx {
#[must_use]
pub fn sas_address(&self) -> [u8; 8usize] {
self.sas_address
}
#[must_use]
pub fn logical_unit_number(&self) -> [u8; 8usize] {
self.logical_unit_number
}
#[must_use]
pub fn info(&self) -> u16 {
self.info
}
#[must_use]
pub fn relative_target_port(&self) -> u16 {
self.relative_target_port
}
}
impl fmt::Debug for SasEx {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SasEx")
.field("sas_address", &{ self.sas_address })
.field("logical_unit_number", &{ self.logical_unit_number })
.field("info", &{ self.info })
.field("relative_target_port", &{ self.relative_target_port })
.finish()
}
}
impl TryFrom<&DevicePathNode> for &SasEx {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
if size_of_val(node) != size_of::<SasEx>() {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const SasEx = node.cast();
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
#[derive(Pointee)]
pub struct Iscsi {
pub(super) header: DevicePathHeader,
pub(super) protocol: crate::proto::device_path::messaging::IscsiProtocol,
pub(super) options: crate::proto::device_path::messaging::IscsiLoginOptions,
pub(super) logical_unit_number: [u8; 8usize],
pub(super) target_portal_group_tag: u16,
pub(super) iscsi_target_name: [u8],
}
impl Iscsi {
#[must_use]
pub fn protocol(&self) -> crate::proto::device_path::messaging::IscsiProtocol {
self.protocol
}
#[must_use]
pub fn options(&self) -> crate::proto::device_path::messaging::IscsiLoginOptions {
self.options
}
#[must_use]
pub fn logical_unit_number(&self) -> [u8; 8usize] {
self.logical_unit_number
}
#[must_use]
pub fn target_portal_group_tag(&self) -> u16 {
self.target_portal_group_tag
}
#[must_use]
pub fn iscsi_target_name(&self) -> &[u8] {
&self.iscsi_target_name
}
}
impl fmt::Debug for Iscsi {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Iscsi")
.field("protocol", &{ self.protocol })
.field("options", &{ self.options })
.field("logical_unit_number", &{ self.logical_unit_number })
.field("target_portal_group_tag", &{ self.target_portal_group_tag })
.field("iscsi_target_name", {
let ptr = addr_of!(self.iscsi_target_name);
let (ptr, len) = PtrExt::to_raw_parts(ptr);
let byte_len = size_of::<u8>() * len;
unsafe { &slice::from_raw_parts(ptr.cast::<u8>(), byte_len) }
})
.finish()
}
}
impl TryFrom<&DevicePathNode> for &Iscsi {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
let static_size = 18usize;
let dst_size = size_of_val(node)
.checked_sub(static_size)
.ok_or(NodeConversionError::InvalidLength)?;
let elem_size = size_of::<u8>();
if dst_size % elem_size != 0 {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const Iscsi = ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size);
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
pub struct NvmeNamespace {
pub(super) header: DevicePathHeader,
pub(super) namespace_identifier: u32,
pub(super) ieee_extended_unique_identifier: u64,
}
impl NvmeNamespace {
#[must_use]
pub fn namespace_identifier(&self) -> u32 {
self.namespace_identifier
}
#[must_use]
pub fn ieee_extended_unique_identifier(&self) -> u64 {
self.ieee_extended_unique_identifier
}
}
impl fmt::Debug for NvmeNamespace {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("NvmeNamespace")
.field("namespace_identifier", &{ self.namespace_identifier })
.field("ieee_extended_unique_identifier", &{
self.ieee_extended_unique_identifier
})
.finish()
}
}
impl TryFrom<&DevicePathNode> for &NvmeNamespace {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
if size_of_val(node) != size_of::<NvmeNamespace>() {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const NvmeNamespace = node.cast();
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
#[derive(Pointee)]
pub struct Uri {
pub(super) header: DevicePathHeader,
pub(super) value: [u8],
}
impl Uri {
#[must_use]
pub fn value(&self) -> &[u8] {
&self.value
}
}
impl fmt::Debug for Uri {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Uri")
.field("value", {
let ptr = addr_of!(self.value);
let (ptr, len) = PtrExt::to_raw_parts(ptr);
let byte_len = size_of::<u8>() * len;
unsafe { &slice::from_raw_parts(ptr.cast::<u8>(), byte_len) }
})
.finish()
}
}
impl TryFrom<&DevicePathNode> for &Uri {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
let static_size = 4usize;
let dst_size = size_of_val(node)
.checked_sub(static_size)
.ok_or(NodeConversionError::InvalidLength)?;
let elem_size = size_of::<u8>();
if dst_size % elem_size != 0 {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const Uri = ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size);
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
pub struct Ufs {
pub(super) header: DevicePathHeader,
pub(super) target_id: u8,
pub(super) logical_unit_number: u8,
}
impl Ufs {
#[must_use]
pub fn target_id(&self) -> u8 {
self.target_id
}
#[must_use]
pub fn logical_unit_number(&self) -> u8 {
self.logical_unit_number
}
}
impl fmt::Debug for Ufs {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Ufs")
.field("target_id", &{ self.target_id })
.field("logical_unit_number", &{ self.logical_unit_number })
.finish()
}
}
impl TryFrom<&DevicePathNode> for &Ufs {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
if size_of_val(node) != size_of::<Ufs>() {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const Ufs = node.cast();
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
pub struct Sd {
pub(super) header: DevicePathHeader,
pub(super) slot_number: u8,
}
impl Sd {
#[must_use]
pub fn slot_number(&self) -> u8 {
self.slot_number
}
}
impl fmt::Debug for Sd {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Sd")
.field("slot_number", &{ self.slot_number })
.finish()
}
}
impl TryFrom<&DevicePathNode> for &Sd {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
if size_of_val(node) != size_of::<Sd>() {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const Sd = node.cast();
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
pub struct Bluetooth {
pub(super) header: DevicePathHeader,
pub(super) device_address: [u8; 6usize],
}
impl Bluetooth {
#[must_use]
pub fn device_address(&self) -> [u8; 6usize] {
self.device_address
}
}
impl fmt::Debug for Bluetooth {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Bluetooth")
.field("device_address", &{ self.device_address })
.finish()
}
}
impl TryFrom<&DevicePathNode> for &Bluetooth {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
if size_of_val(node) != size_of::<Bluetooth>() {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const Bluetooth = node.cast();
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
pub struct Wifi {
pub(super) header: DevicePathHeader,
pub(super) ssid: [u8; 32usize],
}
impl Wifi {
#[must_use]
pub fn ssid(&self) -> [u8; 32usize] {
self.ssid
}
}
impl fmt::Debug for Wifi {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Wifi")
.field("ssid", &{ self.ssid })
.finish()
}
}
impl TryFrom<&DevicePathNode> for &Wifi {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
if size_of_val(node) != size_of::<Wifi>() {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const Wifi = node.cast();
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
pub struct Emmc {
pub(super) header: DevicePathHeader,
pub(super) slot_number: u8,
}
impl Emmc {
#[must_use]
pub fn slot_number(&self) -> u8 {
self.slot_number
}
}
impl fmt::Debug for Emmc {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Emmc")
.field("slot_number", &{ self.slot_number })
.finish()
}
}
impl TryFrom<&DevicePathNode> for &Emmc {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
if size_of_val(node) != size_of::<Emmc>() {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const Emmc = node.cast();
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
pub struct BluetoothLe {
pub(super) header: DevicePathHeader,
pub(super) device_address: [u8; 6usize],
pub(super) address_type: crate::proto::device_path::messaging::BluetoothLeAddressType,
}
impl BluetoothLe {
#[must_use]
pub fn device_address(&self) -> [u8; 6usize] {
self.device_address
}
#[must_use]
pub fn address_type(&self) -> crate::proto::device_path::messaging::BluetoothLeAddressType {
self.address_type
}
}
impl fmt::Debug for BluetoothLe {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("BluetoothLe")
.field("device_address", &{ self.device_address })
.field("address_type", &{ self.address_type })
.finish()
}
}
impl TryFrom<&DevicePathNode> for &BluetoothLe {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
if size_of_val(node) != size_of::<BluetoothLe>() {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const BluetoothLe = node.cast();
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
#[derive(Pointee)]
pub struct Dns {
pub(super) header: DevicePathHeader,
pub(super) address_type: crate::proto::device_path::messaging::DnsAddressType,
pub(super) addresses: [IpAddress],
}
impl Dns {
#[must_use]
pub fn address_type(&self) -> crate::proto::device_path::messaging::DnsAddressType {
self.address_type
}
#[must_use]
pub fn addresses(&self) -> UnalignedSlice<IpAddress> {
let ptr: *const [IpAddress] = addr_of!(self.addresses);
let (ptr, len): (*const (), usize) = PtrExt::to_raw_parts(ptr);
unsafe { UnalignedSlice::new(ptr.cast::<IpAddress>(), len) }
}
}
impl fmt::Debug for Dns {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Dns")
.field("address_type", &{ self.address_type })
.field("addresses", {
let ptr = addr_of!(self.addresses);
let (ptr, len) = PtrExt::to_raw_parts(ptr);
let byte_len = size_of::<IpAddress>() * len;
unsafe { &slice::from_raw_parts(ptr.cast::<u8>(), byte_len) }
})
.finish()
}
}
impl TryFrom<&DevicePathNode> for &Dns {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
let static_size = 5usize;
let dst_size = size_of_val(node)
.checked_sub(static_size)
.ok_or(NodeConversionError::InvalidLength)?;
let elem_size = size_of::<IpAddress>();
if dst_size % elem_size != 0 {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const Dns = ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size);
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
pub struct NvdimmNamespace {
pub(super) header: DevicePathHeader,
pub(super) uuid: [u8; 16usize],
}
impl NvdimmNamespace {
#[must_use]
pub fn uuid(&self) -> [u8; 16usize] {
self.uuid
}
}
impl fmt::Debug for NvdimmNamespace {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("NvdimmNamespace")
.field("uuid", &{ self.uuid })
.finish()
}
}
impl TryFrom<&DevicePathNode> for &NvdimmNamespace {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
if size_of_val(node) != size_of::<NvdimmNamespace>() {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const NvdimmNamespace = node.cast();
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
#[derive(Pointee)]
pub struct RestService {
pub(super) header: DevicePathHeader,
pub(super) service_type: crate::proto::device_path::messaging::RestServiceType,
pub(super) access_mode: crate::proto::device_path::messaging::RestServiceAccessMode,
pub(super) vendor_guid_and_data: [u8],
}
impl RestService {
#[must_use]
pub fn service_type(&self) -> crate::proto::device_path::messaging::RestServiceType {
self.service_type
}
#[must_use]
pub fn access_mode(&self) -> crate::proto::device_path::messaging::RestServiceAccessMode {
self.access_mode
}
}
impl fmt::Debug for RestService {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RestService")
.field("service_type", &{ self.service_type })
.field("access_mode", &{ self.access_mode })
.field("vendor_guid_and_data", {
let ptr = addr_of!(self.vendor_guid_and_data);
let (ptr, len) = PtrExt::to_raw_parts(ptr);
let byte_len = size_of::<u8>() * len;
unsafe { &slice::from_raw_parts(ptr.cast::<u8>(), byte_len) }
})
.finish()
}
}
impl TryFrom<&DevicePathNode> for &RestService {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
let static_size = 6usize;
let dst_size = size_of_val(node)
.checked_sub(static_size)
.ok_or(NodeConversionError::InvalidLength)?;
let elem_size = size_of::<u8>();
if dst_size % elem_size != 0 {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const RestService =
ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size);
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
#[derive(Pointee)]
pub struct NvmeOfNamespace {
pub(super) header: DevicePathHeader,
pub(super) nidt: u8,
pub(super) nid: [u8; 16usize],
pub(super) subsystem_nqn: [u8],
}
impl NvmeOfNamespace {
#[must_use]
pub fn nidt(&self) -> u8 {
self.nidt
}
#[must_use]
pub fn nid(&self) -> [u8; 16usize] {
self.nid
}
#[must_use]
pub fn subsystem_nqn(&self) -> &[u8] {
&self.subsystem_nqn
}
}
impl fmt::Debug for NvmeOfNamespace {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("NvmeOfNamespace")
.field("nidt", &{ self.nidt })
.field("nid", &{ self.nid })
.field("subsystem_nqn", {
let ptr = addr_of!(self.subsystem_nqn);
let (ptr, len) = PtrExt::to_raw_parts(ptr);
let byte_len = size_of::<u8>() * len;
unsafe { &slice::from_raw_parts(ptr.cast::<u8>(), byte_len) }
})
.finish()
}
}
impl TryFrom<&DevicePathNode> for &NvmeOfNamespace {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
let static_size = 21usize;
let dst_size = size_of_val(node)
.checked_sub(static_size)
.ok_or(NodeConversionError::InvalidLength)?;
let elem_size = size_of::<u8>();
if dst_size % elem_size != 0 {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const NvmeOfNamespace =
ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size);
Ok(unsafe { &*node })
}
}
newtype_enum! { # [doc = " Whether the ATAPI device is primary or secondary."] pub enum PrimarySecondary : u8 => { # [doc = " Primary."] PRIMARY = 0x00 , # [doc = " Secondary."] SECONDARY = 0x01 , }
}
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 , }
}
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 , }
}
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 , }
}
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 ; }
}
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 , }
}
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 , }
}
impl Vendor {
pub const PC_ANSI: Guid = guid!("e0c14753-f9be-11d2-9a0c-0090273fc14d");
pub const VT_100: Guid = guid!("dfa66065-b419-11d3-9a2d-0090273fc14d");
pub const VT_100_PLUS: Guid = guid!("7baec70b-57e0-4c76-8e87-2f9e28088343");
pub const VT_UTF8: Guid = guid!("ad15a0d6-8bec-4acf-a073-d01de77e2d88");
}
newtype_enum! { # [doc = " iSCSI network protocol."] pub enum IscsiProtocol : u16 => { # [doc = " TCP."] TCP = 0x0000 , }
}
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 ; }
}
newtype_enum! { # [doc = " BluetoothLE address type."] pub enum BluetoothLeAddressType : u8 => { # [doc = " Public device address."] PUBLIC = 0x00 , # [doc = " Random device address."] RANDOM = 0x01 , }
}
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 , }
}
impl RestService {
#[must_use]
pub fn vendor_guid_and_data(&self) -> Option<(Guid, &[u8])> {
if self.service_type == RestServiceType::VENDOR
&& self.vendor_guid_and_data.len() >= size_of::<Guid>()
{
let (guid, data) = self.vendor_guid_and_data.split_at(size_of::<Guid>());
let guid: [u8; 16] = guid.try_into().unwrap();
Some((Guid::from_bytes(guid), data))
} else {
None
}
}
}
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 , }
}
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 , }
}
}
pub mod media {
use super::*;
#[repr(C, packed)]
pub struct HardDrive {
pub(super) header: DevicePathHeader,
pub(super) partition_number: u32,
pub(super) partition_start: u64,
pub(super) partition_size: u64,
pub(super) partition_signature: [u8; 16usize],
pub(super) partition_format: crate::proto::device_path::media::PartitionFormat,
pub(super) signature_type: u8,
}
impl HardDrive {
#[must_use]
pub fn partition_number(&self) -> u32 {
self.partition_number
}
#[must_use]
pub fn partition_start(&self) -> u64 {
self.partition_start
}
#[must_use]
pub fn partition_size(&self) -> u64 {
self.partition_size
}
#[must_use]
pub fn partition_format(&self) -> crate::proto::device_path::media::PartitionFormat {
self.partition_format
}
}
impl fmt::Debug for HardDrive {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("HardDrive")
.field("partition_number", &{ self.partition_number })
.field("partition_start", &{ self.partition_start })
.field("partition_size", &{ self.partition_size })
.field("partition_signature", &{ self.partition_signature })
.field("partition_format", &{ self.partition_format })
.field("signature_type", &{ self.signature_type })
.finish()
}
}
impl TryFrom<&DevicePathNode> for &HardDrive {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
if size_of_val(node) != size_of::<HardDrive>() {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const HardDrive = node.cast();
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
pub struct CdRom {
pub(super) header: DevicePathHeader,
pub(super) boot_entry: u32,
pub(super) partition_start: u64,
pub(super) partition_size: u64,
}
impl CdRom {
#[must_use]
pub fn boot_entry(&self) -> u32 {
self.boot_entry
}
#[must_use]
pub fn partition_start(&self) -> u64 {
self.partition_start
}
#[must_use]
pub fn partition_size(&self) -> u64 {
self.partition_size
}
}
impl fmt::Debug for CdRom {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("CdRom")
.field("boot_entry", &{ self.boot_entry })
.field("partition_start", &{ self.partition_start })
.field("partition_size", &{ self.partition_size })
.finish()
}
}
impl TryFrom<&DevicePathNode> for &CdRom {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
if size_of_val(node) != size_of::<CdRom>() {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const CdRom = node.cast();
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
#[derive(Pointee)]
pub struct Vendor {
pub(super) header: DevicePathHeader,
pub(super) vendor_guid: Guid,
pub(super) vendor_defined_data: [u8],
}
impl Vendor {
#[must_use]
pub fn vendor_guid(&self) -> Guid {
self.vendor_guid
}
#[must_use]
pub fn vendor_defined_data(&self) -> &[u8] {
&self.vendor_defined_data
}
}
impl fmt::Debug for Vendor {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Vendor")
.field("vendor_guid", &{ self.vendor_guid })
.field("vendor_defined_data", {
let ptr = addr_of!(self.vendor_defined_data);
let (ptr, len) = PtrExt::to_raw_parts(ptr);
let byte_len = size_of::<u8>() * len;
unsafe { &slice::from_raw_parts(ptr.cast::<u8>(), byte_len) }
})
.finish()
}
}
impl TryFrom<&DevicePathNode> for &Vendor {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
let static_size = 20usize;
let dst_size = size_of_val(node)
.checked_sub(static_size)
.ok_or(NodeConversionError::InvalidLength)?;
let elem_size = size_of::<u8>();
if dst_size % elem_size != 0 {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const Vendor = ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size);
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
#[derive(Pointee)]
pub struct FilePath {
pub(super) header: DevicePathHeader,
pub(super) path_name: [u16],
}
impl FilePath {
#[must_use]
pub fn path_name(&self) -> UnalignedSlice<u16> {
let ptr: *const [u16] = addr_of!(self.path_name);
let (ptr, len): (*const (), usize) = PtrExt::to_raw_parts(ptr);
unsafe { UnalignedSlice::new(ptr.cast::<u16>(), len) }
}
}
impl fmt::Debug for FilePath {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("FilePath")
.field("path_name", {
let ptr = addr_of!(self.path_name);
let (ptr, len) = PtrExt::to_raw_parts(ptr);
let byte_len = size_of::<u16>() * len;
unsafe { &slice::from_raw_parts(ptr.cast::<u8>(), byte_len) }
})
.finish()
}
}
impl TryFrom<&DevicePathNode> for &FilePath {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
let static_size = 4usize;
let dst_size = size_of_val(node)
.checked_sub(static_size)
.ok_or(NodeConversionError::InvalidLength)?;
let elem_size = size_of::<u16>();
if dst_size % elem_size != 0 {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const FilePath = ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size);
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
pub struct Protocol {
pub(super) header: DevicePathHeader,
pub(super) protocol_guid: Guid,
}
impl Protocol {
#[must_use]
pub fn protocol_guid(&self) -> Guid {
self.protocol_guid
}
}
impl fmt::Debug for Protocol {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Protocol")
.field("protocol_guid", &{ self.protocol_guid })
.finish()
}
}
impl TryFrom<&DevicePathNode> for &Protocol {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
if size_of_val(node) != size_of::<Protocol>() {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const Protocol = node.cast();
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
#[derive(Pointee)]
pub struct PiwgFirmwareFile {
pub(super) header: DevicePathHeader,
pub(super) data: [u8],
}
impl PiwgFirmwareFile {
#[must_use]
pub fn data(&self) -> &[u8] {
&self.data
}
}
impl fmt::Debug for PiwgFirmwareFile {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("PiwgFirmwareFile")
.field("data", {
let ptr = addr_of!(self.data);
let (ptr, len) = PtrExt::to_raw_parts(ptr);
let byte_len = size_of::<u8>() * len;
unsafe { &slice::from_raw_parts(ptr.cast::<u8>(), byte_len) }
})
.finish()
}
}
impl TryFrom<&DevicePathNode> for &PiwgFirmwareFile {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
let static_size = 4usize;
let dst_size = size_of_val(node)
.checked_sub(static_size)
.ok_or(NodeConversionError::InvalidLength)?;
let elem_size = size_of::<u8>();
if dst_size % elem_size != 0 {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const PiwgFirmwareFile =
ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size);
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
#[derive(Pointee)]
pub struct PiwgFirmwareVolume {
pub(super) header: DevicePathHeader,
pub(super) data: [u8],
}
impl PiwgFirmwareVolume {
#[must_use]
pub fn data(&self) -> &[u8] {
&self.data
}
}
impl fmt::Debug for PiwgFirmwareVolume {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("PiwgFirmwareVolume")
.field("data", {
let ptr = addr_of!(self.data);
let (ptr, len) = PtrExt::to_raw_parts(ptr);
let byte_len = size_of::<u8>() * len;
unsafe { &slice::from_raw_parts(ptr.cast::<u8>(), byte_len) }
})
.finish()
}
}
impl TryFrom<&DevicePathNode> for &PiwgFirmwareVolume {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
let static_size = 4usize;
let dst_size = size_of_val(node)
.checked_sub(static_size)
.ok_or(NodeConversionError::InvalidLength)?;
let elem_size = size_of::<u8>();
if dst_size % elem_size != 0 {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const PiwgFirmwareVolume =
ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size);
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
pub struct RelativeOffsetRange {
pub(super) header: DevicePathHeader,
pub(super) _reserved: u32,
pub(super) starting_offset: u64,
pub(super) ending_offset: u64,
}
impl RelativeOffsetRange {
#[must_use]
pub fn starting_offset(&self) -> u64 {
self.starting_offset
}
#[must_use]
pub fn ending_offset(&self) -> u64 {
self.ending_offset
}
}
impl fmt::Debug for RelativeOffsetRange {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RelativeOffsetRange")
.field("_reserved", &{ self._reserved })
.field("starting_offset", &{ self.starting_offset })
.field("ending_offset", &{ self.ending_offset })
.finish()
}
}
impl TryFrom<&DevicePathNode> for &RelativeOffsetRange {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
if size_of_val(node) != size_of::<RelativeOffsetRange>() {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const RelativeOffsetRange = node.cast();
Ok(unsafe { &*node })
}
}
#[repr(C, packed)]
pub struct RamDisk {
pub(super) header: DevicePathHeader,
pub(super) starting_address: u64,
pub(super) ending_address: u64,
pub(super) disk_type: crate::proto::device_path::media::RamDiskType,
pub(super) disk_instance: u16,
}
impl RamDisk {
#[must_use]
pub fn starting_address(&self) -> u64 {
self.starting_address
}
#[must_use]
pub fn ending_address(&self) -> u64 {
self.ending_address
}
#[must_use]
pub fn disk_type(&self) -> crate::proto::device_path::media::RamDiskType {
self.disk_type
}
#[must_use]
pub fn disk_instance(&self) -> u16 {
self.disk_instance
}
}
impl fmt::Debug for RamDisk {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RamDisk")
.field("starting_address", &{ self.starting_address })
.field("ending_address", &{ self.ending_address })
.field("disk_type", &{ self.disk_type })
.field("disk_instance", &{ self.disk_instance })
.finish()
}
}
impl TryFrom<&DevicePathNode> for &RamDisk {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
if size_of_val(node) != size_of::<RamDisk>() {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const RamDisk = node.cast();
Ok(unsafe { &*node })
}
}
impl HardDrive {
#[must_use]
pub fn partition_signature(&self) -> PartitionSignature {
match self.signature_type {
0 => PartitionSignature::None,
1 => PartitionSignature::Mbr([
self.partition_signature[0],
self.partition_signature[1],
self.partition_signature[2],
self.partition_signature[3],
]),
2 => PartitionSignature::Guid(Guid::from_bytes(self.partition_signature)),
unknown => PartitionSignature::Unknown {
signature_type: unknown,
signature: self.partition_signature,
},
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub enum PartitionSignature {
None,
Mbr([u8; 4]),
Guid(Guid),
Unknown {
signature_type: u8,
signature: [u8; 16],
},
}
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 , }
}
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") , }
}
}
pub mod bios_boot_spec {
use super::*;
#[repr(C, packed)]
#[derive(Pointee)]
pub struct BootSpecification {
pub(super) header: DevicePathHeader,
pub(super) device_type: u16,
pub(super) status_flag: u16,
pub(super) description_string: [u8],
}
impl BootSpecification {
#[must_use]
pub fn device_type(&self) -> u16 {
self.device_type
}
#[must_use]
pub fn status_flag(&self) -> u16 {
self.status_flag
}
#[must_use]
pub fn description_string(&self) -> &[u8] {
&self.description_string
}
}
impl fmt::Debug for BootSpecification {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("BootSpecification")
.field("device_type", &{ self.device_type })
.field("status_flag", &{ self.status_flag })
.field("description_string", {
let ptr = addr_of!(self.description_string);
let (ptr, len) = PtrExt::to_raw_parts(ptr);
let byte_len = size_of::<u8>() * len;
unsafe { &slice::from_raw_parts(ptr.cast::<u8>(), byte_len) }
})
.finish()
}
}
impl TryFrom<&DevicePathNode> for &BootSpecification {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
let static_size = 8usize;
let dst_size = size_of_val(node)
.checked_sub(static_size)
.ok_or(NodeConversionError::InvalidLength)?;
let elem_size = size_of::<u8>();
if dst_size % elem_size != 0 {
return Err(NodeConversionError::InvalidLength);
}
let node: *const DevicePathNode = node;
let node: *const BootSpecification =
ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size);
Ok(unsafe { &*node })
}
}
}
#[derive(Debug)]
pub enum DevicePathNodeEnum<'a> {
EndInstance(&'a end::Instance),
EndEntire(&'a end::Entire),
HardwarePci(&'a hardware::Pci),
HardwarePccard(&'a hardware::Pccard),
HardwareMemoryMapped(&'a hardware::MemoryMapped),
HardwareVendor(&'a hardware::Vendor),
HardwareController(&'a hardware::Controller),
HardwareBmc(&'a hardware::Bmc),
AcpiAcpi(&'a acpi::Acpi),
AcpiExpanded(&'a acpi::Expanded),
AcpiAdr(&'a acpi::Adr),
AcpiNvdimm(&'a acpi::Nvdimm),
MessagingAtapi(&'a messaging::Atapi),
MessagingScsi(&'a messaging::Scsi),
MessagingFibreChannel(&'a messaging::FibreChannel),
MessagingFibreChannelEx(&'a messaging::FibreChannelEx),
MessagingIeee1394(&'a messaging::Ieee1394),
MessagingUsb(&'a messaging::Usb),
MessagingSata(&'a messaging::Sata),
MessagingUsbWwid(&'a messaging::UsbWwid),
MessagingDeviceLogicalUnit(&'a messaging::DeviceLogicalUnit),
MessagingUsbClass(&'a messaging::UsbClass),
MessagingI2o(&'a messaging::I2o),
MessagingMacAddress(&'a messaging::MacAddress),
MessagingIpv4(&'a messaging::Ipv4),
MessagingIpv6(&'a messaging::Ipv6),
MessagingVlan(&'a messaging::Vlan),
MessagingInfiniband(&'a messaging::Infiniband),
MessagingUart(&'a messaging::Uart),
MessagingVendor(&'a messaging::Vendor),
MessagingSasEx(&'a messaging::SasEx),
MessagingIscsi(&'a messaging::Iscsi),
MessagingNvmeNamespace(&'a messaging::NvmeNamespace),
MessagingUri(&'a messaging::Uri),
MessagingUfs(&'a messaging::Ufs),
MessagingSd(&'a messaging::Sd),
MessagingBluetooth(&'a messaging::Bluetooth),
MessagingWifi(&'a messaging::Wifi),
MessagingEmmc(&'a messaging::Emmc),
MessagingBluetoothLe(&'a messaging::BluetoothLe),
MessagingDns(&'a messaging::Dns),
MessagingNvdimmNamespace(&'a messaging::NvdimmNamespace),
MessagingRestService(&'a messaging::RestService),
MessagingNvmeOfNamespace(&'a messaging::NvmeOfNamespace),
MediaHardDrive(&'a media::HardDrive),
MediaCdRom(&'a media::CdRom),
MediaVendor(&'a media::Vendor),
MediaFilePath(&'a media::FilePath),
MediaProtocol(&'a media::Protocol),
MediaPiwgFirmwareFile(&'a media::PiwgFirmwareFile),
MediaPiwgFirmwareVolume(&'a media::PiwgFirmwareVolume),
MediaRelativeOffsetRange(&'a media::RelativeOffsetRange),
MediaRamDisk(&'a media::RamDisk),
BiosBootSpecBootSpecification(&'a bios_boot_spec::BootSpecification),
}
impl<'a> TryFrom<&DevicePathNode> for DevicePathNodeEnum<'a> {
type Error = NodeConversionError;
fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> {
Ok(match node.full_type() {
(DeviceType::END, DeviceSubType::END_INSTANCE) => Self::EndInstance(node.try_into()?),
(DeviceType::END, DeviceSubType::END_ENTIRE) => Self::EndEntire(node.try_into()?),
(DeviceType::HARDWARE, DeviceSubType::HARDWARE_PCI) => {
Self::HardwarePci(node.try_into()?)
}
(DeviceType::HARDWARE, DeviceSubType::HARDWARE_PCCARD) => {
Self::HardwarePccard(node.try_into()?)
}
(DeviceType::HARDWARE, DeviceSubType::HARDWARE_MEMORY_MAPPED) => {
Self::HardwareMemoryMapped(node.try_into()?)
}
(DeviceType::HARDWARE, DeviceSubType::HARDWARE_VENDOR) => {
Self::HardwareVendor(node.try_into()?)
}
(DeviceType::HARDWARE, DeviceSubType::HARDWARE_CONTROLLER) => {
Self::HardwareController(node.try_into()?)
}
(DeviceType::HARDWARE, DeviceSubType::HARDWARE_BMC) => {
Self::HardwareBmc(node.try_into()?)
}
(DeviceType::ACPI, DeviceSubType::ACPI) => Self::AcpiAcpi(node.try_into()?),
(DeviceType::ACPI, DeviceSubType::ACPI_EXPANDED) => {
Self::AcpiExpanded(node.try_into()?)
}
(DeviceType::ACPI, DeviceSubType::ACPI_ADR) => Self::AcpiAdr(node.try_into()?),
(DeviceType::ACPI, DeviceSubType::ACPI_NVDIMM) => Self::AcpiNvdimm(node.try_into()?),
(DeviceType::MESSAGING, DeviceSubType::MESSAGING_ATAPI) => {
Self::MessagingAtapi(node.try_into()?)
}
(DeviceType::MESSAGING, DeviceSubType::MESSAGING_SCSI) => {
Self::MessagingScsi(node.try_into()?)
}
(DeviceType::MESSAGING, DeviceSubType::MESSAGING_FIBRE_CHANNEL) => {
Self::MessagingFibreChannel(node.try_into()?)
}
(DeviceType::MESSAGING, DeviceSubType::MESSAGING_FIBRE_CHANNEL_EX) => {
Self::MessagingFibreChannelEx(node.try_into()?)
}
(DeviceType::MESSAGING, DeviceSubType::MESSAGING_1394) => {
Self::MessagingIeee1394(node.try_into()?)
}
(DeviceType::MESSAGING, DeviceSubType::MESSAGING_USB) => {
Self::MessagingUsb(node.try_into()?)
}
(DeviceType::MESSAGING, DeviceSubType::MESSAGING_SATA) => {
Self::MessagingSata(node.try_into()?)
}
(DeviceType::MESSAGING, DeviceSubType::MESSAGING_USB_WWID) => {
Self::MessagingUsbWwid(node.try_into()?)
}
(DeviceType::MESSAGING, DeviceSubType::MESSAGING_DEVICE_LOGICAL_UNIT) => {
Self::MessagingDeviceLogicalUnit(node.try_into()?)
}
(DeviceType::MESSAGING, DeviceSubType::MESSAGING_USB_CLASS) => {
Self::MessagingUsbClass(node.try_into()?)
}
(DeviceType::MESSAGING, DeviceSubType::MESSAGING_I2O) => {
Self::MessagingI2o(node.try_into()?)
}
(DeviceType::MESSAGING, DeviceSubType::MESSAGING_MAC_ADDRESS) => {
Self::MessagingMacAddress(node.try_into()?)
}
(DeviceType::MESSAGING, DeviceSubType::MESSAGING_IPV4) => {
Self::MessagingIpv4(node.try_into()?)
}
(DeviceType::MESSAGING, DeviceSubType::MESSAGING_IPV6) => {
Self::MessagingIpv6(node.try_into()?)
}
(DeviceType::MESSAGING, DeviceSubType::MESSAGING_VLAN) => {
Self::MessagingVlan(node.try_into()?)
}
(DeviceType::MESSAGING, DeviceSubType::MESSAGING_INFINIBAND) => {
Self::MessagingInfiniband(node.try_into()?)
}
(DeviceType::MESSAGING, DeviceSubType::MESSAGING_UART) => {
Self::MessagingUart(node.try_into()?)
}
(DeviceType::MESSAGING, DeviceSubType::MESSAGING_VENDOR) => {
Self::MessagingVendor(node.try_into()?)
}
(DeviceType::MESSAGING, DeviceSubType::MESSAGING_SCSI_SAS_EX) => {
Self::MessagingSasEx(node.try_into()?)
}
(DeviceType::MESSAGING, DeviceSubType::MESSAGING_ISCSI) => {
Self::MessagingIscsi(node.try_into()?)
}
(DeviceType::MESSAGING, DeviceSubType::MESSAGING_NVME_NAMESPACE) => {
Self::MessagingNvmeNamespace(node.try_into()?)
}
(DeviceType::MESSAGING, DeviceSubType::MESSAGING_URI) => {
Self::MessagingUri(node.try_into()?)
}
(DeviceType::MESSAGING, DeviceSubType::MESSAGING_UFS) => {
Self::MessagingUfs(node.try_into()?)
}
(DeviceType::MESSAGING, DeviceSubType::MESSAGING_SD) => {
Self::MessagingSd(node.try_into()?)
}
(DeviceType::MESSAGING, DeviceSubType::MESSAGING_BLUETOOTH) => {
Self::MessagingBluetooth(node.try_into()?)
}
(DeviceType::MESSAGING, DeviceSubType::MESSAGING_WIFI) => {
Self::MessagingWifi(node.try_into()?)
}
(DeviceType::MESSAGING, DeviceSubType::MESSAGING_EMMC) => {
Self::MessagingEmmc(node.try_into()?)
}
(DeviceType::MESSAGING, DeviceSubType::MESSAGING_BLUETOOTH_LE) => {
Self::MessagingBluetoothLe(node.try_into()?)
}
(DeviceType::MESSAGING, DeviceSubType::MESSAGING_DNS) => {
Self::MessagingDns(node.try_into()?)
}
(DeviceType::MESSAGING, DeviceSubType::MESSAGING_NVDIMM_NAMESPACE) => {
Self::MessagingNvdimmNamespace(node.try_into()?)
}
(DeviceType::MESSAGING, DeviceSubType::MESSAGING_REST_SERVICE) => {
Self::MessagingRestService(node.try_into()?)
}
(DeviceType::MESSAGING, DeviceSubType::MESSAGING_NVME_OF_NAMESPACE) => {
Self::MessagingNvmeOfNamespace(node.try_into()?)
}
(DeviceType::MEDIA, DeviceSubType::MEDIA_HARD_DRIVE) => {
Self::MediaHardDrive(node.try_into()?)
}
(DeviceType::MEDIA, DeviceSubType::MEDIA_CD_ROM) => Self::MediaCdRom(node.try_into()?),
(DeviceType::MEDIA, DeviceSubType::MEDIA_VENDOR) => Self::MediaVendor(node.try_into()?),
(DeviceType::MEDIA, DeviceSubType::MEDIA_FILE_PATH) => {
Self::MediaFilePath(node.try_into()?)
}
(DeviceType::MEDIA, DeviceSubType::MEDIA_PROTOCOL) => {
Self::MediaProtocol(node.try_into()?)
}
(DeviceType::MEDIA, DeviceSubType::MEDIA_PIWG_FIRMWARE_FILE) => {
Self::MediaPiwgFirmwareFile(node.try_into()?)
}
(DeviceType::MEDIA, DeviceSubType::MEDIA_PIWG_FIRMWARE_VOLUME) => {
Self::MediaPiwgFirmwareVolume(node.try_into()?)
}
(DeviceType::MEDIA, DeviceSubType::MEDIA_RELATIVE_OFFSET_RANGE) => {
Self::MediaRelativeOffsetRange(node.try_into()?)
}
(DeviceType::MEDIA, DeviceSubType::MEDIA_RAM_DISK) => {
Self::MediaRamDisk(node.try_into()?)
}
(DeviceType::BIOS_BOOT_SPEC, DeviceSubType::BIOS_BOOT_SPECIFICATION) => {
Self::BiosBootSpecBootSpecification(node.try_into()?)
}
_ => return Err(NodeConversionError::UnsupportedType),
})
}
}
pub mod build {
use super::*;
use crate::proto::device_path::build::{BuildError, BuildNode};
use crate::proto::device_path::{DeviceSubType, DeviceType};
use crate::CStr16;
use core::mem::{size_of_val, MaybeUninit};
pub mod end {
use super::*;
#[derive(Debug)]
pub struct Instance;
unsafe impl BuildNode for Instance {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 4usize;
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::END,
sub_type: DeviceSubType::END_INSTANCE,
length: u16::try_from(size).unwrap(),
});
}
}
}
#[derive(Debug)]
pub struct Entire;
unsafe impl BuildNode for Entire {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 4usize;
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::END,
sub_type: DeviceSubType::END_ENTIRE,
length: u16::try_from(size).unwrap(),
});
}
}
}
}
pub mod hardware {
use super::*;
#[derive(Debug)]
pub struct Pci {
pub function: u8,
pub device: u8,
}
unsafe impl BuildNode for Pci {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 6usize;
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::HARDWARE,
sub_type: DeviceSubType::HARDWARE_PCI,
length: u16::try_from(size).unwrap(),
});
out_ptr
.add(4usize)
.cast::<u8>()
.write_unaligned(self.function);
out_ptr
.add(5usize)
.cast::<u8>()
.write_unaligned(self.device);
}
}
}
#[derive(Debug)]
pub struct Pccard {
pub function: u8,
}
unsafe impl BuildNode for Pccard {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 5usize;
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::HARDWARE,
sub_type: DeviceSubType::HARDWARE_PCCARD,
length: u16::try_from(size).unwrap(),
});
out_ptr
.add(4usize)
.cast::<u8>()
.write_unaligned(self.function);
}
}
}
#[derive(Debug)]
pub struct MemoryMapped {
pub memory_type: MemoryType,
pub start_address: u64,
pub end_address: u64,
}
unsafe impl BuildNode for MemoryMapped {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 24usize;
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::HARDWARE,
sub_type: DeviceSubType::HARDWARE_MEMORY_MAPPED,
length: u16::try_from(size).unwrap(),
});
out_ptr
.add(4usize)
.cast::<MemoryType>()
.write_unaligned(self.memory_type);
out_ptr
.add(8usize)
.cast::<u64>()
.write_unaligned(self.start_address);
out_ptr
.add(16usize)
.cast::<u64>()
.write_unaligned(self.end_address);
}
}
}
#[derive(Debug)]
pub struct Vendor<'a> {
pub vendor_guid: Guid,
pub vendor_defined_data: &'a [u8],
}
unsafe impl<'a> BuildNode for Vendor<'a> {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 20usize + size_of_val(self.vendor_defined_data);
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::HARDWARE,
sub_type: DeviceSubType::HARDWARE_VENDOR,
length: u16::try_from(size).unwrap(),
});
out_ptr
.add(4usize)
.cast::<Guid>()
.write_unaligned(self.vendor_guid);
self.vendor_defined_data
.as_ptr()
.cast::<u8>()
.copy_to_nonoverlapping(
out_ptr.add(20usize),
size_of_val(self.vendor_defined_data),
);
}
}
}
#[derive(Debug)]
pub struct Controller {
pub controller_number: u32,
}
unsafe impl BuildNode for Controller {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 8usize;
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::HARDWARE,
sub_type: DeviceSubType::HARDWARE_CONTROLLER,
length: u16::try_from(size).unwrap(),
});
out_ptr
.add(4usize)
.cast::<u32>()
.write_unaligned(self.controller_number);
}
}
}
#[derive(Debug)]
pub struct Bmc {
pub interface_type: crate::proto::device_path::hardware::BmcInterfaceType,
pub base_address: u64,
}
unsafe impl BuildNode for Bmc {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 13usize;
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::HARDWARE,
sub_type: DeviceSubType::HARDWARE_BMC,
length: u16::try_from(size).unwrap(),
});
out_ptr
.add(4usize)
.cast::<crate::proto::device_path::hardware::BmcInterfaceType>()
.write_unaligned(self.interface_type);
out_ptr
.add(5usize)
.cast::<u64>()
.write_unaligned(self.base_address);
}
}
}
}
pub mod acpi {
use super::*;
#[derive(Debug)]
pub struct Acpi {
pub hid: u32,
pub uid: u32,
}
unsafe impl BuildNode for Acpi {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 12usize;
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::ACPI,
sub_type: DeviceSubType::ACPI,
length: u16::try_from(size).unwrap(),
});
out_ptr.add(4usize).cast::<u32>().write_unaligned(self.hid);
out_ptr.add(8usize).cast::<u32>().write_unaligned(self.uid);
}
}
}
#[derive(Debug)]
pub struct Expanded<'a> {
pub hid: u32,
pub uid: u32,
pub cid: u32,
pub hid_str: &'a [u8],
pub uid_str: &'a [u8],
pub cid_str: &'a [u8],
}
unsafe impl<'a> BuildNode for Expanded<'a> {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 16usize
+ size_of_val(self.hid_str)
+ size_of_val(self.uid_str)
+ size_of_val(self.cid_str);
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::ACPI,
sub_type: DeviceSubType::ACPI_EXPANDED,
length: u16::try_from(size).unwrap(),
});
let mut dst_group_offset = 0;
out_ptr.add(4usize).cast::<u32>().write_unaligned(self.hid);
out_ptr.add(8usize).cast::<u32>().write_unaligned(self.uid);
out_ptr.add(12usize).cast::<u32>().write_unaligned(self.cid);
self.hid_str.as_ptr().cast::<u8>().copy_to_nonoverlapping(
out_ptr.add(16usize + dst_group_offset),
size_of_val(self.hid_str),
);
dst_group_offset += size_of_val(self.hid_str);
self.uid_str.as_ptr().cast::<u8>().copy_to_nonoverlapping(
out_ptr.add(16usize + dst_group_offset),
size_of_val(self.uid_str),
);
dst_group_offset += size_of_val(self.uid_str);
self.cid_str.as_ptr().cast::<u8>().copy_to_nonoverlapping(
out_ptr.add(16usize + dst_group_offset),
size_of_val(self.cid_str),
);
}
}
}
#[derive(Debug)]
pub struct Adr<'a> {
pub adr: &'a AdrSlice,
}
unsafe impl<'a> BuildNode for Adr<'a> {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 4usize + size_of_val(self.adr);
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::ACPI,
sub_type: DeviceSubType::ACPI_ADR,
length: u16::try_from(size).unwrap(),
});
self.adr
.as_ptr()
.cast::<u8>()
.copy_to_nonoverlapping(out_ptr.add(4usize), size_of_val(self.adr));
}
}
}
#[derive(Debug)]
pub struct Nvdimm {
pub nfit_device_handle: u32,
}
unsafe impl BuildNode for Nvdimm {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 8usize;
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::ACPI,
sub_type: DeviceSubType::ACPI_NVDIMM,
length: u16::try_from(size).unwrap(),
});
out_ptr
.add(4usize)
.cast::<u32>()
.write_unaligned(self.nfit_device_handle);
}
}
}
#[repr(transparent)]
#[derive(Debug)]
pub struct AdrSlice([u32]);
impl AdrSlice {
#[must_use]
pub fn new(slice: &[u32]) -> Option<&Self> {
if slice.is_empty() {
None
} else {
let adr_slice: &Self = unsafe { core::mem::transmute(slice) };
Some(adr_slice)
}
}
fn as_ptr(&self) -> *const u32 {
self.0.as_ptr()
}
}
}
pub mod messaging {
use super::*;
#[derive(Debug)]
pub struct Atapi {
pub primary_secondary: crate::proto::device_path::messaging::PrimarySecondary,
pub master_slave: crate::proto::device_path::messaging::MasterSlave,
pub logical_unit_number: u16,
}
unsafe impl BuildNode for Atapi {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 8usize;
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::MESSAGING,
sub_type: DeviceSubType::MESSAGING_ATAPI,
length: u16::try_from(size).unwrap(),
});
out_ptr
.add(4usize)
.cast::<crate::proto::device_path::messaging::PrimarySecondary>()
.write_unaligned(self.primary_secondary);
out_ptr
.add(5usize)
.cast::<crate::proto::device_path::messaging::MasterSlave>()
.write_unaligned(self.master_slave);
out_ptr
.add(6usize)
.cast::<u16>()
.write_unaligned(self.logical_unit_number);
}
}
}
#[derive(Debug)]
pub struct Scsi {
pub target_id: u16,
pub logical_unit_number: u16,
}
unsafe impl BuildNode for Scsi {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 8usize;
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::MESSAGING,
sub_type: DeviceSubType::MESSAGING_SCSI,
length: u16::try_from(size).unwrap(),
});
out_ptr
.add(4usize)
.cast::<u16>()
.write_unaligned(self.target_id);
out_ptr
.add(6usize)
.cast::<u16>()
.write_unaligned(self.logical_unit_number);
}
}
}
#[derive(Debug)]
pub struct FibreChannel {
pub world_wide_name: u64,
pub logical_unit_number: u64,
}
unsafe impl BuildNode for FibreChannel {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 24usize;
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::MESSAGING,
sub_type: DeviceSubType::MESSAGING_FIBRE_CHANNEL,
length: u16::try_from(size).unwrap(),
});
out_ptr.add(4usize).write_bytes(0, size_of::<u32>());
out_ptr
.add(8usize)
.cast::<u64>()
.write_unaligned(self.world_wide_name);
out_ptr
.add(16usize)
.cast::<u64>()
.write_unaligned(self.logical_unit_number);
}
}
}
#[derive(Debug)]
pub struct FibreChannelEx {
pub world_wide_name: [u8; 8usize],
pub logical_unit_number: [u8; 8usize],
}
unsafe impl BuildNode for FibreChannelEx {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 24usize;
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::MESSAGING,
sub_type: DeviceSubType::MESSAGING_FIBRE_CHANNEL_EX,
length: u16::try_from(size).unwrap(),
});
out_ptr.add(4usize).write_bytes(0, size_of::<u32>());
out_ptr
.add(8usize)
.cast::<[u8; 8usize]>()
.write_unaligned(self.world_wide_name);
out_ptr
.add(16usize)
.cast::<[u8; 8usize]>()
.write_unaligned(self.logical_unit_number);
}
}
}
#[derive(Debug)]
pub struct Ieee1394 {
pub guid: [u8; 8usize],
}
unsafe impl BuildNode for Ieee1394 {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 16usize;
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::MESSAGING,
sub_type: DeviceSubType::MESSAGING_1394,
length: u16::try_from(size).unwrap(),
});
out_ptr.add(4usize).write_bytes(0, size_of::<u32>());
out_ptr
.add(8usize)
.cast::<[u8; 8usize]>()
.write_unaligned(self.guid);
}
}
}
#[derive(Debug)]
pub struct Usb {
pub parent_port_number: u8,
pub interface: u8,
}
unsafe impl BuildNode for Usb {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 6usize;
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::MESSAGING,
sub_type: DeviceSubType::MESSAGING_USB,
length: u16::try_from(size).unwrap(),
});
out_ptr
.add(4usize)
.cast::<u8>()
.write_unaligned(self.parent_port_number);
out_ptr
.add(5usize)
.cast::<u8>()
.write_unaligned(self.interface);
}
}
}
#[derive(Debug)]
pub struct Sata {
pub hba_port_number: u16,
pub port_multiplier_port_number: u16,
pub logical_unit_number: u16,
}
unsafe impl BuildNode for Sata {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 10usize;
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::MESSAGING,
sub_type: DeviceSubType::MESSAGING_SATA,
length: u16::try_from(size).unwrap(),
});
out_ptr
.add(4usize)
.cast::<u16>()
.write_unaligned(self.hba_port_number);
out_ptr
.add(6usize)
.cast::<u16>()
.write_unaligned(self.port_multiplier_port_number);
out_ptr
.add(8usize)
.cast::<u16>()
.write_unaligned(self.logical_unit_number);
}
}
}
#[derive(Debug)]
pub struct UsbWwid<'a> {
pub interface_number: u16,
pub device_vendor_id: u16,
pub device_product_id: u16,
pub serial_number: &'a [u16],
}
unsafe impl<'a> BuildNode for UsbWwid<'a> {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 10usize + size_of_val(self.serial_number);
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::MESSAGING,
sub_type: DeviceSubType::MESSAGING_USB_WWID,
length: u16::try_from(size).unwrap(),
});
out_ptr
.add(4usize)
.cast::<u16>()
.write_unaligned(self.interface_number);
out_ptr
.add(6usize)
.cast::<u16>()
.write_unaligned(self.device_vendor_id);
out_ptr
.add(8usize)
.cast::<u16>()
.write_unaligned(self.device_product_id);
self.serial_number
.as_ptr()
.cast::<u8>()
.copy_to_nonoverlapping(
out_ptr.add(10usize),
size_of_val(self.serial_number),
);
}
}
}
#[derive(Debug)]
pub struct DeviceLogicalUnit {
pub logical_unit_number: u8,
}
unsafe impl BuildNode for DeviceLogicalUnit {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 5usize;
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::MESSAGING,
sub_type: DeviceSubType::MESSAGING_DEVICE_LOGICAL_UNIT,
length: u16::try_from(size).unwrap(),
});
out_ptr
.add(4usize)
.cast::<u8>()
.write_unaligned(self.logical_unit_number);
}
}
}
#[derive(Debug)]
pub struct UsbClass {
pub vendor_id: u16,
pub product_id: u16,
pub device_class: u8,
pub device_subclass: u8,
pub device_protocol: u8,
}
unsafe impl BuildNode for UsbClass {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 11usize;
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::MESSAGING,
sub_type: DeviceSubType::MESSAGING_USB_CLASS,
length: u16::try_from(size).unwrap(),
});
out_ptr
.add(4usize)
.cast::<u16>()
.write_unaligned(self.vendor_id);
out_ptr
.add(6usize)
.cast::<u16>()
.write_unaligned(self.product_id);
out_ptr
.add(8usize)
.cast::<u8>()
.write_unaligned(self.device_class);
out_ptr
.add(9usize)
.cast::<u8>()
.write_unaligned(self.device_subclass);
out_ptr
.add(10usize)
.cast::<u8>()
.write_unaligned(self.device_protocol);
}
}
}
#[derive(Debug)]
pub struct I2o {
pub target_id: u32,
}
unsafe impl BuildNode for I2o {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 8usize;
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::MESSAGING,
sub_type: DeviceSubType::MESSAGING_I2O,
length: u16::try_from(size).unwrap(),
});
out_ptr
.add(4usize)
.cast::<u32>()
.write_unaligned(self.target_id);
}
}
}
#[derive(Debug)]
pub struct MacAddress {
pub mac_address: [u8; 32usize],
pub interface_type: u8,
}
unsafe impl BuildNode for MacAddress {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 37usize;
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::MESSAGING,
sub_type: DeviceSubType::MESSAGING_MAC_ADDRESS,
length: u16::try_from(size).unwrap(),
});
out_ptr
.add(4usize)
.cast::<[u8; 32usize]>()
.write_unaligned(self.mac_address);
out_ptr
.add(36usize)
.cast::<u8>()
.write_unaligned(self.interface_type);
}
}
}
#[derive(Debug)]
pub struct Ipv4 {
pub local_ip_address: [u8; 4usize],
pub remote_ip_address: [u8; 4usize],
pub local_port: u16,
pub remote_port: u16,
pub protocol: u16,
pub ip_address_origin: crate::proto::device_path::messaging::Ipv4AddressOrigin,
pub gateway_ip_address: [u8; 4usize],
pub subnet_mask: [u8; 4usize],
}
unsafe impl BuildNode for Ipv4 {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 27usize;
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::MESSAGING,
sub_type: DeviceSubType::MESSAGING_IPV4,
length: u16::try_from(size).unwrap(),
});
out_ptr
.add(4usize)
.cast::<[u8; 4usize]>()
.write_unaligned(self.local_ip_address);
out_ptr
.add(8usize)
.cast::<[u8; 4usize]>()
.write_unaligned(self.remote_ip_address);
out_ptr
.add(12usize)
.cast::<u16>()
.write_unaligned(self.local_port);
out_ptr
.add(14usize)
.cast::<u16>()
.write_unaligned(self.remote_port);
out_ptr
.add(16usize)
.cast::<u16>()
.write_unaligned(self.protocol);
out_ptr
.add(18usize)
.cast::<crate::proto::device_path::messaging::Ipv4AddressOrigin>()
.write_unaligned(self.ip_address_origin);
out_ptr
.add(19usize)
.cast::<[u8; 4usize]>()
.write_unaligned(self.gateway_ip_address);
out_ptr
.add(23usize)
.cast::<[u8; 4usize]>()
.write_unaligned(self.subnet_mask);
}
}
}
#[derive(Debug)]
pub struct Ipv6 {
pub local_ip_address: [u8; 16usize],
pub remote_ip_address: [u8; 16usize],
pub local_port: u16,
pub remote_port: u16,
pub protocol: u16,
pub ip_address_origin: crate::proto::device_path::messaging::Ipv6AddressOrigin,
pub prefix_length: u8,
pub gateway_ip_address: [u8; 16usize],
}
unsafe impl BuildNode for Ipv6 {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 60usize;
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::MESSAGING,
sub_type: DeviceSubType::MESSAGING_IPV6,
length: u16::try_from(size).unwrap(),
});
out_ptr
.add(4usize)
.cast::<[u8; 16usize]>()
.write_unaligned(self.local_ip_address);
out_ptr
.add(20usize)
.cast::<[u8; 16usize]>()
.write_unaligned(self.remote_ip_address);
out_ptr
.add(36usize)
.cast::<u16>()
.write_unaligned(self.local_port);
out_ptr
.add(38usize)
.cast::<u16>()
.write_unaligned(self.remote_port);
out_ptr
.add(40usize)
.cast::<u16>()
.write_unaligned(self.protocol);
out_ptr
.add(42usize)
.cast::<crate::proto::device_path::messaging::Ipv6AddressOrigin>()
.write_unaligned(self.ip_address_origin);
out_ptr
.add(43usize)
.cast::<u8>()
.write_unaligned(self.prefix_length);
out_ptr
.add(44usize)
.cast::<[u8; 16usize]>()
.write_unaligned(self.gateway_ip_address);
}
}
}
#[derive(Debug)]
pub struct Vlan {
pub vlan_id: u16,
}
unsafe impl BuildNode for Vlan {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 6usize;
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::MESSAGING,
sub_type: DeviceSubType::MESSAGING_VLAN,
length: u16::try_from(size).unwrap(),
});
out_ptr
.add(4usize)
.cast::<u16>()
.write_unaligned(self.vlan_id);
}
}
}
#[derive(Debug)]
pub struct Infiniband {
pub resource_flags: crate::proto::device_path::messaging::InfinibandResourceFlags,
pub port_gid: [u8; 16usize],
pub ioc_guid_or_service_id: u64,
pub target_port_id: u64,
pub device_id: u64,
}
unsafe impl BuildNode for Infiniband {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 48usize;
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::MESSAGING,
sub_type: DeviceSubType::MESSAGING_INFINIBAND,
length: u16::try_from(size).unwrap(),
});
out_ptr
.add(4usize)
.cast::<crate::proto::device_path::messaging::InfinibandResourceFlags>()
.write_unaligned(self.resource_flags);
out_ptr
.add(8usize)
.cast::<[u8; 16usize]>()
.write_unaligned(self.port_gid);
out_ptr
.add(24usize)
.cast::<u64>()
.write_unaligned(self.ioc_guid_or_service_id);
out_ptr
.add(32usize)
.cast::<u64>()
.write_unaligned(self.target_port_id);
out_ptr
.add(40usize)
.cast::<u64>()
.write_unaligned(self.device_id);
}
}
}
#[derive(Debug)]
pub struct Uart {
pub baud_rate: u64,
pub data_bits: u8,
pub parity: crate::proto::device_path::messaging::Parity,
pub stop_bits: crate::proto::device_path::messaging::StopBits,
}
unsafe impl BuildNode for Uart {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 19usize;
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::MESSAGING,
sub_type: DeviceSubType::MESSAGING_UART,
length: u16::try_from(size).unwrap(),
});
out_ptr.add(4usize).write_bytes(0, size_of::<u32>());
out_ptr
.add(8usize)
.cast::<u64>()
.write_unaligned(self.baud_rate);
out_ptr
.add(16usize)
.cast::<u8>()
.write_unaligned(self.data_bits);
out_ptr
.add(17usize)
.cast::<crate::proto::device_path::messaging::Parity>()
.write_unaligned(self.parity);
out_ptr
.add(18usize)
.cast::<crate::proto::device_path::messaging::StopBits>()
.write_unaligned(self.stop_bits);
}
}
}
#[derive(Debug)]
pub struct Vendor<'a> {
pub vendor_guid: Guid,
pub vendor_defined_data: &'a [u8],
}
unsafe impl<'a> BuildNode for Vendor<'a> {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 20usize + size_of_val(self.vendor_defined_data);
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::MESSAGING,
sub_type: DeviceSubType::MESSAGING_VENDOR,
length: u16::try_from(size).unwrap(),
});
out_ptr
.add(4usize)
.cast::<Guid>()
.write_unaligned(self.vendor_guid);
self.vendor_defined_data
.as_ptr()
.cast::<u8>()
.copy_to_nonoverlapping(
out_ptr.add(20usize),
size_of_val(self.vendor_defined_data),
);
}
}
}
#[derive(Debug)]
pub struct SasEx {
pub sas_address: [u8; 8usize],
pub logical_unit_number: [u8; 8usize],
pub info: u16,
pub relative_target_port: u16,
}
unsafe impl BuildNode for SasEx {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 24usize;
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::MESSAGING,
sub_type: DeviceSubType::MESSAGING_SCSI_SAS_EX,
length: u16::try_from(size).unwrap(),
});
out_ptr
.add(4usize)
.cast::<[u8; 8usize]>()
.write_unaligned(self.sas_address);
out_ptr
.add(12usize)
.cast::<[u8; 8usize]>()
.write_unaligned(self.logical_unit_number);
out_ptr
.add(20usize)
.cast::<u16>()
.write_unaligned(self.info);
out_ptr
.add(22usize)
.cast::<u16>()
.write_unaligned(self.relative_target_port);
}
}
}
#[derive(Debug)]
pub struct Iscsi<'a> {
pub protocol: crate::proto::device_path::messaging::IscsiProtocol,
pub options: crate::proto::device_path::messaging::IscsiLoginOptions,
pub logical_unit_number: [u8; 8usize],
pub target_portal_group_tag: u16,
pub iscsi_target_name: &'a [u8],
}
unsafe impl<'a> BuildNode for Iscsi<'a> {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 18usize + size_of_val(self.iscsi_target_name);
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::MESSAGING,
sub_type: DeviceSubType::MESSAGING_ISCSI,
length: u16::try_from(size).unwrap(),
});
out_ptr
.add(4usize)
.cast::<crate::proto::device_path::messaging::IscsiProtocol>()
.write_unaligned(self.protocol);
out_ptr
.add(6usize)
.cast::<crate::proto::device_path::messaging::IscsiLoginOptions>()
.write_unaligned(self.options);
out_ptr
.add(8usize)
.cast::<[u8; 8usize]>()
.write_unaligned(self.logical_unit_number);
out_ptr
.add(16usize)
.cast::<u16>()
.write_unaligned(self.target_portal_group_tag);
self.iscsi_target_name
.as_ptr()
.cast::<u8>()
.copy_to_nonoverlapping(
out_ptr.add(18usize),
size_of_val(self.iscsi_target_name),
);
}
}
}
#[derive(Debug)]
pub struct NvmeNamespace {
pub namespace_identifier: u32,
pub ieee_extended_unique_identifier: u64,
}
unsafe impl BuildNode for NvmeNamespace {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 16usize;
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::MESSAGING,
sub_type: DeviceSubType::MESSAGING_NVME_NAMESPACE,
length: u16::try_from(size).unwrap(),
});
out_ptr
.add(4usize)
.cast::<u32>()
.write_unaligned(self.namespace_identifier);
out_ptr
.add(8usize)
.cast::<u64>()
.write_unaligned(self.ieee_extended_unique_identifier);
}
}
}
#[derive(Debug)]
pub struct Uri<'a> {
pub value: &'a [u8],
}
unsafe impl<'a> BuildNode for Uri<'a> {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 4usize + size_of_val(self.value);
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::MESSAGING,
sub_type: DeviceSubType::MESSAGING_URI,
length: u16::try_from(size).unwrap(),
});
self.value
.as_ptr()
.cast::<u8>()
.copy_to_nonoverlapping(out_ptr.add(4usize), size_of_val(self.value));
}
}
}
#[derive(Debug)]
pub struct Ufs {
pub target_id: u8,
pub logical_unit_number: u8,
}
unsafe impl BuildNode for Ufs {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 6usize;
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::MESSAGING,
sub_type: DeviceSubType::MESSAGING_UFS,
length: u16::try_from(size).unwrap(),
});
out_ptr
.add(4usize)
.cast::<u8>()
.write_unaligned(self.target_id);
out_ptr
.add(5usize)
.cast::<u8>()
.write_unaligned(self.logical_unit_number);
}
}
}
#[derive(Debug)]
pub struct Sd {
pub slot_number: u8,
}
unsafe impl BuildNode for Sd {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 5usize;
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::MESSAGING,
sub_type: DeviceSubType::MESSAGING_SD,
length: u16::try_from(size).unwrap(),
});
out_ptr
.add(4usize)
.cast::<u8>()
.write_unaligned(self.slot_number);
}
}
}
#[derive(Debug)]
pub struct Bluetooth {
pub device_address: [u8; 6usize],
}
unsafe impl BuildNode for Bluetooth {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 10usize;
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::MESSAGING,
sub_type: DeviceSubType::MESSAGING_BLUETOOTH,
length: u16::try_from(size).unwrap(),
});
out_ptr
.add(4usize)
.cast::<[u8; 6usize]>()
.write_unaligned(self.device_address);
}
}
}
#[derive(Debug)]
pub struct Wifi {
pub ssid: [u8; 32usize],
}
unsafe impl BuildNode for Wifi {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 36usize;
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::MESSAGING,
sub_type: DeviceSubType::MESSAGING_WIFI,
length: u16::try_from(size).unwrap(),
});
out_ptr
.add(4usize)
.cast::<[u8; 32usize]>()
.write_unaligned(self.ssid);
}
}
}
#[derive(Debug)]
pub struct Emmc {
pub slot_number: u8,
}
unsafe impl BuildNode for Emmc {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 5usize;
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::MESSAGING,
sub_type: DeviceSubType::MESSAGING_EMMC,
length: u16::try_from(size).unwrap(),
});
out_ptr
.add(4usize)
.cast::<u8>()
.write_unaligned(self.slot_number);
}
}
}
#[derive(Debug)]
pub struct BluetoothLe {
pub device_address: [u8; 6usize],
pub address_type: crate::proto::device_path::messaging::BluetoothLeAddressType,
}
unsafe impl BuildNode for BluetoothLe {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 11usize;
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::MESSAGING,
sub_type: DeviceSubType::MESSAGING_BLUETOOTH_LE,
length: u16::try_from(size).unwrap(),
});
out_ptr
.add(4usize)
.cast::<[u8; 6usize]>()
.write_unaligned(self.device_address);
out_ptr
.add(10usize)
.cast::<crate::proto::device_path::messaging::BluetoothLeAddressType>()
.write_unaligned(self.address_type);
}
}
}
#[derive(Debug)]
pub struct Dns<'a> {
pub address_type: crate::proto::device_path::messaging::DnsAddressType,
pub addresses: &'a [IpAddress],
}
unsafe impl<'a> BuildNode for Dns<'a> {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 5usize + size_of_val(self.addresses);
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::MESSAGING,
sub_type: DeviceSubType::MESSAGING_DNS,
length: u16::try_from(size).unwrap(),
});
out_ptr
.add(4usize)
.cast::<crate::proto::device_path::messaging::DnsAddressType>()
.write_unaligned(self.address_type);
self.addresses
.as_ptr()
.cast::<u8>()
.copy_to_nonoverlapping(out_ptr.add(5usize), size_of_val(self.addresses));
}
}
}
#[derive(Debug)]
pub struct NvdimmNamespace {
pub uuid: [u8; 16usize],
}
unsafe impl BuildNode for NvdimmNamespace {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 20usize;
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::MESSAGING,
sub_type: DeviceSubType::MESSAGING_NVDIMM_NAMESPACE,
length: u16::try_from(size).unwrap(),
});
out_ptr
.add(4usize)
.cast::<[u8; 16usize]>()
.write_unaligned(self.uuid);
}
}
}
#[derive(Debug)]
pub struct RestService<'a> {
pub service_type: crate::proto::device_path::messaging::RestServiceType,
pub access_mode: crate::proto::device_path::messaging::RestServiceAccessMode,
pub vendor_guid_and_data: Option<RestServiceVendorData<'a>>,
}
unsafe impl<'a> BuildNode for RestService<'a> {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 6usize + self.build_size_vendor_guid_and_data();
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::MESSAGING,
sub_type: DeviceSubType::MESSAGING_REST_SERVICE,
length: u16::try_from(size).unwrap(),
});
out_ptr
.add(4usize)
.cast::<crate::proto::device_path::messaging::RestServiceType>()
.write_unaligned(self.service_type);
out_ptr
.add(5usize)
.cast::<crate::proto::device_path::messaging::RestServiceAccessMode>()
.write_unaligned(self.access_mode);
self.build_vendor_guid_and_data(&mut out[6usize..])
}
}
}
#[derive(Debug)]
pub struct NvmeOfNamespace<'a> {
pub nidt: u8,
pub nid: [u8; 16usize],
pub subsystem_nqn: &'a [u8],
}
unsafe impl<'a> BuildNode for NvmeOfNamespace<'a> {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 21usize + size_of_val(self.subsystem_nqn);
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::MESSAGING,
sub_type: DeviceSubType::MESSAGING_NVME_OF_NAMESPACE,
length: u16::try_from(size).unwrap(),
});
out_ptr.add(4usize).cast::<u8>().write_unaligned(self.nidt);
out_ptr
.add(5usize)
.cast::<[u8; 16usize]>()
.write_unaligned(self.nid);
self.subsystem_nqn
.as_ptr()
.cast::<u8>()
.copy_to_nonoverlapping(
out_ptr.add(21usize),
size_of_val(self.subsystem_nqn),
);
}
}
}
#[derive(Debug)]
pub struct RestServiceVendorData<'a> {
pub vendor_guid: Guid,
pub vendor_defined_data: &'a [u8],
}
impl<'a> RestService<'a> {
fn build_size_vendor_guid_and_data(&self) -> usize {
if let Some(src) = &self.vendor_guid_and_data {
assert!(
self.service_type
== crate::proto::device_path::messaging::RestServiceType::VENDOR
);
size_of::<Guid>() + size_of_val(src.vendor_defined_data)
} else {
0
}
}
fn build_vendor_guid_and_data(&self, out: &mut [MaybeUninit<u8>]) {
if let Some(src) = &self.vendor_guid_and_data {
assert!(
self.service_type
== crate::proto::device_path::messaging::RestServiceType::VENDOR
);
let (guid_out, data_out) = out.split_at_mut(size_of::<Guid>());
let guid_out_ptr: *mut Guid = maybe_uninit_slice_as_mut_ptr(guid_out).cast();
unsafe {
guid_out_ptr.write_unaligned(src.vendor_guid);
}
let data_out_ptr = maybe_uninit_slice_as_mut_ptr(data_out);
unsafe {
src.vendor_defined_data
.as_ptr()
.copy_to_nonoverlapping(data_out_ptr, data_out.len());
}
}
}
}
}
pub mod media {
use super::*;
#[derive(Debug)]
pub struct HardDrive {
pub partition_number: u32,
pub partition_start: u64,
pub partition_size: u64,
pub partition_signature: crate::proto::device_path::media::PartitionSignature,
pub partition_format: crate::proto::device_path::media::PartitionFormat,
}
unsafe impl BuildNode for HardDrive {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 42usize;
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::MEDIA,
sub_type: DeviceSubType::MEDIA_HARD_DRIVE,
length: u16::try_from(size).unwrap(),
});
out_ptr
.add(4usize)
.cast::<u32>()
.write_unaligned(self.partition_number);
out_ptr
.add(8usize)
.cast::<u64>()
.write_unaligned(self.partition_start);
out_ptr
.add(16usize)
.cast::<u64>()
.write_unaligned(self.partition_size);
out_ptr
.add(24usize)
.cast::<[u8; 16usize]>()
.write_unaligned(self.build_partition_signature());
out_ptr
.add(40usize)
.cast::<crate::proto::device_path::media::PartitionFormat>()
.write_unaligned(self.partition_format);
out_ptr
.add(41usize)
.cast::<u8>()
.write_unaligned(self.build_signature_type());
}
}
}
#[derive(Debug)]
pub struct CdRom {
pub boot_entry: u32,
pub partition_start: u64,
pub partition_size: u64,
}
unsafe impl BuildNode for CdRom {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 24usize;
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::MEDIA,
sub_type: DeviceSubType::MEDIA_CD_ROM,
length: u16::try_from(size).unwrap(),
});
out_ptr
.add(4usize)
.cast::<u32>()
.write_unaligned(self.boot_entry);
out_ptr
.add(8usize)
.cast::<u64>()
.write_unaligned(self.partition_start);
out_ptr
.add(16usize)
.cast::<u64>()
.write_unaligned(self.partition_size);
}
}
}
#[derive(Debug)]
pub struct Vendor<'a> {
pub vendor_guid: Guid,
pub vendor_defined_data: &'a [u8],
}
unsafe impl<'a> BuildNode for Vendor<'a> {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 20usize + size_of_val(self.vendor_defined_data);
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::MEDIA,
sub_type: DeviceSubType::MEDIA_VENDOR,
length: u16::try_from(size).unwrap(),
});
out_ptr
.add(4usize)
.cast::<Guid>()
.write_unaligned(self.vendor_guid);
self.vendor_defined_data
.as_ptr()
.cast::<u8>()
.copy_to_nonoverlapping(
out_ptr.add(20usize),
size_of_val(self.vendor_defined_data),
);
}
}
}
#[derive(Debug)]
pub struct FilePath<'a> {
pub path_name: &'a CStr16,
}
unsafe impl<'a> BuildNode for FilePath<'a> {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 4usize + size_of_val(self.path_name);
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::MEDIA,
sub_type: DeviceSubType::MEDIA_FILE_PATH,
length: u16::try_from(size).unwrap(),
});
self.path_name
.as_ptr()
.cast::<u8>()
.copy_to_nonoverlapping(out_ptr.add(4usize), size_of_val(self.path_name));
}
}
}
#[derive(Debug)]
pub struct Protocol {
pub protocol_guid: Guid,
}
unsafe impl BuildNode for Protocol {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 20usize;
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::MEDIA,
sub_type: DeviceSubType::MEDIA_PROTOCOL,
length: u16::try_from(size).unwrap(),
});
out_ptr
.add(4usize)
.cast::<Guid>()
.write_unaligned(self.protocol_guid);
}
}
}
#[derive(Debug)]
pub struct PiwgFirmwareFile<'a> {
pub data: &'a [u8],
}
unsafe impl<'a> BuildNode for PiwgFirmwareFile<'a> {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 4usize + size_of_val(self.data);
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::MEDIA,
sub_type: DeviceSubType::MEDIA_PIWG_FIRMWARE_FILE,
length: u16::try_from(size).unwrap(),
});
self.data
.as_ptr()
.cast::<u8>()
.copy_to_nonoverlapping(out_ptr.add(4usize), size_of_val(self.data));
}
}
}
#[derive(Debug)]
pub struct PiwgFirmwareVolume<'a> {
pub data: &'a [u8],
}
unsafe impl<'a> BuildNode for PiwgFirmwareVolume<'a> {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 4usize + size_of_val(self.data);
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::MEDIA,
sub_type: DeviceSubType::MEDIA_PIWG_FIRMWARE_VOLUME,
length: u16::try_from(size).unwrap(),
});
self.data
.as_ptr()
.cast::<u8>()
.copy_to_nonoverlapping(out_ptr.add(4usize), size_of_val(self.data));
}
}
}
#[derive(Debug)]
pub struct RelativeOffsetRange {
pub starting_offset: u64,
pub ending_offset: u64,
}
unsafe impl BuildNode for RelativeOffsetRange {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 24usize;
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::MEDIA,
sub_type: DeviceSubType::MEDIA_RELATIVE_OFFSET_RANGE,
length: u16::try_from(size).unwrap(),
});
out_ptr.add(4usize).write_bytes(0, size_of::<u32>());
out_ptr
.add(8usize)
.cast::<u64>()
.write_unaligned(self.starting_offset);
out_ptr
.add(16usize)
.cast::<u64>()
.write_unaligned(self.ending_offset);
}
}
}
#[derive(Debug)]
pub struct RamDisk {
pub starting_address: u64,
pub ending_address: u64,
pub disk_type: crate::proto::device_path::media::RamDiskType,
pub disk_instance: u16,
}
unsafe impl BuildNode for RamDisk {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 38usize;
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::MEDIA,
sub_type: DeviceSubType::MEDIA_RAM_DISK,
length: u16::try_from(size).unwrap(),
});
out_ptr
.add(4usize)
.cast::<u64>()
.write_unaligned(self.starting_address);
out_ptr
.add(12usize)
.cast::<u64>()
.write_unaligned(self.ending_address);
out_ptr
.add(20usize)
.cast::<crate::proto::device_path::media::RamDiskType>()
.write_unaligned(self.disk_type);
out_ptr
.add(36usize)
.cast::<u16>()
.write_unaligned(self.disk_instance);
}
}
}
impl HardDrive {
fn build_partition_signature(&self) -> [u8; 16] {
use crate::proto::device_path::media::PartitionSignature::*;
match self.partition_signature {
None => [0u8; 16],
Mbr(mbr) => {
let mut sig = [0u8; 16];
sig[0..4].copy_from_slice(&mbr);
sig
}
Guid(guid) => guid.to_bytes(),
Unknown { signature, .. } => signature,
}
}
fn build_signature_type(&self) -> u8 {
use crate::proto::device_path::media::PartitionSignature::*;
match self.partition_signature {
None => 0,
Mbr(_) => 1,
Guid(_) => 2,
Unknown { signature_type, .. } => signature_type,
}
}
}
}
pub mod bios_boot_spec {
use super::*;
#[derive(Debug)]
pub struct BootSpecification<'a> {
pub device_type: u16,
pub status_flag: u16,
pub description_string: &'a [u8],
}
unsafe impl<'a> BuildNode for BootSpecification<'a> {
fn size_in_bytes(&self) -> Result<u16, BuildError> {
let size = 8usize + size_of_val(self.description_string);
u16::try_from(size).map_err(|_| BuildError::NodeTooBig)
}
fn write_data(&self, out: &mut [MaybeUninit<u8>]) {
let size = usize::from(self.size_in_bytes().unwrap());
assert_eq!(size, out.len());
let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out);
unsafe {
out_ptr
.cast::<DevicePathHeader>()
.write_unaligned(DevicePathHeader {
device_type: DeviceType::BIOS_BOOT_SPEC,
sub_type: DeviceSubType::BIOS_BOOT_SPECIFICATION,
length: u16::try_from(size).unwrap(),
});
out_ptr
.add(4usize)
.cast::<u16>()
.write_unaligned(self.device_type);
out_ptr
.add(6usize)
.cast::<u16>()
.write_unaligned(self.status_flag);
self.description_string
.as_ptr()
.cast::<u8>()
.copy_to_nonoverlapping(
out_ptr.add(8usize),
size_of_val(self.description_string),
);
}
}
}
}
}