11// SPDX-License-Identifier: BSD-3-Clause
22
33use anyhow:: { Context , Result , bail} ;
4- use std:: path:: Path ;
54use std:: process:: Command ;
65use std:: str;
76
8- use crate :: mount:: { remount_boot_ro, remount_boot_rw} ;
7+ /// Shared GRUB environment path used by default helpers
8+ static GRUB_PATH : & str = "/boot/grub2/grubenv" ;
99
1010/// fetches boot_counter value, none if not set
11- pub fn get_boot_counter ( grub_path : & str ) -> Result < Option < i32 > > {
11+ pub fn get_boot_counter ( ) -> Result < Option < i32 > > {
12+ get_boot_counter_at ( GRUB_PATH )
13+ }
14+
15+ fn get_boot_counter_at ( grub_path : & str ) -> Result < Option < i32 > > {
1216 let grub_vars = Command :: new ( "grub2-editenv" )
1317 . arg ( grub_path)
1418 . arg ( "list" )
@@ -33,8 +37,12 @@ pub fn get_boot_counter(grub_path: &str) -> Result<Option<i32>> {
3337}
3438
3539/// sets grub variable boot_counter if not set
36- pub fn set_boot_counter ( reboot_count : u16 , grub_path : & str , mount_info_path : & str ) -> Result < ( ) > {
37- match get_boot_counter ( grub_path) {
40+ pub fn set_boot_counter ( reboot_count : u16 ) -> Result < ( ) > {
41+ set_boot_counter_at ( reboot_count, GRUB_PATH )
42+ }
43+
44+ fn set_boot_counter_at ( reboot_count : u16 , grub_path : & str ) -> Result < ( ) > {
45+ match get_boot_counter_at ( grub_path) {
3846 Ok ( Some ( i) ) => {
3947 bail ! ( "already set boot_counter={i}" ) ;
4048 }
@@ -48,36 +56,56 @@ pub fn set_boot_counter(reboot_count: u16, grub_path: &str, mount_info_path: &st
4856 }
4957
5058 log:: info!( "setting boot counter" ) ;
51- set_grub_var ( "boot_counter" , reboot_count, grub_path, mount_info_path ) ?;
59+ set_grub_var ( "boot_counter" , reboot_count, grub_path) ?;
5260 Ok ( ( ) )
5361}
5462/// sets grub variable boot_success
55- pub fn set_boot_status ( success : bool , grub_path : & str , mount_info_path : & str ) -> Result < ( ) > {
63+ pub fn set_boot_status ( success : bool ) -> Result < ( ) > {
64+ set_boot_status_at ( success, GRUB_PATH )
65+ }
66+
67+ fn set_boot_status_at ( success : bool , grub_path : & str ) -> Result < ( ) > {
5668 if success {
57- set_grub_var ( "boot_success" , 1 , grub_path, mount_info_path ) ?;
58- unset_boot_counter ( grub_path, mount_info_path ) ?;
69+ set_grub_var ( "boot_success" , 1 , grub_path) ?;
70+ unset_boot_counter_at ( grub_path) ?;
5971 return Ok ( ( ) ) ;
6072 }
61- set_grub_var ( "boot_success" , 0 , grub_path, mount_info_path )
73+ set_grub_var ( "boot_success" , 0 , grub_path)
6274}
6375
6476/// unset boot_counter
65- pub fn unset_boot_counter ( grub_path : & str , mount_info_path : & str ) -> Result < ( ) > {
66- unset_grub_var ( "boot_counter" , grub_path, mount_info_path)
77+ pub fn unset_boot_counter ( ) -> Result < ( ) > {
78+ unset_boot_counter_at ( GRUB_PATH )
79+ }
80+
81+ fn unset_boot_counter_at ( grub_path : & str ) -> Result < ( ) > {
82+ unset_grub_var ( "boot_counter" , grub_path)
6783}
6884
6985/// sets greenboot_rollback_trigger=1
70- pub fn set_rollback_trigger ( grub_path : & str , mount_info_path : & str ) -> Result < ( ) > {
71- set_grub_var ( "greenboot_rollback_trigger" , 1 , grub_path, mount_info_path)
86+ pub fn set_rollback_trigger ( ) -> Result < ( ) > {
87+ set_rollback_trigger_at ( GRUB_PATH )
88+ }
89+
90+ fn set_rollback_trigger_at ( grub_path : & str ) -> Result < ( ) > {
91+ set_grub_var ( "greenboot_rollback_trigger" , 1 , grub_path)
7292}
7393
7494/// unsets greenboot_rollback_trigger
75- pub fn unset_rollback_trigger ( grub_path : & str , mount_info_path : & str ) -> Result < ( ) > {
76- unset_grub_var ( "greenboot_rollback_trigger" , grub_path, mount_info_path)
95+ pub fn unset_rollback_trigger ( ) -> Result < ( ) > {
96+ unset_rollback_trigger_at ( GRUB_PATH )
97+ }
98+
99+ fn unset_rollback_trigger_at ( grub_path : & str ) -> Result < ( ) > {
100+ unset_grub_var ( "greenboot_rollback_trigger" , grub_path)
77101}
78102
79103/// gets greenboot_rollback_trigger value, returns true if set to 1
80- pub fn get_rollback_trigger ( grub_path : & str ) -> Result < bool > {
104+ pub fn get_rollback_trigger ( ) -> Result < bool > {
105+ get_rollback_trigger_at ( GRUB_PATH )
106+ }
107+
108+ fn get_rollback_trigger_at ( grub_path : & str ) -> Result < bool > {
81109 let grub_vars = Command :: new ( "grub2-editenv" )
82110 . arg ( grub_path)
83111 . arg ( "list" )
@@ -94,44 +122,52 @@ pub fn get_rollback_trigger(grub_path: &str) -> Result<bool> {
94122 Ok ( false ) // Not set means false
95123}
96124
97- fn unset_grub_var ( key : & str , grub_path : & str , mount_info_path : & str ) -> Result < ( ) > {
98- remount_boot_rw ( Path :: new ( mount_info_path ) ) . context ( "Failed to remount /boot as rw" ) ? ;
99- Command :: new ( "grub2-editenv" )
125+ fn unset_grub_var ( key : & str , grub_path : & str ) -> Result < ( ) > {
126+ // Execute GRUB command and capture result
127+ let grub_result = Command :: new ( "grub2-editenv" )
100128 . arg ( grub_path)
101129 . arg ( "unset" )
102130 . arg ( key)
103131 . status ( )
104132 . context ( "Unable to clear boot_counter" ) ?;
133+
134+ if !grub_result. success ( ) {
135+ bail ! ( "Failed to unset grubenv key: {key}" ) ;
136+ }
137+
105138 log:: info!( "Clear grubenv: {key}" ) ;
106- remount_boot_ro ( Path :: new ( mount_info_path ) ) . context ( "Failed to remount /boot as read-only" )
139+ Ok ( ( ) )
107140}
108141
109- fn set_grub_var ( key : & str , val : u16 , grub_path : & str , mount_info_path : & str ) -> Result < ( ) > {
110- remount_boot_rw ( Path :: new ( mount_info_path ) ) . context ( "Failed to remount /boot as rw" ) ? ;
111- Command :: new ( "grub2-editenv" )
142+ fn set_grub_var ( key : & str , val : u16 , grub_path : & str ) -> Result < ( ) > {
143+ // Execute GRUB command and capture result
144+ let grub_result = Command :: new ( "grub2-editenv" )
112145 . arg ( grub_path)
113146 . arg ( "set" )
114147 . arg ( format ! ( "{key}={val}" ) )
115148 . status ( )
116149 . context ( "Unable to set grubenv" ) ?;
150+
151+ if !grub_result. success ( ) {
152+ bail ! ( "Failed to set grubenv key: {key}" ) ;
153+ }
154+
117155 log:: info!( "Set grubenv: {key}={val}" ) ;
118- remount_boot_ro ( Path :: new ( mount_info_path ) ) . context ( "Failed to remount /boot as read-only" )
156+ Ok ( ( ) )
119157}
120158
121159#[ cfg( test) ]
122160mod tests {
123161 use super :: {
124- get_boot_counter , get_rollback_trigger , set_boot_counter , set_rollback_trigger ,
125- unset_boot_counter , unset_rollback_trigger ,
162+ get_boot_counter_at , get_rollback_trigger_at , set_boot_counter_at , set_rollback_trigger_at ,
163+ unset_boot_counter_at , unset_rollback_trigger_at ,
126164 } ;
127165 use anyhow:: Context ;
128166 use std:: fs;
129167 use std:: process:: Command ;
130168 use tempfile:: TempDir ;
131169 use tempfile:: tempdir;
132170
133- static MOUNT_INFO_PATH : & str = "testing_assets/mounts" ;
134-
135171 fn setup_test_paths ( ) -> ( TempDir , String ) {
136172 let temp_dir = tempdir ( ) . unwrap ( ) ;
137173 let temp_grubenv = temp_dir. path ( ) . join ( "grubenv" ) ;
@@ -142,8 +178,8 @@ mod tests {
142178 #[ test]
143179 fn test_boot_counter_set ( ) {
144180 let ( _temp_dir, grubenv) = setup_test_paths ( ) ;
145- set_boot_counter ( 10 , & grubenv, MOUNT_INFO_PATH ) . unwrap ( ) ;
146- assert_eq ! ( get_boot_counter ( & grubenv) . unwrap( ) , Some ( 10 ) ) ;
181+ set_boot_counter_at ( 10 , & grubenv) . unwrap ( ) ;
182+ assert_eq ! ( get_boot_counter_at ( & grubenv) . unwrap( ) , Some ( 10 ) ) ;
147183 }
148184
149185 #[ test]
@@ -155,8 +191,8 @@ mod tests {
155191 . arg ( "boot_counter=99" )
156192 . status ( )
157193 . context ( "Cannot create grub variable boot_counter" ) ;
158- set_boot_counter ( 20 , & grubenv, MOUNT_INFO_PATH ) . ok ( ) ;
159- assert_eq ! ( get_boot_counter ( & grubenv) . unwrap( ) , Some ( 99 ) ) ;
194+ set_boot_counter_at ( 20 , & grubenv) . ok ( ) ;
195+ assert_eq ! ( get_boot_counter_at ( & grubenv) . unwrap( ) , Some ( 99 ) ) ;
160196 }
161197
162198 #[ test]
@@ -168,8 +204,8 @@ mod tests {
168204 . arg ( "boot_counter=foo" )
169205 . status ( )
170206 . context ( "Cannot create grub variable boot_counter" ) ;
171- set_boot_counter ( 13 , & grubenv, MOUNT_INFO_PATH ) . unwrap ( ) ;
172- assert_eq ! ( get_boot_counter ( & grubenv) . unwrap( ) , Some ( 13 ) ) ;
207+ set_boot_counter_at ( 13 , & grubenv) . unwrap ( ) ;
208+ assert_eq ! ( get_boot_counter_at ( & grubenv) . unwrap( ) , Some ( 13 ) ) ;
173209 }
174210
175211 #[ test]
@@ -181,8 +217,8 @@ mod tests {
181217 . arg ( "boot_counter=199" )
182218 . status ( )
183219 . context ( "Cannot create grub variable boot_counter" ) ;
184- unset_boot_counter ( & grubenv, MOUNT_INFO_PATH ) . unwrap ( ) ;
185- assert_eq ! ( get_boot_counter ( & grubenv) . unwrap( ) , None ) ;
220+ unset_boot_counter_at ( & grubenv) . unwrap ( ) ;
221+ assert_eq ! ( get_boot_counter_at ( & grubenv) . unwrap( ) , None ) ;
186222 }
187223
188224 #[ test]
@@ -194,42 +230,42 @@ mod tests {
194230 . arg ( "boot_counter=99" )
195231 . status ( )
196232 . context ( "Cannot create grub variable boot_counter" ) ;
197- assert_eq ! ( get_boot_counter ( & grubenv) . unwrap( ) , Some ( 99 ) ) ;
233+ assert_eq ! ( get_boot_counter_at ( & grubenv) . unwrap( ) , Some ( 99 ) ) ;
198234 }
199235
200236 #[ test]
201237 fn test_rollback_trigger_functions ( ) {
202238 let ( _temp_dir, grubenv) = setup_test_paths ( ) ;
203239
204240 // Test when rollback trigger is not set
205- assert ! ( !get_rollback_trigger ( & grubenv) . unwrap( ) ) ;
241+ assert ! ( !get_rollback_trigger_at ( & grubenv) . unwrap( ) ) ;
206242
207243 // Test setting rollback trigger
208- set_rollback_trigger ( & grubenv, MOUNT_INFO_PATH ) . unwrap ( ) ;
209- assert ! ( get_rollback_trigger ( & grubenv) . unwrap( ) ) ;
244+ set_rollback_trigger_at ( & grubenv) . unwrap ( ) ;
245+ assert ! ( get_rollback_trigger_at ( & grubenv) . unwrap( ) ) ;
210246
211247 // Test unsetting rollback trigger
212- unset_rollback_trigger ( & grubenv, MOUNT_INFO_PATH ) . unwrap ( ) ;
213- assert ! ( !get_rollback_trigger ( & grubenv) . unwrap( ) ) ;
248+ unset_rollback_trigger_at ( & grubenv) . unwrap ( ) ;
249+ assert ! ( !get_rollback_trigger_at ( & grubenv) . unwrap( ) ) ;
214250 }
215251
216252 #[ test]
217253 fn test_rollback_trigger_with_other_vars ( ) {
218254 let ( _temp_dir, grubenv) = setup_test_paths ( ) ;
219255
220256 // Set boot counter
221- set_boot_counter ( 3 , & grubenv, MOUNT_INFO_PATH ) . unwrap ( ) ;
257+ set_boot_counter_at ( 3 , & grubenv) . unwrap ( ) ;
222258
223259 // Set rollback trigger
224- set_rollback_trigger ( & grubenv, MOUNT_INFO_PATH ) . unwrap ( ) ;
260+ set_rollback_trigger_at ( & grubenv) . unwrap ( ) ;
225261
226262 // Both should coexist
227- assert_eq ! ( get_boot_counter ( & grubenv) . unwrap( ) , Some ( 3 ) ) ;
228- assert ! ( get_rollback_trigger ( & grubenv) . unwrap( ) ) ;
263+ assert_eq ! ( get_boot_counter_at ( & grubenv) . unwrap( ) , Some ( 3 ) ) ;
264+ assert ! ( get_rollback_trigger_at ( & grubenv) . unwrap( ) ) ;
229265
230266 // Unset rollback trigger, boot_counter should remain
231- unset_rollback_trigger ( & grubenv, MOUNT_INFO_PATH ) . unwrap ( ) ;
232- assert_eq ! ( get_boot_counter ( & grubenv) . unwrap( ) , Some ( 3 ) ) ;
233- assert ! ( !get_rollback_trigger ( & grubenv) . unwrap( ) ) ;
267+ unset_rollback_trigger_at ( & grubenv) . unwrap ( ) ;
268+ assert_eq ! ( get_boot_counter_at ( & grubenv) . unwrap( ) , Some ( 3 ) ) ;
269+ assert ! ( !get_rollback_trigger_at ( & grubenv) . unwrap( ) ) ;
234270 }
235271}
0 commit comments