Merge pull request #31 from nix-community/aarch64
This commit is contained in:
commit
644dc8a269
|
@ -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": {
|
||||
|
|
|
@ -74,11 +74,12 @@
|
|||
"x86_64-linux"
|
||||
|
||||
# Not actively tested, but may work:
|
||||
# "aarch64-linux"
|
||||
"aarch64-linux"
|
||||
];
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
|
@ -234,6 +235,7 @@
|
|||
let
|
||||
systemdUkify = pkgs.systemdMinimal.override {
|
||||
withEfi = true;
|
||||
withBootloader = true;
|
||||
withUkify = true;
|
||||
};
|
||||
in
|
||||
|
|
|
@ -103,7 +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.boot.kernelPackages.stdenv.hostPlatform.system} \
|
||||
--systemd ${config.systemd.package} \
|
||||
--systemd-boot-loader-config ${loaderConfigFile} \
|
||||
--public-key ${cfg.publicKeyFile} \
|
||||
|
|
|
@ -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<Self> {
|
||||
Ok(match system_double {
|
||||
"x86_64-linux" => Self::X86,
|
||||
"aarch64-linux" => Self::AArch64,
|
||||
_ => bail!(format!("Unsupported NixOS system: {}.", system_double)),
|
||||
})
|
||||
}
|
||||
}
|
|
@ -3,14 +3,16 @@ 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;
|
||||
|
||||
/// Generic ESP paths which can be specific to a bootloader
|
||||
pub trait EspPaths<const N: usize> {
|
||||
/// Build an ESP path structure out of the ESP root directory
|
||||
fn new(esp: impl AsRef<Path>) -> Self;
|
||||
fn new(esp: impl AsRef<Path>, arch: Architecture) -> Self;
|
||||
|
||||
/// Return the used file paths to store as garbage collection roots.
|
||||
fn iter(&self) -> std::array::IntoIter<&PathBuf, N>;
|
||||
|
@ -33,8 +35,17 @@ impl EspGenerationPaths {
|
|||
pub fn new<const N: usize, P: EspPaths<N>>(
|
||||
esp_paths: &P,
|
||||
generation: &Generation,
|
||||
system: Architecture,
|
||||
) -> Result<Self> {
|
||||
let bootspec = &generation.spec.bootspec.bootspec;
|
||||
let bootspec_system: Architecture = Architecture::from_nixos_system(&bootspec.system)?;
|
||||
|
||||
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
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
pub mod architecture;
|
||||
pub mod esp;
|
||||
pub mod gc;
|
||||
pub mod generation;
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ use anyhow::{Context, Result};
|
|||
use clap::{Parser, Subcommand};
|
||||
|
||||
use crate::install;
|
||||
use lanzaboote_tool::architecture::Architecture;
|
||||
use lanzaboote_tool::signature::KeyPair;
|
||||
|
||||
/// The default log level.
|
||||
|
@ -30,6 +31,10 @@ enum Commands {
|
|||
|
||||
#[derive(Parser)]
|
||||
struct InstallCommand {
|
||||
/// System for lanzaboote binaries, e.g. defines the EFI fallback path
|
||||
#[arg(long)]
|
||||
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.system)?,
|
||||
args.systemd,
|
||||
args.systemd_boot_loader_config,
|
||||
key_pair,
|
||||
|
|
|
@ -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<Path>) -> Self {
|
||||
fn new(esp: impl AsRef<Path>, 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,
|
||||
}
|
||||
|
|
|
@ -10,8 +10,10 @@ 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::architecture::Architecture;
|
||||
use lanzaboote_tool::esp::{EspGenerationPaths, EspPaths};
|
||||
use lanzaboote_tool::gc::Roots;
|
||||
use lanzaboote_tool::generation::{Generation, GenerationLink};
|
||||
|
@ -30,11 +32,14 @@ pub struct Installer {
|
|||
configuration_limit: usize,
|
||||
esp_paths: SystemdEspPaths,
|
||||
generation_links: Vec<PathBuf>,
|
||||
arch: Architecture,
|
||||
}
|
||||
|
||||
impl Installer {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
lanzaboote_stub: PathBuf,
|
||||
arch: Architecture,
|
||||
systemd: PathBuf,
|
||||
systemd_boot_loader_config: PathBuf,
|
||||
key_pair: KeyPair,
|
||||
|
@ -43,7 +48,7 @@ impl Installer {
|
|||
generation_links: Vec<PathBuf>,
|
||||
) -> Self {
|
||||
let mut gc_roots = Roots::new();
|
||||
let esp_paths = SystemdEspPaths::new(esp);
|
||||
let esp_paths = SystemdEspPaths::new(esp, arch);
|
||||
gc_roots.extend(esp_paths.iter());
|
||||
|
||||
Self {
|
||||
|
@ -56,6 +61,7 @@ impl Installer {
|
|||
configuration_limit,
|
||||
esp_paths,
|
||||
generation_links,
|
||||
arch,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -238,7 +244,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 +290,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());
|
||||
|
@ -335,7 +341,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),
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
pub mod architecture;
|
|
@ -1,3 +1,4 @@
|
|||
mod architecture;
|
||||
mod cli;
|
||||
mod esp;
|
||||
mod install;
|
||||
|
|
|
@ -17,6 +17,23 @@ 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 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 SYSTEM: &str = "i686-linux";
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub static SYSTEM: &str = "x86_64-linux";
|
||||
|
||||
/// Create a mock generation link.
|
||||
///
|
||||
/// Works like `setup_generation_link_from_toplevel` but already sets up toplevel.
|
||||
|
@ -55,7 +72,7 @@ pub fn setup_generation_link_from_toplevel(
|
|||
],
|
||||
"label": "LanzaOS",
|
||||
"toplevel": toplevel,
|
||||
"system": "x86_64-linux",
|
||||
"system": SYSTEM,
|
||||
},
|
||||
"org.nixos-community.lanzaboote": { "osRelease": toplevel.join("os-release") }
|
||||
});
|
||||
|
@ -78,13 +95,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<PathBuf> {
|
||||
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)));
|
||||
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 +141,13 @@ pub fn lanzaboote_install(
|
|||
) -> Result<Output> {
|
||||
// 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(SYSTEM)?;
|
||||
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";
|
||||
|
@ -131,6 +158,8 @@ pub fn lanzaboote_install(
|
|||
.env("LANZABOOTE_STUB", test_systemd_stub)
|
||||
.arg("-vv")
|
||||
.arg("install")
|
||||
.arg("--system")
|
||||
.arg(SYSTEM)
|
||||
.arg("--systemd")
|
||||
.arg(test_systemd)
|
||||
.arg("--systemd-boot-loader-config")
|
||||
|
|
|
@ -2,11 +2,13 @@ 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;
|
||||
|
||||
use common::{hash_file, mtime, remove_signature, verify_signature};
|
||||
use common::{hash_file, mtime, remove_signature, verify_signature, SYSTEM};
|
||||
|
||||
#[test]
|
||||
fn keep_systemd_boot_binaries() -> Result<()> {
|
||||
|
@ -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(SYSTEM).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(SYSTEM).unwrap();
|
||||
esp.path()
|
||||
.join("EFI/BOOT/")
|
||||
.join(arch.efi_fallback_filename())
|
||||
}
|
||||
|
|
|
@ -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" ]
|
||||
|
|
Loading…
Reference in New Issue