param([string]$SevenZip, [string]$GitHubAddress)
$ErrorActionPreference = 'Stop'
$root = Split-Path -Parent $PSScriptRoot
$downloads = Join-Path $root '.tools/downloads'
New-Item -ItemType Directory -Force $downloads | Out-Null
$lock = Get-Content -LiteralPath (Join-Path $root 'tools-lock.json') -Raw -Encoding UTF8 | ConvertFrom-Json
function Verify-File($file, $dependency) {
(Test-Path -LiteralPath $file) -and ((Get-FileHash -LiteralPath $file -Algorithm $dependency.algorithm).Hash -eq $dependency.hash)
}
foreach ($dependency in $lock.dependencies) {
$file = Join-Path $downloads $dependency.file
if (!(Verify-File $file $dependency)) {
Write-Host ('Downloading ' + $dependency.name)
$partial = $file + '.partial'
$curlArgs = @('--fail','--location','--retry','3','--retry-all-errors','--connect-timeout','20','--max-time','600','--output',$partial)
if ($GitHubAddress) {
$curlArgs += @('--resolve',('raw.githubusercontent.com:443:' + $GitHubAddress),'--resolve',('release-assets.githubusercontent.com:443:' + $GitHubAddress))
}
$curlArgs += $dependency.url
& curl.exe @curlArgs
if ($LASTEXITCODE -ne 0 -and $dependency.mirror_used) {
Write-Host ('Trying the recorded mirror for ' + $dependency.name + '; the same pinned hash remains mandatory.')
$curlArgs[$curlArgs.Length-1] = $dependency.mirror_used
& curl.exe @curlArgs
}
if ($LASTEXITCODE -ne 0) { throw ('Download failed: ' + $dependency.url) }
if (!(Verify-File $partial $dependency)) { throw ('Hash mismatch: ' + $dependency.file + '. The partial file was preserved for diagnosis.') }
Move-Item -LiteralPath $partial -Destination $file -Force
}
Write-Host ('Verified ' + $dependency.file)
}
if (!$SevenZip) {
$command = Get-Command 7z.exe -ErrorAction SilentlyContinue
if ($command) { $SevenZip = $command.Source }
else {
$toolbox = Join-Path $env:LOCALAPPDATA 'JetBrains/Toolbox/bin/7z.exe'
if (Test-Path -LiteralPath $toolbox) { $SevenZip = $toolbox }
}
}
if (!$SevenZip -or !(Test-Path -LiteralPath $SevenZip)) { throw '7-Zip is required to unpack the QEMU NSIS archive without running its administrator installer. Install 7-Zip, or pass -SevenZip C:\path\7z.exe.' }
$qemu = Join-Path $root '.tools/qemu'
New-Item -ItemType Directory -Force $qemu | Out-Null
$qemuDependency = $lock.dependencies | Where-Object file -eq 'qemu-w64-setup-20260811.exe'
$qemuStamp = Join-Path $qemu '.xfe-package-hash'
if (!(Test-Path -LiteralPath $qemuStamp) -or (Get-Content -LiteralPath $qemuStamp -Raw).Trim() -ne $qemuDependency.hash) {
& $SevenZip x (Join-Path $downloads 'qemu-w64-setup-20260811.exe') ('-o'+$qemu) -y -bso0 -bsp0
if ($LASTEXITCODE -ne 0) { throw 'QEMU extraction failed; stop running QEMU instances before refreshing its binaries' }
Set-Content -LiteralPath $qemuStamp -Value $qemuDependency.hash
}
$limine = Join-Path $root '.tools/limine'
New-Item -ItemType Directory -Force $limine | Out-Null
Expand-Archive -LiteralPath (Join-Path $downloads 'limine-binary.zip') -DestinationPath $limine -Force
foreach ($name in @('BOOTX64.EFI','BOOTAA64.EFI','LICENSE','3RDPARTY.md')) {
Copy-Item -LiteralPath (Join-Path $limine ('limine-binary/'+$name)) -Destination (Join-Path $limine $name) -Force
}
$firmware = Join-Path $root '.tools/firmware'
New-Item -ItemType Directory -Force $firmware | Out-Null
foreach ($name in @('edk2-x86_64-code.fd','edk2-i386-vars.fd','edk2-aarch64-code.fd','edk2-arm-vars.fd')) {
if (!(Test-Path -LiteralPath (Join-Path $firmware $name))) {
& $SevenZip x (Join-Path $downloads ($name+'.bz2')) ('-o'+$firmware) -y -bso0 -bsp0
if ($LASTEXITCODE -ne 0) { throw ('Firmware extraction failed: ' + $name) }
}
}
Copy-Item -LiteralPath (Join-Path $downloads 'edk2-licenses.txt') -Destination $firmware -Force
$llvm = Join-Path $root '.tools/llvm'
if (!(Test-Path -LiteralPath (Join-Path $llvm 'bin/clang.exe'))) {
New-Item -ItemType Directory -Force $llvm | Out-Null
& $SevenZip x (Join-Path $downloads 'LLVM-20.1.8-win64.exe') ('-o'+$llvm) -y -bso0 -bsp0
if ($LASTEXITCODE -ne 0) { throw 'LLVM extraction failed' }
}
Write-Host 'Project-local dependencies are ready. No installer was run and PATH was not changed.'
param([string]$SevenZip, [string]$GitHubAddress)
$ErrorActionPreference = 'Stop'
$root = Split-Path -Parent $PSScriptRoot
$downloads = Join-Path $root '.tools/downloads'
New-Item -ItemType Directory -Force $downloads | Out-Null
$lock = Get-Content -LiteralPath (Join-Path $root 'tools-lock.json') -Raw -Encoding UTF8 | ConvertFrom-Json
function Verify-File($file, $dependency) {
(Test-Path -LiteralPath $file) -and ((Get-FileHash -LiteralPath $file -Algorithm $dependency.algorithm).Hash -eq $dependency.hash)
}
foreach ($dependency in $lock.dependencies) {
$file = Join-Path $downloads $dependency.file
if (!(Verify-File $file $dependency)) {
Write-Host ('Downloading ' + $dependency.name)
$partial = $file + '.partial'
$curlArgs = @('--fail','--location','--retry','3','--retry-all-errors','--connect-timeout','20','--max-time','600','--output',$partial)
if ($GitHubAddress) {
$curlArgs += @('--resolve',('raw.githubusercontent.com:443:' + $GitHubAddress),'--resolve',('release-assets.githubusercontent.com:443:' + $GitHubAddress))
}
$curlArgs += $dependency.url
& curl.exe @curlArgs
if ($LASTEXITCODE -ne 0 -and $dependency.mirror_used) {
Write-Host ('Trying the recorded mirror for ' + $dependency.name + '; the same pinned hash remains mandatory.')
$curlArgs[$curlArgs.Length-1] = $dependency.mirror_used
& curl.exe @curlArgs
}
if ($LASTEXITCODE -ne 0) { throw ('Download failed: ' + $dependency.url) }
if (!(Verify-File $partial $dependency)) { throw ('Hash mismatch: ' + $dependency.file + '. The partial file was preserved for diagnosis.') }
Move-Item -LiteralPath $partial -Destination $file -Force
}
Write-Host ('Verified ' + $dependency.file)
}
if (!$SevenZip) {
$command = Get-Command 7z.exe -ErrorAction SilentlyContinue
if ($command) { $SevenZip = $command.Source }
else {
$toolbox = Join-Path $env:LOCALAPPDATA 'JetBrains/Toolbox/bin/7z.exe'
if (Test-Path -LiteralPath $toolbox) { $SevenZip = $toolbox }
}
}
if (!$SevenZip -or !(Test-Path -LiteralPath $SevenZip)) { throw '7-Zip is required to unpack the QEMU NSIS archive without running its administrator installer. Install 7-Zip, or pass -SevenZip C:\path\7z.exe.' }
$qemu = Join-Path $root '.tools/qemu'
New-Item -ItemType Directory -Force $qemu | Out-Null
$qemuDependency = $lock.dependencies | Where-Object file -eq 'qemu-w64-setup-20260811.exe'
$qemuStamp = Join-Path $qemu '.xfe-package-hash'
if (!(Test-Path -LiteralPath $qemuStamp) -or (Get-Content -LiteralPath $qemuStamp -Raw).Trim() -ne $qemuDependency.hash) {
& $SevenZip x (Join-Path $downloads 'qemu-w64-setup-20260811.exe') ('-o'+$qemu) -y -bso0 -bsp0
if ($LASTEXITCODE -ne 0) { throw 'QEMU extraction failed; stop running QEMU instances before refreshing its binaries' }
Set-Content -LiteralPath $qemuStamp -Value $qemuDependency.hash
}
$limine = Join-Path $root '.tools/limine'
New-Item -ItemType Directory -Force $limine | Out-Null
Expand-Archive -LiteralPath (Join-Path $downloads 'limine-binary.zip') -DestinationPath $limine -Force
foreach ($name in @('BOOTX64.EFI','BOOTAA64.EFI','LICENSE','3RDPARTY.md')) {
Copy-Item -LiteralPath (Join-Path $limine ('limine-binary/'+$name)) -Destination (Join-Path $limine $name) -Force
}
$firmware = Join-Path $root '.tools/firmware'
New-Item -ItemType Directory -Force $firmware | Out-Null
foreach ($name in @('edk2-x86_64-code.fd','edk2-i386-vars.fd','edk2-aarch64-code.fd','edk2-arm-vars.fd')) {
if (!(Test-Path -LiteralPath (Join-Path $firmware $name))) {
& $SevenZip x (Join-Path $downloads ($name+'.bz2')) ('-o'+$firmware) -y -bso0 -bsp0
if ($LASTEXITCODE -ne 0) { throw ('Firmware extraction failed: ' + $name) }
}
}
Copy-Item -LiteralPath (Join-Path $downloads 'edk2-licenses.txt') -Destination $firmware -Force
$llvm = Join-Path $root '.tools/llvm'
if (!(Test-Path -LiteralPath (Join-Path $llvm 'bin/clang.exe'))) {
New-Item -ItemType Directory -Force $llvm | Out-Null
& $SevenZip x (Join-Path $downloads 'LLVM-20.1.8-win64.exe') ('-o'+$llvm) -y -bso0 -bsp0
if ($LASTEXITCODE -ne 0) { throw 'LLVM extraction failed' }
}
Write-Host 'Project-local dependencies are ready. No installer was run and PATH was not changed.'