@@ -18,6 +18,7 @@ use crate::{fmt, io};
18
18
#[ derive( Debug ) ]
19
19
pub struct Command {
20
20
prog : OsString ,
21
+ args : Vec < OsString > ,
21
22
stdout : Option < Stdio > ,
22
23
stderr : Option < Stdio > ,
23
24
}
@@ -39,12 +40,11 @@ pub enum Stdio {
39
40
40
41
impl Command {
41
42
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 }
43
44
}
44
45
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 ( ) ) ;
48
48
}
49
49
50
50
pub fn env_mut ( & mut self ) -> & mut CommandEnv {
@@ -72,7 +72,7 @@ impl Command {
72
72
}
73
73
74
74
pub fn get_args ( & self ) -> CommandArgs < ' _ > {
75
- panic ! ( "unsupported" )
75
+ CommandArgs { iter : self . args . iter ( ) }
76
76
}
77
77
78
78
pub fn get_envs ( & self ) -> CommandEnvs < ' _ > {
@@ -116,6 +116,12 @@ impl Command {
116
116
pub fn output ( & mut self ) -> io:: Result < ( ExitStatus , Vec < u8 > , Vec < u8 > ) > {
117
117
let mut cmd = uefi_command_internal:: Image :: load_image ( & self . prog ) ?;
118
118
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
+
119
125
// Setup Stdout
120
126
let stdout = self . stdout . unwrap_or ( Stdio :: MakePipe ) ;
121
127
let stdout = Self :: create_pipe ( stdout) ?;
@@ -315,7 +321,7 @@ mod uefi_command_internal {
315
321
stdout : Option < helpers:: OwnedProtocol < PipeProtocol > > ,
316
322
stderr : Option < helpers:: OwnedProtocol < PipeProtocol > > ,
317
323
st : OwnedTable < r_efi:: efi:: SystemTable > ,
318
- args : Option < Vec < u16 > > ,
324
+ args : Option < ( * mut u16 , usize ) > ,
319
325
}
320
326
321
327
impl Image {
@@ -449,20 +455,20 @@ mod uefi_command_internal {
449
455
}
450
456
}
451
457
452
- pub fn set_args ( & mut self , args : & OsStr ) {
458
+ pub fn set_args ( & mut self , args : Box < [ u16 ] > ) {
453
459
let loaded_image: NonNull < loaded_image:: Protocol > =
454
460
helpers:: open_protocol ( self . handle , loaded_image:: PROTOCOL_GUID ) . unwrap ( ) ;
455
461
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 args_size: u32 = crate :: mem:: size_of_val ( & args) . try_into ( ) . unwrap ( ) ;
464
+ let ptr = Box :: into_raw ( args) . as_mut_ptr ( ) ;
458
465
459
466
unsafe {
460
- ( * loaded_image. as_ptr ( ) ) . load_options =
461
- args. as_mut_ptr ( ) as * mut crate :: ffi:: c_void ;
467
+ ( * loaded_image. as_ptr ( ) ) . load_options = ptr as * mut crate :: ffi:: c_void ;
462
468
( * loaded_image. as_ptr ( ) ) . load_options_size = args_size;
463
469
}
464
470
465
- self . args = Some ( args ) ;
471
+ self . args = Some ( ( ptr , len ) ) ;
466
472
}
467
473
468
474
fn update_st_crc32 ( & mut self ) -> io:: Result < ( ) > {
@@ -502,6 +508,10 @@ mod uefi_command_internal {
502
508
( ( * bt. as_ptr ( ) ) . unload_image ) ( self . handle . as_ptr ( ) ) ;
503
509
}
504
510
}
511
+
512
+ if let Some ( ( ptr, len) ) = self . args {
513
+ let _ = unsafe { Box :: from_raw ( crate :: ptr:: slice_from_raw_parts_mut ( ptr, len) ) } ;
514
+ }
505
515
}
506
516
}
507
517
@@ -681,4 +691,38 @@ mod uefi_command_internal {
681
691
}
682
692
}
683
693
}
694
+
695
+ pub fn create_args ( prog : & OsStr , args : & [ OsString ] ) -> Box < [ u16 ] > {
696
+ const QUOTE : u16 = 0x0022 ;
697
+ const SPACE : u16 = 0x0020 ;
698
+ const CARET : u16 = 0x005e ;
699
+ const NULL : u16 = 0 ;
700
+
701
+ // This is the lower bound on the final length under the assumption that
702
+ // the arguments only contain ASCII characters.
703
+ let mut res = Vec :: with_capacity ( args. iter ( ) . map ( |arg| arg. len ( ) + 3 ) . sum ( ) ) ;
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
+ }
684
728
}
0 commit comments