From 9d9797327d4618913f2018487b586a578a4e9ebc Mon Sep 17 00:00:00 2001 From: Jarl Evanson Date: Sun, 13 Apr 2025 13:21:26 -0500 Subject: [PATCH] uefi: Move PoolString to enable additional use --- uefi/src/boot.rs | 2 +- uefi/src/data_types/mod.rs | 3 ++- uefi/src/data_types/strs.rs | 39 ++++++++++++++++++++++++++++++ uefi/src/proto/device_path/text.rs | 33 +++---------------------- 4 files changed, 46 insertions(+), 31 deletions(-) diff --git a/uefi/src/boot.rs b/uefi/src/boot.rs index d36e59dae..a06e84cab 100644 --- a/uefi/src/boot.rs +++ b/uefi/src/boot.rs @@ -1318,7 +1318,7 @@ unsafe fn get_memory_map_and_exit_boot_services(buf: &mut [u8]) -> Result) -> MemoryMapOwned { // LOADER_DATA is the default and also used by the Linux kernel: diff --git a/uefi/src/data_types/mod.rs b/uefi/src/data_types/mod.rs index 2c94b2062..9b428e53b 100644 --- a/uefi/src/data_types/mod.rs +++ b/uefi/src/data_types/mod.rs @@ -169,7 +169,8 @@ mod opaque; mod strs; pub use strs::{ - CStr16, CStr8, EqStrUntilNul, FromSliceWithNulError, FromStrWithBufError, UnalignedCStr16Error, + CStr16, CStr8, EqStrUntilNul, FromSliceWithNulError, FromStrWithBufError, PoolString, + UnalignedCStr16Error, }; /// These functions are used in the implementation of the [`cstr8`] macro. diff --git a/uefi/src/data_types/strs.rs b/uefi/src/data_types/strs.rs index fc69782f1..2b625e6b8 100644 --- a/uefi/src/data_types/strs.rs +++ b/uefi/src/data_types/strs.rs @@ -1,12 +1,17 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 +use uefi_raw::Status; + use super::chars::{Char16, Char8, NUL_16, NUL_8}; use super::UnalignedSlice; +use crate::mem::PoolAllocation; use crate::polyfill::maybe_uninit_slice_assume_init_ref; use core::borrow::Borrow; use core::ffi::CStr; use core::fmt::{self, Display, Formatter}; use core::mem::MaybeUninit; +use core::ops::Deref; +use core::ptr::NonNull; use core::{ptr, slice}; #[cfg(feature = "alloc")] @@ -718,6 +723,40 @@ impl PartialEq for &CStr16 { } } +/// UCS-2 string allocated from UEFI pool memory. +/// +/// This is similar to a [`CString16`], but used for memory that was allocated +/// internally by UEFI rather than the Rust allocator. +/// +/// [`CString16`]: crate::CString16 +#[derive(Debug)] +pub struct PoolString(PoolAllocation); + +impl PoolString { + /// Create a [`PoolString`] from a [`CStr16`] residing in a buffer allocated + /// using [`allocate_pool()`][cbap]. + /// + /// # Safety + /// + /// The caller must ensure that the buffer points to a valid [`CStr16`] and + /// resides in a buffer allocated using [`allocate_pool()`][cbap] + /// + /// [cbap]: crate::boot::allocate_pool() + pub unsafe fn new(text: *const Char16) -> crate::Result { + NonNull::new(text.cast_mut()) + .map(|p| Self(PoolAllocation::new(p.cast()))) + .ok_or(Status::OUT_OF_RESOURCES.into()) + } +} + +impl Deref for PoolString { + type Target = CStr16; + + fn deref(&self) -> &Self::Target { + unsafe { CStr16::from_ptr(self.0.as_ptr().as_ptr().cast()) } + } +} + impl UnalignedSlice<'_, u16> { /// Create a [`CStr16`] from an [`UnalignedSlice`] using an aligned /// buffer for storage. The lifetime of the output is tied to `buf`, diff --git a/uefi/src/proto/device_path/text.rs b/uefi/src/proto/device_path/text.rs index 6ea22e1a8..7c39c8921 100644 --- a/uefi/src/proto/device_path/text.rs +++ b/uefi/src/proto/device_path/text.rs @@ -10,11 +10,11 @@ // if there is insufficient memory. So we treat any NULL output as an // `OUT_OF_RESOURCES` error. +use crate::data_types::PoolString; use crate::mem::PoolAllocation; use crate::proto::device_path::{DevicePath, DevicePathNode}; use crate::proto::unsafe_protocol; -use crate::{CStr16, Char16, Result, Status}; -use core::ops::Deref; +use crate::{CStr16, Result, Status}; use core::ptr::NonNull; use uefi_raw::protocol::device_path::{DevicePathFromTextProtocol, DevicePathToTextProtocol}; @@ -47,31 +47,6 @@ pub struct DisplayOnly(pub bool); #[derive(Clone, Copy, Debug)] pub struct AllowShortcuts(pub bool); -/// UCS-2 string allocated from UEFI pool memory. -/// -/// This is similar to a [`CString16`], but used for memory that was allocated -/// internally by UEFI rather than the Rust allocator. -/// -/// [`CString16`]: crate::CString16 -#[derive(Debug)] -pub struct PoolString(PoolAllocation); - -impl PoolString { - fn new(text: *const Char16) -> Result { - NonNull::new(text.cast_mut()) - .map(|p| Self(PoolAllocation::new(p.cast()))) - .ok_or(Status::OUT_OF_RESOURCES.into()) - } -} - -impl Deref for PoolString { - type Target = CStr16; - - fn deref(&self) -> &Self::Target { - unsafe { CStr16::from_ptr(self.0.as_ptr().as_ptr().cast()) } - } -} - /// Protocol for converting a [`DevicePath`] or `DevicePathNode`] to a string. #[derive(Debug)] #[repr(transparent)] @@ -98,7 +73,7 @@ impl DevicePathToText { allow_shortcuts.0.into(), ) }; - PoolString::new(text.cast()) + unsafe { PoolString::new(text.cast()) } } /// Convert a [`DevicePath`] to a [`PoolString`]. @@ -120,7 +95,7 @@ impl DevicePathToText { allow_shortcuts.0.into(), ) }; - PoolString::new(text.cast()) + unsafe { PoolString::new(text.cast()) } } }