Skip to content

Commit 5a27fb8

Browse files
RenTrieuphip1611
andcommitted
uefi: Splitting get_env() into two separate functions
The UEFI get_env() implementation is used for getting individual environment variable values and also environment variable names. This is not intuitive so this commit splits the function into two dedicated ones: one for accessing values and the other for accessing names. Co-authored-by: Philipp Schuster <phip1611@gmail.com>
1 parent 0f30078 commit 5a27fb8

File tree

2 files changed

+73
-64
lines changed

2 files changed

+73
-64
lines changed

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

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,12 @@ use uefi::proto::shell::Shell;
55
use uefi::{CStr16, boot};
66
use uefi_raw::Status;
77

8-
/// Test ``get_env()`` and ``set_env()``
8+
/// Test ``get_env()``, ``get_envs()``, and ``set_env()``
99
pub fn test_env(shell: &ScopedProtocol<Shell>) {
1010
let mut test_buf = [0u16; 128];
1111

12-
/* Test retrieving list of environment variable names (null input) */
13-
let cur_env_vec = shell
14-
.get_env(None)
15-
.expect("Could not get environment variable");
12+
/* Test retrieving list of environment variable names */
13+
let cur_env_vec = shell.get_envs();
1614
assert_eq!(
1715
*cur_env_vec.first().unwrap(),
1816
CStr16::from_str_with_buf("path", &mut test_buf).unwrap()
@@ -21,27 +19,35 @@ pub fn test_env(shell: &ScopedProtocol<Shell>) {
2119
*cur_env_vec.get(1).unwrap(),
2220
CStr16::from_str_with_buf("nonesting", &mut test_buf).unwrap()
2321
);
22+
let default_len = cur_env_vec.len();
2423

2524
/* Test setting and getting a specific environment variable */
2625
let mut test_env_buf = [0u16; 32];
2726
let test_var = CStr16::from_str_with_buf("test_var", &mut test_env_buf).unwrap();
2827
let mut test_val_buf = [0u16; 32];
2928
let test_val = CStr16::from_str_with_buf("test_val", &mut test_val_buf).unwrap();
30-
assert!(shell.get_env(Some(test_var)).is_none());
29+
assert!(shell.get_env(test_var).is_none());
3130
let status = shell.set_env(test_var, test_val, false);
3231
assert_eq!(status, Status::SUCCESS);
33-
let cur_env_str = *shell
34-
.get_env(Some(test_var))
35-
.expect("Could not get environment variable")
36-
.first()
37-
.unwrap();
32+
let cur_env_str = shell
33+
.get_env(test_var)
34+
.expect("Could not get environment variable");
3835
assert_eq!(cur_env_str, test_val);
3936

37+
assert!(!cur_env_vec.contains(&test_var));
38+
let cur_env_vec = shell.get_envs();
39+
assert!(cur_env_vec.contains(&test_var));
40+
assert_eq!(cur_env_vec.len(), default_len + 1);
41+
4042
/* Test deleting environment variable */
4143
let test_val = CStr16::from_str_with_buf("", &mut test_val_buf).unwrap();
4244
let status = shell.set_env(test_var, test_val, false);
4345
assert_eq!(status, Status::SUCCESS);
44-
assert!(shell.get_env(Some(test_var)).is_none());
46+
assert!(shell.get_env(test_var).is_none());
47+
48+
let cur_env_vec = shell.get_envs();
49+
assert!(!cur_env_vec.contains(&test_var));
50+
assert_eq!(cur_env_vec.len(), default_len);
4551
}
4652

4753
/// Test ``get_cur_dir()`` and ``set_cur_dir()``

uefi/src/proto/shell/mod.rs

Lines changed: 55 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -10,75 +10,76 @@ use uefi_raw::Status;
1010

1111
use core::ptr;
1212

13-
pub use uefi_raw::protocol::shell::ShellProtocol;
13+
use uefi_raw::protocol::shell::ShellProtocol;
1414

1515
use crate::{CStr16, Char16};
1616

1717
/// Shell Protocol
1818
#[derive(Debug)]
1919
#[repr(transparent)]
20-
#[unsafe_protocol(uefi_raw::protocol::shell::ShellProtocol::GUID)]
21-
pub struct Shell(uefi_raw::protocol::shell::ShellProtocol);
20+
#[unsafe_protocol(ShellProtocol::GUID)]
21+
pub struct Shell(ShellProtocol);
2222

2323
impl Shell {
24-
/// Gets the environment variable or list of environment variables
24+
/// Gets the value of the specified environment variable
2525
///
2626
/// # Arguments
2727
///
2828
/// * `name` - The environment variable name of which to retrieve the
29-
/// value
30-
/// If None, will return all defined shell environment
31-
/// variables
29+
/// value.
3230
///
3331
/// # Returns
3432
///
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
33+
/// * `Some(<env_value>)` - &CStr16 containing the value of the
34+
/// environment variable
35+
/// * `None` - If environment variable does not exist
3836
#[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()) };
37+
pub fn get_env(&self, name: &CStr16) -> Option<&CStr16> {
38+
let name_ptr: *const Char16 = core::ptr::from_ref::<CStr16>(name).cast();
39+
let var_val = unsafe { (self.0.get_env)(name_ptr.cast()) };
40+
if var_val.is_null() {
41+
None
42+
} else {
43+
unsafe { Some(CStr16::from_ptr(var_val.cast())) }
44+
}
45+
}
5346

54-
let mut cur_start = cur_env_ptr;
55-
let mut cur_len = 0;
47+
/// Gets the list of environment variables
48+
///
49+
/// # Returns
50+
///
51+
/// * `Vec<env_names>` - Vector of environment variable names
52+
#[must_use]
53+
pub fn get_envs(&self) -> Vec<&CStr16> {
54+
let mut env_vec: Vec<&CStr16> = Vec::new();
55+
let cur_env_ptr = unsafe { (self.0.get_env)(ptr::null()) };
56+
57+
let mut cur_start = cur_env_ptr;
58+
let mut cur_len = 0;
5659

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;
60+
let mut i = 0;
61+
let mut null_count = 0;
62+
unsafe {
63+
while null_count <= 1 {
64+
if (*(cur_env_ptr.add(i))) == Char16::from_u16_unchecked(0).into() {
65+
if cur_len > 0 {
66+
env_vec.push(CStr16::from_char16_with_nul(
67+
&(*ptr::slice_from_raw_parts(cur_start.cast(), cur_len + 1)),
68+
).unwrap());
7769
}
70+
cur_len = 0;
71+
null_count += 1;
72+
} else {
73+
if null_count > 0 {
74+
cur_start = cur_env_ptr.add(i);
75+
}
76+
null_count = 0;
77+
cur_len += 1;
7878
}
79+
i += 1;
7980
}
8081
}
81-
Some(env_vec)
82+
env_vec
8283
}
8384

8485
/// Sets the environment variable
@@ -87,12 +88,12 @@ impl Shell {
8788
///
8889
/// * `name` - The environment variable for which to set the value
8990
/// * `value` - The new value of the environment variable
90-
/// * `volatile` - Indicates whether or not the variable is volatile or
91+
/// * `volatile` - Indicates whether the variable is volatile or
9192
/// not
9293
///
9394
/// # Returns
9495
///
95-
/// * `Status::SUCCESS` The variable was successfully set
96+
/// * `Status::SUCCESS` - The variable was successfully set
9697
pub fn set_env(&self, name: &CStr16, value: &CStr16, volatile: bool) -> Status {
9798
let name_ptr: *const Char16 = core::ptr::from_ref::<CStr16>(name).cast();
9899
let value_ptr: *const Char16 = core::ptr::from_ref::<CStr16>(value).cast();
@@ -105,12 +106,13 @@ impl Shell {
105106
///
106107
/// * `file_system_mapping` - The file system mapping for which to get
107108
/// the current directory
109+
///
108110
/// # Returns
109111
///
110112
/// * `Some(cwd)` - CStr16 containing the current working directory
111113
/// * `None` - Could not retrieve current directory
112114
#[must_use]
113-
pub fn get_cur_dir<'a>(&'a self, file_system_mapping: Option<&CStr16>) -> Option<&'a CStr16> {
115+
pub fn get_cur_dir(&self, file_system_mapping: Option<&CStr16>) -> Option<&CStr16> {
114116
let mapping_ptr: *const Char16 = file_system_mapping.map_or(ptr::null(), |x| (x.as_ptr()));
115117
let cur_dir = unsafe { (self.0.get_cur_dir)(mapping_ptr.cast()) };
116118
if cur_dir.is_null() {
@@ -127,13 +129,14 @@ impl Shell {
127129
/// * `file_system` - Pointer to the file system's mapped name.
128130
/// * `directory` - Points to the directory on the device specified by
129131
/// `file_system`.
132+
///
130133
/// # Returns
131134
///
132-
/// * `Status::SUCCESS` The directory was successfully set
135+
/// * `Status::SUCCESS` - The directory was successfully set
133136
///
134137
/// # Errors
135138
///
136-
/// * `Status::EFI_NOT_FOUND` The directory does not exist
139+
/// * `Status::EFI_NOT_FOUND` - The directory does not exist
137140
pub fn set_cur_dir(&self, file_system: Option<&CStr16>, directory: Option<&CStr16>) -> Status {
138141
let fs_ptr: *const Char16 = file_system.map_or(ptr::null(), |x| (x.as_ptr()));
139142
let dir_ptr: *const Char16 = directory.map_or(ptr::null(), |x| (x.as_ptr()));

0 commit comments

Comments
 (0)