Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ libc = "0.2"
# use — the detached .sig is a cross-repo wire contract.
ed25519-compact = { version = "2", default-features = false }

vaportpm-attest = { git = "https://github.com/lockboot/vaportpm" }
# Pinned to the vaportpm v0.3.0 release commit: immutable SHA + a `version` guard (the build fails
# if the rev ever drifts to a commit whose crate version isn't 0.3.0). Tag is not GPG-signed yet;
# a signed release will follow. Bump both on the next vaportpm release.
vaportpm-attest = { git = "https://github.com/lockboot/vaportpm", rev = "7041f461eb33bc15ad914466042b7befe358d119", version = "=0.3.0" }

reqwest = { version = "=0.12.24", default-features = false, features = ["blocking", "rustls-tls-webpki-roots-no-provider"] }
rustls = { version = "=0.23.23", default-features = false, features = ["std", "tls12"] }
Expand Down
2 changes: 2 additions & 0 deletions Dockerfile.build
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ RUN apt-get -qq update && \
fdisk \
findutils \
gdisk \
gnupg \
gzip \
kmod \
make \
Expand All @@ -23,6 +24,7 @@ RUN apt-get -qq update && \
python3 \
python3-pip \
qemu-efi-aarch64 \
rpm \
rpm2cpio \
sbsigntool \
util-linux \
Expand Down
81 changes: 17 additions & 64 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,71 +28,13 @@ DEFAULT_STAGE2_URL = https://lockboot.s3.us-east-1.amazonaws.com/examples/stage2
user-data.json:
wget -O "$@" $(DEFAULT_STAGE2_URL)

# ---- Docker images (shared lockboot family; built locally, never published) ----
# BUILD_IMAGE compiles everything; HARNESS_IMAGE (from stage0) runs the qemu chain
# test. Both are built by the workspace `make image` from stage0 (the canonical
# Dockerfiles); a standalone CI clone builds BUILD_IMAGE itself via docker-build-base.
BUILD_IMAGE = lockboot:build
HARNESS_IMAGE = lockboot:harness
RUNTIME_IMAGE ?= lockboot:latest
# ---- Shared build harness (docker images + DOCKER_RUN plumbing) ----
# Vendored byte-identically from stage0/build.mk (the canonical source) via the workspace
# `make sync-harness`; do not hand-edit. `make check-harness` guards against drift.
include build.mk

.PHONY: docker-build-base
docker-build-base:
docker build -f Dockerfile.build -t $(BUILD_IMAGE) .

# ---- Docker run plumbing (keep identical across repos; mirrors stage0/Makefile) ----
# Own build artifacts by whoever owns the checkout, not the caller's euid. Under
# `gh act` the caller is root but the bind-mounted tree is still yours, so stat
# keeps output user-owned instead of trampling the project dir with root files.
USER_ID := $(shell stat -c %u .)
GROUP_ID := $(shell stat -c %g .)

KVM_GID := $(shell stat -c %g /dev/kvm 2>/dev/null || echo "")
KVM_MOUNT := $(shell test -e /dev/kvm && echo "-v /dev/kvm:/dev/kvm")
DOCKER_OPT_KVM := $(if $(KVM_GID),--group-add $(KVM_GID)) $(KVM_MOUNT)

# Recursive-docker passthrough: the UKI rule and runtime-image build shell out to
# the HOST docker daemon (rootfs extraction / buildx), so forward the socket + gid.
DOCKER_SOCK_GID := $(shell stat -c %g /var/run/docker.sock 2>/dev/null || echo "")
DOCKER_SOCK_MOUNT := $(shell test -e /var/run/docker.sock && echo "-v /var/run/docker.sock:/var/run/docker.sock")
DOCKER_OPT_DOCKER := $(DOCKER_SOCK_MOUNT) $(if $(DOCKER_SOCK_GID),--group-add $(DOCKER_SOCK_GID))

DOCKER_SAMEUSER := -u $(USER_ID):$(GROUP_ID)

# Host-path translation for docker-in-devcontainer. Inside the devcontainer /src is
# a host bind mount and the inner Docker talks to the HOST daemon, which cannot
# resolve /src/... paths; translate $(CURDIR) to the real host path (the bracketed
# subpath findmnt reports for the /src bind). On the host CURDIR is not under /src,
# so this is a pass-through and your workflow is unchanged. Keep identical across repos.
HOST_DIR := $(CURDIR)
ifneq ($(filter /src/%,$(CURDIR)),)
SRC_BIND := $(shell findmnt -fnro SOURCE --target /src 2>/dev/null | sed -n 's/.*\[\(.*\)\]$$/\1/p')
ifneq ($(SRC_BIND),)
HOST_DIR := $(SRC_BIND)$(CURDIR:/src%=%)
endif
endif

