1*a7ebe2d4SWarner Losh.\" 2*a7ebe2d4SWarner Losh.\" SPDX-License-Identifier: BSD-2-Clause 3*a7ebe2d4SWarner Losh.\" 4*a7ebe2d4SWarner Losh.Dd July 5, 2026 5*a7ebe2d4SWarner Losh.Dt BOOT-TEST.SH 8 6*a7ebe2d4SWarner Losh.Os 7*a7ebe2d4SWarner Losh.Sh NAME 8*a7ebe2d4SWarner Losh.Nm boot-test.sh 9*a7ebe2d4SWarner Losh.Nd automated boot loader regression tests under QEMU 10*a7ebe2d4SWarner Losh.Sh SYNOPSIS 11*a7ebe2d4SWarner Losh.Nm 12*a7ebe2d4SWarner Losh.Op Fl A 13*a7ebe2d4SWarner Losh.Op Fl a Ar arch 14*a7ebe2d4SWarner Losh.Op Fl b | Fl B 15*a7ebe2d4SWarner Losh.Op Fl j Ar jobs 16*a7ebe2d4SWarner Losh.Op Fl o Ar dir 17*a7ebe2d4SWarner Losh.Op Fl t Ar regex 18*a7ebe2d4SWarner Losh.Op Fl T Ar seconds 19*a7ebe2d4SWarner Losh.Nm 20*a7ebe2d4SWarner Losh.Fl -netboot-teardown 21*a7ebe2d4SWarner Losh.Sh DESCRIPTION 22*a7ebe2d4SWarner Losh.Nm 23*a7ebe2d4SWarner Loshbuilds a minimal bootable tree, assembles disk, CD, and network boot images 24*a7ebe2d4SWarner Loshfor every boot configuration a target architecture supports, boots each image 25*a7ebe2d4SWarner Loshunder 26*a7ebe2d4SWarner Losh.Xr qemu 1 , 27*a7ebe2d4SWarner Loshand checks that it reaches userland and prints a success marker. 28*a7ebe2d4SWarner LoshIt runs almost entirely as an unprivileged user, with one exception: the 29*a7ebe2d4SWarner Losh.Ar netboot-bios 30*a7ebe2d4SWarner Loshand 31*a7ebe2d4SWarner Losh.Ar netboot-efi 32*a7ebe2d4SWarner Loshtests need a real 33*a7ebe2d4SWarner Losh.Xr vmnet 4 34*a7ebe2d4SWarner Loshinterface and 35*a7ebe2d4SWarner Losh.Xr dnsmasq 8 36*a7ebe2d4SWarner Loshinstead of QEMU's user-mode networking, so that DHCP can hand out a 37*a7ebe2d4SWarner Loshroot-path. 38*a7ebe2d4SWarner LoshCreating the interface and giving it an address require root, so 39*a7ebe2d4SWarner Losh.Nm 40*a7ebe2d4SWarner Loshruns 41*a7ebe2d4SWarner Losh.Xr sudo 8 42*a7ebe2d4SWarner Loshonce to set both up, then leaves them running; later runs detect the 43*a7ebe2d4SWarner Loshexisting setup and do not prompt again. 44*a7ebe2d4SWarner LoshSee 45*a7ebe2d4SWarner Losh.Sx Netboot networking 46*a7ebe2d4SWarner Loshbelow. 47*a7ebe2d4SWarner Losh.Pp 48*a7ebe2d4SWarner Losh.Nm 49*a7ebe2d4SWarner Loshmust be run from the 50*a7ebe2d4SWarner Losh.Pa stand 51*a7ebe2d4SWarner Loshdirectory of a FreeBSD source tree and assumes that 52*a7ebe2d4SWarner Losh.Cm buildworld 53*a7ebe2d4SWarner Loshand 54*a7ebe2d4SWarner Losh.Cm buildkernel 55*a7ebe2d4SWarner Loshhave already completed for each target architecture. 56*a7ebe2d4SWarner LoshPer-architecture parameters 57*a7ebe2d4SWarner Losh.Pq QEMU machine, boot capabilities, kernel config, and so on 58*a7ebe2d4SWarner Loshare read from 59*a7ebe2d4SWarner Losh.Pa boot-test.json 60*a7ebe2d4SWarner Loshin the same directory as the script. 61*a7ebe2d4SWarner Losh.Pp 62*a7ebe2d4SWarner LoshEach architecture is processed in five phases: 63*a7ebe2d4SWarner Loshextract a minimal userland from a release ISO 64*a7ebe2d4SWarner Losh.Pq 0 , 65*a7ebe2d4SWarner Loshinstall the kernel and boot loaders into a tree 66*a7ebe2d4SWarner Losh.Pq 1 , 67*a7ebe2d4SWarner Loshcreate the base filesystem images 68*a7ebe2d4SWarner Losh.Pq 2 , 69*a7ebe2d4SWarner Loshassemble the per-configuration boot images and register a test for each 70*a7ebe2d4SWarner Losh.Pq 3 , 71*a7ebe2d4SWarner Loshand run the registered tests 72*a7ebe2d4SWarner Losh.Pq 4 . 73*a7ebe2d4SWarner LoshImages are built one architecture at a time; the tests for all selected 74*a7ebe2d4SWarner Losharchitectures then run in parallel so that a run costs roughly one timeout 75*a7ebe2d4SWarner Loshrather than one per test. 76*a7ebe2d4SWarner Losh.Pp 77*a7ebe2d4SWarner LoshThe options are as follows: 78*a7ebe2d4SWarner Losh.Bl -tag -width indent 79*a7ebe2d4SWarner Losh.It Fl a Ar arch 80*a7ebe2d4SWarner LoshTest 81*a7ebe2d4SWarner Losh.Ar arch . 82*a7ebe2d4SWarner LoshMay be given more than once to test several. 83*a7ebe2d4SWarner LoshThe default is the host architecture reported by 84*a7ebe2d4SWarner Losh.Nm uname Fl p . 85*a7ebe2d4SWarner LoshSupported values are 86*a7ebe2d4SWarner Losh.Ar amd64 , 87*a7ebe2d4SWarner Losh.Ar aarch64 , 88*a7ebe2d4SWarner Losh.Ar armv7 , 89*a7ebe2d4SWarner Losh.Ar riscv64 , 90*a7ebe2d4SWarner Losh.Ar powerpc , 91*a7ebe2d4SWarner Losh.Ar powerpc64 , 92*a7ebe2d4SWarner Loshand 93*a7ebe2d4SWarner Losh.Ar powerpc64le . 94*a7ebe2d4SWarner Losh.It Fl A 95*a7ebe2d4SWarner LoshTest every supported architecture. 96*a7ebe2d4SWarner Losh.It Fl b 97*a7ebe2d4SWarner LoshSkip the build and install phase and reuse the existing boot tree. 98*a7ebe2d4SWarner Losh.It Fl B 99*a7ebe2d4SWarner LoshSkip the build, install, and image-creation phases and reuse existing images. 100*a7ebe2d4SWarner Losh.It Fl j Ar jobs 101*a7ebe2d4SWarner LoshRun at most 102*a7ebe2d4SWarner Losh.Ar jobs 103*a7ebe2d4SWarner LoshQEMU instances at once. 104*a7ebe2d4SWarner LoshThe default is unlimited. 105*a7ebe2d4SWarner Losh.It Fl o Ar dir 106*a7ebe2d4SWarner LoshWrite images and logs to 107*a7ebe2d4SWarner Losh.Ar dir 108*a7ebe2d4SWarner Loshinstead of the per-architecture object directory. 109*a7ebe2d4SWarner LoshMay only be used with a single architecture. 110*a7ebe2d4SWarner Losh.It Fl t Ar regex 111*a7ebe2d4SWarner LoshRun only the tests whose name matches the extended regular expression 112*a7ebe2d4SWarner Losh.Ar regex . 113*a7ebe2d4SWarner Losh.It Fl T Ar seconds 114*a7ebe2d4SWarner LoshSet the per-test QEMU timeout. 115*a7ebe2d4SWarner LoshThe default is 60 seconds, or 180 for the powerpc targets. 116*a7ebe2d4SWarner Losh.It Fl -netboot-teardown 117*a7ebe2d4SWarner LoshDestroy the 118*a7ebe2d4SWarner Losh.Xr vmnet 4 119*a7ebe2d4SWarner Loshinterfaces and stop the 120*a7ebe2d4SWarner Losh.Xr dnsmasq 8 121*a7ebe2d4SWarner Loshinstance created for the netboot tests 122*a7ebe2d4SWarner Losh.Pq Sx Netboot networking . 123*a7ebe2d4SWarner LoshMust be run with 124*a7ebe2d4SWarner Losh.Xr sudo 8 . 125*a7ebe2d4SWarner LoshNot needed in normal use; the setup is left running between runs on purpose. 126*a7ebe2d4SWarner Losh.El 127*a7ebe2d4SWarner Losh.Ss Tests per architecture 128*a7ebe2d4SWarner LoshThe tests generated for an architecture are the applicable combinations of the 129*a7ebe2d4SWarner Loshboot interface, the on-disk layout, and the loader interpreter. 130*a7ebe2d4SWarner LoshThe interpreters are 131*a7ebe2d4SWarner Losh.Ar lua , 132*a7ebe2d4SWarner Losh.Ar 4th , 133*a7ebe2d4SWarner Loshand 134*a7ebe2d4SWarner Losh.Ar simp , 135*a7ebe2d4SWarner Loshplus the 136*a7ebe2d4SWarner Losh.Ar boot1 137*a7ebe2d4SWarner Loshchain loader for UEFI; the filesystems are UFS and, where the platform supports 138*a7ebe2d4SWarner Loshit, ZFS. 139*a7ebe2d4SWarner LoshWhich of the following families are built is driven by each architecture's 140*a7ebe2d4SWarner Loshcapabilities declared in 141*a7ebe2d4SWarner Losh.Pa boot-test.json : 142*a7ebe2d4SWarner Losh.Bl -tag -width "linuxboot" -compact 143*a7ebe2d4SWarner Losh.It Sy BIOS 144*a7ebe2d4SWarner LoshGPT (UFS, ZFS) and MBR (UFS) disks, once per interpreter. 145*a7ebe2d4SWarner Losh.It Sy UEFI 146*a7ebe2d4SWarner LoshGPT (UFS, ZFS) and MBR (UFS) disks, once per interpreter. 147*a7ebe2d4SWarner Losh.It Sy hybrid 148*a7ebe2d4SWarner LoshA single GPT or MBR image booted both as BIOS and as UEFI. 149*a7ebe2d4SWarner Losh.It Sy OFW 150*a7ebe2d4SWarner LoshApple Partition Map disk (UFS, ZFS) on 151*a7ebe2d4SWarner Losh.Ar powerpc . 152*a7ebe2d4SWarner Losh.It Sy PReP 153*a7ebe2d4SWarner LoshMBR disk on 154*a7ebe2d4SWarner Losh.Ar powerpc64 155*a7ebe2d4SWarner Loshand 156*a7ebe2d4SWarner Losh.Ar powerpc64le . 157*a7ebe2d4SWarner Losh.It Sy CD 158*a7ebe2d4SWarner LoshEl Torito for BIOS, a hybrid BIOS+UEFI ISO, and the OFW and CHRP variants. 159*a7ebe2d4SWarner Losh.It Sy linuxboot 160*a7ebe2d4SWarner LoshUFS and ZFS, booted through the Linux kexec loader. 161*a7ebe2d4SWarner Losh.It Sy netboot 162*a7ebe2d4SWarner LoshBIOS PXE, UEFI, and iPXE memory-disk boot of a RAM root. 163*a7ebe2d4SWarner Losh.El 164*a7ebe2d4SWarner LoshA full run 165*a7ebe2d4SWarner Losh.Pq Fl A 166*a7ebe2d4SWarner Loshcurrently yields on the order of 80 tests. 167*a7ebe2d4SWarner Losh.Ss Netboot networking 168*a7ebe2d4SWarner LoshQEMU's user-mode 169*a7ebe2d4SWarner Losh.Pq slirp 170*a7ebe2d4SWarner Loshnetworking can hand out an address and a TFTP bootfile, but it cannot send a 171*a7ebe2d4SWarner LoshDHCP root-path 172*a7ebe2d4SWarner Losh.Pq option 17 . 173*a7ebe2d4SWarner LoshWithout one, the FreeBSD loader falls back to NFS for every file fetch after 174*a7ebe2d4SWarner Loshthe initial bootfile and fails, since there is no NFS server to fall back to. 175*a7ebe2d4SWarner LoshSending a root-path of 176*a7ebe2d4SWarner Losh.Dq Li tftp://<gw>/ 177*a7ebe2d4SWarner Loshkeeps the loader on TFTP instead, which is what 178*a7ebe2d4SWarner Losh.Ar netboot-bios 179*a7ebe2d4SWarner Loshand 180*a7ebe2d4SWarner Losh.Ar netboot-efi 181*a7ebe2d4SWarner Loshneed. 182*a7ebe2d4SWarner Losh.Pp 183*a7ebe2d4SWarner LoshTo get a real root-path, 184*a7ebe2d4SWarner Losh.Nm 185*a7ebe2d4SWarner Loshgives each of those tests its own 186*a7ebe2d4SWarner Losh.Xr vmnet 4 187*a7ebe2d4SWarner Loshinterface and a private 188*a7ebe2d4SWarner Losh.Li /30 189*a7ebe2d4SWarner Loshcarved out of 190*a7ebe2d4SWarner Losh.Cm netboot_subnet_base 191*a7ebe2d4SWarner Loshin 192*a7ebe2d4SWarner Losh.Pa boot-test.json , 193*a7ebe2d4SWarner Loshand runs a single 194*a7ebe2d4SWarner Losh.Xr dnsmasq 8 195*a7ebe2d4SWarner Loshinstance serving all of them. 196*a7ebe2d4SWarner Losh.Xr vmnet 4 197*a7ebe2d4SWarner Loshis used rather than the more familiar 198*a7ebe2d4SWarner Losh.Xr tap 4 , 199*a7ebe2d4SWarner Losheven though QEMU treats them identically and both are clones of the same 200*a7ebe2d4SWarner Loshunderlying driver: closing the control device automatically brings a 201*a7ebe2d4SWarner Losh.Xr tap 4 202*a7ebe2d4SWarner Loshinterface down and deletes its address, which would undo the setup below 203*a7ebe2d4SWarner Loshevery time QEMU exits, but 204*a7ebe2d4SWarner Losh.Xr vmnet 4 205*a7ebe2d4SWarner Loshinterfaces keep their configuration across opens. 206*a7ebe2d4SWarner LoshCreating the interface and assigning it an address both require root even 207*a7ebe2d4SWarner Loshwhen 208*a7ebe2d4SWarner Losh.Va net.link.tap.user_open 209*a7ebe2d4SWarner Loshis set 210*a7ebe2d4SWarner Losh.Pq that only governs opening the cloning device itself , 211*a7ebe2d4SWarner Loshso 212*a7ebe2d4SWarner Losh.Nm 213*a7ebe2d4SWarner Loshinvokes 214*a7ebe2d4SWarner Losh.Xr sudo 8 215*a7ebe2d4SWarner Loshonce to create the interfaces 216*a7ebe2d4SWarner Losh.Pq chowning the resulting device nodes back to the invoking user 217*a7ebe2d4SWarner Loshand start 218*a7ebe2d4SWarner Losh.Xr dnsmasq 8 . 219*a7ebe2d4SWarner LoshBecause the interfaces persist until explicitly destroyed, 220*a7ebe2d4SWarner Losh.Nm 221*a7ebe2d4SWarner Loshleaves them and 222*a7ebe2d4SWarner Losh.Xr dnsmasq 8 223*a7ebe2d4SWarner Loshrunning afterward; subsequent runs detect the existing setup by comparing a 224*a7ebe2d4SWarner Loshhash of the intended configuration and skip 225*a7ebe2d4SWarner Losh.Xr sudo 8 226*a7ebe2d4SWarner Loshentirely, so the prompt is normally seen once per boot rather than once per 227*a7ebe2d4SWarner Loshrun. 228*a7ebe2d4SWarner LoshUse 229*a7ebe2d4SWarner Losh.Fl -netboot-teardown 230*a7ebe2d4SWarner Loshto tear the setup down manually. 231*a7ebe2d4SWarner Losh.Pp 232*a7ebe2d4SWarner LoshThe 233*a7ebe2d4SWarner Losh.Ar netboot-ramdisk 234*a7ebe2d4SWarner Loshand 235*a7ebe2d4SWarner Losh.Ar netboot-bios-memdisk 236*a7ebe2d4SWarner Loshtests boot entirely from an in-memory image and never need a root-path, so 237*a7ebe2d4SWarner Loshthey stay on QEMU's user-mode networking. 238*a7ebe2d4SWarner Losh.Sh REQUIREMENTS 239*a7ebe2d4SWarner Losh.Nm 240*a7ebe2d4SWarner Loshuses 241*a7ebe2d4SWarner Losh.Xr makefs 8 242*a7ebe2d4SWarner Loshand 243*a7ebe2d4SWarner Losh.Xr mkimg 1 244*a7ebe2d4SWarner Loshfrom the base system, and the 245*a7ebe2d4SWarner Losh.Xr jq 1 , 246*a7ebe2d4SWarner Losh.Xr expect 1 , 247*a7ebe2d4SWarner Losh.Xr qemu 1 , 248*a7ebe2d4SWarner Loshand 249*a7ebe2d4SWarner Losh.Xr dnsmasq 8 250*a7ebe2d4SWarner Loshpackages 251*a7ebe2d4SWarner Losh.Pq Pa textproc/jq , Pa lang/expect , Pa emulators/qemu , Pa dns/dnsmasq . 252*a7ebe2d4SWarner LoshThe network boot tests additionally require the 253*a7ebe2d4SWarner Losh.Pa sysutils/ipxe 254*a7ebe2d4SWarner Loshand 255*a7ebe2d4SWarner Losh.Pa sysutils/syslinux 256*a7ebe2d4SWarner Loshpackages. 257*a7ebe2d4SWarner Losh.Sh ENVIRONMENT 258*a7ebe2d4SWarner Losh.Bl -tag -width ".Ev HOME" 259*a7ebe2d4SWarner Losh.It Ev HOME 260*a7ebe2d4SWarner LoshRelease ISO images and the optional custom 261*a7ebe2d4SWarner Losh.Pa openbios-ppc 262*a7ebe2d4SWarner Loshfirmware are looked for in 263*a7ebe2d4SWarner Losh.Pa ~/iso . 264*a7ebe2d4SWarner Losh.El 265*a7ebe2d4SWarner Losh.Sh FILES 266*a7ebe2d4SWarner Losh.Bl -tag -width ".Pa boot-test.json" -compact 267*a7ebe2d4SWarner Losh.It Pa boot-test.json 268*a7ebe2d4SWarner LoshPer-architecture configuration, parsed with 269*a7ebe2d4SWarner Losh.Xr jq 1 . 270*a7ebe2d4SWarner Losh.It Pa ~/iso/FreeBSD-*-RELEASE-*-disc1.iso.xz 271*a7ebe2d4SWarner LoshRelease ISO supplying the minimal userland. 272*a7ebe2d4SWarner Losh.It Pa ~/iso/openbios-ppc 273*a7ebe2d4SWarner LoshOptional replacement OpenBIOS firmware for the powerpc targets. 274*a7ebe2d4SWarner Losh.El 275*a7ebe2d4SWarner Losh.Sh EXIT STATUS 276*a7ebe2d4SWarner Losh.Nm 277*a7ebe2d4SWarner Loshexits 0 if every test that ran passed, and non-zero if any test failed or 278*a7ebe2d4SWarner Loshtimed out. 279*a7ebe2d4SWarner Losh.Sh EXAMPLES 280*a7ebe2d4SWarner LoshTest the host architecture: 281*a7ebe2d4SWarner Losh.Pp 282*a7ebe2d4SWarner Losh.Dl "sh ../tools/boot/boot-test.sh" 283*a7ebe2d4SWarner Losh.Pp 284*a7ebe2d4SWarner LoshRe-run only the ZFS tests for 285*a7ebe2d4SWarner Losh.Ar amd64 286*a7ebe2d4SWarner Loshagainst previously built images: 287*a7ebe2d4SWarner Losh.Pp 288*a7ebe2d4SWarner Losh.Dl "sh ../tools/boot/boot-test.sh -a amd64 -B -t zfs" 289*a7ebe2d4SWarner Losh.Pp 290*a7ebe2d4SWarner LoshTest every architecture: 291*a7ebe2d4SWarner Losh.Pp 292*a7ebe2d4SWarner Losh.Dl "sh ../tools/boot/boot-test.sh -A" 293*a7ebe2d4SWarner Losh.Sh SEE ALSO 294*a7ebe2d4SWarner Losh.Xr expect 1 , 295*a7ebe2d4SWarner Losh.Xr jq 1 , 296*a7ebe2d4SWarner Losh.Xr mkimg 1 , 297*a7ebe2d4SWarner Losh.Xr gptboot 8 , 298*a7ebe2d4SWarner Losh.Xr loader 8 , 299*a7ebe2d4SWarner Losh.Xr makefs 8 , 300*a7ebe2d4SWarner Losh.Xr pxeboot 8 , 301*a7ebe2d4SWarner Losh.Xr uefi 8 302*a7ebe2d4SWarner Losh.Sh AUTHORS 303*a7ebe2d4SWarner Losh.An Warner Losh Aq Mt imp@FreeBSD.org 304