Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F168919005
D58008.id181227.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
36 KB
Referenced Files
None
Subscribers
None
D58008.id181227.diff
View Options
diff --git a/tools/boot/boot-test.sh b/tools/boot/boot-test.sh
new file mode 100755
--- /dev/null
+++ b/tools/boot/boot-test.sh
@@ -0,0 +1,1189 @@
+#!/bin/sh
+#
+# boot-test.sh - Automated boot loader regression tests
+#
+# Builds a minimal bootable tree, assembles disk images for all supported
+# boot configurations, then runs each in QEMU with a timeout looking for
+# "SUCCESS".
+#
+# All tests run as an unprivileged user. No root required.
+# Assumes buildworld and buildkernel have already been done for the
+# target architecture.
+#
+# Usage:
+# cd /usr/src/stand && sh ../tools/boot/boot-test.sh [options]
+#
+# Options:
+# -a ARCH Architecture to test (default: amd64)
+# Supported: amd64, aarch64, armv7, riscv64, powerpc64, powerpc64le
+# -b Skip build/install phase (reuse existing tree)
+# -B Skip build/install and image creation (reuse existing images)
+# -t REGEX Only run tests matching REGEX
+# -T SECONDS QEMU timeout (default: per-arch, 60; 180 for powerpc64)
+# -j JOBS Max parallel QEMU instances (default: unlimited)
+# -o DIR Output directory for images and logs
+
+set -e
+
+die() {
+ echo "FATAL: $*" >&2
+ exit 1
+}
+
+# --------------------------------------------------------------------------
+# Architecture configuration
+#
+# config_defaults() sets every ARCH_* variable to a sane default; each
+# config_<arch> calls it and then overrides only what differs. The
+# generic phases iterate over what's declared.
+#
+# ARCH_CAPS is a space-separated capability list, queried with has():
+# bios efi ofw linuxboot zfs mbr cd
+# --------------------------------------------------------------------------
+
+# Test whether the current arch declares a capability, e.g. "has efi".
+has() {
+ case " ${ARCH_CAPS} " in
+ *" $1 "*) return 0 ;;
+ esac
+ return 1
+}
+
+config_defaults() {
+ ARCH_QEMU_MACHINE=""
+ ARCH_QEMU_CPU=""
+ ARCH_QEMU_EXTRA=""
+ ARCH_EFI_FIRMWARE=""
+ ARCH_EFI_BOOTNAME=""
+ ARCH_BYTE_ORDER=little
+ ARCH_CAPS=""
+ ARCH_EFI_LOADERS="loader_lua loader_4th loader_simp boot1"
+ ARCH_BIOS_LOADERS=""
+ ARCH_LINUX_CONSOLE=""
+ ARCH_KERNCONF=GENERIC
+ ARCH_HINTS=""
+ ARCH_TIMEOUT=60 # QEMU per-test timeout (seconds), -T overrides
+}
+
+config_amd64() {
+ config_defaults
+ ARCH_QEMU_BIN=qemu-system-x86_64
+ ARCH_EFI_FIRMWARE=/usr/local/share/qemu/edk2-x86_64-code.fd
+ ARCH_EFI_BOOTNAME=bootx64
+ ARCH_CAPS="bios efi linuxboot zfs mbr cd"
+ ARCH_BIOS_LOADERS="lua 4th simp"
+ ARCH_LINUX_CONSOLE="console=ttyS0,115200"
+ ARCH_MAKE_TARGET="TARGET_ARCH=amd64 TARGET=amd64"
+ ARCH_ISO_NAME=amd64
+ ARCH_HINTS=${SRCTOP}/sys/amd64/conf/GENERIC.hints
+}
+
+config_aarch64() {
+ config_defaults
+ ARCH_QEMU_BIN=qemu-system-aarch64
+ ARCH_QEMU_MACHINE="-machine virt,gic-version=3"
+ ARCH_QEMU_CPU="-cpu cortex-a57"
+ ARCH_QEMU_EXTRA="-smp 4"
+ ARCH_EFI_FIRMWARE=/usr/local/share/qemu/edk2-aarch64-code.fd
+ ARCH_EFI_BOOTNAME=bootaa64
+ ARCH_CAPS="efi linuxboot zfs"
+ ARCH_MAKE_TARGET="TARGET=arm64 TARGET_ARCH=aarch64"
+ ARCH_ISO_NAME=arm64-aarch64
+}
+
+config_armv7() {
+ config_defaults
+ ARCH_QEMU_BIN=qemu-system-arm
+ ARCH_QEMU_MACHINE="-machine virt"
+ ARCH_QEMU_CPU="-cpu cortex-a15"
+ ARCH_EFI_FIRMWARE=/usr/local/share/qemu/edk2-arm-code.fd
+ ARCH_EFI_BOOTNAME=bootarm
+ ARCH_CAPS="efi"
+ ARCH_MAKE_TARGET="TARGET=arm TARGET_ARCH=armv7"
+ ARCH_ISO_NAME=arm-armv7
+}
+
+config_riscv64() {
+ config_defaults
+ ARCH_QEMU_BIN=qemu-system-riscv64
+ ARCH_QEMU_MACHINE="-machine virt"
+ ARCH_QEMU_EXTRA="-bios /usr/local/share/opensbi/lp64/generic/firmware/fw_jump.elf -kernel /usr/local/share/u-boot/u-boot-qemu-riscv64/u-boot.bin"
+ ARCH_EFI_FIRMWARE=""
+ ARCH_EFI_BOOTNAME=bootriscv64
+ ARCH_CAPS="efi zfs"
+ ARCH_MAKE_TARGET="TARGET=riscv TARGET_ARCH=riscv64"
+ ARCH_ISO_NAME=riscv-riscv64
+}
+
+config_powerpc64() {
+ config_defaults
+ ARCH_QEMU_BIN=qemu-system-ppc64
+ ARCH_QEMU_MACHINE="-M mac99,via=pmu"
+ ARCH_QEMU_CPU="-cpu 970fx"
+ ARCH_BYTE_ORDER=big
+ ARCH_CAPS="ofw zfs cd"
+ ARCH_EFI_LOADERS=""
+ ARCH_MAKE_TARGET="TARGET=powerpc TARGET_ARCH=powerpc64"
+ ARCH_ISO_NAME=powerpc-powerpc64
+ ARCH_KERNCONF=GENERIC64
+ ARCH_TIMEOUT=180 # OFW/ATA boot under QEMU is very slow
+}
+
+config_powerpc64le() {
+ config_defaults
+ ARCH_QEMU_BIN=qemu-system-ppc64
+ ARCH_QEMU_MACHINE="-machine pseries"
+ ARCH_CAPS="zfs linuxboot"
+ ARCH_EFI_LOADERS=""
+ ARCH_LINUX_CONSOLE="console=hvc0" # pseries PAPR hypervisor console
+ ARCH_MAKE_TARGET="TARGET=powerpc TARGET_ARCH=powerpc64le"
+ ARCH_ISO_NAME=powerpc-powerpc64le
+ ARCH_KERNCONF=GENERIC64
+}
+
+# --- Configuration ---
+
+TIMEOUT="" # empty until set by -T; else defaults to ARCH_TIMEOUT
+SKIP_BUILD=false
+SKIP_IMAGES=false
+TEST_FILTER=""
+MAX_JOBS=0
+OUTDIR=""
+ARCH=amd64
+
+while getopts "a:bBt:T:j:o:" opt; do
+ case "$opt" in
+ a) ARCH="$OPTARG" ;; # XXX handle "all" in the future
+ b) SKIP_BUILD=true ;;
+ B) SKIP_BUILD=true; SKIP_IMAGES=true ;;
+ t) TEST_FILTER="$OPTARG" ;;
+ T) TIMEOUT="$OPTARG" ;;
+ j) MAX_JOBS="$OPTARG" ;;
+ o) OUTDIR="$OPTARG" ;;
+ ?) echo "Usage: $0 [-a arch] [-b] [-B] [-t regex] [-T secs] [-j jobs] [-o dir]" >&2
+ exit 1 ;;
+ esac
+done
+
+SRCTOP=$(make -v SRCTOP) || die "Run from stand/ directory in a FreeBSD source tree"
+cd ${SRCTOP}/stand
+
+# Load architecture configuration
+type config_${ARCH} > /dev/null 2>&1 || die "Unknown architecture: ${ARCH}"
+config_${ARCH}
+
+# Fall back to the arch's default timeout unless -T was given
+[ -n "${TIMEOUT}" ] || TIMEOUT=${ARCH_TIMEOUT}
+
+# Get the arch-specific OBJDIR (contains the TARGET_ARCH component)
+if [ -n "${ARCH_MAKE_TARGET}" ]; then
+ ARCH_OBJDIR=$(make buildenv ${ARCH_MAKE_TARGET} \
+ BUILDENV_SHELL="make -V .OBJDIR" 2>/dev/null | tail -1)
+else
+ ARCH_OBJDIR=$(make -v .OBJDIR)
+fi
+[ -n "${ARCH_OBJDIR}" ] || die "Cannot determine OBJDIR for ${ARCH}"
+
+if [ -z "$OUTDIR" ]; then
+ OUTDIR=${ARCH_OBJDIR}/boot-test
+fi
+IMGDIR=${OUTDIR}/images
+LOGDIR=${OUTDIR}/logs
+DESTDIR=${OUTDIR}/tree
+
+# The smallest FAT32 filesystem is 33292 KB
+espsize=33292
+
+# Linux kernel version for linuxboot tests
+LINUX_VERSION=6.18.2
+
+mkdir -p ${IMGDIR} ${LOGDIR}
+
+# --------------------------------------------------------------------------
+# QEMU command builders
+# --------------------------------------------------------------------------
+
+qemu_base() {
+ img=$1
+ extra=$2
+ echo "${ARCH_QEMU_BIN} -m 1g ${ARCH_QEMU_MACHINE} ${ARCH_QEMU_CPU} ${ARCH_QEMU_EXTRA} ${extra} -drive file=${img},format=raw -nographic -monitor none -serial stdio"
+}
+
+qemu_efi() {
+ local extra=""
+ [ -n "${ARCH_EFI_FIRMWARE}" ] && extra="-drive file=${ARCH_EFI_FIRMWARE},format=raw,if=pflash,readonly=on"
+ qemu_base $1 "${extra}"
+}
+
+qemu_bios() {
+ qemu_base $1 ""
+}
+
+qemu_bios_cdrom() {
+ img=$1
+ echo "${ARCH_QEMU_BIN} -m 1g ${ARCH_QEMU_MACHINE} ${ARCH_QEMU_CPU} ${ARCH_QEMU_EXTRA} -cdrom ${img} -nographic -monitor none -serial stdio"
+}
+
+qemu_efi_cdrom() {
+ img=$1
+ echo "${ARCH_QEMU_BIN} -m 1g ${ARCH_QEMU_MACHINE} ${ARCH_QEMU_CPU} ${ARCH_QEMU_EXTRA} -drive file=${ARCH_EFI_FIRMWARE},format=raw,if=pflash,readonly=on -cdrom ${img} -nographic -monitor none -serial stdio"
+}
+
+qemu_ofw() {
+ img=$1
+ # QEMU's bundled OpenBIOS is missing fixes we need for a while, so prefer
+ # a custom openbios-ppc cached alongside the ISOs (${ISODIR}) if present.
+ bios=""
+ [ -f "${ISODIR}/openbios-ppc" ] && bios="-bios ${ISODIR}/openbios-ppc"
+ # Attach the disk on the default (macio IDE) bus: OpenBIOS aliases that
+ # as "hd" and auto-probes hd:,\\:tbxi to find the Apple_Bootstrap
+ # (boot1.hfs) partition. virtio disks are not reachable as "hd", so
+ # OF's boot probe finds nothing and drops to the "0 >" prompt.
+ echo "${ARCH_QEMU_BIN} -m 1g ${ARCH_QEMU_MACHINE} ${ARCH_QEMU_CPU} ${ARCH_QEMU_EXTRA} ${bios} -vga none -drive file=${img},format=raw -nographic -monitor none -serial stdio"
+}
+
+qemu_ofw_cdrom() {
+ img=$1
+ bios=""
+ [ -f "${ISODIR}/openbios-ppc" ] && bios="-bios ${ISODIR}/openbios-ppc"
+ # -boot d boots the (macio IDE) CD-ROM, which OpenBIOS aliases as "cd"
+ # and probes cd:,\\:tbxi for the Apple/OF boot block.
+ echo "${ARCH_QEMU_BIN} -m 1g ${ARCH_QEMU_MACHINE} ${ARCH_QEMU_CPU} ${ARCH_QEMU_EXTRA} ${bios} -vga none -boot d -cdrom ${img} -nographic -monitor none -serial stdio"
+}
+
+# Direct linuxboot: hand the Linux kernel and initrd to QEMU on the command
+# line (-kernel/-initrd) rather than off an ESP. Used by platforms with no
+# EFI/ESP (e.g. powerpc64le/pseries); the FreeBSD root disk is attached the
+# same way as every other test via qemu_base.
+qemu_linuxboot() {
+ img=$1
+ kernel=$2
+ initrd=$3
+ extra="-kernel ${kernel} -initrd ${initrd}"
+ [ -n "${ARCH_LINUX_CONSOLE}" ] && extra="${extra} -append ${ARCH_LINUX_CONSOLE}"
+ qemu_base ${img} "${extra}"
+}
+
+# --------------------------------------------------------------------------
+# Phase 0: Extract minimal userland from release ISO
+# --------------------------------------------------------------------------
+
+# Binaries needed for a minimal bootable userland.
+# Libraries are inferred from these via ldd on the host equivalents.
+USERLAND_BINS="sbin/fastboot sbin/halt sbin/init bin/sh sbin/sysctl"
+
+# ISO images live in ~/iso, named:
+# FreeBSD-15.1-RELEASE-${ARCH_ISO_NAME}-disc1.iso
+# (armv7 uses disk1.iso but the user has ensured it's tar-readable)
+ISODIR=${HOME}/iso
+FREEBSD_VERSION=15.1
+
+find_iso() {
+ for suffix in disc1.iso disc1.iso.xz; do
+ f=${ISODIR}/FreeBSD-${FREEBSD_VERSION}-RELEASE-${ARCH_ISO_NAME}-${suffix}
+ if [ -f "$f" ]; then
+ echo "$f"
+ return
+ fi
+ done
+ die "No ISO found for ${ARCH} in ${ISODIR} (looked for FreeBSD-${FREEBSD_VERSION}-RELEASE-${ARCH_ISO_NAME}-disc1.iso)"
+}
+
+install_minimal_userland() {
+ echo " Extracting minimal userland from release ISO..."
+
+ iso=$(find_iso)
+
+ # Determine library paths from host equivalents of our binaries
+ host_bins=""
+ for b in ${USERLAND_BINS}; do
+ host_bins="${host_bins} /${b}"
+ done
+ lib_paths=$(ldd ${host_bins} 2>/dev/null \
+ | awk 'NF == 4 { print $3 }' | sort -u)
+
+ # Build the list of paths to extract: binaries + libraries + rtld
+ extract_list=""
+ for b in ${USERLAND_BINS}; do
+ extract_list="${extract_list} ./${b}"
+ done
+ for l in ${lib_paths}; do
+ extract_list="${extract_list} .${l}"
+ done
+ extract_list="${extract_list} ./libexec/ld-elf.so.1"
+
+ # Some architectures (e.g., armv7) need libgcc_s.so.1 even though
+ # the host binaries don't. Always try to extract it.
+ extract_list="${extract_list} ./lib/libgcc_s.so.1"
+
+ # Extract the files from the tarball.
+ tar -C ${DESTDIR} -xf ${iso} ${extract_list} \
+ >> ${LOGDIR}/installuserland.log 2>&1 || true
+}
+
+# --------------------------------------------------------------------------
+# Phase 1: Build the boot tree
+# --------------------------------------------------------------------------
+
+build_tree() {
+ echo "=== Phase 1: Building boot tree ==="
+
+ rm -rf ${DESTDIR}
+ mkdir -p ${DESTDIR}/boot/defaults
+ mkdir -p ${DESTDIR}/boot/kernel
+ mkdir -p ${DESTDIR}/boot/uboot
+ mkdir -p ${DESTDIR}/sbin ${DESTDIR}/bin \
+ ${DESTDIR}/lib ${DESTDIR}/libexec \
+ ${DESTDIR}/etc ${DESTDIR}/dev
+
+ # Install kernel
+ # I'd prefer this to be MINIMAL, but GENERIC is needed until I work out what
+ # different devices we boot from...
+ (cd ${SRCTOP} && make installkernel \
+ ${ARCH_MAKE_TARGET} \
+ KERNCONF=${ARCH_KERNCONF} \
+ MODULES_OVERRIDE="ufs zfs acl_nfs4 crypto zlib cd9660" \
+ DESTDIR=${DESTDIR} \
+ MK_KERNEL_SYMBOLS=no \
+ MK_INSTALL_AS_USER=yes) > ${LOGDIR}/installkernel.log 2>&1 \
+ || die "Kernel install failed (see ${LOGDIR}/installkernel.log)"
+
+ # Install boot loaders
+ make buildenv ${ARCH_MAKE_TARGET} \
+ DESTDIR=${DESTDIR} \
+ MK_MAN=no \
+ MK_INSTALL_AS_USER=yes \
+ MK_DEBUG_FILES=no \
+ BUILDENV_SHELL="make all install" \
+ >> ${LOGDIR}/installloader.log 2>&1 \
+ || die "Boot loader install failed (see ${LOGDIR}/installloader.log)"
+
+ # Install minimal userland (works for both native and cross builds)
+ install_minimal_userland
+
+ # Remove default loader symlinks -- we add them back per-image via
+ # mtree overlays to test each loader variant individually.
+ # /boot/loader is the BIOS stage-3 (amd64 only).
+ # /boot/loader.efi is what boot1.efi chainloads (all EFI platforms).
+ # OFW is the exception: its /boot/loader is the one real loader (no
+ # lua/4th/simp variants are built), so keep it in the tree.
+ has ofw || rm -f ${DESTDIR}/boot/loader
+ rm -f ${DESTDIR}/boot/loader.efi
+
+ # Serial console configuration. boot.config is consumed only by the
+ # BIOS boot blocks; its -h/-D/-S flags are meaningless on EFI/OFW, so
+ # only write it where BIOS booting is supported.
+ if has bios; then
+ echo -h -D -S115200 > ${DESTDIR}/boot.config
+ fi
+ # Unified loader.conf: always load ufs, zfs, and cd9660
+ cat > ${DESTDIR}/boot/loader.conf <<EOF
+boot_serial=YES
+comconsole_speed=115200
+autoboot_delay=1
+ufs_load="YES"
+zfs_load="YES"
+cd9660_load="YES"
+EOF
+ if [ -n "${ARCH_HINTS}" ] && [ -f "${ARCH_HINTS}" ]; then
+ cp ${ARCH_HINTS} ${DESTDIR}/boot/device.hints
+ fi
+
+ # Test /etc/rc - prints success and halts
+ cat > ${DESTDIR}/etc/rc <<'RCEOF'
+#!/bin/sh
+
+sysctl machdep.bootmethod
+echo "RC COMMAND RUNNING -- SUCCESS!!!!!"
+halt -p
+RCEOF
+ chmod +x ${DESTDIR}/etc/rc
+
+ # Create fstab used by UFS mtree overlays
+ cat > ${OUTDIR}/fstab.ufs <<EOF
+/dev/ufs/root / ufs rw 1 1
+EOF
+ # Create fstab used by CD mtree overlays
+ cat > ${OUTDIR}/fstab.cd <<EOF
+/dev/iso9660/FBSDTEST / cd9660 ro 0 0
+EOF
+
+ echo "Boot tree built in ${DESTDIR}"
+}
+
+# --------------------------------------------------------------------------
+# Phase 2: Create base filesystem images
+#
+# Uses mtree overlays to vary the /boot/loader and /etc/fstab
+# without copying the tree. The base tree has no /boot/loader or
+# /etc/fstab; each image adds what it needs via an mtree spec file
+# passed as a second source to makefs.
+# --------------------------------------------------------------------------
+
+# Create a UFS image with a specific loader variant via mtree overlay
+make_one_ufs() {
+ variant=$1
+ img=${IMGDIR}/bootable-ufs-${variant}.img
+ mt=$(mktemp ${OUTDIR}/ufs-mtree.XXXXXX)
+
+ echo " Creating UFS image with loader_${variant}..."
+ echo "./etc/fstab type=file mode=0644 contents=${OUTDIR}/fstab.ufs" > ${mt}
+ # BIOS: /boot/loader -> loader_<variant>
+ if [ -n "${ARCH_BIOS_LOADERS}" ]; then
+ echo "./boot/loader type=file mode=0644 contents=${DESTDIR}/boot/loader_${variant}" >> ${mt}
+ fi
+ # OFW: boot1.hfs chainloads the single /boot/loader already in the
+ # tree (no per-variant overlay needed).
+ # EFI: /boot/loader.efi -> loader_<variant>.efi (needed for boot1.efi chainload)
+ if has efi; then
+ echo "./boot/loader.efi type=file mode=0755 contents=${DESTDIR}/boot/loader_${variant}.efi" >> ${mt}
+ fi
+ makefs -t ffs -B ${ARCH_BYTE_ORDER} -M 10m -o label=root -o version=2 \
+ ${img} ${mt} ${DESTDIR} >> ${LOGDIR}/imagebuild.log 2>&1
+ rm -f ${mt}
+}
+
+# Create a ZFS image with a specific loader variant via mtree overlay
+make_one_zfs() {
+ variant=$1
+ img=${IMGDIR}/bootable-zfs-${variant}.img
+ mt=$(mktemp ${OUTDIR}/zfs-mtree.XXXXXX)
+
+ echo " Creating ZFS image with loader_${variant}..."
+ > ${mt}
+ # BIOS: /boot/loader -> loader_<variant>
+ if [ -n "${ARCH_BIOS_LOADERS}" ]; then
+ echo "./boot/loader type=link link=loader_${variant}" >> ${mt}
+ fi
+ # OFW: boot1.hfs chainloads the single /boot/loader already in the
+ # tree (no per-variant overlay needed).
+ # EFI: /boot/loader.efi -> loader_<variant>.efi (needed for boot1.efi chainload)
+ if has efi; then
+ echo "./boot/loader.efi type=file mode=0755 contents=${DESTDIR}/boot/loader_${variant}.efi" >> ${mt}
+ fi
+ makefs -t zfs -s 100m \
+ -o poolname=ztestroot -o bootfs=ztestroot -o rootpath=/ \
+ ${img} ${mt} ${DESTDIR} >> ${LOGDIR}/imagebuild.log 2>&1
+ rm -f ${mt}
+}
+
+# Create an ESP with the given EFI loader using an mtree spec
+make_one_esp() {
+ loader_name=$1 # e.g., loader_lua, loader_4th, loader_simp, boot1
+ esp=${IMGDIR}/${loader_name}.esp
+ mt=$(mktemp ${OUTDIR}/esp-mtree.XXXXXX)
+
+ echo " Creating ESP with ${loader_name}.efi..."
+ cat > ${mt} <<EOF
+./efi type=dir uname=root gname=wheel mode=0755
+./efi/boot type=dir uname=root gname=wheel mode=0755
+./efi/boot/${ARCH_EFI_BOOTNAME}.efi type=file uname=root gname=wheel mode=0755 contents=${DESTDIR}/boot/${loader_name}.efi
+EOF
+ makefs -t msdos \
+ -o fat_type=32 \
+ -o sectors_per_cluster=1 \
+ -o volume_label=EFISYS \
+ -s ${espsize}k \
+ ${esp} ${mt} >> ${LOGDIR}/imagebuild.log 2>&1
+ rm -f ${mt}
+}
+
+# Create a small ESP for CD hybrid boot using an mtree spec
+make_cd_esp() {
+ file=$1
+ loader=$2
+ mt=$(mktemp ${OUTDIR}/cd-esp-mtree.XXXXXX)
+
+ cat > ${mt} <<EOF
+./efi type=dir uname=root gname=wheel mode=0755
+./efi/boot type=dir uname=root gname=wheel mode=0755
+./efi/boot/${ARCH_EFI_BOOTNAME}.efi type=file uname=root gname=wheel mode=0755 contents=${loader}
+EOF
+ makefs -t msdos \
+ -o fat_type=12 \
+ -o sectors_per_cluster=1 \
+ -o volume_label=EFISYS \
+ -s 2048k \
+ ${file} ${mt} >> ${LOGDIR}/imagebuild.log 2>&1
+ rm -f ${mt}
+}
+
+# Find the pre-built Linux kernel EFI binary for linuxboot
+find_linux_kernel() {
+ target_arch=$(echo ${ARCH_MAKE_TARGET} | sed 's/.*TARGET_ARCH=//;s/ .*//')
+ linuxboot_dir=${ARCH_OBJDIR}/../../linuxboot/data/output
+
+ # amd64 has .efi suffix, others don't
+ for f in \
+ ${linuxboot_dir}/${target_arch}.linux.v${LINUX_VERSION}.efi \
+ ${linuxboot_dir}/${target_arch}.linux.v${LINUX_VERSION} \
+ ${linuxboot_dir}/${target_arch}.v${LINUX_VERSION}.efi \
+ ${linuxboot_dir}/${target_arch}.v${LINUX_VERSION}; do
+ if [ -f "$f" ]; then
+ echo "$f"
+ return
+ fi
+ done
+ return 1
+}
+
+# Build a linuxboot initrd using tar --format newc with an mtree spec.
+# No root/sudo required -- device nodes are written directly into the
+# cpio archive via mtree type=char entries.
+make_linuxboot_initrd() {
+ initrd=${IMGDIR}/linuxboot-initrd.cpio.gz
+ mt=$(mktemp ${OUTDIR}/initrd-mtree.XXXXXX)
+
+ echo " Creating linuxboot initrd..."
+
+ # Build mtree spec for the initrd contents
+ cat > ${mt} <<EOF
+./init type=file mode=0755 contents=${DESTDIR}/boot/loader.kboot
+./dev type=dir mode=0755
+./dev/console type=char mode=0600 device=freebsd,5,0
+./dev/tty type=char mode=0600 device=freebsd,5,1
+./dev/ttyS0 type=char mode=0600 device=freebsd,4,64
+./boot type=dir mode=0755
+./boot/defaults type=dir mode=0755
+./boot/defaults/loader.conf type=file mode=0644 contents=${DESTDIR}/boot/defaults/loader.conf
+./boot/lua type=dir mode=0755
+EOF
+
+ # Add all lua files
+ for f in ${DESTDIR}/boot/lua/*.lua; do
+ [ -f "$f" ] || continue
+ bn=$(basename $f)
+ echo "./boot/lua/${bn} type=file mode=0644 contents=$f" >> ${mt}
+ done
+
+ # Add loader.help.kboot if present
+ if [ -f "${DESTDIR}/boot/loader.help.kboot" ]; then
+ echo "./boot/loader.help.kboot type=file mode=0644 contents=${DESTDIR}/boot/loader.help.kboot" >> ${mt}
+ fi
+
+ # Create the kboot-specific loader.conf
+ kboot_conf=$(mktemp ${OUTDIR}/kboot-loader-conf.XXXXXX)
+ cat > ${kboot_conf} <<EOF
+# Kboot configuration -- FreeBSD ${ARCH}
+boot_serial="YES"
+EOF
+ if [ "${ARCH}" = "amd64" ]; then
+ cat >> ${kboot_conf} <<EOF
+hw.uart.console="io:1016,br:115200"
+EOF
+ fi
+ echo "./boot/loader.conf type=file mode=0644 contents=${kboot_conf}" >> ${mt}
+
+ # Create the initrd as a gzip-compressed newc cpio archive
+ tar --format newc -cf - @${mt} 2>> ${LOGDIR}/imagebuild.log | \
+ gzip > ${initrd}
+
+ rm -f ${mt} ${kboot_conf}
+}
+
+# Build a linuxboot ESP containing the Linux kernel, initrd, and startup.nsh
+make_linuxboot_esp() {
+ linux_kernel=$1
+ esp=${IMGDIR}/linuxboot.esp
+ mt=$(mktemp ${OUTDIR}/linuxboot-esp-mtree.XXXXXX)
+
+ echo " Creating linuxboot ESP..."
+
+ # Generate startup.nsh
+ startup=${OUTDIR}/startup.nsh
+ cat > ${startup} <<EOF
+\\linux.efi ${ARCH_LINUX_CONSOLE} initrd=\\initrd
+EOF
+
+ cat > ${mt} <<EOF
+./startup.nsh type=file mode=0644 contents=${startup}
+./linux.efi type=file mode=0755 contents=${linux_kernel}
+./initrd type=file mode=0644 contents=${IMGDIR}/linuxboot-initrd.cpio.gz
+EOF
+ makefs -t msdos \
+ -o fat_type=32 \
+ -o sectors_per_cluster=1 \
+ -o volume_label=EFISYS \
+ -s 100m \
+ ${esp} ${mt} >> ${LOGDIR}/imagebuild.log 2>&1
+ rm -f ${mt}
+}
+
+make_base_images() {
+ echo "=== Phase 2: Creating base filesystem images ==="
+
+ # UFS images - one per BIOS loader variant, plus one for EFI (uses lua)
+ if [ -n "${ARCH_BIOS_LOADERS}" ]; then
+ for v in ${ARCH_BIOS_LOADERS}; do
+ make_one_ufs $v
+ done
+ else
+ # EFI-only arches still need one UFS image
+ make_one_ufs lua
+ fi
+
+ # ZFS images (if supported)
+ if has zfs; then
+ if [ -n "${ARCH_BIOS_LOADERS}" ]; then
+ for v in ${ARCH_BIOS_LOADERS}; do
+ make_one_zfs $v
+ done
+ else
+ make_one_zfs lua
+ fi
+ fi
+
+ # ESP images (if EFI is supported)
+ if has efi; then
+ for l in ${ARCH_EFI_LOADERS}; do
+ make_one_esp $l
+ done
+ fi
+
+ # Linuxboot initrd + ESP (if supported and Linux kernel is available)
+ if has linuxboot; then
+ linux_kernel=$(find_linux_kernel) || true
+ if [ -n "${linux_kernel}" ]; then
+ make_linuxboot_initrd
+ # EFI arches chainload the kernel+initrd off an ESP; platforms
+ # without EFI hand them to QEMU directly (-kernel/-initrd), so
+ # they need no ESP.
+ has efi && make_linuxboot_esp ${linux_kernel}
+ else
+ echo " WARNING: Linux kernel not found for linuxboot, skipping"
+ echo " Expected in: ${ARCH_OBJDIR}/../../linuxboot/data/output/"
+ fi
+ fi
+
+ echo "Base images created in ${IMGDIR}"
+}
+
+# --------------------------------------------------------------------------
+# Phase 3: Assemble disk images and register tests
+# --------------------------------------------------------------------------
+
+# Test registration - uses temp files since /bin/sh doesn't have arrays
+TESTLIST=${OUTDIR}/test-list.txt
+> ${TESTLIST}
+
+register_test() {
+ name=$1
+ shift
+ echo "$*" > ${OUTDIR}/test-cmd-${name}.sh
+ echo "${name}" >> ${TESTLIST}
+}
+
+assemble_efi_gpt() {
+ echo " Assembling EFI+GPT images..."
+ for loader in ${ARCH_EFI_LOADERS}; do
+ esp=${IMGDIR}/${loader}.esp
+ fstypes="ufs"
+ has zfs && fstypes="ufs zfs"
+ for fs in ${fstypes}; do
+ name="efi-gpt-${fs}-${loader}"
+ img=${IMGDIR}/${name}.img
+
+ # For EFI, the stage-3 in the filesystem doesn't matter, use lua variant
+ case ${fs} in
+ ufs) fsimg=${IMGDIR}/bootable-ufs-lua.img; ptype="freebsd-ufs" ;;
+ zfs) fsimg=${IMGDIR}/bootable-zfs-lua.img; ptype="freebsd-zfs" ;;
+ esac
+
+ mkimg -s gpt \
+ -p efi:=${esp} \
+ -p ${ptype}:=${fsimg} \
+ -o ${img} >> ${LOGDIR}/imagebuild.log 2>&1
+
+ register_test ${name} $(qemu_efi ${img})
+ done
+ done
+}
+
+assemble_efi_mbr() {
+ echo " Assembling EFI+MBR images..."
+ for loader in ${ARCH_EFI_LOADERS}; do
+ esp=${IMGDIR}/${loader}.esp
+ name="efi-mbr-ufs-${loader}"
+ img=${IMGDIR}/${name}.img
+ ufs=${IMGDIR}/bootable-ufs-lua.img
+
+ mkimg -s bsd -p freebsd-ufs:=${ufs} -o ${img}.s2 >> ${LOGDIR}/imagebuild.log 2>&1
+ mkimg -a 1 -s mbr -p efi:=${esp} -p freebsd:=${img}.s2 -o ${img} >> ${LOGDIR}/imagebuild.log 2>&1
+ rm -f ${img}.s2
+
+ register_test ${name} $(qemu_efi ${img})
+ done
+}
+
+assemble_bios_gpt() {
+ echo " Assembling BIOS+GPT images..."
+ for variant in ${ARCH_BIOS_LOADERS}; do
+ # UFS
+ name="bios-gpt-ufs-loader_${variant}"
+ img=${IMGDIR}/${name}.img
+ ufs=${IMGDIR}/bootable-ufs-${variant}.img
+
+ mkimg -s gpt -b ${DESTDIR}/boot/pmbr \
+ -p freebsd-boot:=${DESTDIR}/boot/gptboot \
+ -p freebsd-ufs:=${ufs} \
+ -o ${img} >> ${LOGDIR}/imagebuild.log 2>&1
+
+ register_test ${name} $(qemu_bios ${img})
+
+ # ZFS
+ if has zfs; then
+ name="bios-gpt-zfs-loader_${variant}"
+ img=${IMGDIR}/${name}.img
+ zfs=${IMGDIR}/bootable-zfs-${variant}.img
+
+ mkimg -s gpt -b ${DESTDIR}/boot/pmbr \
+ -p freebsd-boot:=${DESTDIR}/boot/gptzfsboot \
+ -p freebsd-zfs:=${zfs} \
+ -o ${img} >> ${LOGDIR}/imagebuild.log 2>&1
+
+ register_test ${name} $(qemu_bios ${img})
+ fi
+ done
+}
+
+assemble_bios_mbr() {
+ echo " Assembling BIOS+MBR images..."
+ for variant in ${ARCH_BIOS_LOADERS}; do
+ name="bios-mbr-ufs-loader_${variant}"
+ img=${IMGDIR}/${name}.img
+ ufs=${IMGDIR}/bootable-ufs-${variant}.img
+
+ mkimg -s bsd -b ${DESTDIR}/boot/boot \
+ -p freebsd-ufs:=${ufs} -o ${img}.s1 >> ${LOGDIR}/imagebuild.log 2>&1
+ # Note: boot0sio has a longish timeout, and does work but
+ # takes longer than 30s so we use mbr.
+ mkimg -a 1 -s mbr -b ${DESTDIR}/boot/mbr \
+ -p freebsd:=${img}.s1 -o ${img} >> ${LOGDIR}/imagebuild.log 2>&1
+ rm -f ${img}.s1
+
+ register_test ${name} $(qemu_bios ${img})
+ done
+}
+
+# Hybrid GPT images: ESP + freebsd-boot + filesystem, tested with both BIOS and EFI
+assemble_both_gpt() {
+ echo " Assembling hybrid BIOS+EFI GPT images..."
+ for loader in loader_lua loader_4th loader_simp; do
+ esp=${IMGDIR}/${loader}.esp
+ fstypes="ufs"
+ has zfs && fstypes="ufs zfs"
+ for fs in ${fstypes}; do
+ name_base="both-gpt-${fs}-${loader}"
+ img=${IMGDIR}/${name_base}.img
+
+ case ${fs} in
+ ufs)
+ fsimg=${IMGDIR}/bootable-ufs-lua.img
+ ptype="freebsd-ufs"
+ bootblk=${DESTDIR}/boot/gptboot
+ ;;
+ zfs)
+ fsimg=${IMGDIR}/bootable-zfs-lua.img
+ ptype="freebsd-zfs"
+ bootblk=${DESTDIR}/boot/gptzfsboot
+ ;;
+ esac
+
+ mkimg -b ${DESTDIR}/boot/pmbr -s gpt \
+ -p efi:=${esp} \
+ -p freebsd-boot:=${bootblk} \
+ -p ${ptype}:=${fsimg} \
+ -o ${img} >> ${LOGDIR}/imagebuild.log 2>&1
+
+ register_test "${name_base}-bios" $(qemu_bios ${img})
+ register_test "${name_base}-efi" $(qemu_efi ${img})
+ done
+ done
+}
+
+# Hybrid MBR images: ESP + freebsd(boot+ufs), tested with both BIOS and EFI
+assemble_both_mbr() {
+ echo " Assembling hybrid BIOS+EFI MBR images..."
+ for loader in loader_lua loader_4th loader_simp; do
+ esp=${IMGDIR}/${loader}.esp
+ name_base="both-mbr-ufs-${loader}"
+ img=${IMGDIR}/${name_base}.img
+ ufs=${IMGDIR}/bootable-ufs-lua.img
+
+ mkimg -s bsd -b ${DESTDIR}/boot/boot \
+ -p freebsd-ufs:=${ufs} -o ${img}.s2 >> ${LOGDIR}/imagebuild.log 2>&1
+ mkimg -a 2 -s mbr -b ${DESTDIR}/boot/mbr \
+ -p efi:=${esp} \
+ -p freebsd:=${img}.s2 -o ${img} >> ${LOGDIR}/imagebuild.log 2>&1
+ rm -f ${img}.s2
+
+ register_test "${name_base}-bios" $(qemu_bios ${img})
+ register_test "${name_base}-efi" $(qemu_efi ${img})
+ done
+}
+
+assemble_cd() {
+ echo " Assembling CD images..."
+
+ # mtree to add loader and fstab to image
+ mt1=$(mktemp ${OUTDIR}/cd-mtree.XXXXXX)
+ variant=lua
+ cat > ${mt1} <<EOF
+./boot/loader type=file mode=0644 contents=${DESTDIR}/boot/loader_${variant}
+./etc/fstab type=file mode=0644 contents=${OUTDIR}/fstab.cd
+EOF
+
+ # cdboot - BIOS CD boot via El Torito
+ name="bios-cd-cdboot"
+ img=${IMGDIR}/${name}.iso
+ makefs -t cd9660 \
+ -o bootimage=i386\;${DESTDIR}/boot/cdboot \
+ -o no-emul-boot \
+ -o rockridge \
+ -o label=FBSDTEST \
+ ${img} ${mt1} ${DESTDIR} >> ${LOGDIR}/imagebuild.log 2>&1
+ register_test ${name} $(qemu_bios_cdrom ${img})
+
+ # isoboot - hybrid BIOS+EFI CD (tests isoboot for BIOS, loader.efi for EFI)
+ name="hybrid-cd-isoboot"
+ img=${IMGDIR}/${name}.iso
+ espfile=$(mktemp ${OUTDIR}/efiboot.XXXXXX)
+ make_cd_esp ${espfile} ${DESTDIR}/boot/loader_lua.efi
+
+ makefs -t cd9660 \
+ -o bootimage=i386\;${DESTDIR}/boot/cdboot \
+ -o no-emul-boot \
+ -o bootimage=i386\;${espfile} \
+ -o no-emul-boot \
+ -o platformid=efi \
+ -o rockridge \
+ -o label=FBSDTEST \
+ ${img} ${mt1} ${DESTDIR} >> ${LOGDIR}/imagebuild.log 2>&1
+
+ # Overlay hybrid GPT for isoboot
+ imgsize=$(stat -f %z "${img}")
+
+ # Find the EFI partition in the ISO to reference it
+ espstart=""
+ espsize_cd=""
+ for entry in $(etdump --format shell ${img}); do
+ eval ${entry}
+ if [ "${et_platform}" = "efi" ]; then
+ espstart=$(expr ${et_lba} \* 2048)
+ espsize_cd=$(expr ${et_sectors} \* 512)
+ break
+ fi
+ done
+
+ if [ -n "${espstart}" ]; then
+ hybrid=$(mktemp ${OUTDIR}/hybrid.XXXXXX)
+ mkimg -s gpt \
+ --capacity ${imgsize} \
+ -b ${DESTDIR}/boot/pmbr \
+ -p freebsd-boot:=${DESTDIR}/boot/isoboot \
+ -p efi::${espsize_cd}:${espstart} \
+ -o ${hybrid} >> ${LOGDIR}/imagebuild.log 2>&1
+ dd if=${hybrid} of=${img} bs=32k count=1 conv=notrunc >> ${LOGDIR}/imagebuild.log 2>&1
+ rm -f ${hybrid}
+ fi
+
+ rm -f ${espfile}
+
+ # Test the hybrid ISO with both BIOS and EFI
+ register_test "${name}-bios" $(qemu_bios_cdrom ${img})
+ register_test "${name}-efi" $(qemu_efi_cdrom ${img})
+
+ rm -f ${mt1}
+}
+
+assemble_ofw() {
+ echo " Assembling Open Firmware images..."
+ # APM partitioned disk with boot1.hfs
+ fstypes="ufs"
+ has zfs && fstypes="ufs zfs"
+ for fs in ${fstypes}; do
+ name="ofw-apm-${fs}"
+ img=${IMGDIR}/${name}.img
+
+ case ${fs} in
+ ufs) fsimg=${IMGDIR}/bootable-ufs-lua.img; ptype="freebsd-ufs" ;;
+ zfs) fsimg=${IMGDIR}/bootable-zfs-lua.img; ptype="freebsd-zfs" ;;
+ esac
+
+ mkimg -a 1 -s apm \
+ -p freebsd-boot:=${DESTDIR}/boot/boot1.hfs \
+ -p ${ptype}:=${fsimg} \
+ -o ${img} >> ${LOGDIR}/imagebuild.log 2>&1
+
+ register_test ${name} $(qemu_ofw ${img})
+ done
+}
+
+# Open Firmware bootable CD. Mirrors release/powerpc/mkisoimages.sh: build the
+# Apple/OF "macppc" boot image by dd'ing /boot/loader into the hfs-boot block
+# at its "Loader START" offset, then hand that to makefs as the El Torito
+# no-emul boot image. OpenBIOS finds it via cd:,\\:tbxi.
+assemble_ofw_cd() {
+ echo " Assembling Open Firmware CD image..."
+ name="ofw-cd"
+ img=${IMGDIR}/${name}.iso
+
+ # cd9660 root fstab overlay
+ mt=$(mktemp ${OUTDIR}/ofwcd-mtree.XXXXXX)
+ echo "./etc/fstab type=file mode=0644 contents=${OUTDIR}/fstab.cd" > ${mt}
+
+ # Apple/OF boot block with the loader embedded at "Loader START".
+ bootblock=$(mktemp ${OUTDIR}/hfs-boot.XXXXXX)
+ uudecode -p ${SRCTOP}/release/powerpc/hfs-boot.bz2.uu | bunzip2 > ${bootblock}
+ offset=$(hd ${bootblock} | grep 'Loader START' | cut -f 1 -d ' ')
+ offset=$((0x${offset} / 512))
+ dd if=${DESTDIR}/boot/loader of=${bootblock} seek=${offset} conv=notrunc \
+ >> ${LOGDIR}/imagebuild.log 2>&1
+
+ makefs -t cd9660 \
+ -o bootimage=macppc\;${bootblock} \
+ -o no-emul-boot \
+ -o rockridge \
+ -o label=FBSDTEST \
+ ${img} ${mt} ${DESTDIR} >> ${LOGDIR}/imagebuild.log 2>&1
+
+ rm -f ${bootblock} ${mt}
+ register_test ${name} $(qemu_ofw_cdrom ${img})
+}
+
+assemble_linuxboot() {
+ echo " Assembling linuxboot images..."
+ esp=${IMGDIR}/linuxboot.esp
+ fstypes="ufs"
+ has zfs && fstypes="ufs zfs"
+ for fs in ${fstypes}; do
+ name="linuxboot-gpt-${fs}"
+ img=${IMGDIR}/${name}.img
+
+ case ${fs} in
+ ufs) fsimg=${IMGDIR}/bootable-ufs-lua.img; ptype="freebsd-ufs" ;;
+ zfs) fsimg=${IMGDIR}/bootable-zfs-lua.img; ptype="freebsd-zfs" ;;
+ esac
+
+ mkimg -s gpt \
+ -p efi:=${esp} \
+ -p ${ptype}:=${fsimg} \
+ -o ${img} >> ${LOGDIR}/imagebuild.log 2>&1
+
+ register_test ${name} $(qemu_efi ${img})
+ done
+}
+
+# Linuxboot for platforms without an ESP: the kernel+initrd go on the QEMU
+# command line, and the disk is just the FreeBSD root filesystem in a GPT
+# (no ESP partition). loader.kboot mounts root from that disk.
+assemble_linuxboot_direct() {
+ echo " Assembling linuxboot (direct kernel/initrd) images..."
+ linux_kernel=$(find_linux_kernel) || return 0
+ initrd=${IMGDIR}/linuxboot-initrd.cpio.gz
+ fstypes="ufs"
+ has zfs && fstypes="ufs zfs"
+ for fs in ${fstypes}; do
+ name="linuxboot-${fs}"
+ img=${IMGDIR}/${name}.img
+
+ case ${fs} in
+ ufs) fsimg=${IMGDIR}/bootable-ufs-lua.img; ptype="freebsd-ufs" ;;
+ zfs) fsimg=${IMGDIR}/bootable-zfs-lua.img; ptype="freebsd-zfs" ;;
+ esac
+
+ mkimg -s gpt \
+ -p ${ptype}:=${fsimg} \
+ -o ${img} >> ${LOGDIR}/imagebuild.log 2>&1
+
+ register_test ${name} $(qemu_linuxboot ${img} ${linux_kernel} ${initrd})
+ done
+}
+
+assemble_all_images() {
+ echo "=== Phase 3: Assembling disk images ==="
+
+ if has efi; then
+ if [ -r "${ARCH_EFI_FIRMWARE}" ]; then
+ assemble_efi_gpt
+ if has mbr; then
+ assemble_efi_mbr
+ fi
+ elif [ -n "${ARCH_EFI_FIRMWARE}" ]; then
+ echo "WARNING: EFI firmware not found at ${ARCH_EFI_FIRMWARE}, skipping EFI tests"
+ else
+ # riscv64 uses u-boot with EFI payload
+ assemble_efi_gpt
+ fi
+ fi
+
+ if has bios; then
+ assemble_bios_gpt
+ if has mbr; then
+ assemble_bios_mbr
+ fi
+ fi
+
+ if has bios && has efi && [ -r "${ARCH_EFI_FIRMWARE}" ]; then
+ assemble_both_gpt
+ if has mbr; then
+ assemble_both_mbr
+ fi
+ fi
+
+ if has cd; then
+ if has ofw; then
+ assemble_ofw_cd
+ else
+ assemble_cd
+ fi
+ fi
+
+ if has ofw; then
+ assemble_ofw
+ fi
+
+ if has linuxboot; then
+ if [ -f "${IMGDIR}/linuxboot.esp" ]; then
+ assemble_linuxboot
+ elif [ -f "${IMGDIR}/linuxboot-initrd.cpio.gz" ]; then
+ assemble_linuxboot_direct
+ fi
+ fi
+}
+
+# --------------------------------------------------------------------------
+# Phase 4: Run tests in parallel
+# --------------------------------------------------------------------------
+
+run_one_test() {
+ name=$1
+ log="${LOGDIR}/${name}.log"
+ cmd=$(cat ${OUTDIR}/test-cmd-${name}.sh)
+
+ expect -c "
+ set timeout ${TIMEOUT}
+ log_file -noappend \"${log}\"
+ spawn {*}${cmd}
+ expect {
+ \"SUCCESS\" { exit 0 }
+ timeout { exit 1 }
+ eof { exit 2 }
+ }
+ " >/dev/null 2>&1
+ return $?
+}
+
+wait_for_slot() {
+ # Wait until fewer than MAX_JOBS are running
+ while true; do
+ running=0
+ for p in ${active_pids}; do
+ if kill -0 $p 2>/dev/null; then
+ running=$((running + 1))
+ fi
+ done
+ [ ${running} -lt ${MAX_JOBS} ] && break
+ sleep 1
+ done
+}
+
+run_all_tests() {
+ echo "=== Phase 4: Running tests ==="
+
+ total=0
+ skipped=0
+ active_pids=""
+
+ # Record pid-to-name mapping for result collection
+ results_map=${OUTDIR}/results-map.txt
+ > ${results_map}
+
+ while read name; do
+ # Apply test filter if given
+ if [ -n "${TEST_FILTER}" ]; then
+ echo "${name}" | grep -qE "${TEST_FILTER}" || {
+ skipped=$((skipped + 1))
+ continue
+ }
+ fi
+
+ total=$((total + 1))
+
+ # Job throttling
+ if [ ${MAX_JOBS} -gt 0 ]; then
+ wait_for_slot
+ fi
+
+ run_one_test "${name}" &
+ pid=$!
+ active_pids="${active_pids} ${pid}"
+ echo "${pid} ${name}" >> ${results_map}
+ done < ${TESTLIST}
+
+ echo " ${total} tests launched (${skipped} skipped by filter), waiting..."
+ echo ""
+
+ # Collect results - disable errexit since wait returns the child's exit status
+ set +e
+ pass=0
+ fail=0
+ timeout_count=0
+ while read pid tname; do
+ wait ${pid}
+ rc=$?
+ case ${rc} in
+ 0)
+ result="PASS"
+ pass=$((pass + 1))
+ ;;
+ 1)
+ result="TIMEOUT"
+ timeout_count=$((timeout_count + 1))
+ ;;
+ *)
+ result="FAIL"
+ fail=$((fail + 1))
+ ;;
+ esac
+ printf " %-45s %s\n" "${tname}" "${result}"
+ done < ${results_map}
+
+ echo ""
+ echo "=== Results: ${pass} passed, ${fail} failed, ${timeout_count} timed out (of ${total}) ==="
+ echo "Logs in ${LOGDIR}"
+
+ rm -f ${results_map}
+ [ ${fail} -eq 0 ] && [ ${timeout_count} -eq 0 ]
+}
+
+# --------------------------------------------------------------------------
+# Main
+# --------------------------------------------------------------------------
+
+# Preflight checks
+for prog in expect ${ARCH_QEMU_BIN} makefs mkimg; do
+ which ${prog} >/dev/null 2>&1 || die "${prog} not found in PATH"
+done
+
+echo "FreeBSD boot loader test suite (${ARCH})"
+echo "Output: ${OUTDIR}"
+echo ""
+
+if ! ${SKIP_BUILD}; then
+ build_tree
+fi
+
+if ! ${SKIP_IMAGES}; then
+ if [ ! -d "${DESTDIR}" ]; then
+ die "No boot tree at ${DESTDIR}. Run without -b first."
+ fi
+ make_base_images
+ assemble_all_images
+fi
+
+if [ ! -s "${TESTLIST}" ]; then
+ die "No tests registered. Run without -B first."
+fi
+
+run_all_tests
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Aug 31, 6:29 PM (5 h, 34 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34631015
Default Alt Text
D58008.id181227.diff (36 KB)
Attached To
Mode
D58008: boot-test.sh: Test many boot loader combinations.
Attached
Detach File
Event Timeline
Log In to Comment