# Mount the WORKSPACE (parent of this repo) at /src so builds reuse the shared
# workspace-level .cargo/.rustup (matching the devcontainer), instead of creating
# per-repo copies. The repo then lives at /src/$(REPO_NAME).
REPO_NAME := $(notdir $(HOST_DIR))
HOST_WS := $(patsubst %/,%,$(dir $(HOST_DIR)))

# Under CI / `gh act` (CI=true, runs as root) keep cargo/rustup caches ephemeral
# inside the container, so root-owned dirs never land in the bind-mounted project.
# Locally (no CI) the image's CARGO_HOME=/src/.cargo + RUSTUP_HOME=/src/.rustup win,
# i.e. the shared workspace caches.
CACHE_ENV := $(if $(CI),-e CARGO_HOME=/tmp/.cargo -e RUSTUP_HOME=/tmp/.rustup)

DOCKER_RUN = docker run --rm \
--privileged \
-v $(HOST_WS):/src \
-h lockboot \
--add-host lockboot:127.0.0.1 \
-e OWNER_UID=$(USER_ID) \
-e OWNER_GID=$(GROUP_ID) \
$(CACHE_ENV) \
-w /src/$(REPO_NAME)
# stage1-only: runtime OCI image tag for the docker-runtime / buildx targets below.
RUNTIME_IMAGE ?= lockboot:latest

docker-shell-base: docker-build-base
$(DOCKER_RUN) -ti $(DOCKER_SAMEUSER) $(DOCKER_OPT_DOCKER) $(DOCKER_OPT_KVM) $(BUILD_IMAGE) bash
Expand Down Expand Up @@ -143,6 +85,17 @@ tools/build-uki/mkuki: docker-build-base
$(DOCKER_RUN) $(DOCKER_SAMEUSER) $(BUILD_IMAGE) \
bash -c "cargo build --release --locked -p mkuki --target x86_64-unknown-linux-musl && cp -v target/x86_64-unknown-linux-musl/release/mkuki $@"

# Regenerate tools/build-uki/fedora-deps.mk (pinned, GPG-verified kernel + systemd-boot stub).
# make update-fedora-deps FCOS=44.20260621.3.1 [SYSTEMD=259.6-1.fc44] [KERNEL=<nvr>]
# Kernel NVR is read from the FCOS build manifest; the stub is pulled from Fedora (explicit SYSTEMD,
# else latest stable via Bodhi). Every RPM's Fedora GPG signature is verified before it is pinned.
.PHONY: update-fedora-deps
update-fedora-deps: docker-build-base
@[ -n "$(FCOS)" ] || [ -n "$(KERNEL)" ] || { echo "set FCOS=<version> (and optionally SYSTEMD=<nvr>)"; exit 1; }
$(DOCKER_RUN) $(DOCKER_SAMEUSER) $(BUILD_IMAGE) \
python3 tools/build-uki/update-fedora-deps.py \
$(if $(FCOS),--fcos $(FCOS)) $(if $(SYSTEMD),--systemd $(SYSTEMD)) $(if $(KERNEL),--kernel $(KERNEL))


#####################################################################
# Runtime container image (busybox + stage1) -> ghcr on uki-v* tags.
Expand Down
77 changes: 77 additions & 0 deletions build.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# ---- Lock.Boot shared build harness ----------------------------------------------------------
# Runs every cargo/tool invocation inside the locally-built lockboot:build image, so builds are
# cc-free-by-design and byte-reproducible (rust-lld + musl, shared /src/.cargo + /src/.rustup).
#
# CANONICAL SOURCE: stage0/build.mk. This file is vendored byte-identically into each participating
# repo (stage1, vaportpm, ...) because CI checks out each repo ALONE (no workspace parent), so a
# shared harness cannot be a cross-repo include -- it must live in the repo. Do NOT hand-edit the
# copies: edit stage0/build.mk, then run `make sync-harness` from the workspace ($(CANON)=stage0),
# guarded by `make check-harness`.
#
# Each repo's Makefile does `include build.mk` and defines its own targets, invoking cargo as
# $(DOCKER_RUN) $(DOCKER_SAMEUSER) $(BUILD_IMAGE) cargo ...
# with a `docker-build-base` prerequisite so the image is built on demand (incl. standalone CI).

