#!/bin/bash # create-iso.sh — Create a bootable ISO from kernel + initramfs # Uses isolinux (syslinux) for Phase 1 simplicity (GRUB in Phase 3) set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" ROOTFS_DIR="${ROOTFS_DIR:-$PROJECT_ROOT/build/rootfs-work}" OUTPUT_DIR="${OUTPUT_DIR:-$PROJECT_ROOT/output}" VERSION="$(cat "$PROJECT_ROOT/VERSION")" OS_NAME="kubesolo-os" ISO_STAGING="$ROOTFS_DIR/iso-staging" ISO_OUTPUT="$OUTPUT_DIR/${OS_NAME}-${VERSION}.iso" VMLINUZ="$ROOTFS_DIR/vmlinuz" INITRAMFS="$ROOTFS_DIR/kubesolo-os.gz" # Validate inputs for f in "$VMLINUZ" "$INITRAMFS"; do if [ ! -f "$f" ]; then echo "ERROR: Missing required file: $f" echo "Run 'make initramfs' first." exit 1 fi done # Check for required tools for cmd in mkisofs xorriso genisoimage; do if command -v "$cmd" >/dev/null 2>&1; then MKISO_CMD="$cmd" break fi done if [ -z "${MKISO_CMD:-}" ]; then echo "ERROR: Need mkisofs, genisoimage, or xorriso to create ISO" exit 1 fi # --- Stage ISO contents --- rm -rf "$ISO_STAGING" mkdir -p "$ISO_STAGING/boot/isolinux" cp "$VMLINUZ" "$ISO_STAGING/boot/vmlinuz" cp "$INITRAMFS" "$ISO_STAGING/boot/kubesolo-os.gz" # Find isolinux.bin ISOLINUX_BIN="" for path in /usr/lib/ISOLINUX/isolinux.bin /usr/lib/syslinux/isolinux.bin \ /usr/share/syslinux/isolinux.bin /usr/lib/syslinux/bios/isolinux.bin; do [ -f "$path" ] && ISOLINUX_BIN="$path" && break done if [ -z "$ISOLINUX_BIN" ]; then echo "ERROR: Cannot find isolinux.bin. Install syslinux/isolinux package." exit 1 fi cp "$ISOLINUX_BIN" "$ISO_STAGING/boot/isolinux/" # Copy ldlinux.c32 if it exists (needed by syslinux 6+) LDLINUX_DIR="$(dirname "$ISOLINUX_BIN")" for mod in ldlinux.c32 libcom32.c32 libutil.c32 mboot.c32; do [ -f "$LDLINUX_DIR/$mod" ] && cp "$LDLINUX_DIR/$mod" "$ISO_STAGING/boot/isolinux/" done # Isolinux config cat > "$ISO_STAGING/boot/isolinux/isolinux.cfg" << 'EOF' DEFAULT kubesolo TIMEOUT 30 PROMPT 0 LABEL kubesolo MENU LABEL KubeSolo OS KERNEL /boot/vmlinuz INITRD /boot/kubesolo-os.gz APPEND quiet kubesolo.data=LABEL=KSOLODATA LABEL kubesolo-debug MENU LABEL KubeSolo OS (debug) KERNEL /boot/vmlinuz INITRD /boot/kubesolo-os.gz APPEND kubesolo.data=LABEL=KSOLODATA kubesolo.debug console=ttyS0,115200n8 LABEL kubesolo-shell MENU LABEL KubeSolo OS (emergency shell) KERNEL /boot/vmlinuz INITRD /boot/kubesolo-os.gz APPEND kubesolo.shell console=ttyS0,115200n8 LABEL kubesolo-nopersist MENU LABEL KubeSolo OS (RAM only, no persistence) KERNEL /boot/vmlinuz INITRD /boot/kubesolo-os.gz APPEND kubesolo.nopersist EOF # --- Create ISO --- mkdir -p "$OUTPUT_DIR" case "$MKISO_CMD" in xorriso) xorriso -as mkisofs \ -o "$ISO_OUTPUT" \ -isohybrid-mbr /usr/lib/ISOLINUX/isohdpfx.bin 2>/dev/null || true \ -c boot/isolinux/boot.cat \ -b boot/isolinux/isolinux.bin \ -no-emul-boot \ -boot-load-size 4 \ -boot-info-table \ "$ISO_STAGING" ;; *) "$MKISO_CMD" \ -o "$ISO_OUTPUT" \ -b boot/isolinux/isolinux.bin \ -c boot/isolinux/boot.cat \ -no-emul-boot \ -boot-load-size 4 \ -boot-info-table \ -J -R -V "KUBESOLOOS" \ "$ISO_STAGING" ;; esac # Make ISO hybrid-bootable (USB stick) if command -v isohybrid >/dev/null 2>&1; then isohybrid "$ISO_OUTPUT" 2>/dev/null || true fi # Clean staging rm -rf "$ISO_STAGING" echo "" echo "==> ISO created: $ISO_OUTPUT" echo " Size: $(du -h "$ISO_OUTPUT" | cut -f1)" echo "" echo " Boot in QEMU: make dev-vm" echo " Write to USB: dd if=$ISO_OUTPUT of=/dev/sdX bs=4M status=progress"