Page MenuHomeFreeBSD

D58008.id181227.diff
No OneTemporary

D58008.id181227.diff

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

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)

Event Timeline