# ---- Docker images (shared lockboot family; built locally, never published) ----
BUILD_IMAGE = lockboot:build
HARNESS_IMAGE = lockboot:harness

.PHONY: docker-build-base
docker-build-base:
docker build -f Dockerfile.build -t $(BUILD_IMAGE) .

# ---- Docker run plumbing (keep identical across repos) ----
# Own build artifacts by whoever owns the checkout, not the caller's euid. Under
# `gh act` the caller is root but the bind-mounted tree is still yours, so stat
# keeps output user-owned instead of trampling the project dir with root files.
# On a normal host/devcontainer run this equals `id -u`/`id -g`, so nothing changes.
USER_ID := $(shell stat -c %u .)
GROUP_ID := $(shell stat -c %g .)

KVM_GID := $(shell stat -c %g /dev/kvm 2>/dev/null || echo "")
KVM_MOUNT := $(shell test -e /dev/kvm && echo "-v /dev/kvm:/dev/kvm")
DOCKER_OPT_KVM := $(if $(KVM_GID),--group-add $(KVM_GID)) $(KVM_MOUNT)

# Recursive-docker passthrough: rules that shell out to the HOST docker daemon (e.g. stage1's UKI
# rootfs extraction / runtime-image buildx) forward the socket + its gid. Defined here for every
# repo; harmless (expands empty) when a repo has no such rule.
DOCKER_SOCK_GID := $(shell stat -c %g /var/run/docker.sock 2>/dev/null || echo "")
DOCKER_SOCK_MOUNT := $(shell test -e /var/run/docker.sock && echo "-v /var/run/docker.sock:/var/run/docker.sock")
DOCKER_OPT_DOCKER := $(DOCKER_SOCK_MOUNT) $(if $(DOCKER_SOCK_GID),--group-add $(DOCKER_SOCK_GID))

DOCKER_SAMEUSER := -u $(USER_ID):$(GROUP_ID)

# Host-path translation for docker-in-devcontainer. Inside the devcontainer /src is
# a host bind mount and the inner Docker talks to the HOST daemon, which cannot
# resolve /src/... paths; translate $(CURDIR) to the real host path (the bracketed
# subpath findmnt reports for the /src bind). On the host CURDIR is not under /src,
# so this is a pass-through and your workflow is unchanged. Keep identical across repos.
HOST_DIR := $(CURDIR)
ifneq ($(filter /src/%,$(CURDIR)),)
SRC_BIND := $(shell findmnt -fnro SOURCE --target /src 2>/dev/null | sed -n 's/.*\[\(.*\)\]$$/\1/p')
ifneq ($(SRC_BIND),)
HOST_DIR := $(SRC_BIND)$(CURDIR:/src%=%)
endif
endif

# Mount the WORKSPACE (parent of this repo) at /src so builds reuse the shared
# workspace-level .cargo/.rustup (matching the devcontainer), instead of creating
# per-repo copies. The repo then lives at /src/$(REPO_NAME).
REPO_NAME := $(notdir $(HOST_DIR))
HOST_WS := $(patsubst %/,%,$(dir $(HOST_DIR)))

# Under CI / `gh act` (CI=true, runs as root) keep cargo/rustup caches ephemeral
# inside the container, so root-owned dirs never land in the bind-mounted project.
# Locally (no CI) the image's CARGO_HOME=/src/.cargo + RUSTUP_HOME=/src/.rustup win,
# i.e. the shared workspace caches.
CACHE_ENV := $(if $(CI),-e CARGO_HOME=/tmp/.cargo -e RUSTUP_HOME=/tmp/.rustup)

DOCKER_RUN = docker run --rm \
--privileged \
-v $(HOST_WS):/src \
-h lockboot \
--add-host lockboot:127.0.0.1 \
-e OWNER_UID=$(USER_ID) \
-e OWNER_GID=$(GROUP_ID) \
$(CACHE_ENV) \
-w /src/$(REPO_NAME)
54 changes: 21 additions & 33 deletions tools/build-uki/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,33 +12,26 @@ BUSYBOX_APK := busybox-static-$(BUSYBOX_VERSION).apk
BUSYBOX_URL_x86_64 := $(ALPINE_BASE_URL)/x86_64/$(BUSYBOX_APK)
BUSYBOX_URL_aarch64 := $(ALPINE_BASE_URL)/aarch64/$(BUSYBOX_APK)

