1
1
//! UEFI services available at runtime, even after the OS boots.
2
2
3
3
use super :: Header ;
4
+ use crate :: result:: Error ;
4
5
use crate :: table:: boot:: MemoryDescriptor ;
5
- use crate :: { Result , Status } ;
6
+ use crate :: { CStr16 , Char16 , Guid , Result , Status } ;
6
7
use bitflags:: bitflags;
7
8
use core:: fmt;
8
9
use core:: mem:: MaybeUninit ;
@@ -26,7 +27,27 @@ pub struct RuntimeServices {
26
27
desc_version : u32 ,
27
28
virtual_map : * mut MemoryDescriptor ,
28
29
) -> Status ,
29
- _pad2 : [ usize ; 5 ] ,
30
+ _pad2 : usize ,
31
+ get_variable : unsafe extern "efiapi" fn (
32
+ variable_name : * const Char16 ,
33
+ vendor_guid : * const Guid ,
34
+ attributes : * mut VariableAttributes ,
35
+ data_size : * mut usize ,
36
+ data : * mut u8 ,
37
+ ) -> Status ,
38
+ get_next_variable_name : unsafe extern "efiapi" fn (
39
+ variable_name_size : * mut usize ,
40
+ variable_name : * mut u16 ,
41
+ vendor_guid : * mut Guid ,
42
+ ) -> Status ,
43
+ set_variable : unsafe extern "efiapi" fn (
44
+ variable_name : * const Char16 ,
45
+ vendor_guid : * const Guid ,
46
+ attributes : VariableAttributes ,
47
+ data_size : usize ,
48
+ data : * const u8 ,
49
+ ) -> Status ,
50
+ _pad3 : usize ,
30
51
reset : unsafe extern "efiapi" fn (
31
52
rt : ResetType ,
32
53
@@ -82,6 +103,68 @@ impl RuntimeServices {
82
103
( self . set_virtual_address_map ) ( map_size, entry_size, entry_version, map_ptr) . into ( )
83
104
}
84
105
106
+ /// Get the size (in bytes) of a variable. This can be used to find out how
107
+ /// big of a buffer should be passed in to `get_variable`.
108
+ pub fn get_variable_size ( & self , name : & CStr16 , vendor : & Guid ) -> Result < usize > {
109
+ let mut data_size = 0 ;
110
+ let status = unsafe {
111
+ ( self . get_variable ) (
112
+ name. as_ptr ( ) ,
113
+ vendor,
114
+ ptr:: null_mut ( ) ,
115
+ & mut data_size,
116
+ ptr:: null_mut ( ) ,
117
+ )
118
+ } ;
119
+
120
+ if status == Status :: BUFFER_TOO_SMALL {
121
+ Status :: SUCCESS . into_with_val ( || data_size)
122
+ } else {
123
+ Err ( Error :: from ( status) )
124
+ }
125
+ }
126
+
127
+ /// Get the contents and attributes of a variable. The size of `buf` must
128
+ /// be at least as big as the variable's size, although it can be
129
+ /// larger. If it is too small, `BUFFER_TOO_SMALL` is returned.
130
+ ///
131
+ /// On success, a tuple containing the variable's value (a slice of `buf`)
132
+ /// and the variable's attributes is returned.
133
+ pub fn get_variable < ' a > (
134
+ & self ,
135
+ name : & CStr16 ,
136
+ vendor : & Guid ,
137
+ buf : & ' a mut [ u8 ] ,
138
+ ) -> Result < ( & ' a [ u8 ] , VariableAttributes ) > {
139
+ let mut attributes = VariableAttributes :: empty ( ) ;
140
+ let mut data_size = buf. len ( ) ;
141
+ unsafe {
142
+ ( self . get_variable ) (
143
+ name. as_ptr ( ) ,
144
+ vendor,
145
+ & mut attributes,
146
+ & mut data_size,
147
+ buf. as_mut_ptr ( ) ,
148
+ )
149
+ . into_with_val ( move || ( & buf[ ..data_size] , attributes) )
150
+ }
151
+ }
152
+
153
+ /// Set the value of a variable. This can be used to create a new variable,
154
+ /// update an existing variable, or (when the size of `data` is zero)
155
+ /// delete a variable.
156
+ pub fn set_variable (
157
+ & self ,
158
+ name : & CStr16 ,
159
+ vendor : & Guid ,
160
+ attributes : VariableAttributes ,
161
+ data : & [ u8 ] ,
162
+ ) -> Result {
163
+ unsafe {
164
+ ( self . set_variable ) ( name. as_ptr ( ) , vendor, attributes, data. len ( ) , data. as_ptr ( ) ) . into ( )
165
+ }
166
+ }
167
+
85
168
/// Resets the computer.
86
169
pub fn reset ( & self , rt : ResetType , status : Status , data : Option < & [ u8 ] > ) -> ! {
87
170
let ( size, data) = match data {
@@ -245,6 +328,52 @@ pub struct TimeCapabilities {
245
328
pub sets_to_zero : bool ,
246
329
}
247
330
331
+ bitflags ! {
332
+ /// Flags describing the attributes of a variable.
333
+ pub struct VariableAttributes : u32 {
334
+ /// Variable is maintained across a power cycle.
335
+ const NON_VOLATILE = 0x01 ;
336
+
337
+ /// Variable is accessible during the time that boot services are
338
+ /// accessible.
339
+ const BOOTSERVICE_ACCESS = 0x02 ;
340
+
341
+ /// Variable is accessible during the time that runtime services are
342
+ /// accessible.
343
+ const RUNTIME_ACCESS = 0x04 ;
344
+
345
+ /// Variable is stored in the portion of NVR allocated for error
346
+ /// records.
347
+ const HARDWARE_ERROR_RECORD = 0x08 ;
348
+
349
+ /// Deprecated.
350
+ const AUTHENTICATED_WRITE_ACCESS = 0x10 ;
351
+
352
+ /// Variable payload begins with an EFI_VARIABLE_AUTHENTICATION_2
353
+ /// structure.
354
+ const TIME_BASED_AUTHENTICATED_WRITE_ACCESS = 0x20 ;
355
+
356
+ /// This is never set in the attributes returned by
357
+ /// `get_variable`. When passed to `set_variable`, the variable payload
358
+ /// will be appended to the current value of the variable if supported
359
+ /// by the firmware.
360
+ const APPEND_WRITE = 0x40 ;
361
+
362
+ /// Variable payload begins with an EFI_VARIABLE_AUTHENTICATION_3
363
+ /// structure.
364
+ const ENHANCED_AUTHENTICATED_ACCESS = 0x80 ;
365
+ }
366
+ }
367
+
368
+ /// Vendor GUID used to access global variables.
369
+ pub const GLOBAL_VARIABLE : Guid = Guid :: from_values (
370
+ 0x8be4df61 ,
371
+ 0x93ca ,
372
+ 0x11d2 ,
373
+ 0xaa0d ,
374
+ [ 0x00 , 0xe0 , 0x98 , 0x03 , 0x2b , 0x8c ] ,
375
+ ) ;
376
+
248
377
/// The type of system reset.
249
378
#[ derive( Debug , Copy , Clone , Eq , PartialEq ) ]
250
379
#[ repr( u32 ) ]
0 commit comments