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 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")?;