# systemd-boot-unsigned from Fedora 41 (provides EFI stub)
# v256 supports PE vmlinuz on aarch64 (LoadImage/StartImage instead of direct jump)
# x86_64 provides: /usr/lib/systemd/boot/efi/linuxx64.efi.stub
# aarch64 provides: /usr/lib/systemd/boot/efi/linuxaa64.efi.stub
SYSTEMD_BOOT_VERSION := 256.17-1.fc41
SYSTEMD_BOOT_SHA256_x86_64 := ec5ce2a3e685750a7743cf933ed9ff583fe4e90cef743c76349a158631b3dae5
SYSTEMD_BOOT_SHA256_aarch64 := f188ea9f918be9c2314c4208c0c247bd6dc7eae96df85fa9e3c672619853ddcf
# ---- Fedora kernel + systemd-boot EFI stub ----
# Versions + SHA256 pins live in fedora-deps.mk (GENERATED, GPG-verified); bump them with
# make update-fedora-deps FCOS=<version> [SYSTEMD=<nvr>] (target in ../../Makefile).
# The systemd stub provides the EFI stub (linuxx64/aa64.efi.stub, PE-vmlinuz capable on aarch64);
# kernel-modules-core carries the ena (AWS) + gve (GCP) NIC drivers. RPMs come from koji's SIGNED
# path and are GPG-verified against $(FEDORA_KEY) on every download (download-verify-rpm.sh).
include fedora-deps.mk

FEDORA_KEY := keys/RPM-GPG-KEY-fedora-$(FEDORA_RELEASE)-primary

SYSTEMD_BOOT_RPM_x86_64 := systemd-boot-unsigned-$(SYSTEMD_BOOT_VERSION).x86_64.rpm
SYSTEMD_BOOT_RPM_aarch64 := systemd-boot-unsigned-$(SYSTEMD_BOOT_VERSION).aarch64.rpm
SYSTEMD_BOOT_URL_x86_64 := https://kojipkgs.fedoraproject.org/packages/systemd/256.17/1.fc41/x86_64/$(SYSTEMD_BOOT_RPM_x86_64)
SYSTEMD_BOOT_URL_aarch64 := https://kojipkgs.fedoraproject.org/packages/systemd/256.17/1.fc41/aarch64/$(SYSTEMD_BOOT_RPM_aarch64)
SYSTEMD_BOOT_URL_x86_64 := $(SYSTEMD_BOOT_BASE_URL)/x86_64/$(SYSTEMD_BOOT_RPM_x86_64)
SYSTEMD_BOOT_URL_aarch64 := $(SYSTEMD_BOOT_BASE_URL)/aarch64/$(SYSTEMD_BOOT_RPM_aarch64)

# Fedora 41 kernel 6.12 (has both ena and gve drivers)
FEDORA_KERNEL_VERSION := 6.12.4-200.fc41
FEDORA_KERNEL_BASE_URL := https://kojipkgs.fedoraproject.org/packages/kernel/6.12.4/200.fc41

# kernel-core (contains vmlinuz)
FEDORA_KERNEL_CORE_SHA256_x86_64 := f7df5e7d36b7ed4c311f358340fcf2ae414cd1b4b8ad8d8555bb5cae2403cfc3
FEDORA_KERNEL_CORE_SHA256_aarch64 := 5494b00c95832eb52b39b306fd4ab912893824cd0419612fb52fc97643fa56cb
FEDORA_KERNEL_CORE_RPM_x86_64 := kernel-core-$(FEDORA_KERNEL_VERSION).x86_64.rpm
FEDORA_KERNEL_CORE_RPM_aarch64 := kernel-core-$(FEDORA_KERNEL_VERSION).aarch64.rpm
FEDORA_KERNEL_CORE_URL_x86_64 := $(FEDORA_KERNEL_BASE_URL)/x86_64/$(FEDORA_KERNEL_CORE_RPM_x86_64)
FEDORA_KERNEL_CORE_URL_aarch64 := $(FEDORA_KERNEL_BASE_URL)/aarch64/$(FEDORA_KERNEL_CORE_RPM_aarch64)

