Skip to content

Commit c1c5bef

Browse files
authored
Unrolled build for #151014
Rollup merge of #151014 - Ayush1325:uefi-cmd-path, r=jhpratt,nicholasbishop std: sys: process: uefi: Add program searching - Follow UEFI Shell search flow to search for programs while launching. - Tested using OVMF on QEMU. @rustbot label +O-UEFI
2 parents ca9a134 + 47bec22 commit c1c5bef

1 file changed

Lines changed: 34 additions & 2 deletions

File tree

library/std/src/sys/process/uefi.rs

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::collections::BTreeMap;
55
pub use crate::ffi::OsString as EnvKey;
66
use crate::ffi::{OsStr, OsString};
77
use crate::num::{NonZero, NonZeroI32};
8-
use crate::path::Path;
8+
use crate::path::{Path, PathBuf};
99
use crate::process::StdioPipes;
1010
use crate::sys::fs::File;
1111
use crate::sys::io::error_string;
@@ -138,7 +138,9 @@ impl Command {
138138
}
139139

140140
pub 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)]
370402
mod uefi_command_internal {
371403
use r_efi::protocols::{loaded_image, simple_text_input, simple_text_output};

0 commit comments

Comments
 (0)