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 fd136bb

Browse files
committed
uefi: Modifying Vars to return environment variable values in addition to names
1 parent 3e9bff8 commit fd136bb

File tree

2 files changed

+73
-19
lines changed

2 files changed

+73
-19
lines changed

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ use uefi::{boot, cstr16};
88
pub fn test_env(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
}

‎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
}
@@ -144,9 +160,33 @@ impl Shell {
144160
#[cfg(test)]
145161
mod tests {
146162
use super::*;
163+
use alloc::collections::BTreeMap;
147164
use alloc::vec::Vec;
148165
use uefi::cstr16;
149166

167+
struct ShellMock<'a> {
168+
inner: BTreeMap<&'a CStr16, &'a CStr16>,
169+
}
170+
171+
impl<'a> ShellMock<'a> {
172+
fn new(names: Vec<&'a CStr16>, values: Vec<&'a CStr16>) -> ShellMock<'a> {
173+
let mut inner_map = BTreeMap::new();
174+
for (name, val) in names.iter().zip(values.iter()) {
175+
inner_map.insert(*name, *val);
176+
}
177+
ShellMock { inner: inner_map }
178+
}
179+
}
180+
impl<'a> ShellVar for ShellMock<'a> {
181+
fn var(&self, name: &CStr16) -> Option<&CStr16> {
182+
if let Some(val) = self.inner.get(name) {
183+
Some(*val)
184+
} else {
185+
None
186+
}
187+
}
188+
}
189+
150190
/// Testing Vars struct
151191
#[test]
152192
fn test_vars() {
@@ -155,9 +195,11 @@ mod tests {
155195
vars_mock.push(0);
156196
vars_mock.push(0);
157197
let mut vars = Vars {
158-
inner: vars_mock.as_ptr().cast(),
198+
names: vars_mock.as_ptr().cast(),
199+
protocol: &ShellMock::new(Vec::new(), Vec::new()),
159200
placeholder: PhantomData,
160201
};
202+
161203
assert!(vars.next().is_none());
162204

163205
// One environment variable in Vars
@@ -168,10 +210,14 @@ mod tests {
168210
vars_mock.push(0);
169211
vars_mock.push(0);
170212
let vars = Vars {
171-
inner: vars_mock.as_ptr().cast(),
213+
names: vars_mock.as_ptr().cast(),
214+
protocol: &ShellMock::new(Vec::from([cstr16!("foo")]), Vec::from([cstr16!("value")])),
172215
placeholder: PhantomData,
173216
};
174-
assert_eq!(vars.collect::<Vec<_>>(), Vec::from([cstr16!("foo")]));
217+
assert_eq!(
218+
vars.collect::<Vec<_>>(),
219+
Vec::from([(cstr16!("foo"), Some(cstr16!("value")))])
220+
);
175221

176222
// Multiple environment variables in Vars
177223
let mut vars_mock = Vec::<u16>::new();
@@ -192,12 +238,20 @@ mod tests {
192238
vars_mock.push(0);
193239

194240
let vars = Vars {
195-
inner: vars_mock.as_ptr().cast(),
241+
names: vars_mock.as_ptr().cast(),
242+
protocol: &ShellMock::new(
243+
Vec::from([cstr16!("foo1"), cstr16!("bar"), cstr16!("baz2")]),
244+
Vec::from([cstr16!("value"), cstr16!("one"), cstr16!("two")]),
245+
),
196246
placeholder: PhantomData,
197247
};
198248
assert_eq!(
199249
vars.collect::<Vec<_>>(),
200-
Vec::from([cstr16!("foo1"), cstr16!("bar"), cstr16!("baz2")])
250+
Vec::from([
251+
(cstr16!("foo1"), Some(cstr16!("value"))),
252+
(cstr16!("bar"), Some(cstr16!("one"))),
253+
(cstr16!("baz2"), Some(cstr16!("two")))
254+
])
201255
);
202256
}
203257
}

0 commit comments

Comments
(0)

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