@@ -21,6 +21,12 @@ use crate::slice;
21
21
use crate :: sync:: atomic:: { AtomicPtr , Ordering } ;
22
22
use crate :: sys_common:: wstr:: WStrUnits ;
23
23
24
+ type BootInstallMultipleProtocolInterfaces =
25
+ unsafe extern "efiapi" fn ( _: * mut r_efi:: efi:: Handle , _: ...) -> r_efi:: efi:: Status ;
26
+
27
+ type BootUninstallMultipleProtocolInterfaces =
28
+ unsafe extern "efiapi" fn ( _: r_efi:: efi:: Handle , _: ...) -> r_efi:: efi:: Status ;
29
+
24
30
const BOOT_SERVICES_UNAVAILABLE : io:: Error =
25
31
const_io_error ! ( io:: ErrorKind :: Other , "Boot Services are no longer available" ) ;
26
32
@@ -231,6 +237,13 @@ impl DevicePath {
231
237
protocol : NonNull < r_efi:: protocols:: device_path_from_text:: Protocol > ,
232
238
) -> io:: Result < DevicePath > {
233
239
let path_vec = p. encode_wide ( ) . chain ( Some ( 0 ) ) . collect :: < Vec < u16 > > ( ) ;
240
+ if path_vec[ ..path_vec. len ( ) - 1 ] . contains ( & 0 ) {
241
+ return Err ( const_io_error ! (
242
+ io:: ErrorKind :: InvalidInput ,
243
+ "strings passed to UEFI cannot contain NULs" ,
244
+ ) ) ;
245
+ }
246
+
234
247
let path =
235
248
unsafe { ( ( * protocol. as_ptr ( ) ) . convert_text_to_device_path ) ( path_vec. as_ptr ( ) ) } ;
236
249
@@ -267,17 +280,9 @@ impl DevicePath {
267
280
"DevicePathFromText Protocol not found"
268
281
) )
269
282
}
270
- }
271
-
272
- impl AsRef < r_efi:: protocols:: device_path:: Protocol > for DevicePath {
273
- fn as_ref ( & self ) -> & r_efi:: protocols:: device_path:: Protocol {
274
- unsafe { self . 0 . as_ref ( ) }
275
- }
276
- }
277
283
278
- impl AsMut < r_efi:: protocols:: device_path:: Protocol > for DevicePath {
279
- fn as_mut ( & mut self ) -> & mut r_efi:: protocols:: device_path:: Protocol {
280
- unsafe { self . 0 . as_mut ( ) }
284
+ pub ( crate ) fn as_ptr ( & self ) -> * mut r_efi:: protocols:: device_path:: Protocol {
285
+ self . 0 . as_ptr ( )
281
286
}
282
287
}
283
288
@@ -292,74 +297,122 @@ impl Drop for DevicePath {
292
297
}
293
298
}
294
299
295
- pub ( crate ) struct Protocol < T > {
300
+ pub ( crate ) struct OwnedProtocol < T > {
296
301
guid : r_efi:: efi:: Guid ,
297
302
handle : NonNull < crate :: ffi:: c_void > ,
298
- protocol : Box < T > ,
303
+ protocol : * mut T ,
299
304
}
300
305
301
- impl < T > Protocol < T > {
302
- const fn new (
303
- guid : r_efi:: efi:: Guid ,
304
- handle : NonNull < crate :: ffi:: c_void > ,
305
- protocol : Box < T > ,
306
- ) -> Self {
307
- Self { guid, handle, protocol }
308
- }
309
-
310
- pub ( crate ) fn create ( protocol : T , mut guid : r_efi:: efi:: Guid ) -> io:: Result < Self > {
311
- let boot_services: NonNull < r_efi:: efi:: BootServices > =
306
+ impl < T > OwnedProtocol < T > {
307
+ // FIXME: Consider using unsafe trait for matching protocol with guid
308
+ pub ( crate ) unsafe fn create ( protocol : T , mut guid : r_efi:: efi:: Guid ) -> io:: Result < Self > {
309
+ let bt: NonNull < r_efi:: efi:: BootServices > =
312
310
boot_services ( ) . ok_or ( BOOT_SERVICES_UNAVAILABLE ) ?. cast ( ) ;
313
- let mut protocol = Box :: new ( protocol) ;
311
+ let protocol : * mut T = Box :: into_raw ( Box :: new ( protocol) ) ;
314
312
let mut handle: r_efi:: efi:: Handle = crate :: ptr:: null_mut ( ) ;
315
313
314
+ // FIXME: Move into r-efi once extended_varargs_abi_support is stablized
315
+ let func: BootInstallMultipleProtocolInterfaces =
316
+ unsafe { crate :: mem:: transmute ( ( * bt. as_ptr ( ) ) . install_multiple_protocol_interfaces ) } ;
317
+
316
318
let r = unsafe {
317
- ( ( * boot_services . as_ptr ( ) ) . install_protocol_interface ) (
319
+ func (
318
320
& mut handle,
319
- & mut guid,
320
- r_efi :: efi :: NATIVE_INTERFACE ,
321
- protocol . as_mut ( ) as * mut T as * mut crate :: ffi:: c_void ,
321
+ & mut guid as * mut _ as * mut crate :: ffi :: c_void ,
322
+ protocol as * mut crate :: ffi :: c_void ,
323
+ crate :: ptr :: null_mut ( ) as * mut crate :: ffi:: c_void ,
322
324
)
323
325
} ;
324
326
325
327
if r. is_error ( ) {
328
+ drop ( unsafe { Box :: from_raw ( protocol) } ) ;
326
329
return Err ( crate :: io:: Error :: from_raw_os_error ( r. as_usize ( ) ) ) ;
327
330
} ;
328
331
329
332
let handle = NonNull :: new ( handle)
330
333
. ok_or ( io:: const_io_error!( io:: ErrorKind :: Uncategorized , "found null handle" ) ) ?;
331
334
332
- Ok ( Self :: new ( guid, handle, protocol) )
335
+ Ok ( Self { guid, handle, protocol } )
333
336
}
334
337
335
338
pub ( crate ) fn handle ( & self ) -> NonNull < crate :: ffi:: c_void > {
336
339
self . handle
337
340
}
338
341
}
339
342
340
- impl < T > Drop for Protocol < T > {
343
+ impl < T > Drop for OwnedProtocol < T > {
341
344
fn drop ( & mut self ) {
345
+ // Do not deallocate a runtime protocol
342
346
if let Some ( bt) = boot_services ( ) {
343
347
let bt: NonNull < r_efi:: efi:: BootServices > = bt. cast ( ) ;
344
- unsafe {
345
- ( ( * bt. as_ptr ( ) ) . uninstall_protocol_interface ) (
348
+ // FIXME: Move into r-efi once extended_varargs_abi_support is stablized
349
+ let func: BootUninstallMultipleProtocolInterfaces = unsafe {
350
+ crate :: mem:: transmute ( ( * bt. as_ptr ( ) ) . uninstall_multiple_protocol_interfaces )
351
+ } ;
352
+ let status = unsafe {
353
+ func (
346
354
self . handle . as_ptr ( ) ,
347
- & mut self . guid ,
348
- self . protocol . as_mut ( ) as * mut T as * mut crate :: ffi:: c_void ,
355
+ & mut self . guid as * mut _ as * mut crate :: ffi:: c_void ,
356
+ self . protocol as * mut crate :: ffi:: c_void ,
357
+ crate :: ptr:: null_mut ( ) as * mut crate :: ffi:: c_void ,
349
358
)
350
359
} ;
360
+
361
+ // Leak the protocol in case uninstall fails
362
+ if status == r_efi:: efi:: Status :: SUCCESS {
363
+ let _ = unsafe { Box :: from_raw ( self . protocol ) } ;
364
+ }
351
365
}
352
366
}
353
367
}
354
368
355
- impl < T > AsRef < T > for Protocol < T > {
369
+ impl < T > AsRef < T > for OwnedProtocol < T > {
356
370
fn as_ref ( & self ) -> & T {
357
- & self . protocol
371
+ unsafe { self . protocol . as_ref ( ) . unwrap ( ) }
372
+ }
373
+ }
374
+
375
+ pub ( crate ) struct OwnedTable < T > {
376
+ layout : crate :: alloc:: Layout ,
377
+ ptr : * mut T ,
378
+ }
379
+
380
+ impl < T > OwnedTable < T > {
381
+ pub ( crate ) fn from_table_header ( hdr : & r_efi:: efi:: TableHeader ) -> Self {
382
+ let header_size = hdr. header_size as usize ;
383
+ let layout = crate :: alloc:: Layout :: from_size_align ( header_size, 8 ) . unwrap ( ) ;
384
+ let ptr = unsafe { crate :: alloc:: alloc ( layout) as * mut T } ;
385
+ Self { layout, ptr }
386
+ }
387
+
388
+ pub ( crate ) const fn as_ptr ( & self ) -> * const T {
389
+ self . ptr
390
+ }
391
+
392
+ pub ( crate ) const fn as_mut_ptr ( & self ) -> * mut T {
393
+ self . ptr
358
394
}
359
395
}
360
396
361
- impl < T > AsMut < T > for Protocol < T > {
362
- fn as_mut ( & mut self ) -> & mut T {
363
- & mut self . protocol
397
+ impl OwnedTable < r_efi:: efi:: SystemTable > {
398
+ pub ( crate ) fn from_table ( tbl : * const r_efi:: efi:: SystemTable ) -> Self {
399
+ let hdr = unsafe { ( * tbl) . hdr } ;
400
+
401
+ let owned_tbl = Self :: from_table_header ( & hdr) ;
402
+ unsafe {
403
+ crate :: ptr:: copy_nonoverlapping (
404
+ tbl as * const u8 ,
405
+ owned_tbl. as_mut_ptr ( ) as * mut u8 ,
406
+ hdr. header_size as usize ,
407
+ )
408
+ } ;
409
+
410
+ owned_tbl
411
+ }
412
+ }
413
+
414
+ impl < T > Drop for OwnedTable < T > {
415
+ fn drop ( & mut self ) {
416
+ unsafe { crate :: alloc:: dealloc ( self . ptr as * mut u8 , self . layout ) } ;
364
417
}
365
418
}
0 commit comments