@@ -14,6 +14,7 @@ use r_efi::protocols::{device_path, device_path_to_text, shell};
1414
1515use crate :: ffi:: { OsStr , OsString } ;
1616use crate :: io:: { self , const_error} ;
17+ use crate :: iter:: Iterator ;
1718use crate :: mem:: { MaybeUninit , size_of} ;
1819use crate :: os:: uefi:: env:: boot_services;
1920use crate :: os:: uefi:: ffi:: { OsStrExt , OsStringExt } ;
@@ -160,11 +161,11 @@ pub(crate) fn image_handle_protocol<T>(protocol_guid: Guid) -> io::Result<NonNul
160161 open_protocol ( system_handle, protocol_guid)
161162}
162163
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 ] > > {
164165 fn path_to_text (
165166 protocol : NonNull < device_path_to_text:: Protocol > ,
166167 path : NonNull < device_path:: Protocol > ,
167- ) -> io:: Result < OsString > {
168+ ) -> io:: Result < Box < [ u16 ] > > {
168169 let path_ptr: * mut r_efi:: efi:: Char16 = unsafe {
169170 ( ( * protocol. as_ptr ( ) ) . convert_device_path_to_text ) (
170171 path. as_ptr ( ) ,
@@ -175,17 +176,8 @@ pub(crate) fn device_path_to_text(path: NonNull<device_path::Protocol>) -> io::R
175176 )
176177 } ;
177178
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" ) )
189181 }
190182
191183 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
214206 Err ( io:: const_error!( io:: ErrorKind :: NotFound , "No device path to text protocol found" ) )
215207}
216208
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+
217214/// Gets RuntimeServices.
218215pub ( crate ) fn runtime_services ( ) -> Option < NonNull < r_efi:: efi:: RuntimeServices > > {
219216 let system_table: NonNull < r_efi:: efi:: SystemTable > =
@@ -222,14 +219,14 @@ pub(crate) fn runtime_services() -> Option<NonNull<r_efi::efi::RuntimeServices>>
222219 NonNull :: new ( runtime_services)
223220}
224221
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 > ) ;
226223
227- impl DevicePath {
224+ impl OwnedDevicePath {
228225 pub ( crate ) fn from_text ( p : & OsStr ) -> io:: Result < Self > {
229226 fn inner (
230227 p : & OsStr ,
231228 protocol : NonNull < r_efi:: protocols:: device_path_from_text:: Protocol > ,
232- ) -> io:: Result < DevicePath > {
229+ ) -> io:: Result < OwnedDevicePath > {
233230 let path_vec = p. encode_wide ( ) . chain ( Some ( 0 ) ) . collect :: < Vec < u16 > > ( ) ;
234231 if path_vec[ ..path_vec. len ( ) - 1 ] . contains ( & 0 ) {
235232 return Err ( const_error ! (
@@ -242,7 +239,7 @@ impl DevicePath {
242239 unsafe { ( ( * protocol. as_ptr ( ) ) . convert_text_to_device_path ) ( path_vec. as_ptr ( ) ) } ;
243240
244241 NonNull :: new ( path)
245- . map ( DevicePath )
242+ . map ( OwnedDevicePath )
246243 . ok_or_else ( || const_error ! ( io:: ErrorKind :: InvalidFilename , "Invalid Device Path" ) )
247244 }
248245
@@ -275,12 +272,12 @@ impl DevicePath {
275272 ) )
276273 }
277274
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 {
279276 self . 0 . as_ptr ( )
280277 }
281278}
282279
283- impl Drop for DevicePath {
280+ impl Drop for OwnedDevicePath {
284281 fn drop ( & mut self ) {
285282 if let Some ( bt) = boot_services ( ) {
286283 let bt: NonNull < r_efi:: efi:: BootServices > = bt. cast ( ) ;
@@ -291,6 +288,13 @@ impl Drop for DevicePath {
291288 }
292289}
293290
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+
294298pub ( crate ) struct OwnedProtocol < T > {
295299 guid : r_efi:: efi:: Guid ,
296300 handle : NonNull < crate :: ffi:: c_void > ,
@@ -411,6 +415,15 @@ impl<T> Drop for OwnedTable<T> {
411415 }
412416}
413417
418+ /// Create an Owned UEFI string from raw pointer. Allows string allocations and conversions
419+ ///
420+ /// SAFETY: This function assumes that Rust has ownership over this string
421+ fn owned_uefi_string_from_raw ( ptr : * mut r_efi:: efi:: Char16 ) -> Option < Box < [ r_efi:: efi:: Char16 ] > > {
422+ let str_len = unsafe { WStrUnits :: new ( ptr) ?. count ( ) } ;
423+ let str_slice = crate :: ptr:: slice_from_raw_parts_mut ( ptr. cast ( ) , str_len) ;
424+ Some ( unsafe { Box :: from_raw ( str_slice) } )
425+ }
426+
414427/// Create OsString from a pointer to NULL terminated UTF-16 string
415428pub ( crate ) fn os_string_from_raw ( ptr : * mut r_efi:: efi:: Char16 ) -> Option < OsString > {
416429 let path_len = unsafe { WStrUnits :: new ( ptr) ?. count ( ) } ;
0 commit comments