# kernel-modules-core (contains core .ko modules including gve and ena)
FEDORA_KERNEL_MODULES_SHA256_x86_64 := 7d9e7d9f925de56f04c103a65011285d0ded2fc45a79ca1b300828316916200c
FEDORA_KERNEL_MODULES_SHA256_aarch64 := 4bbe3e2922b044519d126cc1a06f0416d3f4f26523f0bae75d5fe355d4abb7ac
FEDORA_KERNEL_MODULES_RPM_x86_64 := kernel-modules-core-$(FEDORA_KERNEL_VERSION).x86_64.rpm
FEDORA_KERNEL_MODULES_RPM_aarch64 := kernel-modules-core-$(FEDORA_KERNEL_VERSION).aarch64.rpm
FEDORA_KERNEL_MODULES_URL_x86_64 := $(FEDORA_KERNEL_BASE_URL)/x86_64/$(FEDORA_KERNEL_MODULES_RPM_x86_64)
Expand All @@ -60,12 +53,12 @@ aarch64: $(addprefix aarch64/,$(TARGETS))
@tar --warning=no-unknown-keyword -xzOf $< bin/busybox.static > "$@"
@chmod +x "$@"

# Download systemd-boot-unsigned RPM from Fedora
# Download + SHA256 + GPG-verify systemd-boot-unsigned RPM (signed Fedora koji path)
x86_64/$(SYSTEMD_BOOT_RPM_x86_64):
@./download-and-verify.sh "$@" "$(SYSTEMD_BOOT_SHA256_x86_64)" "$(SYSTEMD_BOOT_URL_x86_64)"
@./download-verify-rpm.sh "$@" "$(SYSTEMD_BOOT_SHA256_x86_64)" "$(SYSTEMD_BOOT_URL_x86_64)" "$(FEDORA_KEY)"

aarch64/$(SYSTEMD_BOOT_RPM_aarch64):
@./download-and-verify.sh "$@" "$(SYSTEMD_BOOT_SHA256_aarch64)" "$(SYSTEMD_BOOT_URL_aarch64)"
@./download-verify-rpm.sh "$@" "$(SYSTEMD_BOOT_SHA256_aarch64)" "$(SYSTEMD_BOOT_URL_aarch64)" "$(FEDORA_KEY)"

# Extract EFI stub from systemd-boot RPM
x86_64/stub.efi: x86_64/$(SYSTEMD_BOOT_RPM_x86_64)
Expand All @@ -78,37 +71,32 @@ aarch64/stub.efi: aarch64/$(SYSTEMD_BOOT_RPM_aarch64)
@rpm2cpio $< | cpio -i --quiet --to-stdout ./usr/lib/systemd/boot/efi/linuxaa64.efi.stub > $@
@chmod +x $@

# Download Fedora kernel-core RPMs from kojipkgs
# Download + SHA256 + GPG-verify Fedora kernel-core RPMs (signed koji path)
x86_64/$(FEDORA_KERNEL_CORE_RPM_x86_64):
@./download-and-verify.sh "$@" "$(FEDORA_KERNEL_CORE_SHA256_x86_64)" "$(FEDORA_KERNEL_CORE_URL_x86_64)"
@./download-verify-rpm.sh "$@" "$(FEDORA_KERNEL_CORE_SHA256_x86_64)" "$(FEDORA_KERNEL_CORE_URL_x86_64)" "$(FEDORA_KEY)"

x86_64/kernel-core.rpm: x86_64/$(FEDORA_KERNEL_CORE_RPM_x86_64)
@ln -sf $(notdir $<) $@

aarch64/$(FEDORA_KERNEL_CORE_RPM_aarch64):
@./download-and-verify.sh "$@" "$(FEDORA_KERNEL_CORE_SHA256_aarch64)" "$(FEDORA_KERNEL_CORE_URL_aarch64)"
@./download-verify-rpm.sh "$@" "$(FEDORA_KERNEL_CORE_SHA256_aarch64)" "$(FEDORA_KERNEL_CORE_URL_aarch64)" "$(FEDORA_KEY)"

aarch64/kernel-core.rpm: aarch64/$(FEDORA_KERNEL_CORE_RPM_aarch64)
@ln -sf $(notdir $<) $@

# Download Fedora kernel-modules-core RPMs from kojipkgs
# Download + SHA256 + GPG-verify Fedora kernel-modules-core RPMs (signed koji path; has ena + gve)
x86_64/$(FEDORA_KERNEL_MODULES_RPM_x86_64):
@./download-and-verify.sh "$@" "$(FEDORA_KERNEL_MODULES_SHA256_x86_64)" "$(FEDORA_KERNEL_MODULES_URL_x86_64)"
@./download-verify-rpm.sh "$@" "$(FEDORA_KERNEL_MODULES_SHA256_x86_64)" "$(FEDORA_KERNEL_MODULES_URL_x86_64)" "$(FEDORA_KEY)"

x86_64/kernel-modules-core.rpm: x86_64/$(FEDORA_KERNEL_MODULES_RPM_x86_64)
@ln -sf $(notdir $<) $@

