Skip to content

Commit 647067d

Browse files
committed
Implemented get_env() shell function
1 parent ef218c1 commit 647067d

File tree

2 files changed

+106
-16
lines changed

2 files changed

+106
-16
lines changed

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

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,49 @@
11
use uefi::boot;
2-
use uefi::proto::shell::Shell;
2+
use uefi::proto::shell::{Shell, ShellFileHandle};
33
use uefi::CStr16;
44

55
pub fn test() {
66
info!("Running shell protocol tests");
77

88
let handle = boot::get_handle_for_protocol::<Shell>().expect("No Shell handles");
9+
// let mut fs = uefi::fs::FileSystem::new(sfs
10+
// let (fs_handle, mut sfs) = find_test_disk();
911

1012
let mut shell =
1113
boot::open_protocol_exclusive::<Shell>(handle).expect("Failed to open Shell protocol");
1214

1315
// create some files
1416
let mut test_buf = [0u16; 12];
1517
let test_str = CStr16::from_str_with_buf("test", &mut test_buf).unwrap();
16-
shell.create_file(test_str, 0);
18+
19+
let cur_env_str = shell.get_env(None).expect("Could not get environment variable");
20+
info!("cur_env_str size: {}", cur_env_str.num_chars());
21+
info!("cur_env_str: {}", cur_env_str);
22+
// for (i, c) in cur_env_str.iter().enumerate() {
23+
// info!("cur_env_str: i: {}, c: {}", i, c);
24+
// }
25+
26+
// let mut cur_fs_buf = [0u16; 32];
27+
// let cur_fs_str = CStr16::from_str_with_buf("", &mut cur_fs_buf).unwrap();
28+
// info!("cur_fs_str size 1: {}", cur_fs_str.num_chars());
29+
let cur_fs_str = shell.get_cur_dir(None).expect("Could not get the current file system mapping");
30+
info!("cur_fs_str size: {}", cur_fs_str.num_chars());
31+
info!("cur_fs_str: {}", cur_fs_str);
32+
// for (i, c) in cur_fs_str.iter().enumerate() {
33+
// info!("cur_fs_str: i: {}, c: {}", i, c);
34+
// }
35+
36+
// unsafe {
37+
// info!("cur_fs_str: {}", cur_fs_str);
38+
// let mut expected_fs_str_buf = [0u16; 32];
39+
// assert_eq!(cur_fs_str, CStr16::from_str_with_buf("", &mut expected_fs_str_buf).unwrap());
40+
// //
41+
// Create a file
42+
// let status = shell.create_file(test_str, 0).expect("Could not create file");
43+
// let mut size: u64 = 0;
44+
// shell.get_file_size(f_handle, &mut size);
45+
// assert_eq!(size, 0);
46+
// }
1747

1848
// get file tree
1949
// let mut str_buf = [0u16; 12];

uefi/src/proto/shell/mod.rs

Lines changed: 74 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! EFI Shell Protocol v2.2
22
3-
use core::{ffi::c_void, marker::PhantomData, mem::MaybeUninit, ptr::NonNull};
3+
use core::{ffi::c_void, marker::PhantomData, mem::MaybeUninit, ptr};
44

55
use uefi_macros::unsafe_protocol;
66

@@ -18,7 +18,9 @@ pub struct Shell {
1818
environment: *const *const CStr16,
1919
out_status: *mut Status,
2020
) -> Status,
21-
get_env: usize,
21+
get_env: extern "efiapi" fn(
22+
name: *const Char16,
23+
) -> *const Char16,
2224
set_env: usize,
2325
get_alias: usize,
2426
set_alias: usize,
@@ -29,7 +31,7 @@ pub struct Shell {
2931
get_file_path_from_device_path: usize,
3032
set_map: usize,
3133

32-
get_cur_dir: extern "efiapi" fn(file_system_mapping: *const Char16) -> *const CStr16,
34+
get_cur_dir: extern "efiapi" fn(file_system_mapping: *const Char16) -> *const Char16,
3335
set_cur_dir: usize,
3436
open_file_list: usize,
3537
free_file_list: extern "efiapi" fn(file_list: *mut *mut ShellFileInfo),
@@ -49,7 +51,7 @@ pub struct Shell {
4951
create_file: extern "efiapi" fn(
5052
file_name: &CStr16,
5153
file_attribs: u64,
52-
out_file_handle: *mut ShellFileHandle,
54+
out_file_handle: ShellFileHandle,
5355
) -> Status,
5456
read_file: usize,
5557
write_file: usize,
@@ -66,7 +68,10 @@ pub struct Shell {
6668
file_dir_handle: ShellFileHandle,
6769
out_file_list: *mut *mut ShellFileInfo,
6870
) -> Status,
69-
get_file_size: usize,
71+
get_file_size: extern "efiapi" fn(
72+
file_handle: ShellFileHandle,
73+
size: *mut u64
74+
) -> Status,
7075

7176
open_root: usize,
7277
open_root_by_handle: usize,
@@ -109,6 +114,29 @@ impl Shell {
109114
.to_result_with_val(|| unsafe { out_status.assume_init() })
110115
}
111116

117+
/// Gets the environment variable or list of environment variables
118+
///
119+
/// # Arguments
120+
///
121+
/// * `name` - The environment variable name of which to retrieve the
122+
/// value
123+
/// If None, will return all defined shell environment
124+
/// variables
125+
///
126+
/// # Returns
127+
///
128+
/// * `Some(env_value)` - Value of the environment variable
129+
/// * `None` - Environment variable doesn't exist
130+
pub fn get_env<'a>(&'a self, name: Option<&CStr16>) -> Option<&'a CStr16> {
131+
let name_ptr: *const Char16 = name.map_or(core::ptr::null(), |x| (x as *const CStr16).cast());
132+
let var_val = (self.get_env)(name_ptr);
133+
if var_val.is_null() {
134+
None
135+
} else {
136+
unsafe { Some(CStr16::from_ptr(var_val)) }
137+
}
138+
}
139+
112140
/// TODO
113141
#[must_use]
114142
pub fn get_cur_dir<'a>(&'a self, file_system_mapping: Option<&CStr16>) -> Option<&'a CStr16> {
@@ -118,7 +146,7 @@ impl Shell {
118146
if cur_dir.is_null() {
119147
None
120148
} else {
121-
unsafe { Some(&*cur_dir) }
149+
unsafe { Some(CStr16::from_ptr(cur_dir)) }
122150
}
123151
}
124152

