diff --git a/CHANGELOG.md b/CHANGELOG.md index 83a40d4b8..ae609c619 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ - Added `RuntimeServices::get_variable_boxed` (requires the `alloc` feature). - Added `CStr16::as_bytes` - Added `AsRef<[u8]>` and `Borrow<[u8]>` for `Cstr8` and `CStr16`. +- Added `LoadedImageDevicePath` protocol. ### Changed diff --git a/uefi-test-runner/src/proto/device_path.rs b/uefi-test-runner/src/proto/device_path.rs index caf9903c5..a8f5f7acb 100644 --- a/uefi-test-runner/src/proto/device_path.rs +++ b/uefi-test-runner/src/proto/device_path.rs @@ -1,6 +1,6 @@ use uefi::prelude::*; use uefi::proto::device_path::text::*; -use uefi::proto::device_path::DevicePath; +use uefi::proto::device_path::{DevicePath, LoadedImageDevicePath}; use uefi::proto::loaded_image::LoadedImage; use uefi::table::boot::BootServices; @@ -48,4 +48,16 @@ pub fn test(image: Handle, bt: &BootServices) { .expect("Failed to convert text to device path"); assert_eq!(path, convert); } + + // Get the `LoadedImageDevicePath`. Verify it start with the same nodes as + // `device_path`. + let loaded_image_device_path = bt + .open_protocol_exclusive::(image) + .expect("Failed to open LoadedImageDevicePath protocol"); + for (n1, n2) in device_path + .node_iter() + .zip(loaded_image_device_path.node_iter()) + { + assert_eq!(n1, n2); + } } diff --git a/uefi/src/proto/device_path/mod.rs b/uefi/src/proto/device_path/mod.rs index 7a23e5243..522d0a48f 100644 --- a/uefi/src/proto/device_path/mod.rs +++ b/uefi/src/proto/device_path/mod.rs @@ -85,6 +85,7 @@ use crate::proto::{unsafe_protocol, ProtocolPointer}; use core::ffi::c_void; use core::fmt::{self, Debug, Formatter}; use core::mem; +use core::ops::Deref; use ptr_meta::Pointee; opaque_type! { @@ -610,6 +611,35 @@ pub enum NodeConversionError { UnsupportedType, } +/// Protocol for accessing the device path that was passed in to [`load_image`] +/// when loading a PE/COFF image. +/// +/// The layout of this type is the same as a [`DevicePath`]. +/// +/// [`load_image`]: crate::table::boot::BootServices::load_image +#[repr(transparent)] +#[unsafe_protocol("bc62157e-3e33-4fec-9920-2d3b36d750df")] +#[derive(Pointee)] +pub struct LoadedImageDevicePath(DevicePath); + +impl ProtocolPointer for LoadedImageDevicePath { + unsafe fn ptr_from_ffi(ptr: *const c_void) -> *const Self { + ptr_meta::from_raw_parts(ptr.cast(), DevicePath::size_in_bytes_from_ptr(ptr)) + } + + unsafe fn mut_ptr_from_ffi(ptr: *mut c_void) -> *mut Self { + ptr_meta::from_raw_parts_mut(ptr.cast(), DevicePath::size_in_bytes_from_ptr(ptr)) + } +} + +impl Deref for LoadedImageDevicePath { + type Target = DevicePath; + + fn deref(&self) -> &DevicePath { + &self.0 + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/uefi/src/table/boot.rs b/uefi/src/table/boot.rs index aa5d5871d..d743da062 100644 --- a/uefi/src/table/boot.rs +++ b/uefi/src/table/boot.rs @@ -986,10 +986,11 @@ impl BootServices { /// image. /// /// If the image is successfully loaded, a [`Handle`] supporting the - /// [`LoadedImage`] and `LoadedImageDevicePath` protocols is + /// [`LoadedImage`] and [`LoadedImageDevicePath`] protocols is /// returned. The image can be started with [`start_image`] or /// unloaded with [`unload_image`]. /// + /// [`LoadedImageDevicePath`]: crate::proto::device_path::LoadedImageDevicePath /// [`start_image`]: BootServices::start_image /// [`unload_image`]: BootServices::unload_image ///