Files
Yaya48 5d9a60a926 hw/arm: add authenticated A6 IMG3 boot lab
Model the A6 crypto, interrupt, USB, and platform blocks needed to boot SecureROM through iBSS into iBEC Recovery.

Add local lab identity, IMG3, and APTicket tooling, patched macOS recovery utilities, UART and GDB access, and English end-user documentation.
2026-09-01 09:51:49 -07:00

185 lines
5.6 KiB
PowerShell

[CmdletBinding()]
param(
[string]$RomPath = (Join-Path $PSScriptRoot 'firmware\s5l8950x-secure-rom.bin'),
[Alias('IbootPath')]
[string]$DfuImagePath,
[string]$MsysRoot = 'C:\msys64',
[ValidateRange(1024, 65535)]
[int]$UsbBridgePort = 26050,
[switch]$NoWindowsUsb,
[switch]$SkipBuild,
[switch]$Trace,
[ValidateRange(0, 65535)]
[int]$GdbPort = 0,
[switch]$Paused
)
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
if ([Environment]::OSVersion.Platform -ne [PlatformID]::Win32NT) {
throw 'This launcher requires native Windows.'
}
$qemuSource = $PSScriptRoot
$buildDir = Join-Path $qemuSource 'build'
$mingwBin = Join-Path $MsysRoot 'mingw64\bin'
$msysBin = Join-Path $MsysRoot 'usr\bin'
$ninja = Join-Path $mingwBin 'ninja.exe'
$qemu = Join-Path $buildDir 'qemu-system-arm.exe'
$buildTemp = Join-Path $buildDir 'tmp'
$bridge = Join-Path $PSScriptRoot 'windows\QemuA6UsbBridge\build\Release\x64\QemuA6UsbBridge.exe'
$bridgeBuild = Join-Path $PSScriptRoot 'windows\QemuA6UsbBridge\build-bridge.ps1'
$bridgeStdout = Join-Path $buildDir 'a6-usb-bridge.log'
$bridgeStderr = Join-Path $buildDir 'a6-usb-bridge-error.log'
if (-not (Test-Path -LiteralPath $RomPath -PathType Leaf)) {
throw "SecureROM not found: $RomPath"
}
$rom = Get-Item -LiteralPath $RomPath
if ($rom.Length -ne 0x10000) {
throw "SecureROM must be exactly 65536 bytes (actual size: $($rom.Length))."
}
$dfuImage = $null
if ($DfuImagePath) {
if (-not (Test-Path -LiteralPath $DfuImagePath -PathType Leaf)) {
throw "DFU/iBSS image not found: $DfuImagePath"
}
$dfuImage = Get-Item -LiteralPath $DfuImagePath
if ($dfuImage.Length -eq 0) {
throw "The DFU/iBSS image is empty: $($dfuImage.FullName)"
}
}
$windowsUsb = -not $NoWindowsUsb -and $null -eq $dfuImage
$env:Path = "$mingwBin;$msysBin;$env:Path"
if (-not $SkipBuild) {
if (-not (Test-Path -LiteralPath $ninja -PathType Leaf)) {
throw "MinGW64 Ninja not found: $ninja"
}
if (-not (Test-Path -LiteralPath (Join-Path $msysBin 'sort.exe') -PathType Leaf)) {
throw "The MSYS2 tool set is incomplete: $msysBin"
}
if (-not (Test-Path -LiteralPath (Join-Path $buildDir 'build.ninja') -PathType Leaf)) {
throw "qemu\build is not configured. Configure QEMU from MSYS2 MinGW64 with --target-list=arm-softmmu."
}
[IO.Directory]::CreateDirectory($buildTemp) | Out-Null
$env:TMP = $buildTemp
$env:TEMP = $buildTemp
$env:TMPDIR = $buildTemp
& $ninja -C $buildDir qemu-system-arm.exe
if ($LASTEXITCODE -ne 0) {
throw "The QEMU build failed with exit code $LASTEXITCODE."
}
}
if (-not (Test-Path -LiteralPath $qemu -PathType Leaf)) {
throw "QEMU binary not found: $qemu"
}
$machines = & $qemu -machine help 2>&1
if ($LASTEXITCODE -ne 0 -or -not ($machines -match '^iphone5\s')) {
throw 'This QEMU binary does not include the iphone5 machine.'
}
$qemuArgs = @(
'-machine', 'iphone5',
'-bios', $rom.FullName,
'-no-reboot',
'-no-shutdown'
)
if ($dfuImage) {
$qemuArgs += @(
'-global',
"s5l8950x-usb-otg.dfu-image=$($dfuImage.FullName)"
)
}
if ($windowsUsb) {
$qemuArgs += @(
'-chardev', "socket,id=a6usb,host=127.0.0.1,port=$UsbBridgePort,server=on,wait=off",
'-global', 's5l8950x-usb-otg.usb-bridge=a6usb'
)
}
if ($Paused -and $GdbPort -eq 0) {
$GdbPort = 1234
}
if ($GdbPort -gt 0) {
$qemuArgs += @('-gdb', "tcp:127.0.0.1:$GdbPort")
}
if ($Paused) {
$qemuArgs += '-S'
}
# UART0 and the monitor stay multiplexed on the native console, including
# while the CPU is stopped for a debugger (Ctrl+A C toggles the monitor).
$qemuArgs += @('-display', 'none', '-serial', 'mon:stdio')
if ($Trace) {
$tracePath = Join-Path $buildDir 'a6-boot.log'
$qemuArgs += @(
'-d', 'in_asm,cpu_reset,guest_errors,unimp',
'-D', $tracePath
)
Write-Host "QEMU trace : $tracePath"
}
Write-Host "Native Windows QEMU : $qemu"
Write-Host "SecureROM : $($rom.FullName)"
if ($dfuImage) {
Write-Host "DFU/iBSS image : $($dfuImage.FullName)"
}
if ($windowsUsb) {
if (-not (Test-Path -LiteralPath $bridge -PathType Leaf)) {
& $bridgeBuild -Configuration Release
}
Write-Host 'Windows USB : Apple DFU VID_05AC&PID_1227 through UDE'
Write-Host "QEMU bridge : 127.0.0.1:$UsbBridgePort"
Write-Host "USB bridge log : $bridgeStdout"
}
if ($dfuImage) {
Write-Host 'The USB cable and DFU transfer are simulated internally.'
} elseif ($windowsUsb) {
Write-Host 'Windows exposes the virtual DFU phone to unmodified host tools.'
} else {
Write-Host 'Recovery and the USB cable are simulated; the ROM is waiting in DFU mode.'
}
Write-Host 'A6 UART : this console (Ctrl+A C = monitor)'
Write-Host 'Press Ctrl+A, then X to quit.'
if ($GdbPort -gt 0) {
Write-Host "Debugger : remote GDB at 127.0.0.1:$GdbPort"
Write-Host "LLDB : lldb -o 'gdb-remote 127.0.0.1:$GdbPort'"
}
if ($Paused) {
Write-Host 'CPU : paused until the debugger issues continue'
}
$bridgeProcess = $null
$exitCode = 1
try {
if ($windowsUsb) {
$bridgeProcess = Start-Process -FilePath $bridge `
-ArgumentList @('127.0.0.1', $UsbBridgePort.ToString()) `
-WindowStyle Hidden -PassThru `
-RedirectStandardOutput $bridgeStdout `
-RedirectStandardError $bridgeStderr
}
& $qemu @qemuArgs
$exitCode = $LASTEXITCODE
} finally {
if ($null -ne $bridgeProcess -and -not $bridgeProcess.HasExited) {
Stop-Process -Id $bridgeProcess.Id
$bridgeProcess.WaitForExit()
}
}
exit $exitCode