Skip to content

Commit fe6727f

Browse files
committed
uefi: Implementing wrappers for EFI Shell env functions
This commit implements wrappers for the following EFI Shell Protocol functions: set_env() and get_env()
1 parent a86c8d7 commit fe6727f

File tree

1 file changed

+89
-1
lines changed

1 file changed

+89
-1
lines changed

uefi/src/proto/shell/mod.rs

Lines changed: 89 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,100 @@
22

33
//! EFI Shell Protocol v2.2
44
5-
use crate::proto::unsafe_protocol;
5+
#![cfg(feature = "alloc")]
6+
7+
use alloc::vec::Vec;
8+
use uefi_macros::unsafe_protocol;
9+
use uefi_raw::Status;
10+
11+
use core::ptr;
612

713
pub use uefi_raw::protocol::shell::ShellProtocol;
814

15+
use crate::{CStr16, Char16};
16+
917
/// Shell Protocol
1018
#[derive(Debug)]
1119
#[repr(transparent)]
1220
#[unsafe_protocol(uefi_raw::protocol::shell::ShellProtocol::GUID)]
1321
pub struct Shell(uefi_raw::protocol::shell::ShellProtocol);
22+
23+
impl Shell {
24+
/// Gets the environment variable or list of environment variables
25+
///
26+
/// # Arguments
27+
///
28+
/// * `name` - The environment variable name of which to retrieve the
29+
/// value
30+
/// If None, will return all defined shell environment
31+
/// variables
32+
///
33+
/// # Returns
34+
///
35+
/// * `Some(Vec<env_value>)` - Value of the environment variable
36+
/// * `Some(Vec<env_names>)` - Vector of environment variable names
37+
/// * `None` - Environment variable doesn't exist
38+
#[must_use]
39+
pub fn get_env<'a>(&'a self, name: Option<&CStr16>) -> Option<Vec<&'a CStr16>> {
40+
let mut env_vec = Vec::new();
41+
match name {
42+
Some(n) => {
43+
let name_ptr: *const Char16 = core::ptr::from_ref::<CStr16>(n).cast();
44+
let var_val = unsafe { (self.0.get_env)(name_ptr.cast()) };
45+
if var_val.is_null() {
46+
return None;
47+
} else {
48+
unsafe { env_vec.push(CStr16::from_ptr(var_val.cast())) };
49+
}
50+
}
51+
None => {
52+
let cur_env_ptr = unsafe { (self.0.get_env)(ptr::null()) };
53+
54+
let mut cur_start = cur_env_ptr;
55+
let mut cur_len = 0;
56+
57+
let mut i = 0;
58+
let mut null_count = 0;
59+
unsafe {
60+
while null_count <= 1 {
61+
if (*(cur_env_ptr.add(i))) == Char16::from_u16_unchecked(0).into() {
62+
if cur_len > 0 {
63+
env_vec.push(CStr16::from_char16_with_nul_unchecked(
64+
&(*ptr::slice_from_raw_parts(cur_start.cast(), cur_len + 1)),
65+
));
66+
}
67+
cur_len = 0;
68+
null_count += 1;
69+
} else {
70+
if null_count > 0 {
71+
cur_start = cur_env_ptr.add(i);
72+
}
73+
null_count = 0;
74+
cur_len += 1;
75+
}
76+
i += 1;
77+
}
78+
}
79+
}
80+
}
81+
Some(env_vec)
82+
}
83+
84+
/// Sets the environment variable
85+
///
86+
/// # Arguments
87+
///
88+
/// * `name` - The environment variable for which to set the value
89+
/// * `value` - The new value of the environment variable
90+
/// * `volatile` - Indicates whether or not the variable is volatile or
91+
/// not
92+
///
93+
/// # Returns
94+
///
95+
/// * `Status::SUCCESS` The variable was successfully set
96+
pub fn set_env(&self, name: &CStr16, value: &CStr16, volatile: bool) -> Status {
97+
let name_ptr: *const Char16 = core::ptr::from_ref::<CStr16>(name).cast();
98+
let value_ptr: *const Char16 = core::ptr::from_ref::<CStr16>(value).cast();
99+
unsafe { (self.0.set_env)(name_ptr.cast(), value_ptr.cast(), volatile) }
100+
}
101+
}

0 commit comments

Comments
 (0)