@@ -35,6 +35,7 @@ pub struct StdioPipes {
35
35
pub stderr : Option < AnonPipe > ,
36
36
}
37
37
38
+ #[ derive( Copy , Clone ) ]
38
39
pub enum Stdio {
39
40
Inherit ,
40
41
Null ,
@@ -96,14 +97,14 @@ impl Command {
96
97
97
98
fn create_pipe (
98
99
s : Stdio ,
99
- ) -> io:: Result < Option < helpers:: Protocol < uefi_command_internal:: PipeProtocol > > > {
100
+ ) -> io:: Result < Option < helpers:: OwnedProtocol < uefi_command_internal:: PipeProtocol > > > {
100
101
match s {
101
- Stdio :: MakePipe => helpers:: Protocol :: create (
102
+ Stdio :: MakePipe => helpers:: OwnedProtocol :: create (
102
103
uefi_command_internal:: PipeProtocol :: new ( ) ,
103
104
simple_text_output:: PROTOCOL_GUID ,
104
105
)
105
106
. map ( Some ) ,
106
- Stdio :: Null => helpers:: Protocol :: create (
107
+ Stdio :: Null => helpers:: OwnedProtocol :: create (
107
108
uefi_command_internal:: PipeProtocol :: null ( ) ,
108
109
simple_text_output:: PROTOCOL_GUID ,
109
110
)
@@ -116,36 +117,24 @@ impl Command {
116
117
let mut cmd = uefi_command_internal:: Command :: load_image ( & self . prog ) ?;
117
118
118
119
/* Setup Stdout */
119
- let stdout: Option < helpers:: Protocol < uefi_command_internal:: PipeProtocol > > =
120
- match self . stdout . take ( ) {
121
- Some ( s) => Self :: create_pipe ( s) ,
122
- None => helpers:: Protocol :: create (
123
- uefi_command_internal:: PipeProtocol :: new ( ) ,
124
- simple_text_output:: PROTOCOL_GUID ,
125
- )
126
- . map ( Some ) ,
127
- } ?;
128
- match stdout {
129
- Some ( stdout) => cmd. stdout_init ( stdout) ,
130
- None => cmd. stdout_inherit ( ) ,
120
+ let stdout = self . stdout . unwrap_or ( Stdio :: MakePipe ) ;
121
+ let stdout = Self :: create_pipe ( stdout) ?;
122
+ if let Some ( con) = stdout {
123
+ cmd. stdout_init ( con)
124
+ } else {
125
+ cmd. stdout_inherit ( )
131
126
} ;
132
127
133
128
/* Setup Stderr */
134
- let stderr: Option < helpers:: Protocol < uefi_command_internal:: PipeProtocol > > =
135
- match self . stderr . take ( ) {
136
- Some ( s) => Self :: create_pipe ( s) ,
137
- None => helpers:: Protocol :: create (
138
- uefi_command_internal:: PipeProtocol :: new ( ) ,
139
- simple_text_output:: PROTOCOL_GUID ,
140
- )
141
- . map ( Some ) ,
142
- } ?;
143
- match stderr {
144
- Some ( stderr) => cmd. stderr_init ( stderr) ,
145
- None => cmd. stderr_inherit ( ) ,
129
+ let stderr = self . stderr . unwrap_or ( Stdio :: MakePipe ) ;
130
+ let stderr = Self :: create_pipe ( stderr) ?;
131
+ if let Some ( con) = stderr {
132
+ cmd. stderr_init ( con)
133
+ } else {
134
+ cmd. stderr_inherit ( )
146
135
} ;
147
136
148
- /* No reason to set args if only program name is preset */
137
+ // No reason to set args if only program name is preset
149
138
if !self . args . is_empty ( ) {
150
139
let args = self . args . iter ( ) . fold ( OsString :: from ( & self . prog ) , |mut acc, arg| {
151
140
acc. push ( " " ) ;
@@ -341,8 +330,8 @@ mod uefi_command_internal {
341
330
342
331
pub struct Command {
343
332
handle : NonNull < crate :: ffi:: c_void > ,
344
- stdout : Option < helpers:: Protocol < PipeProtocol > > ,
345
- stderr : Option < helpers:: Protocol < PipeProtocol > > ,
333
+ stdout : Option < helpers:: OwnedProtocol < PipeProtocol > > ,
334
+ stderr : Option < helpers:: OwnedProtocol < PipeProtocol > > ,
346
335
st : Box < r_efi:: efi:: SystemTable > ,
347
336
args : Option < Vec < u16 > > ,
348
337
}
@@ -382,45 +371,52 @@ mod uefi_command_internal {
382
371
383
372
let loaded_image: NonNull < loaded_image:: Protocol > =
384
373
helpers:: open_protocol ( child_handle, loaded_image:: PROTOCOL_GUID ) . unwrap ( ) ;
385
- let mut st: Box < r_efi:: efi:: SystemTable > =
374
+ let st: Box < r_efi:: efi:: SystemTable > =
386
375
Box :: new ( unsafe { crate :: ptr:: read ( ( * loaded_image. as_ptr ( ) ) . system_table ) } ) ;
387
376
388
- unsafe {
389
- ( * loaded_image. as_ptr ( ) ) . system_table = st. as_mut ( ) ;
390
- }
391
-
392
377
Ok ( Self :: new ( child_handle, st) )
393
378
}
394
379
}
395
380
396
- pub fn start_image ( & self ) -> io:: Result < r_efi:: efi:: Status > {
381
+ pub fn start_image ( & mut self ) -> io:: Result < r_efi:: efi:: Status > {
382
+ self . update_st_crc32 ( ) ?;
383
+
384
+ // Use our system table instead of the default one
385
+ let loaded_image: NonNull < loaded_image:: Protocol > =
386
+ helpers:: open_protocol ( self . handle , loaded_image:: PROTOCOL_GUID ) . unwrap ( ) ;
387
+ unsafe {
388
+ ( * loaded_image. as_ptr ( ) ) . system_table = self . st . as_mut ( ) ;
389
+ }
390
+
397
391
let boot_services: NonNull < r_efi:: efi:: BootServices > = boot_services ( )
398
392
. ok_or_else ( || const_io_error ! ( io:: ErrorKind :: NotFound , "Boot Services not found" ) ) ?
399
393
. cast ( ) ;
400
- let mut exit_data_size: MaybeUninit < usize > = MaybeUninit :: uninit ( ) ;
394
+ let mut exit_data_size: usize = 0 ;
401
395
let mut exit_data: MaybeUninit < * mut u16 > = MaybeUninit :: uninit ( ) ;
402
396
403
397
let r = unsafe {
404
398
( ( * boot_services. as_ptr ( ) ) . start_image ) (
405
399
self . handle . as_ptr ( ) ,
406
- exit_data_size. as_mut_ptr ( ) ,
400
+ & mut exit_data_size,
407
401
exit_data. as_mut_ptr ( ) ,
408
402
)
409
403
} ;
410
404
411
405
// Drop exitdata
412
- unsafe {
413
- exit_data_size. assume_init_drop ( ) ;
414
- exit_data. assume_init_drop ( ) ;
406
+ if exit_data_size != 0 {
407
+ unsafe {
408
+ let exit_data = exit_data. assume_init ( ) ;
409
+ ( ( * boot_services. as_ptr ( ) ) . free_pool ) ( exit_data as * mut crate :: ffi:: c_void ) ;
410
+ }
415
411
}
416
412
417
413
Ok ( r)
418
414
}
419
415
420
- pub fn stdout_init ( & mut self , mut protocol : helpers:: Protocol < PipeProtocol > ) {
416
+ pub fn stdout_init ( & mut self , protocol : helpers:: OwnedProtocol < PipeProtocol > ) {
421
417
self . st . console_out_handle = protocol. handle ( ) . as_ptr ( ) ;
422
418
self . st . con_out =
423
- protocol. as_mut ( ) as * mut PipeProtocol as * mut simple_text_output:: Protocol ;
419
+ protocol. as_ref ( ) as * const PipeProtocol as * mut simple_text_output:: Protocol ;
424
420
425
421
self . stdout = Some ( protocol) ;
426
422
}
@@ -432,10 +428,10 @@ mod uefi_command_internal {
432
428
self . st . con_out = unsafe { ( * st. as_ptr ( ) ) . con_out } ;
433
429
}
434
430
435
- pub fn stderr_init ( & mut self , mut protocol : helpers:: Protocol < PipeProtocol > ) {
431
+ pub fn stderr_init ( & mut self , protocol : helpers:: OwnedProtocol < PipeProtocol > ) {
436
432
self . st . standard_error_handle = protocol. handle ( ) . as_ptr ( ) ;
437
433
self . st . std_err =
438
- protocol. as_mut ( ) as * mut PipeProtocol as * mut simple_text_output:: Protocol ;
434
+ protocol. as_ref ( ) as * const PipeProtocol as * mut simple_text_output:: Protocol ;
439
435
440
436
self . stderr = Some ( protocol) ;
441
437
}
@@ -476,6 +472,30 @@ mod uefi_command_internal {
476
472
477
473
self . args = Some ( args) ;
478
474
}
475
+
476
+ fn update_st_crc32 ( & mut self ) -> io:: Result < ( ) > {
477
+ let bt: NonNull < r_efi:: efi:: BootServices > = boot_services ( ) . unwrap ( ) . cast ( ) ;
478
+ let st_size = self . st . hdr . header_size as usize ;
479
+ let mut crc32: u32 = 0 ;
480
+
481
+ // Set crc to 0 before calcuation
482
+ self . st . hdr . crc32 = 0 ;
483
+
484
+ let r = unsafe {
485
+ ( ( * bt. as_ptr ( ) ) . calculate_crc32 ) (
486
+ self . st . as_mut ( ) as * mut r_efi:: efi:: SystemTable as * mut crate :: ffi:: c_void ,
487
+ st_size,
488
+ & mut crc32,
489
+ )
490
+ } ;
491
+
492
+ if r. is_error ( ) {
493
+ Err ( io:: Error :: from_raw_os_error ( r. as_usize ( ) ) )
494
+ } else {
495
+ self . st . hdr . crc32 = crc32;
496
+ Ok ( ( ) )
497
+ }
498
+ }
479
499
}
480
500
481
501
impl Drop for Command {
@@ -501,13 +521,12 @@ mod uefi_command_internal {
501
521
set_cursor_position : simple_text_output:: ProtocolSetCursorPosition ,
502
522
enable_cursor : simple_text_output:: ProtocolEnableCursor ,
503
523
mode : * mut simple_text_output:: Mode ,
504
- _mode : Box < simple_text_output:: Mode > ,
505
524
_buffer : Vec < u16 > ,
506
525
}
507
526
508
527
impl PipeProtocol {
509
528
pub fn new ( ) -> Self {
510
- let mut mode = Box :: new ( simple_text_output:: Mode {
529
+ let mode = Box :: new ( simple_text_output:: Mode {
511
530
max_mode : 0 ,
512
531
mode : 0 ,
513
532
attribute : 0 ,
@@ -525,14 +544,13 @@ mod uefi_command_internal {
525
544
clear_screen : Self :: clear_screen,
526
545
set_cursor_position : Self :: set_cursor_position,
527
546
enable_cursor : Self :: enable_cursor,
528
- mode : mode. as_mut ( ) ,
529
- _mode : mode,
547
+ mode : Box :: into_raw ( mode) ,
530
548
_buffer : Vec :: new ( ) ,
531
549
}
532
550
}
533
551
534
552
pub fn null ( ) -> Self {
535
- let mut mode = Box :: new ( simple_text_output:: Mode {
553
+ let mode = Box :: new ( simple_text_output:: Mode {
536
554
max_mode : 0 ,
537
555
mode : 0 ,
538
556
attribute : 0 ,
@@ -550,8 +568,7 @@ mod uefi_command_internal {
550
568
clear_screen : Self :: clear_screen,
551
569
set_cursor_position : Self :: set_cursor_position,
552
570
enable_cursor : Self :: enable_cursor,
553
- mode : mode. as_mut ( ) ,
554
- _mode : mode,
571
+ mode : Box :: into_raw ( mode) ,
555
572
_buffer : Vec :: new ( ) ,
556
573
}
557
574
}
@@ -660,4 +677,12 @@ mod uefi_command_internal {
660
677
r_efi:: efi:: Status :: UNSUPPORTED
661
678
}
662
679
}
680
+
681
+ impl Drop for PipeProtocol {
682
+ fn drop ( & mut self ) {
683
+ unsafe {
684
+ let _ = Box :: from_raw ( self . mode ) ;
685
+ }
686
+ }
687
+ }
663
688
}
0 commit comments