Files
distro/scripts/mkimage.sh
T
2026-06-02 21:38:47 +02:00

129 lines
4.4 KiB
Bash
Executable File

#!/usr/bin/env bash
#
# Build a bootable initramfs from the installed package set and (optionally)
# launch it in QEMU to test the Weston desktop.
#
# Approach: the entire root filesystem is packed into a single initramfs and
# booted straight from RAM (no disk image, no loop mounts, no root needed).
# dinit runs as PID 1, brings up udev/seatd, autologins, and starts Weston.
#
# Usage:
# scripts/mkimage.sh [-C build-dir] [--run] [--mem MB]
#
# -C, --build-dir orchid build dir (default: $ORCHID_BUILD or build-x86_64)
# --out DIR output dir for artifacts (default: <build-dir>/qemu)
# --mem MB QEMU RAM in MiB (default: 4096)
# --run launch QEMU after building (otherwise just print the command)
#
# Artifacts written to <out>: rootfs/ (installed tree), vmlinuz, initramfs.cpio.gz
set -euo pipefail
here=$(cd "$(dirname "$0")/.." && pwd)
orchid="$here/orchid"
build_dir=${ORCHID_BUILD:-build-x86_64}
out=""
mem=4096
run=0
while [ $# -gt 0 ]; do
case "$1" in
-C|--build-dir) build_dir=$2; shift 2 ;;
--out) out=$2; shift 2 ;;
--mem) mem=$2; shift 2 ;;
--run) run=1; shift ;;
-h|--help) sed -n '2,20p' "$0"; exit 0 ;;
*) echo "unknown argument: $1" >&2; exit 2 ;;
esac
done
[ -d "$build_dir" ] || { echo "build dir not found: $build_dir" >&2; exit 1; }
out=${out:-$build_dir/qemu}
rootfs="$out/rootfs"
mkdir -p "$out"
echo ">> installing packages into $rootfs"
rm -rf "$rootfs"
"$orchid" install -C "$build_dir" "$rootfs"
echo ">> wiring up init"
# The kernel execs /init from an initramfs but does NOT auto-mount devtmpfs, so
# dinit would have no /dev/null to set up service stdio. This tiny bootstrap
# mounts the kernel vfs, then hands off to dinit (PID 1) which runs the rest.
mkdir -p "$rootfs"/{proc,sys,dev,run,tmp}
cat > "$rootfs/init" <<'EOF'
#!/bin/bash
export PATH=/usr/bin:/usr/sbin:/bin:/sbin
mount -t devtmpfs dev /dev 2>/dev/null || true
mount -t proc proc /proc 2>/dev/null || true
mount -t sysfs sys /sys 2>/dev/null || true
exec /sbin/init
EOF
chmod +x "$rootfs/init"
echo ">> regenerating ld.so.cache"
# Target libs are split across /lib, /usr/lib and /usr/lib64; without a cache
# the loader can't find e.g. libstdc++ for dinit (PID 1, before any service
# runs). base-files ships /etc/ld.so.conf + the /lib64 and /bin compat links;
# build the cache now from the assembled rootfs.
# Prefer the *target* ldconfig (run via the target loader) so the cache is in a
# format the target glibc loader accepts; fall back to the host ldconfig.
loader="$rootfs/lib/ld-linux-x86-64.so.2"
tgt_ldconfig="$rootfs/sbin/ldconfig"
if [ -x "$loader" ] && [ -e "$tgt_ldconfig" ]; then
"$loader" --library-path "$rootfs/lib:$rootfs/usr/lib:$rootfs/usr/lib64" \
"$tgt_ldconfig" -r "$rootfs"
elif command -v ldconfig >/dev/null; then
ldconfig -r "$rootfs"
else
echo " warning: no ldconfig available; libraries may not resolve" >&2
fi
echo ">> extracting kernel"
kernel=$(ls -1 "$rootfs"/boot/vmlinuz-* 2>/dev/null | head -n1 || true)
if [ -z "$kernel" ]; then
echo "no kernel in $rootfs/boot (build the 'linux' recipe first)" >&2
exit 1
fi
cp "$kernel" "$out/vmlinuz"
if [ ! -d "$rootfs"/lib/modules ] && [ ! -d "$rootfs"/usr/lib/modules ]; then
echo "warning: no /lib/modules in rootfs — DRM/input drivers built as" >&2
echo " modules won't load (rebuild 'linux' with modules_install)." >&2
fi
echo ">> packing initramfs"
# Pack as a newc cpio + gzip. Run from within rootfs so paths are relative.
( cd "$rootfs" && find . -print0 | cpio --null --create --format=newc --quiet ) \
| gzip -9 > "$out/initramfs.cpio.gz"
echo " initramfs: $(du -h "$out/initramfs.cpio.gz" | cut -f1)"
# Assemble the QEMU command. virtio-gpu gives Weston a DRM/KMS device; virtio
# keyboard/tablet feed libinput; serial is the console for boot logs.
kvm=()
[ -w /dev/kvm ] && kvm=(-enable-kvm -cpu host)
cmd=(
qemu-system-x86_64
"${kvm[@]}"
-m "$mem" -smp 4
-kernel "$out/vmlinuz"
-initrd "$out/initramfs.cpio.gz"
-append "console=ttyS0,115200 loglevel=6"
-device virtio-gpu-pci
-device virtio-keyboard-pci
-device virtio-tablet-pci
-display gtk,gl=on
-serial mon:stdio
)
echo ""
echo ">> QEMU command:"
printf ' %q' "${cmd[@]}"; echo
if [ "$run" -eq 1 ]; then
echo ">> launching QEMU (Ctrl-A X to quit the serial console)"
exec "${cmd[@]}"
fi