From 18771d30f4558811963eebc70f744e51e495768d Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Sun, 25 Dec 2022 21:06:02 +0100 Subject: [PATCH 01/15] lanzaboote: add aarch64-unknown-efi target --- rust/uefi/rust-toolchain.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/uefi/rust-toolchain.toml b/rust/uefi/rust-toolchain.toml index 530928a..362afcd 100644 --- a/rust/uefi/rust-toolchain.toml +++ b/rust/uefi/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] channel = "1.70.0" components = [ "rust-src" ] -targets = [ "x86_64-unknown-uefi" ] +targets = [ "x86_64-unknown-uefi", "aarch64-unknown-uefi" ] From 4521ae21fc37d00698f17560c23ad458e0f3b8ca Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Wed, 21 Dec 2022 04:54:38 +0100 Subject: [PATCH 02/15] platform: clean up flake.nix for aarch64 support --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index 73a9e69..e73f253 100644 --- a/flake.nix +++ b/flake.nix @@ -74,7 +74,7 @@ "x86_64-linux" # Not actively tested, but may work: - # "aarch64-linux" + "aarch64-linux" ]; perSystem = { config, system, pkgs, ... }: From 7acb1b218a58c4dcec00f636f2f7a080d7b89d0a Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Tue, 25 Apr 2023 01:53:46 +0200 Subject: [PATCH 03/15] tool: implement general architecture support - for aarch64, x86 for now --- rust/tool/shared/src/esp.rs | 44 +++++++++++++++++++++++++++++++- rust/tool/systemd/src/install.rs | 5 ++-- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/rust/tool/shared/src/esp.rs b/rust/tool/shared/src/esp.rs index 27cd071..3087d4c 100644 --- a/rust/tool/shared/src/esp.rs +++ b/rust/tool/shared/src/esp.rs @@ -3,10 +3,46 @@ use std::{ path::{Path, PathBuf}, }; -use anyhow::{Context, Result}; +use anyhow::{Context, Result, bail}; use crate::generation::Generation; +/// Supported system +#[allow(dead_code)] +#[non_exhaustive] +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum Architecture { + X86, + AArch64, +} + +impl System { + pub fn systemd_filename(&self) -> &Path { + Path::new(match self { + Self::X86 => "systemd-bootx64.efi", + Self::AArch64 => "systemd-bootaa64.efi" + }) + } + + pub fn efi_fallback_filename(&self) -> &Path { + Path::new(match self { + Self::X86 => "BOOTX64.EFI", + Self::AArch64 => "BOOTAA64.EFI", + }) + } +} + +impl Architecture { + /// Converts from a NixOS system double to a supported system + pub fn from_nixos_system(system_double: &str) -> Result { + Ok(match system_double { + "x86_64-linux" => Self::X86, + "aarch64-linux" => Self::AArch64, + _ => bail!("Unsupported NixOS system double: {}, please open an issue or a PR if you think this should be supported.", system_double) + }) + } +} + /// Generic ESP paths which can be specific to a bootloader pub trait EspPaths { /// Build an ESP path structure out of the ESP root directory @@ -35,6 +71,12 @@ impl EspGenerationPaths { generation: &Generation, ) -> Result { let bootspec = &generation.spec.bootspec.bootspec; + let bootspec_system: Architecture = Architecture::from_nixos_system(&bootspec.system)?; + + assert_eq!( + system, bootspec_system, + "Bootspec's system differs from provided target system, unsupported usecase!" + ); Ok(Self { kernel: esp_paths diff --git a/rust/tool/systemd/src/install.rs b/rust/tool/systemd/src/install.rs index 789cb3f..36c528a 100644 --- a/rust/tool/systemd/src/install.rs +++ b/rust/tool/systemd/src/install.rs @@ -12,7 +12,7 @@ use tempfile::TempDir; use crate::esp::SystemdEspPaths; use crate::version::SystemdVersion; -use lanzaboote_tool::esp::{EspGenerationPaths, EspPaths}; +use lanzaboote_tool::esp::{EspGenerationPaths, EspPaths, Architecture}; use lanzaboote_tool::gc::Roots; use lanzaboote_tool::generation::{Generation, GenerationLink}; use lanzaboote_tool::os_release::OsRelease; @@ -335,7 +335,8 @@ impl Installer { fn install_systemd_boot(&self) -> Result<()> { let systemd_boot = self .systemd - .join("lib/systemd/boot/efi/systemd-bootx64.efi"); + .join("lib/systemd/boot/efi") + .join(self.arch.systemd_filename()); let paths = [ (&systemd_boot, &self.esp_paths.efi_fallback), From 9af0e56527b9db105e282d4c64d59b54c67711ff Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Tue, 25 Apr 2023 17:26:12 +0200 Subject: [PATCH 04/15] tool(esp): add systemd stub filenames mapping for systems --- rust/tool/shared/src/esp.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/rust/tool/shared/src/esp.rs b/rust/tool/shared/src/esp.rs index 3087d4c..e81ef7b 100644 --- a/rust/tool/shared/src/esp.rs +++ b/rust/tool/shared/src/esp.rs @@ -16,7 +16,14 @@ pub enum Architecture { AArch64, } -impl System { +impl Architecture { + pub fn systemd_stub_filename(&self) -> &Path { + Path::new(match self { + Self::X86 => "linuxx64.efi.stub", + Self::AArch64 => "linuxaa64.efi.stub" + }) + } + pub fn systemd_filename(&self) -> &Path { Path::new(match self { Self::X86 => "systemd-bootx64.efi", From acc4c2e0a1dde9bfa31594524775d81822e733f4 Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Tue, 25 Apr 2023 17:26:40 +0200 Subject: [PATCH 06/15] tool(tests): use library to use the "target architecture" properly in tests --- rust/tool/systemd/tests/common/mod.rs | 31 ++++++++++++++++++++++--- rust/tool/systemd/tests/systemd_boot.rs | 2 +- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/rust/tool/systemd/tests/common/mod.rs b/rust/tool/systemd/tests/common/mod.rs index f0a97ec..82d9380 100644 --- a/rust/tool/systemd/tests/common/mod.rs +++ b/rust/tool/systemd/tests/common/mod.rs @@ -17,6 +17,21 @@ use rand::{thread_rng, Rng}; use serde_json::json; use sha2::{Digest, Sha256}; +use lanzaboote_tool::architecture::Architecture; +use lzbt_systemd::architecture::SystemdArchitectureExt; + +/// Returns the host platform system +/// in the system double format for +/// our usual targets. +#[cfg(target_arch = "aarch64")] +pub static TARGET_SYSTEM_DOUBLE: &'static str = "aarch64-linux"; + +#[cfg(target_arch = "x86")] +pub static TARGET_SYSTEM_DOUBLE: &'static str = "i686-linux"; + +#[cfg(target_arch = "x86_64")] +pub static TARGET_SYSTEM_DOUBLE: &'static str = "x86_64-linux"; + /// Create a mock generation link. /// /// Works like `setup_generation_link_from_toplevel` but already sets up toplevel. @@ -55,7 +70,7 @@ pub fn setup_generation_link_from_toplevel( ], "label": "LanzaOS", "toplevel": toplevel, - "system": "x86_64-linux", + "system": TARGET_SYSTEM_DOUBLE, }, "org.nixos-community.lanzaboote": { "osRelease": toplevel.join("os-release") } }); @@ -78,13 +93,18 @@ pub fn setup_generation_link_from_toplevel( /// Accepts the temporary directory as a parameter so that the invoking function retains control of /// it (and when it goes out of scope). pub fn setup_toplevel(tmpdir: &Path) -> Result { + let system = Architecture::from_nixos_system(TARGET_SYSTEM_DOUBLE)?; // Generate a random toplevel name so that multiple toplevel paths can live alongside each // other in the same directory. let toplevel = tmpdir.join(format!("toplevel-{}", random_string(8))); fs::create_dir(&toplevel)?; let test_systemd = systemd_location_from_env()?; - let test_systemd_stub = format!("{test_systemd}/lib/systemd/boot/efi/linuxx64.efi.stub"); + let systemd_stub_filename = system.systemd_stub_filename(); + let test_systemd_stub = format!( + "{test_systemd}/lib/systemd/boot/efi/{systemd_stub_filename}", + systemd_stub_filename = systemd_stub_filename.display() + ); let initrd_path = toplevel.join("initrd"); let kernel_path = toplevel.join("kernel"); @@ -119,8 +139,13 @@ pub fn lanzaboote_install( ) -> Result { // To simplify the test setup, we use the systemd stub here instead of the lanzaboote stub. See // the comment in setup_toplevel for details. + let system = Architecture::from_nixos_system(TARGET_SYSTEM_DOUBLE)?; let test_systemd = systemd_location_from_env()?; - let test_systemd_stub = format!("{test_systemd}/lib/systemd/boot/efi/linuxx64.efi.stub"); + let systemd_stub_filename = system.systemd_stub_filename(); + let test_systemd_stub = format!( + "{test_systemd}/lib/systemd/boot/efi/{systemd_stub_filename}", + systemd_stub_filename = systemd_stub_filename.display() + ); let test_loader_config_path = tempfile::NamedTempFile::new()?; let test_loader_config = r"timeout 0\nconsole-mode 1\n"; diff --git a/rust/tool/systemd/tests/systemd_boot.rs b/rust/tool/systemd/tests/systemd_boot.rs index c6a07ed..03eb803 100644 --- a/rust/tool/systemd/tests/systemd_boot.rs +++ b/rust/tool/systemd/tests/systemd_boot.rs @@ -6,7 +6,7 @@ use tempfile::tempdir; mod common; -use common::{hash_file, mtime, remove_signature, verify_signature}; +use common::{hash_file, mtime, remove_signature, verify_signature, TARGET_SYSTEM_DOUBLE}; #[test] fn keep_systemd_boot_binaries() -> Result<()> { From e5c1d74e3fe5a6d3ec7544ebff59c2eebe029b1c Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Fri, 16 Jun 2023 16:23:39 +0200 Subject: [PATCH 07/15] tool: introduce --target-system to choose target architecture We will hard fail in case of encountering different architectures in bootspec. This should still be compatible with cross-compiling systems in the future. --- nix/modules/lanzaboote.nix | 1 + rust/tool/shared/src/esp.rs | 1 + rust/tool/systemd/src/cli.rs | 6 ++++++ rust/tool/systemd/src/install.rs | 7 +++++-- 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/nix/modules/lanzaboote.nix b/nix/modules/lanzaboote.nix index 92939db..d55e825 100644 --- a/nix/modules/lanzaboote.nix +++ b/nix/modules/lanzaboote.nix @@ -104,6 +104,7 @@ in ''} ${cfg.package}/bin/lzbt install \ + --system ${config.nixpkgs.hostPlatform.system} \ --systemd ${config.systemd.package} \ --systemd-boot-loader-config ${loaderConfigFile} \ --public-key ${cfg.publicKeyFile} \ diff --git a/rust/tool/shared/src/esp.rs b/rust/tool/shared/src/esp.rs index e81ef7b..9437cb0 100644 --- a/rust/tool/shared/src/esp.rs +++ b/rust/tool/shared/src/esp.rs @@ -76,6 +76,7 @@ impl EspGenerationPaths { pub fn new>( esp_paths: &P, generation: &Generation, + system: Architecture, ) -> Result { let bootspec = &generation.spec.bootspec.bootspec; let bootspec_system: Architecture = Architecture::from_nixos_system(&bootspec.system)?; diff --git a/rust/tool/systemd/src/cli.rs b/rust/tool/systemd/src/cli.rs index df86121..c8d4b47 100644 --- a/rust/tool/systemd/src/cli.rs +++ b/rust/tool/systemd/src/cli.rs @@ -3,6 +3,7 @@ use std::path::PathBuf; use anyhow::{Context, Result}; use clap::{Parser, Subcommand}; +use crate::esp::Architecture; use crate::install; use lanzaboote_tool::signature::KeyPair; @@ -30,6 +31,10 @@ enum Commands { #[derive(Parser)] struct InstallCommand { + /// Target system + #[arg(long)] + target_system: String, + /// Systemd path #[arg(long)] systemd: PathBuf, @@ -90,6 +95,7 @@ fn install(args: InstallCommand) -> Result<()> { install::Installer::new( PathBuf::from(lanzaboote_stub), + Architecture::from_nixos_system(&args.target_system)?, args.systemd, args.systemd_boot_loader_config, key_pair, diff --git a/rust/tool/systemd/src/install.rs b/rust/tool/systemd/src/install.rs index 36c528a..c5fc764 100644 --- a/rust/tool/systemd/src/install.rs +++ b/rust/tool/systemd/src/install.rs @@ -30,11 +30,13 @@ pub struct Installer { configuration_limit: usize, esp_paths: SystemdEspPaths, generation_links: Vec, + arch: Architecture, } impl Installer { pub fn new( lanzaboote_stub: PathBuf, + arch: Architecture, systemd: PathBuf, systemd_boot_loader_config: PathBuf, key_pair: KeyPair, @@ -56,6 +58,7 @@ impl Installer { configuration_limit, esp_paths, generation_links, + arch, } } @@ -238,7 +241,7 @@ impl Installer { let bootspec = &generation.spec.bootspec.bootspec; - let esp_gen_paths = EspGenerationPaths::new(&self.esp_paths, generation)?; + let esp_gen_paths = EspGenerationPaths::new(&self.esp_paths, generation, self.arch)?; self.gc_roots.extend(esp_gen_paths.to_iter()); let initrd_content = fs::read( @@ -284,7 +287,7 @@ impl Installer { let bootspec = &generation.spec.bootspec.bootspec; - let esp_gen_paths = EspGenerationPaths::new(&self.esp_paths, generation)?; + let esp_gen_paths = EspGenerationPaths::new(&self.esp_paths, generation, self.arch)?; let kernel_cmdline = assemble_kernel_cmdline(&bootspec.init, bootspec.kernel_params.clone()); From 609c11f26d7e035abcd66f3691171151b1b41a0e Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Fri, 16 Jun 2023 16:42:19 +0200 Subject: [PATCH 08/15] tool(systemd-boot): install it once instead of checking for each generation systemd-boot is now installed once for many generations rather than multiple times. This means it is not really possible to manage different system in the same "machine", which is a very obscure usecase, theoretically possible, but not yet encountered. --- rust/tool/shared/src/esp.rs | 2 +- rust/tool/systemd/src/install.rs | 4 ++-- rust/tool/systemd/tests/common/mod.rs | 2 ++ rust/tool/systemd/tests/systemd_boot.rs | 12 ++++++++++-- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/rust/tool/shared/src/esp.rs b/rust/tool/shared/src/esp.rs index 9437cb0..348e64c 100644 --- a/rust/tool/shared/src/esp.rs +++ b/rust/tool/shared/src/esp.rs @@ -53,7 +53,7 @@ impl Architecture { /// Generic ESP paths which can be specific to a bootloader pub trait EspPaths { /// Build an ESP path structure out of the ESP root directory - fn new(esp: impl AsRef) -> Self; + fn new(esp: impl AsRef, arch: Architecture) -> Self; /// Return the used file paths to store as garbage collection roots. fn iter(&self) -> std::array::IntoIter<&PathBuf, N>; diff --git a/rust/tool/systemd/src/install.rs b/rust/tool/systemd/src/install.rs index c5fc764..d0de11d 100644 --- a/rust/tool/systemd/src/install.rs +++ b/rust/tool/systemd/src/install.rs @@ -45,8 +45,8 @@ impl Installer { generation_links: Vec, ) -> Self { let mut gc_roots = Roots::new(); - let esp_paths = SystemdEspPaths::new(esp); - gc_roots.extend(esp_paths.iter()); + let esp_paths = EspPaths::new(esp, target_arch); + gc_roots.extend(esp_paths.to_iter()); Self { broken_gens: BTreeSet::new(), diff --git a/rust/tool/systemd/tests/common/mod.rs b/rust/tool/systemd/tests/common/mod.rs index 82d9380..0e1182c 100644 --- a/rust/tool/systemd/tests/common/mod.rs +++ b/rust/tool/systemd/tests/common/mod.rs @@ -156,6 +156,8 @@ pub fn lanzaboote_install( .env("LANZABOOTE_STUB", test_systemd_stub) .arg("-vv") .arg("install") + .arg("--system") + .arg(TARGET_SYSTEM_DOUBLE) .arg("--systemd") .arg(test_systemd) .arg("--systemd-boot-loader-config") diff --git a/rust/tool/systemd/tests/systemd_boot.rs b/rust/tool/systemd/tests/systemd_boot.rs index 03eb803..53e5fbe 100644 --- a/rust/tool/systemd/tests/systemd_boot.rs +++ b/rust/tool/systemd/tests/systemd_boot.rs @@ -2,6 +2,8 @@ use std::fs; use std::path::PathBuf; use anyhow::Result; +use lanzaboote_tool::architecture::Architecture; +use lzbt_systemd::architecture::SystemdArchitectureExt; use tempfile::tempdir; mod common; @@ -113,9 +115,15 @@ fn overwrite_unsigned_systemd_boot_binaries() -> Result<()> { } fn systemd_boot_path(esp: &tempfile::TempDir) -> PathBuf { - esp.path().join("EFI/systemd/systemd-bootx64.efi") + let arch = Architecture::from_nixos_system(TARGET_SYSTEM_DOUBLE).unwrap(); + esp.path() + .join("EFI/systemd/") + .join(arch.systemd_filename()) } fn systemd_boot_fallback_path(esp: &tempfile::TempDir) -> PathBuf { - esp.path().join("EFI/BOOT/BOOTX64.EFI") + let arch = Architecture::from_nixos_system(TARGET_SYSTEM_DOUBLE).unwrap(); + esp.path() + .join("EFI/BOOT/") + .join(arch.efi_fallback_filename()) } From 0107754d62dd5b5738c2f648cd1a9815ae813677 Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Sat, 22 Jul 2023 19:16:39 +0200 Subject: [PATCH 09/15] tool(architecture): make it generic Architecture is now a generic structure that can be specialized via an "external" trait for generating the paths you care about depending on your target bootloader. --- rust/tool/shared/src/architecture.rs | 35 ++++++++++++++++++++ rust/tool/shared/src/esp.rs | 46 ++------------------------- rust/tool/shared/src/lib.rs | 1 + rust/tool/systemd/src/architecture.rs | 19 +++++++++++ rust/tool/systemd/src/cli.rs | 8 ++--- rust/tool/systemd/src/esp.rs | 8 +++-- rust/tool/systemd/src/install.rs | 8 +++-- rust/tool/systemd/src/lib.rs | 1 + rust/tool/systemd/src/main.rs | 1 + 9 files changed, 73 insertions(+), 54 deletions(-) create mode 100644 rust/tool/shared/src/architecture.rs create mode 100644 rust/tool/systemd/src/architecture.rs create mode 100644 rust/tool/systemd/src/lib.rs diff --git a/rust/tool/shared/src/architecture.rs b/rust/tool/shared/src/architecture.rs new file mode 100644 index 0000000..9a55f3b --- /dev/null +++ b/rust/tool/shared/src/architecture.rs @@ -0,0 +1,35 @@ +use std::path::PathBuf; + +use anyhow::{bail, Result}; + +/// Supported system +#[non_exhaustive] +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum Architecture { + X86, + AArch64, +} + +impl Architecture { + pub fn efi_representation(&self) -> &str { + match self { + Self::X86 => "x64", + Self::AArch64 => "aa64", + } + } + + pub fn efi_fallback_filename(&self) -> PathBuf { + format!("BOOT{}.EFI", self.efi_representation().to_ascii_uppercase()).into() + } +} + +impl Architecture { + /// Converts from a NixOS system double to a supported system + pub fn from_nixos_system(system_double: &str) -> Result { + Ok(match system_double { + "x86_64-linux" => Self::X86, + "aarch64-linux" => Self::AArch64, + _ => bail!("Unsupported NixOS system double: {}, please open an issue or a PR if you think this should be supported.", system_double) + }) + } +} diff --git a/rust/tool/shared/src/esp.rs b/rust/tool/shared/src/esp.rs index 348e64c..e09d927 100644 --- a/rust/tool/shared/src/esp.rs +++ b/rust/tool/shared/src/esp.rs @@ -3,53 +3,11 @@ use std::{ path::{Path, PathBuf}, }; -use anyhow::{Context, Result, bail}; +use anyhow::{Context, Result}; +use crate::architecture::Architecture; use crate::generation::Generation; -/// Supported system -#[allow(dead_code)] -#[non_exhaustive] -#[derive(Copy, Clone, PartialEq, Debug)] -pub enum Architecture { - X86, - AArch64, -} - -impl Architecture { - pub fn systemd_stub_filename(&self) -> &Path { - Path::new(match self { - Self::X86 => "linuxx64.efi.stub", - Self::AArch64 => "linuxaa64.efi.stub" - }) - } - - pub fn systemd_filename(&self) -> &Path { - Path::new(match self { - Self::X86 => "systemd-bootx64.efi", - Self::AArch64 => "systemd-bootaa64.efi" - }) - } - - pub fn efi_fallback_filename(&self) -> &Path { - Path::new(match self { - Self::X86 => "BOOTX64.EFI", - Self::AArch64 => "BOOTAA64.EFI", - }) - } -} - -impl Architecture { - /// Converts from a NixOS system double to a supported system - pub fn from_nixos_system(system_double: &str) -> Result { - Ok(match system_double { - "x86_64-linux" => Self::X86, - "aarch64-linux" => Self::AArch64, - _ => bail!("Unsupported NixOS system double: {}, please open an issue or a PR if you think this should be supported.", system_double) - }) - } -} - /// Generic ESP paths which can be specific to a bootloader pub trait EspPaths { /// Build an ESP path structure out of the ESP root directory diff --git a/rust/tool/shared/src/lib.rs b/rust/tool/shared/src/lib.rs index eb3c899..35c1465 100644 --- a/rust/tool/shared/src/lib.rs +++ b/rust/tool/shared/src/lib.rs @@ -1,3 +1,4 @@ +pub mod architecture; pub mod esp; pub mod gc; pub mod generation; diff --git a/rust/tool/systemd/src/architecture.rs b/rust/tool/systemd/src/architecture.rs new file mode 100644 index 0000000..173f148 --- /dev/null +++ b/rust/tool/systemd/src/architecture.rs @@ -0,0 +1,19 @@ +use std::path::PathBuf; + +use lanzaboote_tool::architecture::Architecture; + +/// Systemd-specific architecture helpers +pub trait SystemdArchitectureExt { + fn systemd_stub_filename(&self) -> PathBuf; + fn systemd_filename(&self) -> PathBuf; +} + +impl SystemdArchitectureExt for Architecture { + fn systemd_stub_filename(&self) -> PathBuf { + format!("linux{}.efi.stub", self.efi_representation()).into() + } + + fn systemd_filename(&self) -> PathBuf { + format!("systemd-boot{}.efi", self.efi_representation()).into() + } +} diff --git a/rust/tool/systemd/src/cli.rs b/rust/tool/systemd/src/cli.rs index c8d4b47..90d91c0 100644 --- a/rust/tool/systemd/src/cli.rs +++ b/rust/tool/systemd/src/cli.rs @@ -3,8 +3,8 @@ use std::path::PathBuf; use anyhow::{Context, Result}; use clap::{Parser, Subcommand}; -use crate::esp::Architecture; use crate::install; +use lanzaboote_tool::architecture::Architecture; use lanzaboote_tool::signature::KeyPair; /// The default log level. @@ -31,9 +31,9 @@ enum Commands { #[derive(Parser)] struct InstallCommand { - /// Target system + /// System for lanzaboote binaries, e.g. defines the EFI fallback path #[arg(long)] - target_system: String, + system: String, /// Systemd path #[arg(long)] @@ -95,7 +95,7 @@ fn install(args: InstallCommand) -> Result<()> { install::Installer::new( PathBuf::from(lanzaboote_stub), - Architecture::from_nixos_system(&args.target_system)?, + Architecture::from_nixos_system(&args.system)?, args.systemd, args.systemd_boot_loader_config, key_pair, diff --git a/rust/tool/systemd/src/esp.rs b/rust/tool/systemd/src/esp.rs index e3afd6e..7227367 100644 --- a/rust/tool/systemd/src/esp.rs +++ b/rust/tool/systemd/src/esp.rs @@ -1,5 +1,7 @@ use std::path::{Path, PathBuf}; +use crate::architecture::SystemdArchitectureExt; +use lanzaboote_tool::architecture::Architecture; use lanzaboote_tool::esp::EspPaths; /// Paths to the boot files that are not specific to a generation. @@ -18,7 +20,7 @@ pub struct SystemdEspPaths { } impl EspPaths<10> for SystemdEspPaths { - fn new(esp: impl AsRef) -> Self { + fn new(esp: impl AsRef, architecture: Architecture) -> Self { let esp = esp.as_ref(); let efi = esp.join("EFI"); let efi_nixos = efi.join("nixos"); @@ -34,9 +36,9 @@ impl EspPaths<10> for SystemdEspPaths { nixos: efi_nixos, linux: efi_linux, efi_fallback_dir: efi_efi_fallback_dir.clone(), - efi_fallback: efi_efi_fallback_dir.join("BOOTX64.EFI"), + efi_fallback: efi_efi_fallback_dir.join(architecture.efi_fallback_filename()), systemd: efi_systemd.clone(), - systemd_boot: efi_systemd.join("systemd-bootx64.efi"), + systemd_boot: efi_systemd.join(architecture.systemd_filename()), loader, systemd_boot_loader_config, } diff --git a/rust/tool/systemd/src/install.rs b/rust/tool/systemd/src/install.rs index d0de11d..55a0733 100644 --- a/rust/tool/systemd/src/install.rs +++ b/rust/tool/systemd/src/install.rs @@ -10,9 +10,11 @@ use anyhow::{anyhow, Context, Result}; use nix::unistd::syncfs; use tempfile::TempDir; +use crate::architecture::SystemdArchitectureExt; use crate::esp::SystemdEspPaths; use crate::version::SystemdVersion; -use lanzaboote_tool::esp::{EspGenerationPaths, EspPaths, Architecture}; +use lanzaboote_tool::architecture::Architecture; +use lanzaboote_tool::esp::{EspGenerationPaths, EspPaths}; use lanzaboote_tool::gc::Roots; use lanzaboote_tool::generation::{Generation, GenerationLink}; use lanzaboote_tool::os_release::OsRelease; @@ -45,8 +47,8 @@ impl Installer { generation_links: Vec, ) -> Self { let mut gc_roots = Roots::new(); - let esp_paths = EspPaths::new(esp, target_arch); - gc_roots.extend(esp_paths.to_iter()); + let esp_paths = SystemdEspPaths::new(esp, arch); + gc_roots.extend(esp_paths.iter()); Self { broken_gens: BTreeSet::new(), diff --git a/rust/tool/systemd/src/lib.rs b/rust/tool/systemd/src/lib.rs new file mode 100644 index 0000000..0f1102b --- /dev/null +++ b/rust/tool/systemd/src/lib.rs @@ -0,0 +1 @@ +pub mod architecture; diff --git a/rust/tool/systemd/src/main.rs b/rust/tool/systemd/src/main.rs index b453557..51633de 100644 --- a/rust/tool/systemd/src/main.rs +++ b/rust/tool/systemd/src/main.rs @@ -1,3 +1,4 @@ +mod architecture; mod cli; mod esp; mod install; From 1330292008775aff4155b3825cf69be167718271 Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Thu, 14 Sep 2023 15:25:51 +0200 Subject: [PATCH 10/15] tool/systemd: make clippy happy I guess --- rust/tool/systemd/src/install.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/rust/tool/systemd/src/install.rs b/rust/tool/systemd/src/install.rs index 55a0733..bdcb676 100644 --- a/rust/tool/systemd/src/install.rs +++ b/rust/tool/systemd/src/install.rs @@ -36,6 +36,7 @@ pub struct Installer { } impl Installer { + #[allow(clippy::too_many_arguments)] pub fn new( lanzaboote_stub: PathBuf, arch: Architecture, From f81c30d7d957e901994acc54241db8a6e51ab5ed Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Thu, 14 Sep 2023 15:33:10 +0200 Subject: [PATCH 11/15] module: use kernel package hostPlatform if nixpkgs.hostPlatform is not available MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sometimes, it is not… --- nix/modules/lanzaboote.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/modules/lanzaboote.nix b/nix/modules/lanzaboote.nix index d55e825..ac586c6 100644 --- a/nix/modules/lanzaboote.nix +++ b/nix/modules/lanzaboote.nix @@ -104,7 +104,7 @@ in ''} ${cfg.package}/bin/lzbt install \ - --system ${config.nixpkgs.hostPlatform.system} \ + --system ${config.nixpkgs.hostPlatform.system or config.boot.kernelPackages.stdenv.hostPlatform.system} \ --systemd ${config.systemd.package} \ --systemd-boot-loader-config ${loaderConfigFile} \ --public-key ${cfg.publicKeyFile} \ From 3bf55f92b871bae05a1832542c724314c1ef1ff0 Mon Sep 17 00:00:00 2001 From: nikstur Date: Thu, 14 Sep 2023 16:15:50 +0200 Subject: [PATCH 12/15] test: clean up a few minor details --- rust/tool/systemd/tests/common/mod.rs | 16 +++++++++------- rust/tool/systemd/tests/systemd_boot.rs | 6 +++--- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/rust/tool/systemd/tests/common/mod.rs b/rust/tool/systemd/tests/common/mod.rs index 0e1182c..ac17003 100644 --- a/rust/tool/systemd/tests/common/mod.rs +++ b/rust/tool/systemd/tests/common/mod.rs @@ -24,13 +24,15 @@ use lzbt_systemd::architecture::SystemdArchitectureExt; /// in the system double format for /// our usual targets. #[cfg(target_arch = "aarch64")] -pub static TARGET_SYSTEM_DOUBLE: &'static str = "aarch64-linux"; +pub static SYSTEM: &str = "aarch64-linux"; +// We do not actually care much about 32 bit. However we can use this to easily test that lzbt +// works with another architecture. #[cfg(target_arch = "x86")] -pub static TARGET_SYSTEM_DOUBLE: &'static str = "i686-linux"; +pub static SYSTEM: &str = "i686-linux"; #[cfg(target_arch = "x86_64")] -pub static TARGET_SYSTEM_DOUBLE: &'static str = "x86_64-linux"; +pub static SYSTEM: &str = "x86_64-linux"; /// Create a mock generation link. /// @@ -70,7 +72,7 @@ pub fn setup_generation_link_from_toplevel( ], "label": "LanzaOS", "toplevel": toplevel, - "system": TARGET_SYSTEM_DOUBLE, + "system": SYSTEM, }, "org.nixos-community.lanzaboote": { "osRelease": toplevel.join("os-release") } }); @@ -93,7 +95,7 @@ pub fn setup_generation_link_from_toplevel( /// Accepts the temporary directory as a parameter so that the invoking function retains control of /// it (and when it goes out of scope). pub fn setup_toplevel(tmpdir: &Path) -> Result { - let system = Architecture::from_nixos_system(TARGET_SYSTEM_DOUBLE)?; + let system = Architecture::from_nixos_system(SYSTEM)?; // Generate a random toplevel name so that multiple toplevel paths can live alongside each // other in the same directory. let toplevel = tmpdir.join(format!("toplevel-{}", random_string(8))); @@ -139,7 +141,7 @@ pub fn lanzaboote_install( ) -> Result { // To simplify the test setup, we use the systemd stub here instead of the lanzaboote stub. See // the comment in setup_toplevel for details. - let system = Architecture::from_nixos_system(TARGET_SYSTEM_DOUBLE)?; + let system = Architecture::from_nixos_system(SYSTEM)?; let test_systemd = systemd_location_from_env()?; let systemd_stub_filename = system.systemd_stub_filename(); let test_systemd_stub = format!( @@ -157,7 +159,7 @@ pub fn lanzaboote_install( .arg("-vv") .arg("install") .arg("--system") - .arg(TARGET_SYSTEM_DOUBLE) + .arg(SYSTEM) .arg("--systemd") .arg(test_systemd) .arg("--systemd-boot-loader-config") diff --git a/rust/tool/systemd/tests/systemd_boot.rs b/rust/tool/systemd/tests/systemd_boot.rs index 53e5fbe..d295f79 100644 --- a/rust/tool/systemd/tests/systemd_boot.rs +++ b/rust/tool/systemd/tests/systemd_boot.rs @@ -8,7 +8,7 @@ use tempfile::tempdir; mod common; -use common::{hash_file, mtime, remove_signature, verify_signature, TARGET_SYSTEM_DOUBLE}; +use common::{hash_file, mtime, remove_signature, verify_signature, SYSTEM}; #[test] fn keep_systemd_boot_binaries() -> Result<()> { @@ -115,14 +115,14 @@ fn overwrite_unsigned_systemd_boot_binaries() -> Result<()> { } fn systemd_boot_path(esp: &tempfile::TempDir) -> PathBuf { - let arch = Architecture::from_nixos_system(TARGET_SYSTEM_DOUBLE).unwrap(); + let arch = Architecture::from_nixos_system(SYSTEM).unwrap(); esp.path() .join("EFI/systemd/") .join(arch.systemd_filename()) } fn systemd_boot_fallback_path(esp: &tempfile::TempDir) -> PathBuf { - let arch = Architecture::from_nixos_system(TARGET_SYSTEM_DOUBLE).unwrap(); + let arch = Architecture::from_nixos_system(SYSTEM).unwrap(); esp.path() .join("EFI/BOOT/") .join(arch.efi_fallback_filename()) From 0b5ce324d7fb9ace6e1bab20f2eaf513585b2aea Mon Sep 17 00:00:00 2001 From: nikstur Date: Thu, 14 Sep 2023 16:18:58 +0200 Subject: [PATCH 13/15] tool: clean up a few minor details --- nix/modules/lanzaboote.nix | 4 +++- rust/tool/shared/src/architecture.rs | 2 +- rust/tool/shared/src/esp.rs | 13 ++++++++----- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/nix/modules/lanzaboote.nix b/nix/modules/lanzaboote.nix index ac586c6..287f3b1 100644 --- a/nix/modules/lanzaboote.nix +++ b/nix/modules/lanzaboote.nix @@ -103,8 +103,10 @@ in ${sbctlWithPki}/bin/sbctl enroll-keys --yes-this-might-brick-my-machine ''} + # Use the system from the kernel's hostPlatform because this should + # always, even in the cross compilation case, be the right system. ${cfg.package}/bin/lzbt install \ - --system ${config.nixpkgs.hostPlatform.system or config.boot.kernelPackages.stdenv.hostPlatform.system} \ + --system ${config.boot.kernelPackages.stdenv.hostPlatform.system} \ --systemd ${config.systemd.package} \ --systemd-boot-loader-config ${loaderConfigFile} \ --public-key ${cfg.publicKeyFile} \ diff --git a/rust/tool/shared/src/architecture.rs b/rust/tool/shared/src/architecture.rs index 9a55f3b..94b1761 100644 --- a/rust/tool/shared/src/architecture.rs +++ b/rust/tool/shared/src/architecture.rs @@ -29,7 +29,7 @@ impl Architecture { Ok(match system_double { "x86_64-linux" => Self::X86, "aarch64-linux" => Self::AArch64, - _ => bail!("Unsupported NixOS system double: {}, please open an issue or a PR if you think this should be supported.", system_double) + _ => bail!(format!("Unsupported NixOS system: {}.", system_double)), }) } } diff --git a/rust/tool/shared/src/esp.rs b/rust/tool/shared/src/esp.rs index e09d927..73a1fa6 100644 --- a/rust/tool/shared/src/esp.rs +++ b/rust/tool/shared/src/esp.rs @@ -3,7 +3,8 @@ use std::{ path::{Path, PathBuf}, }; -use anyhow::{Context, Result}; +use anyhow::{bail, Context, Result}; +use indoc::indoc; use crate::architecture::Architecture; use crate::generation::Generation; @@ -39,10 +40,12 @@ impl EspGenerationPaths { let bootspec = &generation.spec.bootspec.bootspec; let bootspec_system: Architecture = Architecture::from_nixos_system(&bootspec.system)?; - assert_eq!( - system, bootspec_system, - "Bootspec's system differs from provided target system, unsupported usecase!" - ); + if system != bootspec_system { + bail!(indoc! {r#" + The CPU architecture declared in your module differs from the one declared in the + bootspec of the current generation. + "#}) + } Ok(Self { kernel: esp_paths From 976faf9bf56a46a51d92777b04c0d3f9fc078074 Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Thu, 14 Sep 2023 16:55:11 +0200 Subject: [PATCH 14/15] flake: use proper uefi target in general Remove the x86_64 hardcoding. --- flake.nix | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/flake.nix b/flake.nix index e73f253..d5a47e9 100644 --- a/flake.nix +++ b/flake.nix @@ -79,6 +79,7 @@ perSystem = { config, system, pkgs, ... }: let + rustTarget = "${pkgs.hostPlatform.qemuArch}-unknown-uefi"; pkgs = import nixpkgs { system = system; overlays = [ @@ -89,7 +90,7 @@ inherit (pkgs) lib; uefi-rust-stable = pkgs.rust-bin.fromRustupToolchainFile ./rust/uefi/rust-toolchain.toml; - craneLib = crane.lib.x86_64-linux.overrideToolchain uefi-rust-stable; + craneLib = crane.lib.${system}.overrideToolchain uefi-rust-stable; # Build attributes for a Rust application. buildRustApp = lib.makeOverridable ( @@ -145,7 +146,7 @@ stubCrane = buildRustApp { pname = "lanzaboote-stub"; src = craneLib.cleanCargoSource ./rust/uefi; - target = "x86_64-unknown-uefi"; + target = rustTarget; doCheck = false; }; From 7951cbc66893e6ebf1d49a1fa048710240c0141c Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Fri, 29 Sep 2023 02:40:26 +0200 Subject: [PATCH 15/15] flake: bump to get systemd v254 With systemd v254, we get valid AA64 EFI binaries from systemd! --- flake.lock | 6 +++--- flake.nix | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 7e49cc1..8be1779 100644 --- a/flake.lock +++ b/flake.lock @@ -106,11 +106,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1689951833, - "narHash": "sha256-wdpIgb5X0p85RRne74TeUOp9ti7a1k9KDSe4NzsaAGk=", + "lastModified": 1695859332, + "narHash": "sha256-w2a7NW3VtI5FgFPUKslYRGAj5Qb7y4i0I2QO0S/lBMQ=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "ebf4e87429ce7faa51a86a36a7b2e615c8bcc735", + "rev": "248a83fffc10b627da67fa6b25d2c13fc7542628", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index d5a47e9..fd32041 100644 --- a/flake.nix +++ b/flake.nix @@ -235,6 +235,7 @@ let systemdUkify = pkgs.systemdMinimal.override { withEfi = true; + withBootloader = true; withUkify = true; }; in