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}