Hard-cut banger away from source-checkout runtime bundles as an implicit source of\nimage and host defaults. Managed images now own their full boot set,\nimage build starts from an existing registered image, and daemon startup\nno longer synthesizes a default image from host paths.\n\nResolve Firecracker from PATH or firecracker_bin, make SSH keys config-owned\nwith an auto-managed XDG default, replace the external name generator and\npackage manifests with Go code, and keep the vsock helper as a companion\nbinary instead of a user-managed runtime asset.\n\nUpdate the manual scripts, web/CLI forms, config surface, and docs around\nthe new build/manual flow and explicit image registration semantics.\n\nValidation: GOCACHE=/tmp/banger-gocache go test ./..., bash -n scripts/*.sh,\nand make build.
386 lines
11 KiB
Bash
Executable file
386 lines
11 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
log() {
|
|
printf '[make-void-kernel] %s\n' "$*"
|
|
}
|
|
|
|
usage() {
|
|
cat <<'EOF'
|
|
Usage: ./scripts/make-void-kernel.sh [--out-dir <path>] [--mirror <url>] [--arch <arch>] [--kernel-package <name>] [--print-register-flags]
|
|
|
|
Download and stage a Void Linux kernel under ./build/manual/void-kernel for
|
|
the
|
|
experimental Void guest flow.
|
|
|
|
Defaults:
|
|
--out-dir ./build/manual/void-kernel
|
|
--mirror https://repo-default.voidlinux.org
|
|
--arch x86_64
|
|
--kernel-package linux6.12
|
|
|
|
The staged output contains:
|
|
boot/vmlinux-<version> Firecracker-usable kernel extracted from vmlinuz
|
|
boot/vmlinuz-<version> Raw distro boot image from the Void package
|
|
boot/initramfs-<version>.img Matching initramfs generated with dracut
|
|
boot/config-<version> Void kernel config
|
|
lib/modules/<version>/ Matching kernel modules tree
|
|
|
|
If --print-register-flags is passed, the script does not download anything. It
|
|
prints the banger image register flags for an existing staged Void kernel.
|
|
EOF
|
|
}
|
|
|
|
require_command() {
|
|
local name="$1"
|
|
command -v "$name" >/dev/null 2>&1 || {
|
|
log "required command not found: $name"
|
|
exit 1
|
|
}
|
|
}
|
|
|
|
normalize_mirror() {
|
|
local mirror="${1%/}"
|
|
mirror="${mirror%/current}"
|
|
mirror="${mirror%/static}"
|
|
printf '%s\n' "$mirror"
|
|
}
|
|
|
|
find_static_binary() {
|
|
local name="$1"
|
|
find "$STATIC_DIR" -type f \( -name "$name" -o -name "$name.static" \) -perm -u+x | sort | head -n 1
|
|
}
|
|
|
|
find_static_keys_dir() {
|
|
find "$STATIC_DIR" -type d -path '*/var/db/xbps/keys' | sort | head -n 1
|
|
}
|
|
|
|
find_latest_matching() {
|
|
local dir="$1"
|
|
local pattern="$2"
|
|
if [[ ! -d "$dir" ]]; then
|
|
return 1
|
|
fi
|
|
find "$dir" -maxdepth 1 -type f -name "$pattern" | sort | tail -n 1
|
|
}
|
|
|
|
find_latest_module_dir() {
|
|
local root="$1"
|
|
if [[ ! -d "$root" ]]; then
|
|
return 1
|
|
fi
|
|
find "$root" -mindepth 1 -maxdepth 1 -type d | sort | tail -n 1
|
|
}
|
|
|
|
print_register_flags() {
|
|
local kernel=""
|
|
local initrd=""
|
|
local modules=""
|
|
|
|
kernel="$(find_latest_matching "$OUT_DIR/boot" 'vmlinux-*' || true)"
|
|
initrd="$(find_latest_matching "$OUT_DIR/boot" 'initramfs-*' || true)"
|
|
modules="$(find_latest_module_dir "$OUT_DIR/lib/modules" || true)"
|
|
|
|
if [[ -z "$kernel" || -z "$modules" ]]; then
|
|
log "staged Void kernel not found under $OUT_DIR"
|
|
exit 1
|
|
fi
|
|
|
|
printf -- '--kernel %q ' "$kernel"
|
|
if [[ -n "$initrd" ]]; then
|
|
printf -- '--initrd %q ' "$initrd"
|
|
fi
|
|
printf -- '--modules %q\n' "$modules"
|
|
}
|
|
|
|
check_elf() {
|
|
local path="$1"
|
|
readelf -h "$path" >/dev/null 2>&1
|
|
}
|
|
|
|
ensure_stage_root_layout() {
|
|
mkdir -p "$STAGE_ROOT/usr"
|
|
|
|
if [[ ! -e "$STAGE_ROOT/bin" ]]; then
|
|
ln -snf usr/bin "$STAGE_ROOT/bin"
|
|
fi
|
|
if [[ ! -e "$STAGE_ROOT/sbin" ]]; then
|
|
ln -snf usr/bin "$STAGE_ROOT/sbin"
|
|
fi
|
|
if [[ ! -e "$STAGE_ROOT/usr/sbin" ]]; then
|
|
ln -snf bin "$STAGE_ROOT/usr/sbin"
|
|
fi
|
|
if [[ ! -e "$STAGE_ROOT/lib" ]]; then
|
|
ln -snf usr/lib "$STAGE_ROOT/lib"
|
|
fi
|
|
if [[ ! -e "$STAGE_ROOT/lib64" ]]; then
|
|
ln -snf usr/lib "$STAGE_ROOT/lib64"
|
|
fi
|
|
if [[ ! -e "$STAGE_ROOT/usr/lib64" ]]; then
|
|
ln -snf lib "$STAGE_ROOT/usr/lib64"
|
|
fi
|
|
if [[ -x "$STAGE_ROOT/usr/bin/udevd" ]]; then
|
|
mkdir -p "$STAGE_ROOT/usr/lib/udev" "$STAGE_ROOT/usr/lib/systemd"
|
|
if [[ ! -e "$STAGE_ROOT/usr/lib/udev/udevd" ]]; then
|
|
ln -snf ../../bin/udevd "$STAGE_ROOT/usr/lib/udev/udevd"
|
|
fi
|
|
if [[ ! -e "$STAGE_ROOT/usr/lib/systemd/systemd-udevd" ]]; then
|
|
ln -snf ../../bin/udevd "$STAGE_ROOT/usr/lib/systemd/systemd-udevd"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
sync_host_dracut_tree() {
|
|
if [[ ! -d /usr/lib/dracut ]]; then
|
|
log "host dracut support files not found under /usr/lib/dracut"
|
|
exit 1
|
|
fi
|
|
rm -rf "$STAGE_ROOT/usr/lib/dracut"
|
|
mkdir -p "$STAGE_ROOT/usr/lib"
|
|
cp -a /usr/lib/dracut "$STAGE_ROOT/usr/lib/dracut"
|
|
}
|
|
|
|
build_initramfs() {
|
|
local kver="$1"
|
|
local modules_dir="$2"
|
|
local out="$3"
|
|
local config_dir="$TMP_DIR/dracut.conf.d"
|
|
local tmpdir="$TMP_DIR/dracut-tmp"
|
|
local force_drivers="virtio virtio_ring virtio_mmio virtio_blk virtio_net virtio_console ext4 vsock vmw_vsock_virtio_transport"
|
|
|
|
mkdir -p "$config_dir" "$tmpdir"
|
|
ensure_stage_root_layout
|
|
sync_host_dracut_tree
|
|
|
|
log "generating initramfs for kernel $kver with host dracut against the staged Void sysroot"
|
|
env dracutbasedir="/usr/lib/dracut" dracut \
|
|
--force \
|
|
--kver "$kver" \
|
|
--sysroot "$STAGE_ROOT" \
|
|
--kmoddir "$modules_dir" \
|
|
--conf /dev/null \
|
|
--confdir "$config_dir" \
|
|
--tmpdir "$tmpdir" \
|
|
--no-hostonly \
|
|
--filesystems "ext4" \
|
|
--force-drivers "$force_drivers" \
|
|
--gzip \
|
|
"$out"
|
|
}
|
|
|
|
extract_vmlinux() {
|
|
local image="$1"
|
|
local out="$2"
|
|
local tmp="$TMP_DIR/vmlinux.extract"
|
|
|
|
if check_elf "$image"; then
|
|
install -m 0644 "$image" "$out"
|
|
return 0
|
|
fi
|
|
|
|
try_decompress() {
|
|
local header="$1"
|
|
local marker="$2"
|
|
local command="$3"
|
|
local pos=""
|
|
|
|
while IFS= read -r pos; do
|
|
[[ -n "$pos" ]] || continue
|
|
pos="${pos%%:*}"
|
|
tail -c+"$pos" "$image" | eval "$command" >"$tmp" 2>/dev/null || true
|
|
if check_elf "$tmp"; then
|
|
install -m 0644 "$tmp" "$out"
|
|
return 0
|
|
fi
|
|
done < <(tr "$header\n$marker" "\n$marker=" < "$image" | grep -abo "^$marker" || true)
|
|
|
|
return 1
|
|
}
|
|
|
|
try_decompress '\037\213\010' "xy" "gunzip" && return 0
|
|
try_decompress '\3757zXZ\000' "abcde" "unxz" && return 0
|
|
try_decompress "BZh" "xy" "bunzip2" && return 0
|
|
try_decompress '\135\000\000\000' "xxx" "unlzma" && return 0
|
|
try_decompress '\002!L\030' "xxx" "lz4 -d" && return 0
|
|
try_decompress '(\265/\375' "xxx" "unzstd" && return 0
|
|
|
|
return 1
|
|
}
|
|
|
|
resolve_kernel_package_file() {
|
|
local escaped_name=""
|
|
escaped_name="$(printf '%s\n' "$KERNEL_PACKAGE" | sed 's/[.[\*^$()+?{|]/\\&/g')"
|
|
|
|
curl -fsSL "$REPO_URL/" |
|
|
grep -o "${escaped_name}-[0-9][^\" >]*\\.${ARCH}\\.xbps" |
|
|
sort -u |
|
|
tail -n 1
|
|
}
|
|
|
|
cleanup() {
|
|
if [[ -n "${TMP_DIR:-}" && -d "${TMP_DIR:-}" ]]; then
|
|
rm -rf "$TMP_DIR"
|
|
fi
|
|
}
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
MANUAL_DIR="${BANGER_MANUAL_DIR:-$REPO_ROOT/build/manual}"
|
|
OUT_DIR="$MANUAL_DIR/void-kernel"
|
|
MIRROR="https://repo-default.voidlinux.org"
|
|
ARCH="x86_64"
|
|
KERNEL_PACKAGE="linux6.12"
|
|
PRINT_REGISTER_FLAGS=0
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--out-dir)
|
|
OUT_DIR="${2:-}"
|
|
shift 2
|
|
;;
|
|
--mirror)
|
|
MIRROR="${2:-}"
|
|
shift 2
|
|
;;
|
|
--arch)
|
|
ARCH="${2:-}"
|
|
shift 2
|
|
;;
|
|
--kernel-package)
|
|
KERNEL_PACKAGE="${2:-}"
|
|
shift 2
|
|
;;
|
|
--print-register-flags)
|
|
PRINT_REGISTER_FLAGS=1
|
|
shift
|
|
;;
|
|
-h|--help)
|
|
usage
|
|
exit 0
|
|
;;
|
|
*)
|
|
log "unknown option: $1"
|
|
usage
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
MIRROR="$(normalize_mirror "$MIRROR")"
|
|
REPO_URL="$MIRROR/current"
|
|
STATIC_ARCHIVE_URL="$MIRROR/static/xbps-static-latest.x86_64-musl.tar.xz"
|
|
|
|
if [[ "$PRINT_REGISTER_FLAGS" == "1" ]]; then
|
|
print_register_flags
|
|
exit 0
|
|
fi
|
|
|
|
if [[ "$ARCH" != "x86_64" ]]; then
|
|
log "unsupported arch: $ARCH"
|
|
log "this experimental downloader currently supports only x86_64"
|
|
exit 1
|
|
fi
|
|
mkdir -p "$RUNTIME_DIR"
|
|
if [[ -e "$OUT_DIR" ]]; then
|
|
log "output directory already exists: $OUT_DIR"
|
|
log "remove it first if you want to re-stage a different Void kernel"
|
|
exit 1
|
|
fi
|
|
|
|
require_command curl
|
|
require_command tar
|
|
require_command cp
|
|
require_command find
|
|
require_command grep
|
|
require_command cut
|
|
require_command readelf
|
|
require_command file
|
|
require_command install
|
|
require_command tail
|
|
require_command xz
|
|
require_command gzip
|
|
require_command bzip2
|
|
require_command dracut
|
|
|
|
TMP_DIR="$(mktemp -d -t banger-void-kernel-XXXXXX)"
|
|
STATIC_DIR="$TMP_DIR/static"
|
|
STAGE_ROOT="$TMP_DIR/root"
|
|
STAGE_OUT="$TMP_DIR/out"
|
|
STATIC_ARCHIVE="$TMP_DIR/xbps-static.tar.xz"
|
|
trap cleanup EXIT
|
|
|
|
mkdir -p "$STATIC_DIR" "$STAGE_ROOT/var/db/xbps/keys" "$STAGE_OUT/boot" "$STAGE_OUT/lib/modules"
|
|
|
|
log "downloading static XBPS from $STATIC_ARCHIVE_URL"
|
|
curl -fsSL "$STATIC_ARCHIVE_URL" -o "$STATIC_ARCHIVE"
|
|
tar -xf "$STATIC_ARCHIVE" -C "$STATIC_DIR"
|
|
|
|
XBPS_INSTALL="$(find_static_binary xbps-install)"
|
|
STATIC_KEYS_DIR="$(find_static_keys_dir)"
|
|
if [[ -z "$XBPS_INSTALL" || ! -x "$XBPS_INSTALL" ]]; then
|
|
log "failed to locate xbps-install in the static archive"
|
|
exit 1
|
|
fi
|
|
if [[ -z "$STATIC_KEYS_DIR" || ! -d "$STATIC_KEYS_DIR" ]]; then
|
|
log "failed to locate Void repository keys in the static archive"
|
|
exit 1
|
|
fi
|
|
|
|
cp -a "$STATIC_KEYS_DIR/." "$STAGE_ROOT/var/db/xbps/keys/"
|
|
|
|
KERNEL_PACKAGE_FILE="$(resolve_kernel_package_file)"
|
|
if [[ -z "$KERNEL_PACKAGE_FILE" ]]; then
|
|
log "failed to resolve a package file for $KERNEL_PACKAGE in $REPO_URL"
|
|
exit 1
|
|
fi
|
|
|
|
log "staging $KERNEL_PACKAGE_FILE into a temporary root"
|
|
env XBPS_ARCH="$ARCH" "$XBPS_INSTALL" -S -y -U -r "$STAGE_ROOT" -R "$REPO_URL" linux-base "$KERNEL_PACKAGE" dracut eudev >/dev/null
|
|
|
|
VMLINUX_RAW="$(find_latest_matching "$STAGE_ROOT/boot" 'vmlinuz-*' || true)"
|
|
KERNEL_CONFIG="$(find_latest_matching "$STAGE_ROOT/boot" 'config-*' || true)"
|
|
MODULES_DIR="$(find_latest_module_dir "$STAGE_ROOT/usr/lib/modules" || true)"
|
|
KERNEL_VERSION="$(basename "$MODULES_DIR")"
|
|
INITRAMFS_NAME="initramfs-${KERNEL_VERSION}.img"
|
|
INITRAMFS_RAW="$STAGE_OUT/boot/$INITRAMFS_NAME"
|
|
|
|
if [[ -z "$VMLINUX_RAW" || -z "$KERNEL_CONFIG" || -z "$MODULES_DIR" ]]; then
|
|
log "staged Void kernel is missing expected boot artifacts"
|
|
exit 1
|
|
fi
|
|
if [[ ! -x "$STAGE_ROOT/usr/bin/udevd" ]]; then
|
|
log "staged Void sysroot is missing /usr/bin/udevd after package install"
|
|
exit 1
|
|
fi
|
|
|
|
VMLINUX_BASE="$(basename "$VMLINUX_RAW")"
|
|
VMLINUX_OUT="$STAGE_OUT/boot/vmlinux-${VMLINUX_BASE#vmlinuz-}"
|
|
install -m 0644 "$VMLINUX_RAW" "$STAGE_OUT/boot/$VMLINUX_BASE"
|
|
install -m 0644 "$KERNEL_CONFIG" "$STAGE_OUT/boot/$(basename "$KERNEL_CONFIG")"
|
|
build_initramfs "$KERNEL_VERSION" "$MODULES_DIR" "$INITRAMFS_RAW"
|
|
cp -a "$MODULES_DIR" "$STAGE_OUT/lib/modules/"
|
|
|
|
log "extracting Firecracker kernel from $(basename "$VMLINUX_RAW")"
|
|
if ! extract_vmlinux "$VMLINUX_RAW" "$VMLINUX_OUT"; then
|
|
log "failed to extract an uncompressed vmlinux from $VMLINUX_RAW"
|
|
log "raw kernel image type: $(file -b "$VMLINUX_RAW")"
|
|
exit 1
|
|
fi
|
|
|
|
cat >"$STAGE_OUT/metadata.json" <<EOF
|
|
{
|
|
"package": "$KERNEL_PACKAGE_FILE",
|
|
"kernel_path": "$OUT_DIR/boot/$(basename "$VMLINUX_OUT")",
|
|
"raw_kernel_path": "$OUT_DIR/boot/$VMLINUX_BASE",
|
|
"config_path": "$OUT_DIR/boot/$(basename "$KERNEL_CONFIG")",
|
|
"initrd_path": "$OUT_DIR/boot/$INITRAMFS_NAME",
|
|
"modules_dir": "$OUT_DIR/lib/modules/$(basename "$MODULES_DIR")"
|
|
}
|
|
EOF
|
|
|
|
mv "$STAGE_OUT" "$OUT_DIR"
|
|
|
|
log "staged Void kernel artifacts in $OUT_DIR"
|
|
log "kernel image: $OUT_DIR/boot/$(basename "$VMLINUX_OUT")"
|
|
log "initrd image: $OUT_DIR/boot/$INITRAMFS_NAME"
|
|
log "modules dir: $OUT_DIR/lib/modules/$(basename "$MODULES_DIR")"
|