Skip to content

Commit 704e98b

Browse files
committed
Add PoolString to manage the string allocated by boot services
1 parent 149396e commit 704e98b

File tree

2 files changed

+49
-7
lines changed

2 files changed

+49
-7
lines changed

src/proto/device_path/text.rs

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
33
use crate::{
44
proto::{device_path::DevicePath, Protocol},
5+
table::boot::BootServices,
56
unsafe_guid, CStr16, Char16,
67
};
8+
use core::ops::Deref;
79

810
/// This struct is a wrapper of `display_only` parameter
911
/// used by Device Path to Text protocol.
@@ -29,6 +31,43 @@ pub struct DisplayOnly(pub bool);
2931
#[derive(Clone, Copy)]
3032
pub struct AllowShortcuts(pub bool);
3133

34+
/// Wrapper for a string internally allocated from
35+
/// UEFI boot services memory.
36+
pub struct PoolString<'a> {
37+
boot_services: &'a BootServices,
38+
text: *const Char16,
39+
}
40+
41+
impl<'a> PoolString<'a> {
42+
fn new(boot_services: &'a BootServices, text: *const Char16) -> Option<Self> {
43+
if text.is_null() {
44+
None
45+
} else {
46+
Some(Self {
47+
boot_services,
48+
text,
49+
})
50+
}
51+
}
52+
}
53+
54+
impl<'a> Deref for PoolString<'a> {
55+
type Target = CStr16;
56+
57+
fn deref(&self) -> &Self::Target {
58+
unsafe { CStr16::from_ptr(self.text) }
59+
}
60+
}
61+
62+
impl Drop for PoolString<'_> {
63+
fn drop(&mut self) {
64+
let addr = self.text as *mut u8;
65+
self.boot_services
66+
.free_pool(addr)
67+
.expect("Failed to free pool [{addr}]");
68+
}
69+
}
70+
3271
/// Device Path to Text protocol.
3372
///
3473
/// This protocol provides common utility functions for converting device
@@ -54,32 +93,34 @@ impl DevicePathToText {
5493
///
5594
/// Returns `None` if `device_node` was NULL or there was
5695
/// insufficient memory.
57-
pub fn convert_device_node_to_text(
96+
pub fn convert_device_node_to_text<'boot>(
5897
&self,
98+
boot_services: &'boot BootServices,
5999
device_node: &DevicePath,
60100
display_only: DisplayOnly,
61101
allow_shortcuts: AllowShortcuts,
62-
) -> Option<&CStr16> {
102+
) -> Option<PoolString<'boot>> {
63103
let text_device_node = unsafe {
64104
(self.convert_device_node_to_text)(device_node, display_only.0, allow_shortcuts.0)
65105
};
66-
unsafe { Some(CStr16::from_ptr(text_device_node.as_ref()?)) }
106+
PoolString::new(boot_services, text_device_node)
67107
}
68108

69109
/// Convert a device path to its text representation.
70110
///
71111
/// Returns `None` if `device_path` was NULL or there was
72112
/// insufficient memory.
73-
pub fn convert_device_path_to_text(
113+
pub fn convert_device_path_to_text<'boot>(
74114
&self,
115+
boot_services: &'boot BootServices,
75116
device_path: &DevicePath,
76117
display_only: DisplayOnly,
77118
allow_shortcuts: AllowShortcuts,
78-
) -> Option<&CStr16> {
119+
) -> Option<PoolString<'boot>> {
79120
let text_device_path = unsafe {
80121
(self.convert_device_path_to_text)(device_path, display_only.0, allow_shortcuts.0)
81122
};
82-
unsafe { Some(CStr16::from_ptr(text_device_path.as_ref()?)) }
123+
PoolString::new(boot_services, text_device_path)
83124
}
84125
}
85126

uefi-test-runner/src/proto/device_path.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,9 @@ pub fn test(image: Handle, bt: &BootServices) {
4949
);
5050

5151
let text = device_path_to_text
52-
.convert_device_path_to_text(path, DisplayOnly(true), AllowShortcuts(false))
52+
.convert_device_path_to_text(bt, path, DisplayOnly(true), AllowShortcuts(false))
5353
.expect("Failed to convert device path to text");
54+
let text = &*text;
5455
info!("path name: {text}");
5556

5657
let convert = device_path_from_text

0 commit comments

Comments
 (0)