diff --git a/rust/tool/src/esp.rs b/rust/tool/src/esp.rs index 62bc705..36b5d58 100644 --- a/rust/tool/src/esp.rs +++ b/rust/tool/src/esp.rs @@ -5,14 +5,12 @@ use anyhow::{Context, Result}; use crate::generation::Generation; +/// Paths to the boot files that are not specific to a generation. pub struct EspPaths { pub esp: PathBuf, pub efi: PathBuf, pub nixos: PathBuf, - pub kernel: PathBuf, - pub initrd: PathBuf, pub linux: PathBuf, - pub lanzaboote_image: PathBuf, pub efi_fallback_dir: PathBuf, pub efi_fallback: PathBuf, pub systemd: PathBuf, @@ -20,7 +18,7 @@ pub struct EspPaths { } impl EspPaths { - pub fn new(esp: impl AsRef, generation: &Generation) -> Result { + pub fn new(esp: impl AsRef) -> Self { let esp = esp.as_ref(); let efi = esp.join("EFI"); let efi_nixos = efi.join("nixos"); @@ -28,39 +26,25 @@ impl EspPaths { let efi_systemd = efi.join("systemd"); let efi_efi_fallback_dir = efi.join("BOOT"); - let bootspec = &generation.spec.bootspec; - - Ok(Self { + Self { esp: esp.to_path_buf(), efi, - nixos: efi_nixos.clone(), - kernel: efi_nixos.join(nixos_path(&bootspec.kernel, "bzImage")?), - initrd: efi_nixos.join(nixos_path( - bootspec - .initrd - .as_ref() - .context("Lanzaboote does not support missing initrd yet")?, - "initrd", - )?), - linux: efi_linux.clone(), - lanzaboote_image: efi_linux.join(generation_path(generation)), + nixos: efi_nixos, + linux: efi_linux, efi_fallback_dir: efi_efi_fallback_dir.clone(), efi_fallback: efi_efi_fallback_dir.join("BOOTX64.EFI"), systemd: efi_systemd.clone(), systemd_boot: efi_systemd.join("systemd-bootx64.efi"), - }) + } } /// Return the used file paths to store as garbage collection roots. - pub fn to_iter(&self) -> IntoIter<&PathBuf, 11> { + pub fn to_iter(&self) -> IntoIter<&PathBuf, 8> { [ &self.esp, &self.efi, &self.nixos, - &self.kernel, - &self.initrd, &self.linux, - &self.lanzaboote_image, &self.efi_fallback_dir, &self.efi_fallback, &self.systemd, @@ -70,6 +54,38 @@ impl EspPaths { } } +/// Paths to the boot files of a specific generation. +pub struct EspGenerationPaths { + pub kernel: PathBuf, + pub initrd: PathBuf, + pub lanzaboote_image: PathBuf, +} + +impl EspGenerationPaths { + pub fn new(esp_paths: &EspPaths, generation: &Generation) -> Result { + let bootspec = &generation.spec.bootspec; + + Ok(Self { + kernel: esp_paths + .nixos + .join(nixos_path(&bootspec.kernel, "bzImage")?), + initrd: esp_paths.nixos.join(nixos_path( + bootspec + .initrd + .as_ref() + .context("Lanzaboote does not support missing initrd yet")?, + "initrd", + )?), + lanzaboote_image: esp_paths.linux.join(generation_path(generation)), + }) + } + + /// Return the used file paths to store as garbage collection roots. + pub fn to_iter(&self) -> IntoIter<&PathBuf, 3> { + [&self.kernel, &self.initrd, &self.lanzaboote_image].into_iter() + } +} + fn nixos_path(path: impl AsRef, name: &str) -> Result { let resolved = path .as_ref() diff --git a/rust/tool/src/install.rs b/rust/tool/src/install.rs index e7e48ff..db227c7 100644 --- a/rust/tool/src/install.rs +++ b/rust/tool/src/install.rs @@ -6,7 +6,7 @@ use std::process::Command; use anyhow::{Context, Result}; use nix::unistd::sync; -use crate::esp::EspPaths; +use crate::esp::{EspGenerationPaths, EspPaths}; use crate::gc::Roots; use crate::generation::{Generation, GenerationLink}; use crate::os_release::OsRelease; @@ -19,7 +19,7 @@ pub struct Installer { lanzaboote_stub: PathBuf, key_pair: KeyPair, configuration_limit: usize, - esp: PathBuf, + esp_paths: EspPaths, generation_links: Vec, } @@ -31,12 +31,16 @@ impl Installer { esp: PathBuf, generation_links: Vec, ) -> Self { + let mut gc_roots = Roots::new(); + let esp_paths = EspPaths::new(esp); + gc_roots.extend(esp_paths.to_iter()); + Self { - gc_roots: Roots::new(), + gc_roots, lanzaboote_stub, key_pair, configuration_limit, - esp, + esp_paths, generation_links, } } @@ -66,12 +70,12 @@ impl Installer { // the NixOS installation are deleted. Lanzatool takes full control over the esp/EFI/nixos // directory and deletes ALL files that it doesn't know about. Dual- or multiboot setups // that need files in this directory will NOT work. - self.gc_roots.collect_garbage(self.esp.join("EFI/nixos"))?; + self.gc_roots.collect_garbage(&self.esp_paths.nixos)?; // The esp/EFI/Linux directory is assumed to be potentially shared with other distros. // Thus, only files that start with "nixos-" are garbage collected (i.e. potentially // deleted). self.gc_roots - .collect_garbage_with_filter(self.esp.join("EFI/Linux"), |p| { + .collect_garbage_with_filter(&self.esp_paths.linux, |p| { p.file_name() .and_then(|n| n.to_str()) .map_or(false, |n| n.starts_with("nixos-")) @@ -115,8 +119,8 @@ impl Installer { fn install_generation(&mut self, generation: &Generation) -> Result<()> { let bootspec = &generation.spec.bootspec; - let esp_paths = EspPaths::new(&self.esp, generation)?; - self.gc_roots.extend(esp_paths.to_iter()); + let esp_gen_paths = EspGenerationPaths::new(&self.esp_paths, generation)?; + self.gc_roots.extend(esp_gen_paths.to_iter()); let kernel_cmdline = assemble_kernel_cmdline(&bootspec.init, bootspec.kernel_params.clone()); @@ -150,9 +154,9 @@ impl Installer { .join("systemd/lib/systemd/boot/efi/systemd-bootx64.efi"); [ - (&systemd_boot, &esp_paths.efi_fallback), - (&systemd_boot, &esp_paths.systemd_boot), - (&bootspec.kernel, &esp_paths.kernel), + (&systemd_boot, &self.esp_paths.efi_fallback), + (&systemd_boot, &self.esp_paths.systemd_boot), + (&bootspec.kernel, &esp_gen_paths.kernel), ] .into_iter() .try_for_each(|(from, to)| install_signed(&self.key_pair, from, to))?; @@ -160,23 +164,24 @@ impl Installer { // The initrd doesn't need to be signed. Lanzaboote has its // hash embedded and will refuse loading it when the hash // mismatches. - install(&initrd_location, &esp_paths.initrd).context("Failed to install initrd to ESP")?; + install(&initrd_location, &esp_gen_paths.initrd) + .context("Failed to install initrd to ESP")?; let lanzaboote_image = pe::lanzaboote_image( &tempdir, &self.lanzaboote_stub, &os_release_path, &kernel_cmdline, - &esp_paths.kernel, - &esp_paths.initrd, - &esp_paths.esp, + &esp_gen_paths.kernel, + &esp_gen_paths.initrd, + &self.esp_paths.esp, ) .context("Failed to assemble stub")?; install_signed( &self.key_pair, &lanzaboote_image, - &esp_paths.lanzaboote_image, + &esp_gen_paths.lanzaboote_image, ) .context("Failed to install lanzaboote")?; @@ -187,7 +192,7 @@ impl Installer { println!( "Successfully installed lanzaboote to '{}'", - esp_paths.esp.display() + self.esp_paths.esp.display() ); Ok(())