Skip to content

Commit 302d82c

Browse files
authored
Merge pull request #1392 from rust-osdev/bishop-var-exists
uefi: Add uefi::runtime::variable_exists
2 parents 9090f9e + 4e513f0 commit 302d82c

File tree

3 files changed

+47
-0
lines changed

3 files changed

+47
-0
lines changed

uefi-test-runner/src/runtime/vars.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,13 @@ fn test_variables(rt: &RuntimeServices) {
7373

7474
/// Test the variable functions in `uefi::runtime`.
7575
fn test_variables_freestanding() {
76+
assert!(!runtime::variable_exists(NAME, VENDOR).unwrap());
77+
7678
// Create the test variable.
7779
runtime::set_variable(NAME, VENDOR, ATTRS, VALUE).expect("failed to set variable");
7880

81+
assert!(runtime::variable_exists(NAME, VENDOR).unwrap());
82+
7983
// Test `get_variable` with too small of a buffer.
8084
let mut buf = [0u8; 0];
8185
assert_eq!(
@@ -106,6 +110,7 @@ fn test_variables_freestanding() {
106110

107111
// Delete the variable and verify it can no longer be read.
108112
runtime::delete_variable(NAME, VENDOR).expect("failed to delete variable");
113+
assert!(!runtime::variable_exists(NAME, VENDOR).unwrap());
109114
assert_eq!(
110115
runtime::get_variable(NAME, VENDOR, &mut buf)
111116
.unwrap_err()

uefi/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ how to integrate the `uefi` crate into them.
1111
- Added `Handle::new`.
1212
- Added the `uefi::boot`, `uefi::runtime`, and `uefi::system` modules to the
1313
prelude.
14+
- Added `runtime::variable_exists`.
1415

1516
## Changed
1617
- The `BootServices`, `RuntimeServices`, and `SystemTable` structs have been

uefi/src/runtime.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,47 @@ pub unsafe fn set_time(time: &Time) -> Result {
7272
(rt.set_time)(time.cast()).to_result()
7373
}
7474

75+
/// Checks if a variable exists.
76+
///
77+
/// Returns `Ok(true)` if the variable exists, `Ok(false)` if the variable does
78+
/// not exist, or `Err` if the existence of the variable could not be determined.
79+
///
80+
/// # Errors
81+
///
82+
/// * [`Status::DEVICE_ERROR`]: variable could not be read due to a hardware error.
83+
/// * [`Status::SECURITY_VIOLATION`]: variable could not be read due to an
84+
/// authentication error.
85+
/// * [`Status::UNSUPPORTED`]: this platform does not support variable storage
86+
/// after exiting boot services.
87+
pub fn variable_exists(name: &CStr16, vendor: &VariableVendor) -> Result<bool> {
88+
let rt = runtime_services_raw_panicking();
89+
let rt = unsafe { rt.as_ref() };
90+
91+
let attributes = ptr::null_mut();
92+
let data = ptr::null_mut();
93+
let mut data_size = 0;
94+
95+
let status = unsafe {
96+
(rt.get_variable)(
97+
name.as_ptr().cast(),
98+
&vendor.0,
99+
attributes,
100+
&mut data_size,
101+
data,
102+
)
103+
};
104+
105+
match status {
106+
// If the variable exists, the status will be BUFFER_TOO_SMALL because
107+
// data_size is 0. Empty variables do not exist, because setting a
108+
// variable with empty data deletes the variable. In other words, the
109+
// status will never be SUCCESS.
110+
Status::BUFFER_TOO_SMALL => Ok(true),
111+
Status::NOT_FOUND => Ok(false),
112+
_ => Err(Error::from(status)),
113+
}
114+
}
115+
75116
/// Gets the contents and attributes of a variable. The size of `buf` must be at
76117
/// least as big as the variable's size, although it can be larger.
77118
///

0 commit comments

Comments
 (0)