@@ -3,98 +3,118 @@ use alloc::vec::Vec;
33
44use uefi:: proto:: device_path:: DevicePath ;
55use uefi:: runtime:: { VariableAttributes , VariableVendor } ;
6- use uefi:: CString16 ;
6+ use uefi:: { CStr16 , CString16 } ;
77
8- use super :: UefiOS ;
8+ use crate :: os :: error :: { Error , Result } ;
99
10- pub struct BootOptions {
11- pub ( super ) os : UefiOS ,
10+ #[ derive( Debug ) ]
11+ pub struct Variable {
12+ name : CString16 ,
13+ vendor : VariableVendor ,
1214}
1315
16+ impl Variable {
17+ pub fn new ( name : & str , vendor : VariableVendor ) -> Self {
18+ // name.len() should be enough, but...
19+ let mut name_buf = vec ! [ 0u16 ; name. len( ) * 2 + 16 ] ;
20+ let name = CStr16 :: from_str_with_buf ( name, & mut name_buf) . unwrap ( ) ;
21+ Self {
22+ name : name. into ( ) ,
23+ vendor,
24+ }
25+ }
26+
27+ pub fn get ( & self ) -> Result < ( Vec < u8 > , VariableAttributes ) > {
28+ let ( var, attrs) = uefi:: runtime:: get_variable_boxed ( & self . name , & self . vendor )
29+ . map_err ( |e| Error ( format ! ( "Error getting variable: {e:?}" ) ) ) ?;
30+ Ok ( ( var. to_vec ( ) , attrs) )
31+ }
32+
33+ pub fn set ( & self , data : & [ u8 ] , attrs : VariableAttributes ) -> Result < ( ) > {
34+ uefi:: runtime:: set_variable ( & self . name , & self . vendor , attrs, data)
35+ . map_err ( |e| Error ( format ! ( "Error setting variable: {e:?}" ) ) )
36+ }
37+ }
38+
39+ pub struct BootOptions ;
40+
1441impl BootOptions {
15- pub fn current ( & self ) -> u16 {
16- let cur = self
17- . os
18- . get_variable ( "BootCurrent" , & VariableVendor :: GLOBAL_VARIABLE )
42+ pub fn current ( ) -> u16 {
43+ let cur = Variable :: new ( "BootCurrent" , VariableVendor :: GLOBAL_VARIABLE )
44+ . get ( )
1945 . unwrap ( )
2046 . 0 ;
2147 u16:: from_le_bytes ( cur. try_into ( ) . unwrap ( ) )
2248 }
2349
24- pub fn order ( & self ) -> Vec < u16 > {
25- self . os
26- . get_variable ( "BootOrder" , & VariableVendor :: GLOBAL_VARIABLE )
50+ pub fn order ( ) -> Vec < u16 > {
51+ Variable :: new ( "BootOrder" , VariableVendor :: GLOBAL_VARIABLE )
52+ . get ( )
2753 . unwrap ( )
2854 . 0
2955 . chunks ( 2 )
3056 . map ( |x| u16:: from_le_bytes ( x. try_into ( ) . unwrap ( ) ) )
3157 . collect ( )
3258 }
3359
34- pub fn set_order ( & self , order : & [ u16 ] ) {
60+ pub fn set_order ( order : & [ u16 ] ) {
3561 let order: Vec < _ > = order
3662 . iter ( )
3763 . flat_map ( |x| x. to_le_bytes ( ) . into_iter ( ) )
3864 . collect ( ) ;
39- self . os
40- . set_variable (
41- "BootOrder" ,
42- & VariableVendor :: GLOBAL_VARIABLE ,
65+ Variable :: new ( "BootOrder" , VariableVendor :: GLOBAL_VARIABLE )
66+ . set (
67+ & order[ ..] ,
4368 VariableAttributes :: NON_VOLATILE
4469 | VariableAttributes :: BOOTSERVICE_ACCESS
4570 | VariableAttributes :: RUNTIME_ACCESS ,
46- & order[ ..] ,
4771 )
4872 . unwrap ( )
4973 }
5074
51- pub fn set_next ( & self , next : u16 ) {
52- self . os
53- . set_variable (
54- "BootNext" ,
55- & VariableVendor :: GLOBAL_VARIABLE ,
75+ pub fn set_next ( next : u16 ) {
76+ Variable :: new ( "BootNext" , VariableVendor :: GLOBAL_VARIABLE )
77+ . set (
78+ & next. to_le_bytes ( ) ,
5679 VariableAttributes :: NON_VOLATILE
5780 | VariableAttributes :: BOOTSERVICE_ACCESS
5881 | VariableAttributes :: RUNTIME_ACCESS ,
59- & next. to_le_bytes ( ) ,
6082 )
6183 . unwrap ( ) ;
6284 }
6385
64- pub fn reboot_target ( & self ) -> Option < u16 > {
65- let order = self . order ( ) ;
86+ pub fn reboot_target ( ) -> Option < u16 > {
87+ let order = Self :: order ( ) ;
6688 let num_skip = order
6789 . iter ( )
6890 . cloned ( )
69- . position ( |x| x == self . current ( ) )
91+ . position ( |x| x == Self :: current ( ) )
7092 . map ( |x| x + 1 )
7193 . unwrap_or ( 0 ) ;
7294 order. iter ( ) . cloned ( ) . skip ( num_skip) . find ( |x| * x < 0x2000 )
7395 }
7496
75- pub fn get ( & self , id : u16 ) -> Vec < u8 > {
76- self . os
77- . get_variable ( & format ! ( "Boot{id:04X}" ) , & VariableVendor :: GLOBAL_VARIABLE )
97+ pub fn get ( id : u16 ) -> Vec < u8 > {
98+ Variable :: new ( & format ! ( "Boot{id:04X}" ) , VariableVendor :: GLOBAL_VARIABLE )
99+ . get ( )
78100 . unwrap ( )
79101 . 0
80102 }
81103
82- pub fn set ( & self , id : u16 , data : & [ u8 ] ) {
83- self . os
84- . set_variable (
85- & format ! ( "Boot{id:04X}" ) ,
86- & VariableVendor :: GLOBAL_VARIABLE ,
104+ pub fn set ( id : u16 , data : & [ u8 ] ) {
105+ Variable :: new ( & format ! ( "Boot{id:04X}" ) , VariableVendor :: GLOBAL_VARIABLE )
106+ . set (
107+ data,
87108 VariableAttributes :: NON_VOLATILE
88109 | VariableAttributes :: BOOTSERVICE_ACCESS
89110 | VariableAttributes :: RUNTIME_ACCESS ,
90- data,
91111 )
92112 . unwrap ( ) ;
93113 }
94114
95115 /// Boot entry *must* be valid (TODO).
96116 /// Returns boot option description and device path of the option.
97- pub fn boot_entry_info < ' a > ( & self , entry : & ' a [ u8 ] ) -> ( String , & ' a DevicePath ) {
117+ pub fn boot_entry_info ( entry : & [ u8 ] ) -> ( String , & DevicePath ) {
98118 let skip_attropt = & entry[ 6 ..] ;
99119 let end_of_description = skip_attropt
100120 . chunks ( 2 )
0 commit comments