2
2
3
3
use crate :: {
4
4
proto:: { device_path:: DevicePath , Protocol } ,
5
+ table:: boot:: BootServices ,
5
6
unsafe_guid, CStr16 , Char16 ,
6
7
} ;
8
+ use core:: ops:: Deref ;
7
9
8
10
/// This struct is a wrapper of `display_only` parameter
9
11
/// used by Device Path to Text protocol.
@@ -29,6 +31,43 @@ pub struct DisplayOnly(pub bool);
29
31
#[ derive( Clone , Copy ) ]
30
32
pub struct AllowShortcuts ( pub bool ) ;
31
33
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
+
32
71
/// Device Path to Text protocol.
33
72
///
34
73
/// This protocol provides common utility functions for converting device
@@ -54,32 +93,34 @@ impl DevicePathToText {
54
93
///
55
94
/// Returns `None` if `device_node` was NULL or there was
56
95
/// insufficient memory.
57
- pub fn convert_device_node_to_text (
96
+ pub fn convert_device_node_to_text < ' boot > (
58
97
& self ,
98
+ boot_services : & ' boot BootServices ,
59
99
device_node : & DevicePath ,
60
100
display_only : DisplayOnly ,
61
101
allow_shortcuts : AllowShortcuts ,
62
- ) -> Option < & CStr16 > {
102
+ ) -> Option < PoolString < ' boot > > {
63
103
let text_device_node = unsafe {
64
104
( self . convert_device_node_to_text ) ( device_node, display_only. 0 , allow_shortcuts. 0 )
65
105
} ;
66
- unsafe { Some ( CStr16 :: from_ptr ( text_device_node. as_ref ( ) ? ) ) }
106
+ PoolString :: new ( boot_services , text_device_node)
67
107
}
68
108
69
109
/// Convert a device path to its text representation.
70
110
///
71
111
/// Returns `None` if `device_path` was NULL or there was
72
112
/// insufficient memory.
73
- pub fn convert_device_path_to_text (
113
+ pub fn convert_device_path_to_text < ' boot > (
74
114
& self ,
115
+ boot_services : & ' boot BootServices ,
75
116
device_path : & DevicePath ,
76
117
display_only : DisplayOnly ,
77
118
allow_shortcuts : AllowShortcuts ,
78
- ) -> Option < & CStr16 > {
119
+ ) -> Option < PoolString < ' boot > > {
79
120
let text_device_path = unsafe {
80
121
( self . convert_device_path_to_text ) ( device_path, display_only. 0 , allow_shortcuts. 0 )
81
122
} ;
82
- unsafe { Some ( CStr16 :: from_ptr ( text_device_path. as_ref ( ) ? ) ) }
123
+ PoolString :: new ( boot_services , text_device_path)
83
124
}
84
125
}
85
126
0 commit comments