@@ -146,20 +174,30 @@ impl Shell {
146174
(self.close_file)(file_handle).to_result()
147175
}
148176

149-
/// TODO
177+
/// Creates a file or directory by name
178+
///
179+
/// # Arguments
180+
///
181+
/// * `file_name` - Name of the file to be created (null terminated)
182+
/// * `file_attribs` - Attributes of the new file
183+
/// * `file_handle` - On return, points to the created file/directory's
184+
/// handle
150185
pub fn create_file(
151186
&self,
152187
file_name: &CStr16,
153188
file_attribs: u64,
154-
) -> Result<Option<ShellFileHandle>> {
189+
) -> Result<ShellFileHandle> {
155190
// TODO: Find out how we could take a &str instead, or maybe AsRef<str>, though I think it needs `alloc`
156191
// the returned handle can possibly be NULL, so we need to wrap `ShellFileHandle` in an `Option`
157-
let mut out_file_handle: MaybeUninit<Option<ShellFileHandle>> = MaybeUninit::zeroed();
192+
//let mut out_file_handle: MaybeUninit<Option<ShellFileHandle>> = MaybeUninit::zeroed();
193+
// let mut file_handle: ShellFileHandle;
194+
let file_handle = ptr::null();
158195

159-
(self.create_file)(file_name, file_attribs, out_file_handle.as_mut_ptr().cast())
196+
(self.create_file)(file_name, file_attribs, file_handle)
197+
.to_result_with_val(|| file_handle )
160198
// Safety: if this call is successful, `out_file_handle`
161199
// will always be initialized and valid.
162-
.to_result_with_val(|| unsafe { out_file_handle.assume_init() })
200+
// .to_result_with_val(|| unsafe { out_file_handle.assume_init() })
163201
}
164202

165203
/// TODO
@@ -233,12 +271,34 @@ impl Shell {
233271
pub fn flush_file(&self, file_handle: ShellFileHandle) -> Result<()> {
234272
(self.flush_file)(file_handle).to_result()
235273
}
274+
275+
/// Gets the size of a file
276+
///
277+
/// # Arguments
278+
///
279+
/// * `file_handle` - Handle to the file of which the size will be retrieved
280+
/// * `size` - Pointer to u64 to read into
281+
///
282+
/// # Errors
283+
///
284+
/// * [`STATUS::EFI_DEVICE_ERROR] The file could not be accessed
285+
pub fn get_file_size(&self, file_handle: ShellFileHandle, size: *mut u64) -> Result<()> {
286+
(self.get_file_size)(file_handle, size).to_result()
287+
}
236288
}
237289

238290
/// TODO
239-
#[repr(transparent)]
240-
#[derive(Debug)]
241-
pub struct ShellFileHandle(NonNull<c_void>);
291+
// #[repr(transparent)]
292+
// #[derive(Debug)]
293+
pub type ShellFileHandle = *const c_void;
294+
// pub struct ShellFileHandle(c_void);
295+
//
296+
// impl ShellFileHandle {
297+
// /// Creates a new ShellFileHandle from a given c_void pointer
298+
// pub const unsafe fn new(ptr: c_void) -> Self {
299+
// Self(ptr)
300+
// }
301+
// }
242302

243303
/// TODO
244304
#[repr(C)]

0 commit comments

Comments
 (0)