lzbt: abstraction for multiple backends
This generates `lzbt-systemd` binary instead of `lzbt` which is using a special systemd-specific entrypoint. This is part of the effort to enable multiple backends.
This commit is contained in:
parent
7ef2b13780
commit
efe7b40f5c
|
@ -4,8 +4,8 @@ version = "0.3.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "lzbt"
|
name = "lzbt-systemd"
|
||||||
path = "src/main.rs"
|
path = "src/systemd-main.rs"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
|
|
@ -1,65 +1,29 @@
|
||||||
use std::array::IntoIter;
|
use std::{path::{PathBuf, Path}, array::IntoIter};
|
||||||
use std::path::{Path, PathBuf};
|
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
|
|
||||||
use crate::generation::Generation;
|
use crate::common::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 linux: PathBuf,
|
|
||||||
pub efi_fallback_dir: PathBuf,
|
|
||||||
pub efi_fallback: PathBuf,
|
|
||||||
pub systemd: PathBuf,
|
|
||||||
pub systemd_boot: PathBuf,
|
|
||||||
pub loader: PathBuf,
|
|
||||||
pub systemd_boot_loader_config: PathBuf,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EspPaths {
|
|
||||||
pub fn new(esp: impl AsRef<Path>) -> Self {
|
|
||||||
let esp = esp.as_ref();
|
|
||||||
let efi = esp.join("EFI");
|
|
||||||
let efi_nixos = efi.join("nixos");
|
|
||||||
let efi_linux = efi.join("Linux");
|
|
||||||
let efi_systemd = efi.join("systemd");
|
|
||||||
let efi_efi_fallback_dir = efi.join("BOOT");
|
|
||||||
let loader = esp.join("loader");
|
|
||||||
let systemd_boot_loader_config = loader.join("loader.conf");
|
|
||||||
|
|
||||||
Self {
|
|
||||||
esp: esp.to_path_buf(),
|
|
||||||
efi,
|
|
||||||
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"),
|
|
||||||
loader,
|
|
||||||
systemd_boot_loader_config,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/// Generic ESP paths which can be specific to a bootloader
|
||||||
|
// The const generics is necessary because:
|
||||||
|
// (a) we cannot return Trait objects in trait definitions, see https://rust-lang.github.io/impl-trait-initiative/explainer/rpit_trait.html
|
||||||
|
// (b) we cannot return std::slice::Iter<'_, PathBuf> because PathBuf is owned
|
||||||
|
// (c) we cannot return std::slice::Iter<'_, &PathBuf> because then Item = &&PathBuf
|
||||||
|
// (d) we cannot return std::slice::Iter<'_, Path> because Path is unsized
|
||||||
|
// (e) we cannot return std::slice::Iter<'_, &Path> because then Item = &&Path
|
||||||
|
// (f) we can bring an associated type `BorrowedIterator` and then because we want to return
|
||||||
|
// borrows, Rust needs a lifetime and the struct cannot hold the borrow so you need to bring a
|
||||||
|
// PhantomData<'a ()> inside the structure to keep the lifetime, this is needlessly complicated
|
||||||
|
// when this solution ensures proper monomorphisation at a small complexity cost.
|
||||||
|
pub trait EspPaths<const N: usize> {
|
||||||
|
/// Build an ESP path structure out of the ESP root directory
|
||||||
|
fn new(esp: impl AsRef<Path>) -> Self;
|
||||||
/// Return the used file paths to store as garbage collection roots.
|
/// Return the used file paths to store as garbage collection roots.
|
||||||
pub fn to_iter(&self) -> IntoIter<&PathBuf, 10> {
|
fn iter(&self) -> std::array::IntoIter<&PathBuf, N>;
|
||||||
[
|
/// Returns the path containing NixOS EFI binaries
|
||||||
&self.esp,
|
fn nixos_path(&self) -> &Path;
|
||||||
&self.efi,
|
/// Returns the path containing Linux EFI binaries
|
||||||
&self.nixos,
|
fn linux_path(&self) -> &Path;
|
||||||
&self.linux,
|
|
||||||
&self.efi_fallback_dir,
|
|
||||||
&self.efi_fallback,
|
|
||||||
&self.systemd,
|
|
||||||
&self.systemd_boot,
|
|
||||||
&self.loader,
|
|
||||||
&self.systemd_boot_loader_config,
|
|
||||||
]
|
|
||||||
.into_iter()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Paths to the boot files of a specific generation.
|
/// Paths to the boot files of a specific generation.
|
||||||
|
@ -70,21 +34,21 @@ pub struct EspGenerationPaths {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EspGenerationPaths {
|
impl EspGenerationPaths {
|
||||||
pub fn new(esp_paths: &EspPaths, generation: &Generation) -> Result<Self> {
|
pub fn new<const N: usize, P: EspPaths<N>>(esp_paths: &P, generation: &Generation) -> Result<Self> {
|
||||||
let bootspec = &generation.spec.bootspec.bootspec;
|
let bootspec = &generation.spec.bootspec.bootspec;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
kernel: esp_paths
|
kernel: esp_paths
|
||||||
.nixos
|
.nixos_path()
|
||||||
.join(nixos_path(&bootspec.kernel, "bzImage")?),
|
.join(nixos_path(&bootspec.kernel, "bzImage")?),
|
||||||
initrd: esp_paths.nixos.join(nixos_path(
|
initrd: esp_paths.nixos_path().join(nixos_path(
|
||||||
bootspec
|
bootspec
|
||||||
.initrd
|
.initrd
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.context("Lanzaboote does not support missing initrd yet")?,
|
.context("Lanzaboote does not support missing initrd yet")?,
|
||||||
"initrd",
|
"initrd",
|
||||||
)?),
|
)?),
|
||||||
lanzaboote_image: esp_paths.linux.join(generation_path(generation)),
|
lanzaboote_image: esp_paths.linux_path().join(generation_path(generation)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
pub mod esp;
|
||||||
|
pub mod gc;
|
||||||
|
pub mod generation;
|
||||||
|
pub mod os_release;
|
||||||
|
pub mod pe;
|
||||||
|
pub mod signature;
|
||||||
|
pub mod utils;
|
|
@ -3,7 +3,7 @@ use std::fmt;
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
|
|
||||||
use crate::generation::Generation;
|
use crate::common::generation::Generation;
|
||||||
|
|
||||||
/// An os-release file represented by a BTreeMap.
|
/// An os-release file represented by a BTreeMap.
|
||||||
///
|
///
|
|
@ -8,8 +8,8 @@ use anyhow::{Context, Result};
|
||||||
use goblin::pe::PE;
|
use goblin::pe::PE;
|
||||||
use tempfile::TempDir;
|
use tempfile::TempDir;
|
||||||
|
|
||||||
use crate::esp::EspGenerationPaths;
|
use crate::common::esp::EspGenerationPaths;
|
||||||
use crate::utils::{file_hash, tmpname, SecureTempDirExt};
|
use crate::common::utils::{file_hash, tmpname, SecureTempDirExt};
|
||||||
|
|
||||||
/// Assemble a lanzaboote image.
|
/// Assemble a lanzaboote image.
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
|
@ -1,18 +0,0 @@
|
||||||
mod cli;
|
|
||||||
mod esp;
|
|
||||||
mod gc;
|
|
||||||
mod generation;
|
|
||||||
mod install;
|
|
||||||
mod os_release;
|
|
||||||
mod pe;
|
|
||||||
mod signature;
|
|
||||||
mod systemd;
|
|
||||||
mod utils;
|
|
||||||
|
|
||||||
use clap::Parser;
|
|
||||||
|
|
||||||
use cli::Cli;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
Cli::parse().call(module_path!())
|
|
||||||
}
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
mod systemd;
|
||||||
|
pub mod common;
|
||||||
|
|
||||||
|
use clap::Parser;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
systemd::Cli::parse().call(module_path!())
|
||||||
|
}
|
|
@ -3,8 +3,8 @@ use std::path::PathBuf;
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
|
|
||||||
use crate::install;
|
use crate::systemd::install;
|
||||||
use crate::signature::KeyPair;
|
use crate::common::signature::KeyPair;
|
||||||
|
|
||||||
/// The default log level.
|
/// The default log level.
|
||||||
///
|
///
|
|
@ -0,0 +1,67 @@
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
use crate::common::esp::EspPaths;
|
||||||
|
|
||||||
|
/// Paths to the boot files that are not specific to a generation.
|
||||||
|
/// Systemd variant
|
||||||
|
pub struct SystemdEspPaths {
|
||||||
|
pub esp: PathBuf,
|
||||||
|
pub efi: PathBuf,
|
||||||
|
pub nixos: PathBuf,
|
||||||
|
pub linux: PathBuf,
|
||||||
|
pub efi_fallback_dir: PathBuf,
|
||||||
|
pub efi_fallback: PathBuf,
|
||||||
|
pub systemd: PathBuf,
|
||||||
|
pub systemd_boot: PathBuf,
|
||||||
|
pub loader: PathBuf,
|
||||||
|
pub systemd_boot_loader_config: PathBuf,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EspPaths<10> for SystemdEspPaths {
|
||||||
|
fn new(esp: impl AsRef<Path>) -> Self {
|
||||||
|
let esp = esp.as_ref();
|
||||||
|
let efi = esp.join("EFI");
|
||||||
|
let efi_nixos = efi.join("nixos");
|
||||||
|
let efi_linux = efi.join("Linux");
|
||||||
|
let efi_systemd = efi.join("systemd");
|
||||||
|
let efi_efi_fallback_dir = efi.join("BOOT");
|
||||||
|
let loader = esp.join("loader");
|
||||||
|
let systemd_boot_loader_config = loader.join("loader.conf");
|
||||||
|
|
||||||
|
Self {
|
||||||
|
esp: esp.to_path_buf(),
|
||||||
|
efi,
|
||||||
|
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"),
|
||||||
|
loader,
|
||||||
|
systemd_boot_loader_config
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn nixos_path(&self) -> &Path {
|
||||||
|
&self.nixos
|
||||||
|
}
|
||||||
|
|
||||||
|
fn linux_path(&self) -> &Path {
|
||||||
|
&self.linux
|
||||||
|
}
|
||||||
|
|
||||||
|
fn iter(&self) -> std::array::IntoIter<&PathBuf, 10> {
|
||||||
|
[
|
||||||
|
&self.esp,
|
||||||
|
&self.efi,
|
||||||
|
&self.nixos,
|
||||||
|
&self.linux,
|
||||||
|
&self.efi_fallback_dir,
|
||||||
|
&self.efi_fallback,
|
||||||
|
&self.systemd,
|
||||||
|
&self.systemd_boot,
|
||||||
|
&self.loader,
|
||||||
|
&self.systemd_boot_loader_config,
|
||||||
|
].into_iter()
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,14 +10,15 @@ use anyhow::{anyhow, Context, Result};
|
||||||
use nix::unistd::syncfs;
|
use nix::unistd::syncfs;
|
||||||
use tempfile::TempDir;
|
use tempfile::TempDir;
|
||||||
|
|
||||||
use crate::esp::{EspGenerationPaths, EspPaths};
|
use crate::common::gc::Roots;
|
||||||
use crate::gc::Roots;
|
use crate::common::generation::{Generation, GenerationLink};
|
||||||
use crate::generation::{Generation, GenerationLink};
|
use crate::common::os_release::OsRelease;
|
||||||
use crate::os_release::OsRelease;
|
use crate::common::pe;
|
||||||
use crate::pe;
|
use crate::common::signature::KeyPair;
|
||||||
use crate::signature::KeyPair;
|
use crate::common::esp::{EspGenerationPaths, EspPaths};
|
||||||
use crate::systemd::SystemdVersion;
|
use crate::systemd::esp::SystemdEspPaths;
|
||||||
use crate::utils::{file_hash, SecureTempDirExt};
|
use crate::systemd::version::SystemdVersion;
|
||||||
|
use crate::common::utils::{file_hash, SecureTempDirExt};
|
||||||
|
|
||||||
pub struct Installer {
|
pub struct Installer {
|
||||||
broken_gens: BTreeSet<u64>,
|
broken_gens: BTreeSet<u64>,
|
||||||
|
@ -27,7 +28,7 @@ pub struct Installer {
|
||||||
systemd_boot_loader_config: PathBuf,
|
systemd_boot_loader_config: PathBuf,
|
||||||
key_pair: KeyPair,
|
key_pair: KeyPair,
|
||||||
configuration_limit: usize,
|
configuration_limit: usize,
|
||||||
esp_paths: EspPaths,
|
esp_paths: SystemdEspPaths,
|
||||||
generation_links: Vec<PathBuf>,
|
generation_links: Vec<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,8 +43,8 @@ impl Installer {
|
||||||
generation_links: Vec<PathBuf>,
|
generation_links: Vec<PathBuf>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut gc_roots = Roots::new();
|
let mut gc_roots = Roots::new();
|
||||||
let esp_paths = EspPaths::new(esp);
|
let esp_paths = SystemdEspPaths::new(esp);
|
||||||
gc_roots.extend(esp_paths.to_iter());
|
gc_roots.extend(esp_paths.iter());
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
broken_gens: BTreeSet::new(),
|
broken_gens: BTreeSet::new(),
|
|
@ -0,0 +1,6 @@
|
||||||
|
pub mod version;
|
||||||
|
mod cli;
|
||||||
|
mod esp;
|
||||||
|
mod install;
|
||||||
|
|
||||||
|
pub use cli::Cli;
|
|
@ -5,8 +5,8 @@ use std::str::FromStr;
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
|
|
||||||
use crate::os_release::OsRelease;
|
use crate::common::os_release::OsRelease;
|
||||||
use crate::pe;
|
use crate::common::pe;
|
||||||
|
|
||||||
/// A systemd version.
|
/// A systemd version.
|
||||||
///
|
///
|
Loading…
Reference in New Issue