#!/bin/sh # Build a bootable Schunix ISO. # # tools/mkiso.sh [output.iso] # # The disc boots through El Torito's "no emulation" mode, which is the only # one of the three that fits how Schunix actually loads itself. # # floppy emulation caps the image at 2.88 MB; the ramdisk-root kernel # alone is bigger than that. # hard disk emulation presents the image through the BIOS's INT 13h, and # Schunix's loader does not use INT 13h -- it drives # the IDE controller's registers directly, which # cannot reach a BIOS-emulated drive. # no emulation the BIOS loads a chosen run of sectors at 0x7C00 # and gets out of the way. That is this. # # So the layout below is deliberate: -boot-load-size is 1 + STAGE2_SECTORS, # which makes the BIOS place both boot/cdboot and the whole of stage2 in memory # before anything of ours runs. That puts stage2 at 0x7E00 -- byte for byte the # arrangement bootasm.S produces on a hard disk. From there the only difference # is that stage2main.c reads the kernel back with ATAPI instead of ATA. # # STAGE2_SECTORS comes from the environment, set by the Makefile, because this # same number also lives in boot/bootasm.S, boot/stage2main.c and the dd offsets # in schunix.img's recipe. It was previously written out by hand in three # separate spots in this file alone, and raising it for the boot logo is what # turned that from a latent hazard into a broken image. # # NOT using -boot-info-table on purpose: it patches 56 bytes over offset 8 of # the boot image, which is the middle of cdboot's code. stage2main.c finds # where it was loaded from by reading the El Torito boot catalog instead. set -e BUILD=${BUILD:-build} OUT=${1:-schunix.iso} STAGE2_SECTORS=${STAGE2_SECTORS:-48} STAGE2_BYTES=$((STAGE2_SECTORS * 512)) LOAD_SIZE=$((1 + STAGE2_SECTORS)) STAGING="$BUILD/iso" CDBOOT="$BUILD/boot/cdboot" STAGE2="$BUILD/boot/stage2" KERNEL="$BUILD/kernel/kernel" for f in "$CDBOOT" "$STAGE2" "$KERNEL"; do [ -f "$f" ] || { echo "mkiso: missing $f -- run make first" >&2; exit 1; } done # The three pieces must be contiguous and at these exact sizes: stage2main.c's # readseg() finds the kernel at sector (1 + STAGE2_SECTORS) of the boot image, # so a short stage2 would silently shift the kernel out from under it. cdboot_sz=$(wc -c < "$CDBOOT") stage2_sz=$(wc -c < "$STAGE2") [ "$cdboot_sz" -eq 512 ] || { echo "mkiso: cdboot is $cdboot_sz bytes, expected 512" >&2; exit 1; } [ "$stage2_sz" -eq "$STAGE2_BYTES" ] || { echo "mkiso: stage2 is $stage2_sz bytes, expected $STAGE2_BYTES (STAGE2_SECTORS=$STAGE2_SECTORS)" >&2; exit 1; } rm -rf "$STAGING" mkdir -p "$STAGING/boot" cat "$CDBOOT" "$STAGE2" "$KERNEL" > "$STAGING/boot/schunix.bin" # xorriso if it is here, mkisofs otherwise. Both accept the El Torito flags # below unchanged -- xorriso's -as mkisofs mode exists precisely to be # argument-compatible with it. The fallback is not academic: there is no xorriso # package for Windows in scoop, where this is developed, but cdrtools provides # mkisofs.exe. if command -v xorriso >/dev/null 2>&1; then MKISOFS="xorriso -as mkisofs" elif command -v mkisofs >/dev/null 2>&1; then MKISOFS="mkisofs" else echo "mkiso: need xorriso or mkisofs on PATH" >&2 echo " Windows: scoop install cdrtools" >&2 echo " Debian/Ubuntu: apt install xorriso" >&2 exit 1 fi $MKISOFS \ -quiet \ -V SCHUNIX \ -A "Schunix" \ -b boot/schunix.bin \ -no-emul-boot \ -boot-load-size "$LOAD_SIZE" \ -o "$OUT" \ "$STAGING" echo "==> $OUT ($(wc -c < "$OUT") bytes)" echo " qemu-system-x86_64 -cdrom $OUT -boot d"