From 17f4ec7070618a2c79bc3be41cd3b6b2180e1011 Mon Sep 17 00:00:00 2001 From: Huijing Hei Date: Sun, 30 Nov 2025 16:40:04 +0800 Subject: [PATCH 1/2] grubconfig: minor changes to replace variables using `const` --- src/grubconfigs.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/grubconfigs.rs b/src/grubconfigs.rs index 17be02a4..e80d7a3a 100644 --- a/src/grubconfigs.rs +++ b/src/grubconfigs.rs @@ -12,7 +12,7 @@ use crate::freezethaw::fsfreeze_thaw_cycle; /// The subdirectory of /boot we use const GRUB2DIR: &str = "grub2"; -const CONFIGDIR: &str = "/usr/lib/bootupd/grub2-static"; +const CONFIGDIR: &str = "usr/lib/bootupd/grub2-static"; const DROPINDIR: &str = "configs.d"; // The related grub files const GRUBENV: &str = "grubenv"; @@ -43,11 +43,10 @@ pub(crate) fn install( } let configdir = if let Some(src_root) = src_root { - // strip the leading `/` to make the path relative to the given - // source root - src_root.sub_dir(Path::new(CONFIGDIR).strip_prefix("/")?)? + src_root.sub_dir(CONFIGDIR)? } else { - openat::Dir::open(Path::new(CONFIGDIR))? + // Open / if there is no source root + openat::Dir::open("/")?.sub_dir(CONFIGDIR)? }; let mut config = String::from("# Generated by bootupd / do not edit\n\n"); @@ -58,7 +57,7 @@ pub(crate) fn install( .read_to_string(&mut pre)?; config.push_str(pre.as_str()); - let dropindir = configdir.sub_dir(Path::new(DROPINDIR))?; + let dropindir = configdir.sub_dir(DROPINDIR)?; // Sort the files for reproducibility let mut entries = dropindir .list_dir(".")? @@ -85,7 +84,7 @@ pub(crate) fn install( let grub2dir = bootdir.sub_dir(GRUB2DIR)?; grub2dir - .write_file_contents("grub.cfg", GRUBCONFIG_FILE_MODE, config.as_bytes()) + .write_file_contents(GRUBCONFIG, GRUBCONFIG_FILE_MODE, config.as_bytes()) .context("Copying grub-static.cfg")?; println!("Installed: grub.cfg"); @@ -113,7 +112,7 @@ pub(crate) fn install( if let Some(vendordir) = installed_efi_vendor { log::debug!("vendordir={:?}", &vendordir); let vendor = PathBuf::from(vendordir); - let target = &vendor.join("grub.cfg"); + let target = &vendor.join(GRUBCONFIG); let dest_efidir = target_root .sub_dir_optional("boot/efi/EFI") .context("Opening /boot/efi/EFI")?; From 5982e197b19e8d9fe59060b518995afd268e0639 Mon Sep 17 00:00:00 2001 From: Huijing Hei Date: Sun, 30 Nov 2025 16:44:12 +0800 Subject: [PATCH 2/2] efi: install grub.cfg under new vendor during updates When doing switches from RHEL 10 to Fedora 43, after reboot, check grub.cfg and bootuuid.cfg are in old vendor redhat, that will make the machine fails to boot a second time since grub.cfg cannot be found. We need to install the 2 files under new vendor during updates. See https://github.com/coreos/bootupd/issues/1024 --- src/efi.rs | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/src/efi.rs b/src/efi.rs index f600fb45..e0111475 100644 --- a/src/efi.rs +++ b/src/efi.rs @@ -481,14 +481,42 @@ impl Component for Efi { anyhow::bail!("Failed to find all esp devices"); }; + // Get old vendor name from installed filetree + let old_vendor = { + let mut vendor = ""; + for child in currentf.children.keys() { + if child.ends_with(SHIM) { + vendor = child.strip_suffix(&format!("/{SHIM}")).unwrap_or(""); + break; + } + } + vendor.to_owned() + }; + for esp in esp_devices { let destpath = &self.ensure_mounted_esp(rootcxt.path.as_ref(), Path::new(&esp))?; - let destdir = openat::Dir::open(&destpath.join("EFI")).context("opening EFI dir")?; + let dest_efi = destpath.join("EFI"); + let destdir = openat::Dir::open(&dest_efi).context("opening EFI dir")?; validate_esp_fstype(&destdir)?; + log::trace!("applying diff: {}", &diff); filetree::apply_diff(&updated, &destdir, &diff, None) .context("applying filesystem changes")?; + // Install grub.cfg under new vendor + { + // Get new vendor name + let sysroot = rootcxt.path.as_std_path(); + let Some(new_vendor) = self.get_efi_vendor(&sysroot.join(&updated_path))? else { + anyhow::bail!("Failed to find efi vendor in new update"); + }; + if new_vendor != old_vendor && destdir.exists(&old_vendor)? { + grubconfigs::install(sysroot_dir, None, Some(&new_vendor), true)?; + destdir.remove_all(&old_vendor)?; + assert!(destdir.exists(format!("{new_vendor}/{}", grubconfigs::GRUBCONFIG))?); + } + } + // Do the sync before unmount fsfreeze_thaw_cycle(destdir.open_file(".")?)?; drop(destdir); @@ -609,7 +637,7 @@ impl Component for Efi { // Does not support multiple shim for efi if shim_files.len() > 1 { - anyhow::bail!("Found multiple {SHIM} in the image"); + anyhow::bail!("Found multiple {SHIM} in the image: {:?}", shim_files); } if let Some(p) = shim_files.first() { let p = p