@@ -18,6 +18,7 @@ use crate::{fmt, io};
1818#[ derive( Debug ) ]
1919pub struct Command {
2020 prog : OsString ,
21+ args : Vec < OsString > ,
2122 stdout : Option < Stdio > ,
2223 stderr : Option < Stdio > ,
2324}
@@ -39,12 +40,11 @@ pub enum Stdio {
3940
4041impl Command {
4142 pub fn new ( program : & OsStr ) -> Command {
42- Command { prog : program. to_os_string ( ) , stdout : None , stderr : None }
43+ Command { prog : program. to_os_string ( ) , args : Vec :: new ( ) , stdout : None , stderr : None }
4344 }
4445
45- // FIXME: Implement arguments as reverse of parsing algorithm
46- pub fn arg ( & mut self , _arg : & OsStr ) {
47- panic ! ( "unsupported" )
46+ pub fn arg ( & mut self , arg : & OsStr ) {
47+ self . args . push ( arg. to_os_string ( ) ) ;
4848 }
4949
5050 pub fn env_mut ( & mut self ) -> & mut CommandEnv {
@@ -72,7 +72,7 @@ impl Command {
7272 }
7373
7474 pub fn get_args ( & self ) -> CommandArgs < ' _ > {
75- panic ! ( "unsupported" )
75+ CommandArgs { iter : self . args . iter ( ) }
7676 }
7777
7878 pub fn get_envs ( & self ) -> CommandEnvs < ' _ > {
@@ -116,6 +116,12 @@ impl Command {
116116 pub fn output ( & mut self ) -> io:: Result < ( ExitStatus , Vec < u8 > , Vec < u8 > ) > {
117117 let mut cmd = uefi_command_internal:: Image :: load_image ( & self . prog ) ?;
118118
119+ // UEFI adds the bin name by default
120+ if !self . args . is_empty ( ) {
121+ let args = uefi_command_internal:: create_args ( & self . prog , & self . args ) ;
122+ cmd. set_args ( args) ;
123+ }
124+
119125 // Setup Stdout
120126 let stdout = self . stdout . unwrap_or ( Stdio :: MakePipe ) ;
121127 let stdout = Self :: create_pipe ( stdout) ?;
@@ -315,7 +321,7 @@ mod uefi_command_internal {
315321 stdout : Option < helpers:: OwnedProtocol < PipeProtocol > > ,
316322 stderr : Option < helpers:: OwnedProtocol < PipeProtocol > > ,
317323 st : OwnedTable < r_efi:: efi:: SystemTable > ,
318- args : Option < Vec < u16 > > ,
324+ args : Option < ( * mut u16 , usize ) > ,
319325 }
320326
321327 impl Image {
@@ -449,20 +455,22 @@ mod uefi_command_internal {
449455 }
450456 }
451457
452- pub fn set_args ( & mut self , args : & OsStr ) {
458+ pub fn set_args ( & mut self , mut args : Box < [ u16 ] > ) {
453459 let loaded_image: NonNull < loaded_image:: Protocol > =
454460 helpers:: open_protocol ( self . handle , loaded_image:: PROTOCOL_GUID ) . unwrap ( ) ;
455461
456- let mut args = args. encode_wide ( ) . collect :: < Vec < u16 > > ( ) ;
457- let args_size = ( crate :: mem:: size_of :: < u16 > ( ) * args. len ( ) ) as u32 ;
462+ let len = args. len ( ) ;
463+ let ptr = args. as_mut_ptr ( ) ;
464+ crate :: mem:: forget ( args) ;
465+
466+ let args_size = ( crate :: mem:: size_of :: < u16 > ( ) * len) as u32 ;
458467
459468 unsafe {
460- ( * loaded_image. as_ptr ( ) ) . load_options =
461- args. as_mut_ptr ( ) as * mut crate :: ffi:: c_void ;
469+ ( * loaded_image. as_ptr ( ) ) . load_options = ptr as * mut crate :: ffi:: c_void ;
462470 ( * loaded_image. as_ptr ( ) ) . load_options_size = args_size;
463471 }
464472
465- self . args = Some ( args ) ;
473+ self . args = Some ( ( ptr , len ) ) ;
466474 }
467475
468476 fn update_st_crc32 ( & mut self ) -> io:: Result < ( ) > {
@@ -502,6 +510,10 @@ mod uefi_command_internal {
502510 ( ( * bt. as_ptr ( ) ) . unload_image ) ( self . handle . as_ptr ( ) ) ;
503511 }
504512 }
513+
514+ if let Some ( ( ptr, len) ) = self . args {
515+ let _ = unsafe { Box :: from_raw ( crate :: slice:: from_raw_parts_mut ( ptr, len) ) } ;
516+ }
505517 }
506518 }
507519
@@ -681,4 +693,36 @@ mod uefi_command_internal {
681693 }
682694 }
683695 }
696+
697+ pub fn create_args ( prog : & OsStr , args : & [ OsString ] ) -> Box < [ u16 ] > {
698+ const QUOTE : u16 = 0x0022 ;
699+ const SPACE : u16 = 0x0020 ;
700+ const CARET : u16 = 0x005e ;
701+ const NULL : u16 = 0 ;
702+
703+ let mut res = Vec :: new ( ) ;
704+
705+ // Wrap program name in quotes to avoid any problems
706+ res. push ( QUOTE ) ;
707+ res. extend ( prog. encode_wide ( ) ) ;
708+ res. push ( QUOTE ) ;
709+ res. push ( SPACE ) ;
710+
711+ for arg in args {
712+ // Wrap the argument in quotes to be treat as single arg
713+ res. push ( QUOTE ) ;
714+ for c in arg. encode_wide ( ) {
715+ // CARET in quotes is used to escape CARET or QUOTE
716+ if c == QUOTE || c == CARET {
717+ res. push ( CARET ) ;
718+ }
719+ res. push ( c) ;
720+ }
721+ res. push ( QUOTE ) ;
722+
723+ res. push ( SPACE ) ;
724+ }
725+
726+ res. into_boxed_slice ( )
727+ }
684728}
0 commit comments