Skip to content

Commit 6547011

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 90c5ba4 commit 6547011

File tree

2 files changed

+80
-0
lines changed

2 files changed

+80
-0
lines changed

uefi/src/proto/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ pub mod rng;
5151
#[cfg(feature = "alloc")]
5252
pub mod scsi;
5353
pub mod security;
54+
#[cfg(feature = "alloc")]
5455
pub mod shell;
5556
pub mod shell_params;
5657
pub mod shim;

uefi/src/proto/shell/mod.rs

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use crate::proto::unsafe_protocol;
66
use crate::{CStr16, Char16, Error, Result, Status, StatusExt};
77
use core::ptr;
88
use uefi_raw::protocol::shell::ShellProtocol;
9+
use alloc::vec::Vec;
910

1011
/// Shell Protocol
1112
#[derive(Debug)]
@@ -54,4 +55,82 @@ impl Shell {
5455
let dir_ptr: *const Char16 = directory.map_or(ptr::null(), |x| x.as_ptr());
5556
unsafe { (self.0.set_cur_dir)(fs_ptr.cast(), dir_ptr.cast()) }.to_result()
5657
}
58+
59+
/// Gets the environment variable or list of environment variables
60+
///
61+
/// # Arguments
62+
///
63+
/// * `name` - The environment variable name of which to retrieve the
64+
/// value
65+
/// If None, will return all defined shell environment
66+
/// variables
67+
///
68+
/// # Returns
69+
///
70+
/// * `Some(Vec<env_value>)` - Value of the environment variable
71+
/// * `Some(Vec<env_names>)` - Vector of environment variable names
72+
/// * `None` - Environment variable doesn't exist
73+
#[must_use]
74+
pub fn get_env<'a>(&'a self, name: Option<&CStr16>) -> Option<Vec<&'a CStr16>> {
75+
let mut env_vec = Vec::new();
76+
match name {
77+
Some(n) => {
78+
let name_ptr: *const Char16 = core::ptr::from_ref::<CStr16>(n).cast();
79+
let var_val = unsafe { (self.0.get_env)(name_ptr.cast()) };
80+
if var_val.is_null() {
81+
return None;
82+
} else {
83+
unsafe { env_vec.push(CStr16::from_ptr(var_val.cast())) };
84+
}
85+
}
86+
None => {
87+
let cur_env_ptr = unsafe { (self.0.get_env)(ptr::null()) };
88+
89+
let mut cur_start = cur_env_ptr;
90+
let mut cur_len = 0;
91+
92+
let mut i = 0;
93+
let mut null_count = 0;
94+
unsafe {
95+
while null_count <= 1 {
96+
if (*(cur_env_ptr.add(i))) == Char16::from_u16_unchecked(0).into() {
97+
if cur_len > 0 {
98+
env_vec.push(CStr16::from_char16_with_nul_unchecked(
99+
&(*ptr::slice_from_raw_parts(cur_start.cast(), cur_len + 1)),
100+
));
101+
}
102+
cur_len = 0;
103+
null_count += 1;
104+
} else {
105+
if null_count > 0 {
106+
cur_start = cur_env_ptr.add(i);
107+
}
108+
null_count = 0;
109+
cur_len += 1;
110+
}
111+
i += 1;
112+
}
113+
}
114+
}
115+
}
116+
Some(env_vec)
117+
}
118+
119+
/// Sets the environment variable
120+
///
121+
/// # Arguments
122+
///
123+
/// * `name` - The environment variable for which to set the value
124+
/// * `value` - The new value of the environment variable
125+
/// * `volatile` - Indicates whether or not the variable is volatile or
126+
/// not
127+
///
128+
/// # Returns
129+
///
130+
/// * `Status::SUCCESS` The variable was successfully set
131+
pub fn set_env(&self, name: &CStr16, value: &CStr16, volatile: bool) -> Status {
132+
let name_ptr: *const Char16 = core::ptr::from_ref::<CStr16>(name).cast();
133+
let value_ptr: *const Char16 = core::ptr::from_ref::<CStr16>(value).cast();
134+
unsafe { (self.0.set_env)(name_ptr.cast(), value_ptr.cast(), volatile) }
135+
}
57136
}

0 commit comments

Comments
 (0)