Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 116701e

Browse files
committed
uefi: Modifying Vars to return environment variable values in addition to names
1 parent 7a5b955 commit 116701e

File tree

2 files changed

+75
-21
lines changed

2 files changed

+75
-21
lines changed

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ use uefi::proto::shell::Shell;
55
use uefi::{boot, cstr16};
66

77
/// Test `var()`, `vars()`, and `set_var()`
8-
pub fn test_env(shell: &ScopedProtocol<Shell>) {
8+
pub fn test_var(shell: &ScopedProtocol<Shell>) {
99
/* Test retrieving list of environment variable names */
1010
let mut cur_env_vec = shell.vars();
11-
assert_eq!(cur_env_vec.next().unwrap(), cstr16!("path"),);
11+
assert_eq!(cur_env_vec.next().unwrap().0, cstr16!("path"));
1212
// check pre-defined shell variables; see UEFI Shell spec
13-
assert_eq!(cur_env_vec.next().unwrap(), cstr16!("nonesting"),);
13+
assert_eq!(cur_env_vec.next().unwrap().0, cstr16!("nonesting"));
1414
let cur_env_vec = shell.vars();
1515
let default_len = cur_env_vec.count();
1616

@@ -27,15 +27,15 @@ pub fn test_env(shell: &ScopedProtocol<Shell>) {
2727
assert_eq!(cur_env_str, test_val);
2828

2929
let mut found_var = false;
30-
for env_var in cur_env_vec {
30+
for (env_var, _) in cur_env_vec {
3131
if env_var == test_var {
3232
found_var = true;
3333
}
3434
}
3535
assert!(!found_var);
3636
let cur_env_vec = shell.vars();
3737
let mut found_var = false;
38-
for env_var in cur_env_vec {
38+
for (env_var, _) in cur_env_vec {
3939
if env_var == test_var {
4040
found_var = true;
4141
}
@@ -53,7 +53,7 @@ pub fn test_env(shell: &ScopedProtocol<Shell>) {
5353

5454
let cur_env_vec = shell.vars();
5555
let mut found_var = false;
56-
for env_var in cur_env_vec {
56+
for (env_var, _) in cur_env_vec {
5757
if env_var == test_var {
5858
found_var = true;
5959
}
@@ -71,5 +71,5 @@ pub fn test() {
7171
let shell =
7272
boot::open_protocol_exclusive::<Shell>(handle).expect("Failed to open Shell protocol");
7373

74-
test_env(&shell);
74+
test_var(&shell);
7575
}

‎uefi/src/proto/shell/mod.rs

Lines changed: 68 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,30 +17,45 @@ use crate::{CStr16, Char16, Result, StatusExt};
1717
#[unsafe_protocol(ShellProtocol::GUID)]
1818
pub struct Shell(ShellProtocol);
1919

20+
/// Trait for implementing the var function
21+
pub trait ShellVar {
22+
/// Gets the value of the specified environment variable
23+
fn var(&self, name: &CStr16) -> Option<&CStr16>;
24+
}
25+
2026
/// Iterator over the names of environmental variables obtained from the Shell protocol.
2127
#[derive(Debug)]
22-
pub struct Vars<'a> {
28+
pub struct Vars<'a,T:ShellVar> {
2329
/// Char16 containing names of environment variables
24-
inner: *const Char16,
30+
names: *const Char16,
31+
/// Reference to Shell Protocol
32+
protocol: *const T,
2533
/// Placeholder to attach a lifetime to `Vars`
2634
placeholder: PhantomData<&'a CStr16>,
2735
}
2836

29-
impl<'a> Iterator for Vars<'a> {
30-
type Item = &'a CStr16;
37+
impl<'a,T:ShellVar + 'a> Iterator for Vars<'a,T> {
38+
type Item = (&'a CStr16,Option<&'aCStr16>);
3139
// We iterate a list of NUL terminated CStr16s.
3240
// The list is terminated with a double NUL.
3341
fn next(&mut self) -> Option<Self::Item> {
34-
let s = unsafe { CStr16::from_ptr(self.inner) };
42+
let s = unsafe { CStr16::from_ptr(self.names) };
3543
if s.is_empty() {
3644
None
3745
} else {
38-
self.inner = unsafe { self.inner.add(s.num_chars() + 1) };
39-
Some(s)
46+
self.names = unsafe { self.names.add(s.num_chars() + 1) };
47+
Some((s,unsafe{self.protocol.as_ref().unwrap().var(s)}))
4048
}
4149
}
4250
}
4351

52+
impl ShellVar for Shell {
53+
/// Gets the value of the specified environment variable
54+
fn var(&self, name: &CStr16) -> Option<&CStr16> {
55+
self.var(name)
56+
}
57+
}
58+
4459
impl Shell {
4560
/// Gets the value of the specified environment variable
4661
///
@@ -67,10 +82,11 @@ impl Shell {
6782

6883
/// Gets an iterator over the names of all environment variables
6984
#[must_use]
70-
pub fn vars(&self) -> Vars<'_> {
85+
pub fn vars(&self) -> Vars<'_,Self> {
7186
let env_ptr = unsafe { (self.0.get_env)(ptr::null()) };
7287
Vars {
73-
inner: env_ptr.cast::<Char16>(),
88+
names: env_ptr.cast::<Char16>(),
89+
protocol: self,
7490
placeholder: PhantomData,
7591
}
7692
}
@@ -97,9 +113,33 @@ impl Shell {
97113
#[cfg(test)]
98114
mod tests {
99115
use super::*;
116+
use alloc::collections::BTreeMap;
100117
use alloc::vec::Vec;
101118
use uefi::cstr16;
102119

120+
struct ShellMock<'a> {
121+
inner: BTreeMap<&'a CStr16, &'a CStr16>,
122+
}
123+
124+
impl<'a> ShellMock<'a> {
125+
fn new(names: Vec<&'a CStr16>, values: Vec<&'a CStr16>) -> ShellMock<'a> {
126+
let mut inner_map = BTreeMap::new();
127+
for (name, val) in names.iter().zip(values.iter()) {
128+
inner_map.insert(*name, *val);
129+
}
130+
ShellMock { inner: inner_map }
131+
}
132+
}
133+
impl<'a> ShellVar for ShellMock<'a> {
134+
fn var(&self, name: &CStr16) -> Option<&CStr16> {
135+
if let Some(val) = self.inner.get(name) {
136+
Some(*val)
137+
} else {
138+
None
139+
}
140+
}
141+
}
142+
103143
/// Testing Vars struct
104144
#[test]
105145
fn test_vars() {
@@ -108,9 +148,11 @@ mod tests {
108148
vars_mock.push(0);
109149
vars_mock.push(0);
110150
let mut vars = Vars {
111-
inner: vars_mock.as_ptr().cast(),
151+
names: vars_mock.as_ptr().cast(),
152+
protocol: &ShellMock::new(Vec::new(), Vec::new()),
112153
placeholder: PhantomData,
113154
};
155+
114156
assert!(vars.next().is_none());
115157

116158
// One environment variable in Vars
@@ -121,10 +163,14 @@ mod tests {
121163
vars_mock.push(0);
122164
vars_mock.push(0);
123165
let vars = Vars {
124-
inner: vars_mock.as_ptr().cast(),
166+
names: vars_mock.as_ptr().cast(),
167+
protocol: &ShellMock::new(Vec::from([cstr16!("foo")]), Vec::from([cstr16!("value")])),
125168
placeholder: PhantomData,
126169
};
127-
assert_eq!(vars.collect::<Vec<_>>(), Vec::from([cstr16!("foo")]));
170+
assert_eq!(
171+
vars.collect::<Vec<_>>(),
172+
Vec::from([(cstr16!("foo"), Some(cstr16!("value")))])
173+
);
128174

129175
// Multiple environment variables in Vars
130176
let mut vars_mock = Vec::<u16>::new();
@@ -145,12 +191,20 @@ mod tests {
145191
vars_mock.push(0);
146192

147193
let vars = Vars {
148-
inner: vars_mock.as_ptr().cast(),
194+
names: vars_mock.as_ptr().cast(),
195+
protocol: &ShellMock::new(
196+
Vec::from([cstr16!("foo1"), cstr16!("bar"), cstr16!("baz2")]),
197+
Vec::from([cstr16!("value"), cstr16!("one"), cstr16!("two")]),
198+
),
149199
placeholder: PhantomData,
150200
};
151201
assert_eq!(
152202
vars.collect::<Vec<_>>(),
153-
Vec::from([cstr16!("foo1"), cstr16!("bar"), cstr16!("baz2")])
203+
Vec::from([
204+
(cstr16!("foo1"), Some(cstr16!("value"))),
205+
(cstr16!("bar"), Some(cstr16!("one"))),
206+
(cstr16!("baz2"), Some(cstr16!("two")))
207+
])
154208
);
155209
}
156210
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /