129 lines
4.4 KiB
Bash
Executable File
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
|