@@ -5,7 +5,7 @@ use crate::collections::BTreeMap;
55pub use crate :: ffi:: OsString as EnvKey ;
66use crate :: ffi:: { OsStr , OsString } ;
77use crate :: num:: { NonZero , NonZeroI32 } ;
8- use crate :: path:: Path ;
8+ use crate :: path:: { Path , PathBuf } ;
99use crate :: process:: StdioPipes ;
1010use crate :: sys:: fs:: File ;
1111use crate :: sys:: io:: error_string;
@@ -138,7 +138,9 @@ impl Command {
138138}
139139
140140pub fn output ( command : & mut Command ) -> io:: Result < ( ExitStatus , Vec < u8 > , Vec < u8 > ) > {
141- let mut cmd = uefi_command_internal:: Image :: load_image ( & command. prog ) ?;
141+ let prog_path = resolve_program ( & command. prog )
142+ . ok_or ( io:: const_error!( io:: ErrorKind :: NotFound , "could not find the program." ) ) ?;
143+ let mut cmd = uefi_command_internal:: Image :: load_image ( prog_path. as_os_str ( ) ) ?;
142144
143145 // UEFI adds the bin name by default
144146 if !command. args . is_empty ( ) {
@@ -366,6 +368,36 @@ pub fn read_output(
366368 match out. diverge ( ) { }
367369}
368370
371+ // Search for programs similar to UEFI Shell defined in Section 3.6.1. It follows the following flow:
372+ // 1. If program is already absolute path, just check if it exists.
373+ // 2. For non-absolute path, search relative to current directory.
374+ // 3. Search the path list sequentially.
375+ //
376+ // [UEFI Shell Specification](https://uefi.org/sites/default/files/resources/UEFI_Shell_2_2.pdf).
377+ fn resolve_program < S : AsRef < OsStr > + ?Sized > ( prog : & S ) -> Option < PathBuf > {
378+ let absolute_prog_path = crate :: path:: absolute ( prog. as_ref ( ) ) . ok ( ) ?;
379+
380+ match crate :: fs:: exists ( & absolute_prog_path) {
381+ Ok ( true ) => return Some ( absolute_prog_path) ,
382+ // If program path was already absolute and is not found, then stop.
383+ Ok ( false ) if Path :: new ( prog. as_ref ( ) ) . is_absolute ( ) => return None ,
384+ _ => { }
385+ }
386+
387+ // Search for the program in path.
388+ if let Ok ( path_var) = crate :: env:: var ( "path" ) {
389+ for p in crate :: env:: split_paths ( & path_var) {
390+ let temp = p. join ( prog. as_ref ( ) ) ;
391+
392+ if let Ok ( true ) = crate :: fs:: exists ( & temp) {
393+ return Some ( temp) ;
394+ }
395+ }
396+ }
397+
398+ None
399+ }
400+
369401#[ allow( dead_code) ]
370402mod uefi_command_internal {
371403 use r_efi:: protocols:: { loaded_image, simple_text_input, simple_text_output} ;
0 commit comments