shit
This commit is contained in:
Executable
+128
@@ -0,0 +1,128 @@
|
||||
#!/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
|
||||
Reference in New Issue
Block a user