tool: split esp paths

To access paths on the ESP before or after installing generations, split
EspPaths into general EspPaths that only depend on the path to the ESP
and EspGenerationPaths which additionally depend on generation specific
information (e.g. version number and initrd filename).
This commit is contained in:
nikstur 2023-01-18 23:52:13 +01:00
parent 6e452b50df
commit db75203e31
2 changed files with 61 additions and 40 deletions

View File

@ -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<Path>, generation: &Generation) -> Result<Self> {
pub fn new(esp: impl AsRef<Path>) -> 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<Self> {
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<Path>, name: &str) -> Result<PathBuf> {
let resolved = path
.as_ref()

View File

@ -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<PathBuf>,
}
@ -31,12 +31,16 @@ impl Installer {
esp: PathBuf,
generation_links: Vec<PathBuf>,
) -> 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(())