Skip to content

Commit a288116

Browse files
Merge pull request #1740 from RenTrieu/enhancement/efi_shell_interface_cur_dir
EFI Shell Interface: CurDir Functions
2 parents 51fc706 + 18953be commit a288116

File tree

2 files changed

+149
-6
lines changed

2 files changed

+149
-6
lines changed

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

Lines changed: 101 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,112 @@
11
// SPDX-License-Identifier: MIT OR Apache-2.0
22

3-
use uefi::boot;
3+
use uefi::boot::ScopedProtocol;
44
use uefi::proto::shell::Shell;
5+
use uefi::{Error, Status, boot, cstr16};
6+
7+
/// Test `current_dir()` and `set_current_dir()`
8+
pub fn test_current_dir(shell: &ScopedProtocol<Shell>) {
9+
/* Test setting and getting current file system and current directory */
10+
let fs_var = cstr16!("fs0:");
11+
let dir_var = cstr16!("/");
12+
let status = shell.set_current_dir(Some(fs_var), Some(dir_var));
13+
assert!(status.is_ok());
14+
15+
let cur_fs_str = shell
16+
.current_dir(Some(fs_var))
17+
.expect("Could not get the current file system mapping");
18+
let expected_fs_str = cstr16!("FS0:\\");
19+
assert_eq!(cur_fs_str, expected_fs_str);
20+
21+
// Changing current file system
22+
let fs_var = cstr16!("fs1:");
23+
let dir_var = cstr16!("/");
24+
let status = shell.set_current_dir(Some(fs_var), Some(dir_var));
25+
assert!(status.is_ok());
26+
27+
let cur_fs_str = shell
28+
.current_dir(Some(fs_var))
29+
.expect("Could not get the current file system mapping");
30+
assert_ne!(cur_fs_str, expected_fs_str);
31+
let expected_fs_str = cstr16!("FS1:\\");
32+
assert_eq!(cur_fs_str, expected_fs_str);
33+
34+
// Changing current file system and current directory
35+
let fs_var = cstr16!("fs0:");
36+
let dir_var = cstr16!("efi/");
37+
let status = shell.set_current_dir(Some(fs_var), Some(dir_var));
38+
assert!(status.is_ok());
39+
40+
let cur_fs_str = shell
41+
.current_dir(Some(fs_var))
42+
.expect("Could not get the current file system mapping");
43+
assert_ne!(cur_fs_str, expected_fs_str);
44+
let expected_fs_str = cstr16!("FS0:\\efi");
45+
assert_eq!(cur_fs_str, expected_fs_str);
46+
47+
/* Test current working directory cases */
48+
49+
// At this point, the current working file system has not been set
50+
// So we expect a NULL output
51+
assert!(shell.current_dir(None).is_err());
52+
assert_eq!(
53+
shell.current_dir(None).err().unwrap(),
54+
Error::new(Status::NOT_FOUND, ())
55+
);
56+
57+
// Setting the current working file system and current working directory
58+
let dir_var = cstr16!("fs0:/");
59+
let status = shell.set_current_dir(None, Some(dir_var));
60+
assert!(status.is_ok());
61+
let cur_fs_str = shell
62+
.current_dir(Some(fs_var))
63+
.expect("Could not get the current file system mapping");
64+
let expected_fs_str = cstr16!("FS0:");
65+
assert_eq!(cur_fs_str, expected_fs_str);
66+
67+
let cur_fs_str = shell
68+
.current_dir(None)
69+
.expect("Could not get the current file system mapping");
70+
assert_eq!(cur_fs_str, expected_fs_str);
71+
72+
// Changing current working directory
73+
let dir_var = cstr16!("/efi");
74+
let status = shell.set_current_dir(None, Some(dir_var));
75+
assert!(status.is_ok());
76+
let cur_fs_str = shell
77+
.current_dir(Some(fs_var))
78+
.expect("Could not get the current file system mapping");
79+
let expected_fs_str = cstr16!("FS0:\\efi");
80+
assert_eq!(cur_fs_str, expected_fs_str);
81+
let cur_fs_str = shell
82+
.current_dir(None)
83+
.expect("Could not get the current file system mapping");
84+
assert_eq!(cur_fs_str, expected_fs_str);
85+
86+
// Changing current directory in a non-current working file system
87+
let fs_var = cstr16!("fs0:");
88+
let dir_var = cstr16!("efi/tools");
89+
let status = shell.set_current_dir(Some(fs_var), Some(dir_var));
90+
assert!(status.is_ok());
91+
let cur_fs_str = shell
92+
.current_dir(None)
93+
.expect("Could not get the current file system mapping");
94+
assert_ne!(cur_fs_str, expected_fs_str);
95+
96+
let expected_fs_str = cstr16!("FS0:\\efi\\tools");
97+
let cur_fs_str = shell
98+
.current_dir(Some(fs_var))
99+
.expect("Could not get the current file system mapping");
100+
assert_eq!(cur_fs_str, expected_fs_str);
101+
}
5102

