Skip to content

Commit eb33785

Browse files
Merge pull request #772 from FrameworkComputer/shell-params
Add ShellParams protocol
2 parents f845933 + 2c9185b commit eb33785

File tree

9 files changed

+147
-1
lines changed

9 files changed

+147
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
- Added `core::error::Error` implementations to all error types.
2020
- `SystemTable::exit_boot_services` now takes one param `memory_type` to ensure
2121
the memory type of memory map.
22+
- Added the `ShellParams` protocol
2223

2324
### Removed
2425
- `BootServices::memmove` and `BootServices::set_mem` have been removed, use

uefi-raw/src/protocol/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ pub mod driver;
1212
pub mod loaded_image;
1313
pub mod memory_protection;
1414
pub mod rng;
15+
pub mod shell_params;

uefi-raw/src/protocol/shell_params.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
use crate::{guid, Char16, Guid};
2+
use core::ffi::c_void;
3+
4+
pub type ShellFileHandle = *const c_void;
5+
6+
#[derive(Debug)]
7+
#[repr(C)]
8+
pub struct ShellParametersProtocol {
9+
/// Pointer to a list of arguments.
10+
pub argv: *const *const Char16,
11+
/// Number of arguments.
12+
pub argc: usize,
13+
/// Handle of the standard input.
14+
pub std_in: ShellFileHandle,
15+
/// Handle of the standard output.
16+
pub std_out: ShellFileHandle,
17+
/// Handle of the standard error output.
18+
pub std_err: ShellFileHandle,
19+
}
20+
21+
impl ShellParametersProtocol {
22+
pub const GUID: Guid = guid!("752f3136-4e16-4fdc-a22a-e5f46812f4ca");
23+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// ANCHOR: all
2+
// ANCHOR: features
3+
#![no_main]
4+
#![no_std]
5+
// ANCHOR_END: features
6+
7+
use log::error;
8+
// ANCHOR: use
9+
use uefi::{prelude::*, proto::shell_params::ShellParameters};
10+
use uefi_services::println;
11+
12+
extern crate alloc;
13+
use alloc::string::{String, ToString};
14+
use alloc::vec::Vec;
15+
// ANCHOR_END: use
16+
17+
// ANCHOR: entry
18+
#[entry]
19+
fn main(image_handle: Handle, mut system_table: SystemTable<Boot>) -> Status {
20+
// ANCHOR_END: entry
21+
// ANCHOR: services
22+
uefi_services::init(&mut system_table).unwrap();
23+
let boot_services = system_table.boot_services();
24+
// ANCHOR_END: services
25+
26+
// ANCHOR: params
27+
let shell_params =
28+
boot_services.open_protocol_exclusive::<ShellParameters>(image_handle);
29+
let shell_params = match shell_params {
30+
Ok(s) => s,
31+
Err(e) => {
32+
error!("Failed to get ShellParameters protocol");
33+
return e.status();
34+
}
35+
};
36+
37+
// Get as Vec of String, only with alloc feature
38+
let args: Vec<String> =
39+
shell_params.args().map(|x| x.to_string()).collect();
40+
println!("Args: {:?}", args);
41+
42+
// Or without allocating, get a slice of the pointers
43+
println!("Num args: {}", args.len());
44+
if shell_params.args_len() > 1 {
45+
println!("First real arg: '{}'", args[1]);
46+
}
47+
// ANCHOR_END: params
48+
49+
// ANCHOR: return
50+
Status::SUCCESS
51+
}
52+
// ANCHOR_END: return
53+
// ANCHOR_END: all

uefi-test-runner/src/bin/shell_launcher.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ fn efi_main(image: Handle, mut st: SystemTable<Boot>) -> Status {
6969
let mut shell_loaded_image = boot_services
7070
.open_protocol_exclusive::<LoadedImage>(shell_image_handle)
7171
.expect("failed to open LoadedImage protocol");
72-
let load_options = cstr16!(r"shell.efi test_runner.efi");
72+
let load_options = cstr16!(r"shell.efi test_runner.efi arg1 arg2");
7373
unsafe {
7474
shell_loaded_image.set_load_options(
7575
load_options.as_ptr().cast(),

uefi-test-runner/src/proto/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ pub fn test(image: Handle, st: &mut SystemTable<Boot>) {
2020
network::test(bt);
2121
pi::test(bt);
2222
rng::test(bt);
23+
shell_params::test(bt);
2324
string::test(bt);
2425

2526
#[cfg(any(
@@ -63,6 +64,7 @@ mod media;
6364
mod network;
6465
mod pi;
6566
mod rng;
67+
mod shell_params;
6668
#[cfg(any(
6769
target_arch = "x86",
6870
target_arch = "x86_64",
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
use uefi::proto::shell_params::ShellParameters;
2+
use uefi::table::boot::BootServices;
3+
4+
use alloc::string::ToString;
5+
use alloc::vec::Vec;
6+
7+
pub fn test(bt: &BootServices) {
8+
info!("Running loaded image protocol test");
9+
10+
let image = bt
11+
.get_handle_for_protocol::<ShellParameters>()
12+
.expect("No ShellParameters handles");
13+
let shell_params = bt
14+
.open_protocol_exclusive::<ShellParameters>(image)
15+
.expect("Failed to open ShellParameters protocol");
16+
17+
assert_eq!(shell_params.args_len(), 4);
18+
assert_eq!(
19+
shell_params
20+
.args()
21+
.map(|x| x.to_string())
22+
.collect::<Vec<_>>(),
23+
&["shell.efi", "test_runner.efi", "arg1", "arg2"]
24+
);
25+
}

uefi/src/proto/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ pub mod network;
7676
pub mod pi;
7777
pub mod rng;
7878
pub mod security;
79+
pub mod shell_params;
7980
pub mod shim;
8081
pub mod string;
8182
pub mod tcg;

uefi/src/proto/shell_params.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//! `ShellParams` protocol
2+
3+
use crate::proto::unsafe_protocol;
4+
use crate::{data_types, Char16};
5+
use core::slice::from_raw_parts;
6+
use uefi_raw::protocol::shell_params::ShellParametersProtocol;
7+
8+
use crate::CStr16;
9+
10+
/// The ShellParameters protocol.
11+
#[derive(Debug)]
12+
#[repr(transparent)]
13+
#[unsafe_protocol(ShellParametersProtocol::GUID)]
14+
pub struct ShellParameters(ShellParametersProtocol);
15+
16+
impl ShellParameters {
17+
/// Get the number of shell parameter arguments
18+
#[must_use]
19+
pub fn args_len(&self) -> usize {
20+
self.0.argc
21+
}
22+
23+
/// Get an iterator of the shell parameter arguments
24+
pub fn args(&self) -> impl Iterator<Item = &CStr16> {
25+
self.args_slice()
26+
.iter()
27+
.map(|x| unsafe { CStr16::from_ptr(*x) })
28+
}
29+
30+
/// Get a slice of the args, as Char16 pointers
31+
#[must_use]
32+
fn args_slice(&self) -> &[*const Char16] {
33+
unsafe {
34+
from_raw_parts(
35+
self.0.argv.cast::<*const data_types::chars::Char16>(),
36+
self.0.argc,
37+
)
38+
}
39+
}
40+
}

0 commit comments

Comments
 (0)