# Draw on /dev/fb0 and photograph the result. # # bootcheck -Fb proves fbinfo *ran* and that the numbers it read back are the # ones the bootloader programmed. It cannot prove the pixels landed where they # were meant to: a framebuffer written with the wrong stride still reports # every byte accepted, and the only symptom is a picture that shears # progressively down the screen. That is a thing you have to look at. # # tools/fbshot.ps1 gradient through mmap # tools/fbshot.ps1 -Mode bars colour bars through write() param( [ValidateSet('fill', 'bars')] [string]$Mode = 'fill', [int]$BootSeconds = 20, [string]$Qemu = (Find-Qemu) ) # QEMU, on whichever host this is. # # PowerShell 7 runs on Linux, macOS and the BSDs as well as Windows, so these # scripts are usable from all of them -- but the old default was a hardcoded # scoop path under $env:USERPROFILE, which exists on exactly one of those. PATH # first, because a package-managed qemu is on it everywhere; the scoop location # is only a fallback for the Windows install that does not add itself to PATH. function Find-Qemu { $exe = if ($IsWindows -or $env:OS -eq 'Windows_NT') { 'qemu-system-x86_64.exe' } else { 'qemu-system-x86_64' } $onPath = Get-Command $exe -ErrorAction SilentlyContinue if ($onPath) { return $onPath.Source } if ($env:USERPROFILE) { $scoop = Join-Path (Join-Path $env:USERPROFILE 'scoop/apps/qemu/current') $exe if (Test-Path $scoop) { return $scoop } } foreach ($p in @('/usr/bin', '/usr/local/bin', '/opt/homebrew/bin')) { $c = Join-Path $p $exe if (Test-Path $c) { return $c } } throw "qemu-system-x86_64 not found on PATH. Install QEMU, or pass -Qemu ." } $ErrorActionPreference = 'Stop' # Repo root is two levels up: this script lives in tools/windows/. $root = Split-Path (Split-Path $PSScriptRoot -Parent) -Parent $hda = Join-Path $root 'schos.img' # The root filesystem. SchFS is the only root there is: the kernel mounts # device 1 in forkret() and panics if it is not a SchFS volume, so this is # not a choice and there is no -SchFS switch any more. It used to default to # build/fs.img, which stopped being bootable the moment SchFS became root. $hdb = Join-Path $root 'build/schfs.img' $log = Join-Path $root 'build/fbshot.log' $ppm = Join-Path $root "build/fb-$Mode.ppm" Remove-Item -Force $log, $ppm -ErrorAction SilentlyContinue $monPort = 55556 # not crashshot's 55555, so the two can run back to back $psi = New-Object System.Diagnostics.ProcessStartInfo $psi.FileName = $Qemu $psi.Arguments = @( "-drive file=`"$hda`",format=raw,index=0,media=disk" "-drive file=`"$hdb`",format=raw,index=1,media=disk" '-m 1G -smp 1 -cpu qemu64,+rdtscp -machine pc-i440fx-9.2' '-display none' "-chardev stdio,id=c0,logfile=`"$log`"" '-serial chardev:c0' "-monitor tcp:127.0.0.1:$monPort,server,nowait" ) -join ' ' $psi.RedirectStandardInput = $true $psi.UseShellExecute = $false Write-Host "==> booting" -ForegroundColor Cyan $p = [System.Diagnostics.Process]::Start($psi) function Send-Line($text) { foreach ($ch in ($text + "`n").ToCharArray()) { $p.StandardInput.Write($ch) $p.StandardInput.Flush() Start-Sleep -Milliseconds 30 # serial has no flow control } } try { Start-Sleep -Seconds $BootSeconds Write-Host " > fbinfo $Mode" -ForegroundColor DarkGray Send-Line "fbinfo $Mode" Start-Sleep -Seconds 8 # 1.9 MB a pixel at a time is not fast Write-Host "==> capturing the framebuffer" -ForegroundColor Cyan $client = New-Object System.Net.Sockets.TcpClient('127.0.0.1', $monPort) $writer = New-Object System.IO.StreamWriter($client.GetStream()) $writer.AutoFlush = $true Start-Sleep -Milliseconds 500 $writer.WriteLine("screendump $ppm") Start-Sleep -Seconds 2 $writer.WriteLine('quit') Start-Sleep -Milliseconds 500 $client.Close() } finally { if (-not $p.HasExited) { $p.Kill() } Start-Sleep -Milliseconds 800 } if (Test-Path $log) { $text = Get-Content $log -Raw $idx = $text.IndexOf('fbinfo') if ($idx -ge 0) { Write-Host $text.Substring($idx) } } if (Test-Path $ppm) { Write-Host "==> $ppm ($((Get-Item $ppm).Length) bytes)" -ForegroundColor Green } else { Write-Host 'FAIL: no screendump was produced' -ForegroundColor Red exit 1 }