6103
pub fn test() {
7104
info!("Running shell protocol tests");
8105

9106
let handle = boot::get_handle_for_protocol::<Shell>().expect("No Shell handles");
10107

11-
let mut _shell =
108+
let shell =
12109
boot::open_protocol_exclusive::<Shell>(handle).expect("Failed to open Shell protocol");
110+
111+
test_current_dir(&shell);
13112
}

uefi/src/proto/shell/mod.rs

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,55 @@
33
//! EFI Shell Protocol v2.2
44
55
use crate::proto::unsafe_protocol;
6-
7-
pub use uefi_raw::protocol::shell::ShellProtocol;
6+
use crate::{CStr16, Char16, Error, Result, Status, StatusExt};
7+
use core::ptr;
8+
use uefi_raw::protocol::shell::ShellProtocol;
89

910
/// Shell Protocol
1011
#[derive(Debug)]
1112
#[repr(transparent)]
12-
#[unsafe_protocol(uefi_raw::protocol::shell::ShellProtocol::GUID)]
13-
pub struct Shell(uefi_raw::protocol::shell::ShellProtocol);
13+
#[unsafe_protocol(ShellProtocol::GUID)]
14+
pub struct Shell(ShellProtocol);
15+
16+
impl Shell {
17+
/// Returns the current directory on the specified device.
18+
///
19+
/// # Arguments
20+
///
21+
/// * `file_system_mapping` - The file system mapping for which to get
22+
/// the current directory
23+
///
24+
/// # Errors
25+
///
26+
/// * [`Status::NOT_FOUND`] - Could not retrieve current directory
27+
pub fn current_dir(&self, file_system_mapping: Option<&CStr16>) -> Result<&CStr16> {
28+
let mapping_ptr: *const Char16 = file_system_mapping.map_or(ptr::null(), CStr16::as_ptr);
29+
let cur_dir = unsafe { (self.0.get_cur_dir)(mapping_ptr.cast()) };
30+
if cur_dir.is_null() {
31+
Err(Error::new(Status::NOT_FOUND, ()))
32+
} else {
33+
unsafe { Ok(CStr16::from_ptr(cur_dir.cast())) }
34+
}
35+
}
36+
37+
/// Changes the current directory on the specified device
38+
///
39+
/// # Arguments
40+
///
41+
/// * `file_system` - File system's mapped name.
42+
/// * `directory` - Directory on the device specified by
43+
/// `file_system`.
44+
///
45+
/// # Errors
46+
///
47+
/// * [`Status::NOT_FOUND`] - The directory does not exist
48+
pub fn set_current_dir(
49+
&self,
50+
file_system: Option<&CStr16>,
51+
directory: Option<&CStr16>,
52+
) -> Result {
53+
let fs_ptr: *const Char16 = file_system.map_or(ptr::null(), |x| x.as_ptr());
54+
let dir_ptr: *const Char16 = directory.map_or(ptr::null(), |x| x.as_ptr());
55+
unsafe { (self.0.set_cur_dir)(fs_ptr.cast(), dir_ptr.cast()) }.to_result()
56+
}
57+
}

0 commit comments

Comments
 (0)