1#![expect(missing_docs)]
7
8pub use uefi_specs::uefi::time::EFI_TIME;
9
10pub mod in_memory;
11
12use guid::Guid;
13#[cfg(feature = "inspect")]
14pub use inspect_ext::InspectableNvramStorage;
15use std::fmt::Debug;
16use thiserror::Error;
17use ucs2::Ucs2LeSlice;
18use ucs2::Ucs2LeVec;
19
20#[derive(Debug, Error)]
21pub enum NvramStorageError {
22 #[error("error deserializing nvram storage")]
23 Deserialize,
24 #[error("error loading data from Nvram storage")]
25 Load(#[source] Box<dyn std::error::Error + Send + Sync>),
26 #[error("error committing data to Nvram storage")]
27 Commit(#[source] Box<dyn std::error::Error + Send + Sync>),
28 #[error("nvram is out of space")]
29 OutOfSpace,
30 #[error("variable name too long")]
31 VariableNameTooLong,
32 #[error("variable data too long")]
33 VariableDataTooLong,
34}
35
36#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
37pub enum NextVariable {
38 InvalidKey,
39 EndOfList,
40 Exists {
41 name: Ucs2LeVec,
42 vendor: Guid,
43 attr: u32,
44 },
45}
46
47#[async_trait::async_trait]
53pub trait NvramStorage: Send + Sync {
54 async fn get_variable(
57 &mut self,
58 name: &Ucs2LeSlice,
59 vendor: Guid,
60 ) -> Result<Option<(u32, Vec<u8>, EFI_TIME)>, NvramStorageError>;
61
62 async fn set_variable(
67 &mut self,
68 name: &Ucs2LeSlice,
69 vendor: Guid,
70 attr: u32,
71 data: Vec<u8>,
72 timestamp: EFI_TIME,
73 ) -> Result<(), NvramStorageError>;
74
75 async fn append_variable(
83 &mut self,
84 name: &Ucs2LeSlice,
85 vendor: Guid,
86 data: Vec<u8>,
87 timestamp: EFI_TIME,
88 ) -> Result<bool, NvramStorageError>;
89
90 async fn remove_variable(
98 &mut self,
99 name: &Ucs2LeSlice,
100 vendor: Guid,
101 ) -> Result<bool, NvramStorageError>;
102
103 async fn next_variable(
107 &mut self,
108 name_vendor: Option<(&Ucs2LeSlice, Guid)>,
109 ) -> Result<NextVariable, NvramStorageError>;
110
111 async fn is_empty(&mut self) -> Result<bool, NvramStorageError> {
113 Ok(matches!(
114 self.next_variable(None).await?,
115 NextVariable::EndOfList
116 ))
117 }
118}
119
120#[async_trait::async_trait]
121impl NvramStorage for Box<dyn NvramStorage> {
122 async fn get_variable(
123 &mut self,
124 name: &Ucs2LeSlice,
125 vendor: Guid,
126 ) -> Result<Option<(u32, Vec<u8>, EFI_TIME)>, NvramStorageError> {
127 (**self).get_variable(name, vendor).await
128 }
129
130 async fn set_variable(
131 &mut self,
132 name: &Ucs2LeSlice,
133 vendor: Guid,
134 attr: u32,
135 data: Vec<u8>,
136 timestamp: EFI_TIME,
137 ) -> Result<(), NvramStorageError> {
138 (**self)
139 .set_variable(name, vendor, attr, data, timestamp)
140 .await
141 }
142
143 async fn append_variable(
144 &mut self,
145 name: &Ucs2LeSlice,
146 vendor: Guid,
147 data: Vec<u8>,
148 timestamp: EFI_TIME,
149 ) -> Result<bool, NvramStorageError> {
150 (**self)
151 .append_variable(name, vendor, data, timestamp)
152 .await
153 }
154
155 async fn remove_variable(
156 &mut self,
157 name: &Ucs2LeSlice,
158 vendor: Guid,
159 ) -> Result<bool, NvramStorageError> {
160 (**self).remove_variable(name, vendor).await
161 }
162
163 async fn next_variable(
164 &mut self,
165 name_vendor: Option<(&Ucs2LeSlice, Guid)>,
166 ) -> Result<NextVariable, NvramStorageError> {
167 (**self).next_variable(name_vendor).await
168 }
169}
170
171#[cfg(feature = "inspect")]
173mod inspect_ext {
174 use super::*;
175 use inspect::Inspect;
176
177 pub trait InspectableNvramStorage: NvramStorage + Inspect {}
179 impl<T: NvramStorage + Inspect> InspectableNvramStorage for T {}
180
181 #[async_trait::async_trait]
182 impl NvramStorage for Box<dyn InspectableNvramStorage> {
183 async fn get_variable(
184 &mut self,
185 name: &Ucs2LeSlice,
186 vendor: Guid,
187 ) -> Result<Option<(u32, Vec<u8>, EFI_TIME)>, NvramStorageError> {
188 (**self).get_variable(name, vendor).await
189 }
190
191 async fn set_variable(
192 &mut self,
193 name: &Ucs2LeSlice,
194 vendor: Guid,
195 attr: u32,
196 data: Vec<u8>,
197 timestamp: EFI_TIME,
198 ) -> Result<(), NvramStorageError> {
199 (**self)
200 .set_variable(name, vendor, attr, data, timestamp)
201 .await
202 }
203
204 async fn append_variable(
205 &mut self,
206 name: &Ucs2LeSlice,
207 vendor: Guid,
208 data: Vec<u8>,
209 timestamp: EFI_TIME,
210 ) -> Result<bool, NvramStorageError> {
211 (**self)
212 .append_variable(name, vendor, data, timestamp)
213 .await
214 }
215
216 async fn remove_variable(
217 &mut self,
218 name: &Ucs2LeSlice,
219 vendor: Guid,
220 ) -> Result<bool, NvramStorageError> {
221 (**self).remove_variable(name, vendor).await
222 }
223
224 async fn next_variable(
225 &mut self,
226 name_vendor: Option<(&Ucs2LeSlice, Guid)>,
227 ) -> Result<NextVariable, NvramStorageError> {
228 (**self).next_variable(name_vendor).await
229 }
230 }
231}