aarch64/$(FEDORA_KERNEL_MODULES_RPM_aarch64):
@./download-and-verify.sh "$@" "$(FEDORA_KERNEL_MODULES_SHA256_aarch64)" "$(FEDORA_KERNEL_MODULES_URL_aarch64)"
@./download-verify-rpm.sh "$@" "$(FEDORA_KERNEL_MODULES_SHA256_aarch64)" "$(FEDORA_KERNEL_MODULES_URL_aarch64)" "$(FEDORA_KEY)"

aarch64/kernel-modules-core.rpm: aarch64/$(FEDORA_KERNEL_MODULES_RPM_aarch64)
@ln -sf $(notdir $<) $@

# Retrieve package URLs from koji (for reference)
kernel-hash-%:
@echo "Fedora kernel: $(FEDORA_KERNEL_PACKAGE)-$(FEDORA_KERNEL_VERSION).$*"
@echo "Download from: https://koji.fedoraproject.org/koji/buildinfo?buildID=2599252"

clean:
rm -rf x86_64 aarch64

Expand Down
29 changes: 29 additions & 0 deletions tools/build-uki/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,35 @@ REQUIRED_MODULES=(
# Nitro Enclaves
"drivers/misc/nsm.ko"
"drivers/virt/nitro_enclaves/nitro_enclaves.ko"

# Storage stack for stage2. init loads these explicitly, in dependency order, before
# the modules_disabled latch (the payload cannot load them itself, and once the latch
# is set an unresolved dependency can never be pulled on demand -- so we list deps too,
# not relying on modprobe auto-pull). What each provides / can be used for:
# dm-crypt block-device encryption (stage2 uses it for the encrypted /data)
# dm-verity integrity-checked read-only device (stage2's dm-verity'd erofs runtime)
# reed_solomon dm-verity forward-error-correction dependency
# overlay overlay filesystem (stage2's ephemeral overlay root)
# erofs/netfs read-only image filesystem (+ its netfs dependency)
# Extension point: authenticated (not just confidential) /data would additionally need
# dm-integrity + its async_xor -> async_tx (ASYNC_XOR journal) deps; omitted while stage2
# uses confidentiality-only dm-crypt, to keep the measured initramfs minimal.
"drivers/md/dm-crypt.ko"
"drivers/md/dm-verity.ko"
"lib/reed_solomon/reed_solomon.ko"
"fs/overlayfs/overlay.ko"
"fs/erofs/erofs.ko"
"fs/netfs/netfs.ko"

# NVMe disk driver, so stage2 can see the persistent volume (EC2 EBS is NVMe;
# the harness also attaches its disk as NVMe). Never needed to boot (initramfs +
# in-memory payload), so it was previously absent. Dep chain, loaded in order by
# init: hkdf -> nvme-auth, nvme-keyring -> nvme-core -> nvme.
"crypto/hkdf.ko"
"drivers/nvme/common/nvme-auth.ko"
"drivers/nvme/common/nvme-keyring.ko"
"drivers/nvme/host/nvme-core.ko"
"drivers/nvme/host/nvme.ko"
)

for mod_path in "${REQUIRED_MODULES[@]}"; do
Expand Down
30 changes: 30 additions & 0 deletions tools/build-uki/download-verify-rpm.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/bin/bash
# Download a Fedora RPM and verify BOTH its SHA256 pin and its Fedora GPG signature. All four args are
# required -- there is deliberately no way to fetch an RPM here without signature verification. (Busybox
# is an Alpine .apk with no Fedora signature and uses download-and-verify.sh instead.)
set -euo pipefail

OUT="${1:-}"
SHA="${2:-}"
URL="${3:-}"
KEY="${4:-}"
if [ -z "$OUT" ] || [ -z "$SHA" ] || [ -z "$URL" ] || [ -z "$KEY" ]; then
echo "usage: $0 <output_file> <expected_sha256> <url> <gpg_key>" >&2
exit 1
fi

HERE="$(dirname "$0")"
mkdir -p "$(dirname "$OUT")"

[ -f "$OUT" ] || wget -q -O "$OUT" "$URL"

if ! echo "${SHA} ${OUT}" | sha256sum -c - >/dev/null 2>&1; then
echo "SHA256 mismatch: $OUT" >&2
rm -f "$OUT"
exit 1
fi

if ! "$HERE/verify-rpm-gpg.sh" "$OUT" "$KEY"; then
rm -f "$OUT"
exit 1
fi
Loading