Skip to main content

efivar_fix/
lib.rs

1//! efivar is a crate for manipulating EFI variables using the OS interface. This crate is mainly
2//! used by `efivarcli` to implement its functionality.
3//!
4//! On Linux, it is assumed that efivarfs is mounted and available at /sys/firmware/efi/efivars,
5//! which should be the default nowadays on all major distros.
6//!
7//! On Windows, it uses the Get/SetFirmwareEnvironmentVariable family of functions, which require
8//! administrative rights. This also requires adjusting the security token for the current thread
9//! to include SeSystemEnvironmentPrivilege. This is done during the initialization of
10//! SystemManager (see  SystemManager::new() ).
11//!
12//! In-memory and filesystem storage are also provided for testing purposes, or as a way to dump
13//! system variables to an external file.
14
15#![doc(html_root_url = "https://docs.rs/efivar/2.0.0")]
16
17/// EFI constants based on the [UEFI specification](http://www.uefi.org/sites/default/files/resources/UEFI_Spec_2_7.pdf)
18pub mod efi;
19#[cfg(feature = "store")]
20pub mod store;
21
22pub mod boot;
23mod enumerator;
24mod error;
25pub mod push;
26mod reader;
27mod sys;
28pub mod test_utils;
29pub mod utils;
30mod writer;
31
32use boot::{BootVarReader, BootVarWriter};
33
34pub use crate::enumerator::VarEnumerator;
35pub use crate::reader::*;
36pub use crate::writer::VarWriter;
37
38pub use crate::error::Error;
39
40/// Result type for this crate's API functions
41pub type Result<T> = std::result::Result<T, Error>;
42
43/// Represents an EFI variable manager that can read, write and list variables
44pub trait VarManager:
45    VarEnumerator + VarReader + VarWriter + BootVarReader + BootVarWriter
46{
47}
48
49#[derive(Debug, thiserror::Error)]
50pub enum VarManagerInitError {
51    /// System has booted in MBR mode
52    #[error("EFI variables not available (did you boot in BIOS/MBR mode ?)")]
53    EFIVariablesNotAvailable,
54}
55
56use crate::sys::SystemManager;
57/// Returns a `VarManager` that represents the firmware variables of the running system
58///
59/// Reading variables should not require extra permissions, but writing variables will.
60///
61/// ***The returned object will change the values stored in the system's NVRAM. Please be cautious
62/// when using its methods.***
63pub fn system() -> std::result::Result<Box<dyn VarManager>, VarManagerInitError> {
64    SystemManager::new().map(|m| Box::new(m) as Box<dyn VarManager>)
65}
66
67/// Returns a `VarManager` which loads and stores variables to a TOML file. The variable file will
68/// be read when calling this method, and written to when the returned object is dropped.
69///
70/// # Arguments
71///
72/// * `filename`: Path to the TOML file for this variable storage. If the file doesn't exist, it
73///   will be created.
74///
75/// # Examples
76///
77/// ```
78/// # use efivar::file_store;
79/// use efivar::efi::{VariableFlags, Variable};
80/// # {
81/// // Name of the BootOrder variable
82/// let boot_order = Variable::new("BootOrder");
83///
84/// // Create a store from the file doc-test.toml
85/// let mut store = file_store("doc-test.toml");
86/// let value = vec![1, 2, 3, 4];
87/// // Write the value of a variable
88/// store.write(&boot_order, VariableFlags::NON_VOLATILE, &value);
89///
90/// // Check the value of the written variable
91/// let (data, attributes) = store.read(&boot_order).unwrap();
92/// assert_eq!(data, value);
93/// assert_eq!(attributes, VariableFlags::NON_VOLATILE);
94/// // At this point, store is dropped and doc-test.toml will be updated
95/// # }
96/// # std::fs::remove_file("doc-test.toml");
97/// ```
98#[cfg(feature = "store")]
99pub fn file_store<P: Into<std::path::PathBuf>>(filename: P) -> Box<dyn VarManager> {
100    Box::new(store::FileStore::new(filename.into()))
101}
102
103#[cfg(test)]
104mod tests {
105    use super::*;
106    #[test]
107    #[cfg(feature = "store")]
108    fn file_store_roundtrip() {
109        use crate::efi::{Variable, VariableFlags};
110
111        {
112            // Create a store from the file doc-test.toml
113            let mut store = file_store("doc-test.toml");
114            let value = vec![1, 2, 3, 4];
115            // Write the value of a variable
116            store
117                .write(
118                    &Variable::new("BootOrder"),
119                    VariableFlags::NON_VOLATILE,
120                    &value,
121                )
122                .expect("Failed to write value in store");
123
124            // Check the value of the written variable
125            let (data, attributes) = store.read(&Variable::new("BootOrder")).unwrap();
126            assert_eq!(attributes, VariableFlags::NON_VOLATILE);
127            assert_eq!(data, value);
128            // At this point, store is dropped and doc-test.toml will be updated
129        }
130        std::fs::remove_file("doc-test.toml")
131            .expect("Failed to remove temporary file doc-test.toml");
132    }
133}