@@ -35,6 +35,7 @@ pub struct StdioPipes {
3535 pub stderr : Option < AnonPipe > ,
3636}
3737
38+ #[ derive( Copy , Clone ) ]
3839pub enum Stdio {
3940 Inherit ,
4041 Null ,
@@ -96,14 +97,14 @@ impl Command {
9697
9798 fn create_pipe (
9899 s : Stdio ,
99- ) -> io:: Result < Option < helpers:: Protocol < uefi_command_internal:: PipeProtocol > > > {
100+ ) -> io:: Result < Option < helpers:: OwnedProtocol < uefi_command_internal:: PipeProtocol > > > {
100101 match s {
101- Stdio :: MakePipe => helpers:: Protocol :: create (
102+ Stdio :: MakePipe => helpers:: OwnedProtocol :: create (
102103 uefi_command_internal:: PipeProtocol :: new ( ) ,
103104 simple_text_output:: PROTOCOL_GUID ,
104105 )
105106 . map ( Some ) ,
106- Stdio :: Null => helpers:: Protocol :: create (
107+ Stdio :: Null => helpers:: OwnedProtocol :: create (
107108 uefi_command_internal:: PipeProtocol :: null ( ) ,
108109 simple_text_output:: PROTOCOL_GUID ,
109110 )
@@ -116,36 +117,24 @@ impl Command {
116117 let mut cmd = uefi_command_internal:: Command :: load_image ( & self . prog ) ?;
117118
118119 /* 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 ( )
131126 } ;
132127
133128 /* 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 ( )
146135 } ;
147136
148- /* No reason to set args if only program name is preset */
137+ // No reason to set args if only program name is preset
149138 if !self . args . is_empty ( ) {
150139 let args = self . args . iter ( ) . fold ( OsString :: from ( & self . prog ) , |mut acc, arg| {
151140 acc. push ( " " ) ;
@@ -341,8 +330,8 @@ mod uefi_command_internal {
341330
342331 pub struct Command {
343332 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 > > ,
346335 st : Box < r_efi:: efi:: SystemTable > ,
347336 args : Option < Vec < u16 > > ,
348337 }
@@ -382,45 +371,52 @@ mod uefi_command_internal {
382371
383372 let loaded_image: NonNull < loaded_image:: Protocol > =
384373 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 > =
386375 Box :: new ( unsafe { crate :: ptr:: read ( ( * loaded_image. as_ptr ( ) ) . system_table ) } ) ;
387376
388- unsafe {
389- ( * loaded_image. as_ptr ( ) ) . system_table = st. as_mut ( ) ;
390- }
391-
392377 Ok ( Self :: new ( child_handle, st) )
393378 }
394379 }
395380
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+
397391 let boot_services: NonNull < r_efi:: efi:: BootServices > = boot_services ( )
398392 . ok_or_else ( || const_io_error ! ( io:: ErrorKind :: NotFound , "Boot Services not found" ) ) ?
399393 . cast ( ) ;
400- let mut exit_data_size: MaybeUninit < usize > = MaybeUninit :: uninit ( ) ;
394+ let mut exit_data_size: usize = 0 ;
401395 let mut exit_data: MaybeUninit < * mut u16 > = MaybeUninit :: uninit ( ) ;
402396
403397 let r = unsafe {
404398 ( ( * boot_services. as_ptr ( ) ) . start_image ) (
405399 self . handle . as_ptr ( ) ,
406- exit_data_size. as_mut_ptr ( ) ,
400+ & mut exit_data_size,
407401 exit_data. as_mut_ptr ( ) ,
408402 )
409403 } ;
410404
411405 // 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+ }
415411 }
416412
417413 Ok ( r)
418414 }
419415
420- pub fn stdout_init ( & mut self , mut protocol : helpers:: Protocol < PipeProtocol > ) {
416+ pub fn stdout_init ( & mut self , protocol : helpers:: OwnedProtocol < PipeProtocol > ) {
421417 self . st . console_out_handle = protocol. handle ( ) . as_ptr ( ) ;
422418 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 ;
424420
425421 self . stdout = Some ( protocol) ;
426422 }
@@ -432,10 +428,10 @@ mod uefi_command_internal {
432428 self . st . con_out = unsafe { ( * st. as_ptr ( ) ) . con_out } ;
433429 }
434430
435- pub fn stderr_init ( & mut self , mut protocol : helpers:: Protocol < PipeProtocol > ) {
431+ pub fn stderr_init ( & mut self , protocol : helpers:: OwnedProtocol < PipeProtocol > ) {
436432 self . st . standard_error_handle = protocol. handle ( ) . as_ptr ( ) ;
437433 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 ;
439435
440436 self . stderr = Some ( protocol) ;
441437 }
@@ -476,6 +472,30 @@ mod uefi_command_internal {
476472
477473 self . args = Some ( args) ;
478474 }
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+ }
479499 }
480500
481501 impl Drop for Command {
@@ -501,13 +521,12 @@ mod uefi_command_internal {
501521 set_cursor_position : simple_text_output:: ProtocolSetCursorPosition ,
502522 enable_cursor : simple_text_output:: ProtocolEnableCursor ,
503523 mode : * mut simple_text_output:: Mode ,
504- _mode : Box < simple_text_output:: Mode > ,
505524 _buffer : Vec < u16 > ,
506525 }
507526
508527 impl PipeProtocol {
509528 pub fn new ( ) -> Self {
510- let mut mode = Box :: new ( simple_text_output:: Mode {
529+ let mode = Box :: new ( simple_text_output:: Mode {
511530 max_mode : 0 ,
512531 mode : 0 ,
513532 attribute : 0 ,
@@ -525,14 +544,13 @@ mod uefi_command_internal {
525544 clear_screen : Self :: clear_screen,
526545 set_cursor_position : Self :: set_cursor_position,
527546 enable_cursor : Self :: enable_cursor,
528- mode : mode. as_mut ( ) ,
529- _mode : mode,
547+ mode : Box :: into_raw ( mode) ,
530548 _buffer : Vec :: new ( ) ,
531549 }
532550 }
533551
534552 pub fn null ( ) -> Self {
535- let mut mode = Box :: new ( simple_text_output:: Mode {
553+ let mode = Box :: new ( simple_text_output:: Mode {
536554 max_mode : 0 ,
537555 mode : 0 ,
538556 attribute : 0 ,
@@ -550,8 +568,7 @@ mod uefi_command_internal {
550568 clear_screen : Self :: clear_screen,
551569 set_cursor_position : Self :: set_cursor_position,
552570 enable_cursor : Self :: enable_cursor,
553- mode : mode. as_mut ( ) ,
554- _mode : mode,
571+ mode : Box :: into_raw ( mode) ,
555572 _buffer : Vec :: new ( ) ,
556573 }
557574 }
@@ -660,4 +677,12 @@ mod uefi_command_internal {
660677 r_efi:: efi:: Status :: UNSUPPORTED
661678 }
662679 }
680+
681+ impl Drop for PipeProtocol {
682+ fn drop ( & mut self ) {
683+ unsafe {
684+ let _ = Box :: from_raw ( self . mode ) ;
685+ }
686+ }
687+ }
663688}
0 commit comments