@@ -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,38 @@ 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 ( ) {
120+ let stdout: Option < helpers:: OwnedProtocol < uefi_command_internal:: PipeProtocol > > =
121+ match self . stdout {
121122 Some ( s) => Self :: create_pipe ( s) ,
122- None => helpers:: Protocol :: create (
123+ None => helpers:: OwnedProtocol :: create (
123124 uefi_command_internal:: PipeProtocol :: new ( ) ,
124125 simple_text_output:: PROTOCOL_GUID ,
125126 )
126127 . map ( Some ) ,
127128 } ?;
128- match stdout {
129- Some ( stdout) => cmd. stdout_init ( stdout) ,
130- None => cmd. stdout_inherit ( ) ,
129+ if let Some ( con) = stdout {
130+ cmd. stdout_init ( con)
131+ } else {
132+ cmd. stdout_inherit ( )
131133 } ;
132134
133135 /* Setup Stderr */
134- let stderr: Option < helpers:: Protocol < uefi_command_internal:: PipeProtocol > > =
135- match self . stderr . take ( ) {
136+ let stderr: Option < helpers:: OwnedProtocol < uefi_command_internal:: PipeProtocol > > =
137+ match self . stderr {
136138 Some ( s) => Self :: create_pipe ( s) ,
137- None => helpers:: Protocol :: create (
139+ None => helpers:: OwnedProtocol :: create (
138140 uefi_command_internal:: PipeProtocol :: new ( ) ,
139141 simple_text_output:: PROTOCOL_GUID ,
140142 )
141143 . map ( Some ) ,
142144 } ?;
143- match stderr {
144- Some ( stderr) => cmd. stderr_init ( stderr) ,
145- None => cmd. stderr_inherit ( ) ,
145+ if let Some ( con) = stderr {
146+ cmd. stderr_init ( con)
147+ } else {
148+ cmd. stderr_inherit ( )
146149 } ;
147150
148- /* No reason to set args if only program name is preset */
151+ // No reason to set args if only program name is preset
149152 if !self . args . is_empty ( ) {
150153 let args = self . args . iter ( ) . fold ( OsString :: from ( & self . prog ) , |mut acc, arg| {
151154 acc. push ( " " ) ;
@@ -341,8 +344,8 @@ mod uefi_command_internal {
341344
342345 pub struct Command {
343346 handle : NonNull < crate :: ffi:: c_void > ,
344- stdout : Option < helpers:: Protocol < PipeProtocol > > ,
345- stderr : Option < helpers:: Protocol < PipeProtocol > > ,
347+ stdout : Option < helpers:: OwnedProtocol < PipeProtocol > > ,
348+ stderr : Option < helpers:: OwnedProtocol < PipeProtocol > > ,
346349 st : Box < r_efi:: efi:: SystemTable > ,
347350 args : Option < Vec < u16 > > ,
348351 }
@@ -382,45 +385,52 @@ mod uefi_command_internal {
382385
383386 let loaded_image: NonNull < loaded_image:: Protocol > =
384387 helpers:: open_protocol ( child_handle, loaded_image:: PROTOCOL_GUID ) . unwrap ( ) ;
385- let mut st: Box < r_efi:: efi:: SystemTable > =
388+ let st: Box < r_efi:: efi:: SystemTable > =
386389 Box :: new ( unsafe { crate :: ptr:: read ( ( * loaded_image. as_ptr ( ) ) . system_table ) } ) ;
387390
388- unsafe {
389- ( * loaded_image. as_ptr ( ) ) . system_table = st. as_mut ( ) ;
390- }
391-
392391 Ok ( Self :: new ( child_handle, st) )
393392 }
394393 }
395394
396- pub fn start_image ( & self ) -> io:: Result < r_efi:: efi:: Status > {
395+ pub fn start_image ( & mut self ) -> io:: Result < r_efi:: efi:: Status > {
396+ self . update_st_crc32 ( ) ?;
397+
398+ // Use our system table instead of the default one
399+ let loaded_image: NonNull < loaded_image:: Protocol > =
400+ helpers:: open_protocol ( self . handle , loaded_image:: PROTOCOL_GUID ) . unwrap ( ) ;
401+ unsafe {
402+ ( * loaded_image. as_ptr ( ) ) . system_table = self . st . as_mut ( ) ;
403+ }
404+
397405 let boot_services: NonNull < r_efi:: efi:: BootServices > = boot_services ( )
398406 . ok_or_else ( || const_io_error ! ( io:: ErrorKind :: NotFound , "Boot Services not found" ) ) ?
399407 . cast ( ) ;
400- let mut exit_data_size: MaybeUninit < usize > = MaybeUninit :: uninit ( ) ;
408+ let mut exit_data_size: usize = 0 ;
401409 let mut exit_data: MaybeUninit < * mut u16 > = MaybeUninit :: uninit ( ) ;
402410
403411 let r = unsafe {
404412 ( ( * boot_services. as_ptr ( ) ) . start_image ) (
405413 self . handle . as_ptr ( ) ,
406- exit_data_size. as_mut_ptr ( ) ,
414+ & mut exit_data_size,
407415 exit_data. as_mut_ptr ( ) ,
408416 )
409417 } ;
410418
411419 // Drop exitdata
412- unsafe {
413- exit_data_size. assume_init_drop ( ) ;
414- exit_data. assume_init_drop ( ) ;
420+ if exit_data_size != 0 {
421+ unsafe {
422+ let exit_data = exit_data. assume_init ( ) ;
423+ ( ( * boot_services. as_ptr ( ) ) . free_pool ) ( exit_data as * mut crate :: ffi:: c_void ) ;
424+ }
415425 }
416426
417427 Ok ( r)
418428 }
419429
420- pub fn stdout_init ( & mut self , mut protocol : helpers:: Protocol < PipeProtocol > ) {
430+ pub fn stdout_init ( & mut self , protocol : helpers:: OwnedProtocol < PipeProtocol > ) {
421431 self . st . console_out_handle = protocol. handle ( ) . as_ptr ( ) ;
422432 self . st . con_out =
423- protocol. as_mut ( ) as * mut PipeProtocol as * mut simple_text_output:: Protocol ;
433+ protocol. as_ref ( ) as * const PipeProtocol as * mut simple_text_output:: Protocol ;
424434
425435 self . stdout = Some ( protocol) ;
426436 }
@@ -432,10 +442,10 @@ mod uefi_command_internal {
432442 self . st . con_out = unsafe { ( * st. as_ptr ( ) ) . con_out } ;
433443 }
434444
435- pub fn stderr_init ( & mut self , mut protocol : helpers:: Protocol < PipeProtocol > ) {
445+ pub fn stderr_init ( & mut self , protocol : helpers:: OwnedProtocol < PipeProtocol > ) {
436446 self . st . standard_error_handle = protocol. handle ( ) . as_ptr ( ) ;
437447 self . st . std_err =
438- protocol. as_mut ( ) as * mut PipeProtocol as * mut simple_text_output:: Protocol ;
448+ protocol. as_ref ( ) as * const PipeProtocol as * mut simple_text_output:: Protocol ;
439449
440450 self . stderr = Some ( protocol) ;
441451 }
@@ -476,6 +486,30 @@ mod uefi_command_internal {
476486
477487 self . args = Some ( args) ;
478488 }
489+
490+ fn update_st_crc32 ( & mut self ) -> io:: Result < ( ) > {
491+ let bt: NonNull < r_efi:: efi:: BootServices > = boot_services ( ) . unwrap ( ) . cast ( ) ;
492+ let st_size = self . st . hdr . header_size as usize ;
493+ let mut crc32: u32 = 0 ;
494+
495+ // Set crc to 0 before calcuation
496+ self . st . hdr . crc32 = 0 ;
497+
498+ let r = unsafe {
499+ ( ( * bt. as_ptr ( ) ) . calculate_crc32 ) (
500+ self . st . as_mut ( ) as * mut r_efi:: efi:: SystemTable as * mut crate :: ffi:: c_void ,
501+ st_size,
502+ & mut crc32,
503+ )
504+ } ;
505+
506+ if r. is_error ( ) {
507+ Err ( io:: Error :: from_raw_os_error ( r. as_usize ( ) ) )
508+ } else {
509+ self . st . hdr . crc32 = crc32;
510+ Ok ( ( ) )
511+ }
512+ }
479513 }
480514
481515 impl Drop for Command {
@@ -501,13 +535,12 @@ mod uefi_command_internal {
501535 set_cursor_position : simple_text_output:: ProtocolSetCursorPosition ,
502536 enable_cursor : simple_text_output:: ProtocolEnableCursor ,
503537 mode : * mut simple_text_output:: Mode ,
504- _mode : Box < simple_text_output:: Mode > ,
505538 _buffer : Vec < u16 > ,
506539 }
507540
508541 impl PipeProtocol {
509542 pub fn new ( ) -> Self {
510- let mut mode = Box :: new ( simple_text_output:: Mode {
543+ let mode = Box :: new ( simple_text_output:: Mode {
511544 max_mode : 0 ,
512545 mode : 0 ,
513546 attribute : 0 ,
@@ -525,14 +558,13 @@ mod uefi_command_internal {
525558 clear_screen : Self :: clear_screen,
526559 set_cursor_position : Self :: set_cursor_position,
527560 enable_cursor : Self :: enable_cursor,
528- mode : mode. as_mut ( ) ,
529- _mode : mode,
561+ mode : Box :: into_raw ( mode) ,
530562 _buffer : Vec :: new ( ) ,
531563 }
532564 }
533565
534566 pub fn null ( ) -> Self {
535- let mut mode = Box :: new ( simple_text_output:: Mode {
567+ let mode = Box :: new ( simple_text_output:: Mode {
536568 max_mode : 0 ,
537569 mode : 0 ,
538570 attribute : 0 ,
@@ -550,8 +582,7 @@ mod uefi_command_internal {
550582 clear_screen : Self :: clear_screen,
551583 set_cursor_position : Self :: set_cursor_position,
552584 enable_cursor : Self :: enable_cursor,
553- mode : mode. as_mut ( ) ,
554- _mode : mode,
585+ mode : Box :: into_raw ( mode) ,
555586 _buffer : Vec :: new ( ) ,
556587 }
557588 }
@@ -660,4 +691,12 @@ mod uefi_command_internal {
660691 r_efi:: efi:: Status :: UNSUPPORTED
661692 }
662693 }
694+
695+ impl Drop for PipeProtocol {
696+ fn drop ( & mut self ) {
697+ unsafe {
698+ let _ = Box :: from_raw ( self . mode ) ;
699+ }
700+ }
701+ }
663702}
0 commit comments