test: the suite runs on UEFI, and stops testing the BIOS loader's taste
bootcheck has only ever booted through the BIOS loader. That is the path being removed, so the suite had to reach OVMF before the removal rather than after it -- deleting the boot path first would leave nothing running during the work that needs watching most. -Uefi swaps the drives for a pflash pair and the staged ESP, keeping the same layout: ESP on index 0, the SchFS volume on index 1. Every check runs unaltered, so a difference between the two transcripts is a difference in firmware and not in what was asked. The varstore is copied per run; sharing one would let a run that changed a UEFI variable decide how the next one behaves. Both paths now report 110 [ok] with no failures. Three checks did fail on UEFI, and were right to. They asserted xres 800, yres 600 and line_length 3200 -- the mode boot/bios/stage2.S asks VBE for. Under OVMF the firmware picks, here 1280x800 with a 5120-byte stride, which is correct and self-consistent. The checks were pinning the BIOS loader's fixed choice, and could do so only because that choice was fixed. They now assert the invariants the original comment was actually after: a plausible mode, a stride that covers a full row, and a width that is a multiple of 8 -- the last being the mode that sheared under OVMF, where the firmware advertised 1366 and the hardware scanned out 1360. Also reaped a QEMU left holding schfs.img by a run started outside the harness, which its pidfile reaper could not have known about.
This commit is contained in:
parent
751f5718cd
commit
0007853baa
1 changed files with 67 additions and 8 deletions
|
|
@ -26,6 +26,12 @@ param(
|
||||||
# attached, which is the only way to prove the ISO is self-contained.
|
# attached, which is the only way to prove the ISO is self-contained.
|
||||||
# Needs `make iso` first.
|
# Needs `make iso` first.
|
||||||
[switch]$Iso,
|
[switch]$Iso,
|
||||||
|
# Boot through OVMF instead of the BIOS loader. The disk layout is
|
||||||
|
# deliberately the same -- the staged ESP lands on index 0 and the SchFS
|
||||||
|
# volume on index 1 -- so every check below runs unaltered and a difference
|
||||||
|
# in the transcript is a difference in the *firmware path*, not in what was
|
||||||
|
# asked. Needs `make esp` first.
|
||||||
|
[switch]$Uefi,
|
||||||
# Terminal behaviour: pipes, isatty, SIGPIPE, and Ctrl-C. None of these
|
# Terminal behaviour: pipes, isatty, SIGPIPE, and Ctrl-C. None of these
|
||||||
# can be checked by looking at a screenshot, and all of them were broken
|
# can be checked by looking at a screenshot, and all of them were broken
|
||||||
# in ways that looked like broken *commands*.
|
# in ways that looked like broken *commands*.
|
||||||
|
|
@ -243,7 +249,27 @@ $commands += 'echo MARKER-DONE'
|
||||||
$isoPath = Join-Path $root 'schos.iso'
|
$isoPath = Join-Path $root 'schos.iso'
|
||||||
if ($Iso -and -not (Test-Path $isoPath)) { throw "no $isoPath -- run 'make iso' first" }
|
if ($Iso -and -not (Test-Path $isoPath)) { throw "no $isoPath -- run 'make iso' first" }
|
||||||
|
|
||||||
$drives = if ($Iso) {
|
$drives = if ($Uefi) {
|
||||||
|
# The varstore is written by the firmware, so each run gets its own copy.
|
||||||
|
# Sharing one would let a run that changed a UEFI variable -- boot order,
|
||||||
|
# console mode -- decide how the next run behaves, which is exactly the
|
||||||
|
# kind of dependency between runs that makes a suite stop being evidence.
|
||||||
|
$esp = Join-Path $root 'build/esp'
|
||||||
|
if (-not (Test-Path (Join-Path $esp 'EFI/BOOT/BOOTX64.EFI'))) {
|
||||||
|
throw "no staged ESP at $esp -- run 'make esp' first"
|
||||||
|
}
|
||||||
|
$code = Join-Path $root 'build/OVMF_CODE.fd'
|
||||||
|
$vars = Join-Path $root 'build/OVMF_VARS.fd'
|
||||||
|
foreach ($f in @($code, $vars)) {
|
||||||
|
if (-not (Test-Path $f)) { throw "no $f -- run 'make qemu-uefi' once to fetch OVMF" }
|
||||||
|
}
|
||||||
|
$runVars = Join-Path $root 'build/bootcheck-OVMF_VARS.fd'
|
||||||
|
Copy-Item -Force $vars $runVars
|
||||||
|
@("-drive if=pflash,format=raw,unit=0,readonly=on,file=`"$code`""
|
||||||
|
"-drive if=pflash,format=raw,unit=1,file=`"$runVars`""
|
||||||
|
"-drive file=fat:rw:`"$esp`",index=0,media=disk"
|
||||||
|
"-drive file=`"$hdb`",format=raw,index=1,media=disk")
|
||||||
|
} elseif ($Iso) {
|
||||||
@("-cdrom `"$isoPath`"", '-boot d')
|
@("-cdrom `"$isoPath`"", '-boot d')
|
||||||
} else {
|
} else {
|
||||||
@("-drive file=`"$hda`",format=raw,index=0,media=disk"
|
@("-drive file=`"$hda`",format=raw,index=0,media=disk"
|
||||||
|
|
@ -301,7 +327,9 @@ $psi.Arguments = ($drives + $usbDevices + $monitor + @(
|
||||||
$psi.RedirectStandardInput = $true
|
$psi.RedirectStandardInput = $true
|
||||||
$psi.UseShellExecute = $false
|
$psi.UseShellExecute = $false
|
||||||
|
|
||||||
$what = if ($Iso) { 'schos.iso, no hard disk' } else { "hdb = $(Split-Path $hdb -Leaf)" }
|
$what = if ($Uefi) { "OVMF, hdb = $(Split-Path $hdb -Leaf)" }
|
||||||
|
elseif ($Iso) { 'schos.iso, no hard disk' }
|
||||||
|
else { "hdb = $(Split-Path $hdb -Leaf)" }
|
||||||
Write-Host "==> booting ($what)" -ForegroundColor Cyan
|
Write-Host "==> booting ($what)" -ForegroundColor Cyan
|
||||||
$p = [System.Diagnostics.Process]::Start($psi)
|
$p = [System.Diagnostics.Process]::Start($psi)
|
||||||
# Recorded immediately, so that a run killed one instruction later is still
|
# Recorded immediately, so that a run killed one instruction later is still
|
||||||
|
|
@ -505,6 +533,26 @@ function Expect($pattern, $what) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Assert something the transcript does not state literally. Expect can only ask
|
||||||
|
# whether a string is present, which is why the framebuffer checks below used to
|
||||||
|
# hardcode 800x600: it was the only mode the BIOS loader ever set, so a literal
|
||||||
|
# was indistinguishable from an invariant. Under UEFI the firmware chooses, so
|
||||||
|
# the literal was testing the firmware's taste rather than our code.
|
||||||
|
function ExpectThat($cond, $what, $detail) {
|
||||||
|
if ($cond) {
|
||||||
|
Write-Host " [ok] $what" -ForegroundColor Green
|
||||||
|
} else {
|
||||||
|
Write-Host " FAIL: $what ($detail)" -ForegroundColor Red
|
||||||
|
$script:fail = $true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Pull a single "name value" field out of the fbset-style dump.
|
||||||
|
function FbField($name) {
|
||||||
|
if ($script:text -match "(?m)^$name\s+(\d+)") { return [int]$Matches[1] }
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
Expect 'MARKER-DONE' 'shell stayed alive through every command'
|
Expect 'MARKER-DONE' 'shell stayed alive through every command'
|
||||||
Expect 'hello-from-schos' 'a file written on the root filesystem reads back'
|
Expect 'hello-from-schos' 'a file written on the root filesystem reads back'
|
||||||
Expect 'second-line' 'appending to that file works'
|
Expect 'second-line' 'appending to that file works'
|
||||||
|
|
@ -564,14 +612,25 @@ if ($gens.Count -ge 2 -and
|
||||||
|
|
||||||
if ($Fb) {
|
if ($Fb) {
|
||||||
Expect 'id\s+schosfb' 'FBIOGET_FSCREENINFO identifies the device'
|
Expect 'id\s+schosfb' 'FBIOGET_FSCREENINFO identifies the device'
|
||||||
# 800x600 is what boot/bios/stage2.S asks VBE for. Asserting the numbers rather
|
# The bug this guards against is an ioctl that reports success having
|
||||||
# than just "the ioctl returned" is the point: the old code path returned
|
# touched nothing -- a 0x0 screen. What proves the numbers are real is not
|
||||||
# success with an untouched buffer, i.e. a 0x0 screen.
|
# any particular pair of them but that they agree with each other and with
|
||||||
Expect '(?m)^xres\s+800' 'the reported width is the mode actually set'
|
# a mode the hardware could actually scan out.
|
||||||
Expect '(?m)^yres\s+600' 'the reported height is the mode actually set'
|
$xres = FbField 'xres'
|
||||||
|
$yres = FbField 'yres'
|
||||||
|
$line = FbField 'line_length'
|
||||||
|
ExpectThat ($xres -ge 640) 'the reported width is a mode actually set' "xres = $xres"
|
||||||
|
ExpectThat ($yres -ge 480) 'the reported height is a mode actually set' "yres = $yres"
|
||||||
|
# A width that is not a multiple of 8 is the mode that sheared under OVMF:
|
||||||
|
# the firmware advertised 1366 and the hardware scanned out 1360.
|
||||||
|
ExpectThat (($xres % 8) -eq 0) 'the width is a whole number of scanout units' "xres = $xres"
|
||||||
Expect '(?m)^bits_per_pixel\s+32' 'the reported depth is the mode actually set'
|
Expect '(?m)^bits_per_pixel\s+32' 'the reported depth is the mode actually set'
|
||||||
Expect '(?m)^smem_start\s+0x' 'the framebuffer reports a physical address'
|
Expect '(?m)^smem_start\s+0x' 'the framebuffer reports a physical address'
|
||||||
Expect '(?m)^line_length\s+3200' 'the stride comes from VBE, not from xres*bpp'
|
# The stride must come from the mode information, not be recomputed as
|
||||||
|
# xres*bpp -- on a mode whose scanline is padded those two differ, and every
|
||||||
|
# row after the first lands in the wrong place.
|
||||||
|
ExpectThat ($line -ge $xres * 4) 'the stride covers a full row of pixels' "line_length = $line, xres = $xres"
|
||||||
|
ExpectThat (($line % 4) -eq 0) 'the stride is a whole number of pixels' "line_length = $line"
|
||||||
Expect 'transp.*absent' 'the absent alpha channel is reported as length 0'
|
Expect 'transp.*absent' 'the absent alpha channel is reported as length 0'
|
||||||
Expect 'colour bars drawn' 'writing pixels through write() reaches the screen'
|
Expect 'colour bars drawn' 'writing pixels through write() reaches the screen'
|
||||||
Expect 'gradient drawn' 'mmap of /dev/fb0 maps the real framebuffer'
|
Expect 'gradient drawn' 'mmap of /dev/fb0 maps the real framebuffer'
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue