use super::{DevicePath, DevicePathNode, PoolDevicePath};
use crate::mem::PoolAllocation;
use core::ptr::NonNull;
use uefi_macros::unsafe_protocol;
use uefi_raw::Status;
use uefi_raw::protocol::device_path::DevicePathUtilitiesProtocol;
#[derive(Debug)]
#[repr(transparent)]
#[unsafe_protocol(DevicePathUtilitiesProtocol::GUID)]
pub struct DevicePathUtilities(DevicePathUtilitiesProtocol);
impl DevicePathUtilities {
#[must_use]
pub fn get_size(&self, device_path: &DevicePath) -> usize {
unsafe { (self.0.get_device_path_size)(device_path.as_ffi_ptr().cast()) }
}
pub fn duplicate_path(&self, path: &DevicePath) -> crate::Result<PoolDevicePath> {
unsafe {
let ptr = (self.0.duplicate_device_path)(path.as_ffi_ptr().cast());
NonNull::new(ptr.cast_mut())
.map(|p| PoolDevicePath(PoolAllocation::new(p.cast())))
.ok_or_else(|| Status::OUT_OF_RESOURCES.into())
}
}
pub fn append_path(
&self,
path0: &DevicePath,
path1: &DevicePath,
) -> crate::Result<PoolDevicePath> {
unsafe {
let ptr =
(self.0.append_device_path)(path0.as_ffi_ptr().cast(), path1.as_ffi_ptr().cast());
NonNull::new(ptr.cast_mut())
.map(|p| PoolDevicePath(PoolAllocation::new(p.cast())))
.ok_or_else(|| Status::OUT_OF_RESOURCES.into())
}
}
pub fn append_node(
&self,
basepath: &DevicePath,
node: &DevicePathNode,
) -> crate::Result<PoolDevicePath> {
unsafe {
let ptr =
(self.0.append_device_node)(basepath.as_ffi_ptr().cast(), node.as_ffi_ptr().cast());
NonNull::new(ptr.cast_mut())
.map(|p| PoolDevicePath(PoolAllocation::new(p.cast())))
.ok_or_else(|| Status::OUT_OF_RESOURCES.into())
}
}
pub fn append_instance(
&self,
basepath: &DevicePath,
instance: &DevicePath,
) -> crate::Result<PoolDevicePath> {
unsafe {
let ptr = (self.0.append_device_path_instance)(
basepath.as_ffi_ptr().cast(),
instance.as_ffi_ptr().cast(),
);
NonNull::new(ptr.cast_mut())
.map(|p| PoolDevicePath(PoolAllocation::new(p.cast())))
.ok_or_else(|| Status::OUT_OF_RESOURCES.into())
}
}
}