1- use anyhow:: { bail, Result } ;
1+ use anyhow:: { bail, Context , Result } ;
2+ use camino:: Utf8PathBuf ;
3+ use openat_ext:: OpenatDirExt ;
24#[ cfg( target_arch = "powerpc64" ) ]
35use std:: borrow:: Cow ;
46use std:: io:: prelude:: * ;
@@ -8,6 +10,7 @@ use std::process::Command;
810use crate :: blockdev;
911use crate :: bootupd:: RootContext ;
1012use crate :: component:: * ;
13+ use crate :: grubconfigs;
1114use crate :: model:: * ;
1215use crate :: packagesystem;
1316
@@ -142,10 +145,70 @@ impl Component for Bios {
142145 crate :: component:: query_adopt_state ( )
143146 }
144147
148+ // Backup the current grub.cfg and replace with new static config
149+ // - Backup "/boot/loader/grub.cfg" to "/boot/grub2/grub.cfg.bak"
150+ // - Remove symlink "/boot/grub2/grub.cfg"
151+ // - Replace "/boot/grub2/grub.cfg" symlink with new static "grub.cfg"
152+ fn migrate_static_grub_config ( & self , sysroot_path : & str , destdir : & openat:: Dir ) -> Result < ( ) > {
153+ let grub = "boot/grub2" ;
154+ // sysroot_path is /, destdir is Dir of /
155+ let grub_config_path = Utf8PathBuf :: from ( sysroot_path) . join ( grub) ;
156+ let grub_config_dir = destdir. sub_dir ( grub) . context ( "Opening boot/grub2" ) ?;
157+
158+ let grub_config = grub_config_path. join ( grubconfigs:: GRUBCONFIG ) ;
159+
160+ if !grub_config. exists ( ) {
161+ anyhow:: bail!( "Could not find '{}'" , grub_config) ;
162+ }
163+
164+ let mut current_config;
165+ // If /boot/grub2/grub.cfg is not symlink, we need to keep going
166+ if !grub_config. is_symlink ( ) {
167+ println ! ( "'{}' is not a symlink" , grub_config) ;
168+ current_config = grub_config. clone ( ) ;
169+ } else {
170+ // If /boot/grub2/grub.cfg is symlink to /boot/loader/grub.cfg,
171+ // backup it to /boot/grub2/grub.cfg.bak
172+ // Get real file for symlink /boot/grub2/grub.cfg
173+ let real_config = grub_config_dir. read_link ( grubconfigs:: GRUBCONFIG ) ?;
174+ let real_config =
175+ Utf8PathBuf :: from_path_buf ( real_config) . expect ( "Path should be valid UTF-8" ) ;
176+ // Resolve symlink location
177+ current_config = grub_config_path. clone ( ) ;
178+ current_config. push ( real_config) ;
179+ }
180+
181+ let backup_config = grub_config_path. join ( grubconfigs:: GRUBCONFIG_BACKUP ) ;
182+ if !backup_config. exists ( ) {
183+ // Backup the current GRUB config which is hopefully working right now
184+ println ! (
185+ "Creating a backup of the current GRUB config '{}' in '{}'..." ,
186+ current_config, backup_config
187+ ) ;
188+ std:: fs:: copy ( & current_config, & backup_config)
189+ . context ( "Failed to backup GRUB config" ) ?;
190+ }
191+
192+ crate :: grubconfigs:: install ( & destdir, None , true ) ?;
193+
194+ // Remove the real config if it is symlink and will not
195+ // if /boot/grub2/grub.cfg is file
196+ if current_config != grub_config {
197+ println ! ( "Removing {}" , current_config) ;
198+ grub_config_dir. remove_file_optional ( current_config. as_std_path ( ) ) ?;
199+ }
200+
201+ // Synchronize the filesystem containing /boot/grub2 to disk.
202+ let _ = grub_config_dir. syncfs ( ) ;
203+
204+ Ok ( ( ) )
205+ }
206+
145207 fn adopt_update (
146208 & self ,
147209 rootcxt : & RootContext ,
148210 update : & ContentMetadata ,
211+ with_static_config : bool ,
149212 ) -> Result < Option < InstalledContent > > {
150213 let bios_devices = blockdev:: find_colocated_bios_boot ( & rootcxt. devices ) ?;
151214 let Some ( meta) = self . query_adopt ( & bios_devices) ? else {
@@ -157,6 +220,17 @@ impl Component for Bios {
157220 log:: debug!( "Installed grub modules on {parent}" ) ;
158221 }
159222
223+ if with_static_config {
224+ // Install the static config if the OSTree bootloader is not set.
225+ if let Some ( bootloader) = crate :: ostreeutil:: get_ostree_bootloader ( ) ? {
226+ println ! (
227+ "ostree repo 'sysroot.bootloader' config option is currently set to: '{bootloader}'" ,
228+ ) ;
229+ } else {
230+ println ! ( "ostree repo 'sysroot.bootloader' config option is not set yet" ) ;
231+ self . migrate_static_grub_config ( rootcxt. path . as_str ( ) , & rootcxt. sysroot ) ?;
232+ } ;
233+ }
160234 Ok ( Some ( InstalledContent {
161235 meta : update. clone ( ) ,
162236 filetree : None ,
0 commit comments