@@ -14,6 +14,7 @@ use r_efi::protocols::{device_path, device_path_to_text, shell};
14
14
15
15
use crate :: ffi:: { OsStr , OsString } ;
16
16
use crate :: io:: { self , const_error} ;
17
+ use crate :: iter:: Iterator ;
17
18
use crate :: mem:: { MaybeUninit , size_of} ;
18
19
use crate :: os:: uefi:: env:: boot_services;
19
20
use crate :: os:: uefi:: ffi:: { OsStrExt , OsStringExt } ;
@@ -160,11 +161,11 @@ pub(crate) fn image_handle_protocol<T>(protocol_guid: Guid) -> io::Result<NonNul
160
161
open_protocol ( system_handle, protocol_guid)
161
162
}
162
163
163
- pub ( crate ) fn device_path_to_text ( path : NonNull < device_path:: Protocol > ) -> io:: Result < OsString > {
164
+ fn device_path_to_text_raw ( path : NonNull < device_path:: Protocol > ) -> io:: Result < Box < [ u16 ] > > {
164
165
fn path_to_text (
165
166
protocol : NonNull < device_path_to_text:: Protocol > ,
166
167
path : NonNull < device_path:: Protocol > ,
167
- ) -> io:: Result < OsString > {
168
+ ) -> io:: Result < Box < [ u16 ] > > {
168
169
let path_ptr: * mut r_efi:: efi:: Char16 = unsafe {
169
170
( ( * protocol. as_ptr ( ) ) . convert_device_path_to_text ) (
170
171
path. as_ptr ( ) ,
@@ -175,17 +176,8 @@ pub(crate) fn device_path_to_text(path: NonNull<device_path::Protocol>) -> io::R
175
176
)
176
177
} ;
177
178
178
- let path = os_string_from_raw ( path_ptr)
179
- . ok_or ( io:: const_error!( io:: ErrorKind :: InvalidData , "Invalid path" ) ) ?;
180
-
181
- if let Some ( boot_services) = crate :: os:: uefi:: env:: boot_services ( ) {
182
- let boot_services: NonNull < r_efi:: efi:: BootServices > = boot_services. cast ( ) ;
183
- unsafe {
184
- ( ( * boot_services. as_ptr ( ) ) . free_pool ) ( path_ptr. cast ( ) ) ;
185
- }
186
- }
187
-
188
- Ok ( path)
179
+ owned_uefi_string_from_raw ( path_ptr)
180
+ . ok_or ( io:: const_error!( io:: ErrorKind :: InvalidData , "Invalid path" ) )
189
181
}
190
182
191
183
static LAST_VALID_HANDLE : AtomicPtr < crate :: ffi:: c_void > =
@@ -214,6 +206,11 @@ pub(crate) fn device_path_to_text(path: NonNull<device_path::Protocol>) -> io::R
214
206
Err ( io:: const_error!( io:: ErrorKind :: NotFound , "No device path to text protocol found" ) )
215
207
}
216
208
209
+ pub ( crate ) fn device_path_to_text ( path : NonNull < device_path:: Protocol > ) -> io:: Result < OsString > {
210
+ let p = device_path_to_text_raw ( path) ?;
211
+ Ok ( OsString :: from_wide ( & p) )
212
+ }
213
+
217
214
/// Gets RuntimeServices.
218
215
pub ( crate ) fn runtime_services ( ) -> Option < NonNull < r_efi:: efi:: RuntimeServices > > {
219
216
let system_table: NonNull < r_efi:: efi:: SystemTable > =
@@ -222,14 +219,14 @@ pub(crate) fn runtime_services() -> Option<NonNull<r_efi::efi::RuntimeServices>>
222
219
NonNull :: new ( runtime_services)
223
220
}
224
221
225
- pub ( crate ) struct DevicePath ( NonNull < r_efi:: protocols:: device_path:: Protocol > ) ;
222
+ pub ( crate ) struct OwnedDevicePath ( pub ( crate ) NonNull < r_efi:: protocols:: device_path:: Protocol > ) ;
226
223
227
- impl DevicePath {
224
+ impl OwnedDevicePath {
228
225
pub ( crate ) fn from_text ( p : & OsStr ) -> io:: Result < Self > {
229
226
fn inner (
230
227
p : & OsStr ,
231
228
protocol : NonNull < r_efi:: protocols:: device_path_from_text:: Protocol > ,
232
- ) -> io:: Result < DevicePath > {
229
+ ) -> io:: Result < OwnedDevicePath > {
233
230
let path_vec = p. encode_wide ( ) . chain ( Some ( 0 ) ) . collect :: < Vec < u16 > > ( ) ;
234
231
if path_vec[ ..path_vec. len ( ) - 1 ] . contains ( & 0 ) {
235
232
return Err ( const_error ! (
@@ -242,7 +239,7 @@ impl DevicePath {
242
239
unsafe { ( ( * protocol. as_ptr ( ) ) . convert_text_to_device_path ) ( path_vec. as_ptr ( ) ) } ;
243
240
244
241
NonNull :: new ( path)
245
- . map ( DevicePath )
242
+ . map ( OwnedDevicePath )
246
243
. ok_or_else ( || const_error ! ( io:: ErrorKind :: InvalidFilename , "Invalid Device Path" ) )
247
244
}
248
245
@@ -275,12 +272,12 @@ impl DevicePath {
275
272
) )
276
273
}
277
274
278
- pub ( crate ) fn as_ptr ( & self ) -> * mut r_efi:: protocols:: device_path:: Protocol {
275
+ pub ( crate ) const fn as_ptr ( & self ) -> * mut r_efi:: protocols:: device_path:: Protocol {
279
276
self . 0 . as_ptr ( )
280
277
}
281
278
}
282
279
283
- impl Drop for DevicePath {
280
+ impl Drop for OwnedDevicePath {
284
281
fn drop ( & mut self ) {
285
282
if let Some ( bt) = boot_services ( ) {
286
283
let bt: NonNull < r_efi:: efi:: BootServices > = bt. cast ( ) ;
@@ -291,6 +288,13 @@ impl Drop for DevicePath {
291
288
}
292
289
}
293
290
291
+ impl crate :: fmt:: Debug for OwnedDevicePath {
292
+ fn fmt ( & self , f : & mut crate :: fmt:: Formatter < ' _ > ) -> crate :: fmt:: Result {
293
+ let p = device_path_to_text ( self . 0 ) . unwrap ( ) ;
294
+ p. fmt ( f)
295
+ }
296
+ }
297
+
294
298
pub ( crate ) struct OwnedProtocol < T > {
295
299
guid : r_efi:: efi:: Guid ,
296
300
handle : NonNull < crate :: ffi:: c_void > ,
@@ -411,6 +415,16 @@ impl<T> Drop for OwnedTable<T> {
411
415
}
412
416
}
413
417
418
+ /// Create an Owned UEFI string from pointer to NULL terminated UTF-16 string.
419
+ /// Allows string allocations and conversions.
420
+ ///
421
+ /// SAFETY: This function assumes that Rust has ownership over this string
422
+ fn owned_uefi_string_from_raw ( ptr : * mut r_efi:: efi:: Char16 ) -> Option < Box < [ r_efi:: efi:: Char16 ] > > {
423
+ let str_len = unsafe { WStrUnits :: new ( ptr) ?. count ( ) } ;
424
+ let str_slice = crate :: ptr:: slice_from_raw_parts_mut ( ptr. cast ( ) , str_len) ;
425
+ Some ( unsafe { Box :: from_raw ( str_slice) } )
426
+ }
427
+
414
428
/// Create OsString from a pointer to NULL terminated UTF-16 string
415
429
pub ( crate ) fn os_string_from_raw ( ptr : * mut r_efi:: efi:: Char16 ) -> Option < OsString > {
416
430
let path_len = unsafe { WStrUnits :: new ( ptr) ?. count ( ) } ;
0 commit comments