# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License. # See LICENSE.md for license information. # SPDX-License-Identifier: MIT # # Shared by the Haiku components (haikuGcc, haikuGcc2, haikuVm, haikuVm32), # the BeOS VM (installer/lib/beos.sh, which uses its BFS helpers and job # runner protocol) and the Be API ports' gates (scripts/lib/beGate.sh): the # Haiku R1/beta6 release they are all made from, getting files into and out # of its disk images and packages, and the job runner its VM images boot # into. Sourced, not executed. ARCH is a Haiku architecture: x86_64, or # x86_gcc2 (the 32-bit hybrid, gcc2h, whose primary compiler is gcc 2.95 # for BeOS compatibility). # # The job runner: a VM image's UserBootscript (written by haikuVmPrepare) # looks for a disk labelled HAIKU_JOB_VOLUME, mounts it, waits for the # desktop and the media services (the boot script runs before they are up, # and a program opening its sound before the media server has started gets # none), runs its job.sh there with the output going to job.log beside it, # then shuts the machine down, so QEMU exits. A boot without that disk is an # ordinary desktop. Lines on the first serial port mark the job's progress # (HAIKU_JOB_STARTED, HAIKU_JOB_FINISHED). # The anyboot images: a mirror listed on haiku-os.org/get-haiku/r1beta6, and # the SHA256 sums that page gives. HAIKU_ISO_BASE="https://mirrors.rit.edu/haiku/r1beta6" HAIKU_ISO_NAME_x86_64="haiku-r1beta6-x86_64-anyboot.iso" HAIKU_ISO_SHA256_x86_64="bb7743474fd175aea511be1799764ba054465285bbdf54c4722ca61d1fb4f5c9" HAIKU_ISO_NAME_x86_gcc2="haiku-r1beta6-x86_gcc2h-anyboot.iso" HAIKU_ISO_SHA256_x86_gcc2="5a55ad9429f1de9fb5ca5cbcd54de3733ff247cc7919ce5d690fb1271cb1dc76" # The release's packages (hrev59866_79, what the images were built from) in # Haiku's repository, and HaikuPorts' (the compiler's runtime), by the # checksums the repositories' indexes give. HAIKU_REVISION="r1~beta6_hrev59866_79" HAIKU_REPO_BASE="https://eu.hpkg.haiku-os.org/haiku/r1beta6" HAIKU_PORTS_BASE="https://eu.hpkg.haiku-os.org/haikuports/master" # The job runner's disk label and serial port lines, and the applications # it waits for: Deskbar, the media server and its add-on host. HAIKU_JOB_VOLUME="JoeyJob" HAIKU_JOB_WAIT_APPS="application/x-vnd.Be-TSKB application/x-vnd.Be.media-server application/x-vnd.Be.addon-host" HAIKU_JOB_STARTED="JOEY: job started" HAIKU_JOB_FINISHED="JOEY: job finished" # Seconds the runner waits for the job disk to appear while booting. HAIKU_JOB_WAIT_SECONDS=10 # Haiku's build-host tools (component haikuTools). HAIKU_TOOLS="${HAIKU_TOOLS:-${JOEY_OPT:-}/haikuTools/bin}" # haikuBfs IMAGE [OFFSET] -- run the bfs_shell commands on stdin against the # BFS volume in IMAGE (at byte OFFSET, for a partitioned disk), the volume # at /myfs and host files as :PATH. Its output is printed; returns 1 when a # command failed. sync is run before the volume is let go: bfs_shell's quit # reports the volume busy after a copy and would not write it otherwise. haikuBfs() { local image="$1" local offset="${2:-}" local out local errors out="$({ cat; printf 'sync\nquit\n'; } | "$HAIKU_TOOLS/bfs_shell" ${offset:+--start-offset "$offset"} "$image" 2>&1 || true)" printf '%s\n' "$out" errors="$(printf '%s\n' "$out" | grep -i -e 'error' | grep -v 'Unmounting FS failed: Device or resource busy' || true)" [ -z "$errors" ] } # haikuBfsNew IMAGE SIZE LABEL -- a new BFS volume of SIZE (truncate's # suffixes: 64M) in the file IMAGE. haikuBfsNew() { rm -f "$1" truncate -s "$2" "$1" "$HAIKU_TOOLS/bfs_shell" --initialize "$1" "$3" > /dev/null } # haikuBootOffset IMAGE -- the byte offset of an anyboot image's first # partition, its BFS system volume (from the MBR: entry 1's start sector). haikuBootOffset() { python3 - "$1" <<'PY' import struct import sys MBR_ENTRY_1 = 446 ENTRY_START_LBA = 8 SECTOR_BYTES = 512 with open(sys.argv[1], 'rb') as image: mbr = image.read(SECTOR_BYTES) print(struct.unpack_from(' /dev/null || die "cannot copy $2 out of $iso" [ -s "$3" ] || die "$2 is not in $iso" } # haikuRepoPackage BASE ARCH PATH FILE SHA256 -- download (once) and print # a package from a Haiku repository: BASE/ARCH/PATH/packages/FILE. haikuRepoPackage() { fetchFile "$1/$2/$3/packages/$4" "$5" "$4" } # haikuSysroot DEST PACKAGE... -- the parts of the packages a cross compiler # needs (lib and develop) unpacked into DEST/boot/system, where a Haiku # compiler looks for them. haikuSysroot() { local dest="$1" local package shift mkdir -p "$dest/boot/system" for package in "$@"; do # A package with only one of the two warns about the other. "$HAIKU_TOOLS/package" extract -C "$dest/boot/system" "$package" lib develop 2> /dev/null || die "cannot unpack $package" done } # haikuVmPrepare ARCH IMAGE -- the release's anyboot image copied to IMAGE, # booting straight to the desktop (no first-boot prompt) and running the job # runner. haikuVmPrepare() { local iso local tmp iso="$(haikuIso "$1")" tmp="$(mktemp -d)" haikuJobRunner > "$tmp/UserBootscript" # The first-boot prompt (language and keymap, or the installer) comes # up while there are no locale settings. : > "$tmp/Locale settings" cp "$iso" "$2.part" haikuBfs "$2.part" "$(haikuBootOffset "$2.part")" > /dev/null < /dev/null 2>&1 tries=\$((tries + 1)) if [ \$tries -gt $HAIKU_JOB_WAIT_SECONDS ]; then exit 0 fi sleep 1 done for app in $HAIKU_JOB_WAIT_APPS; do waitfor -m \$app done echo "$HAIKU_JOB_STARTED" > \$serial cd /$HAIKU_JOB_VOLUME /bin/sh ./job.sh > job.log 2>&1 echo "$HAIKU_JOB_FINISHED \$?" > \$serial cd / sync shutdown -q EOF }