Compare commits

...

5 Commits

Author SHA1 Message Date
patchzyy 22c13cd785 Bundle mbed TLS in Linux native prebuilt 2026-09-29 21:36:10 +02:00
patchzyy 6b853ca371 Fix Wii certificates (#265)
confirmed as fixed by forgottonice (in dms)
2026-09-29 20:03:35 +02:00
patchzyy 77a8623416 Fix Mac THP memory path (#267) 2026-09-29 20:01:39 +02:00
patchzyy 10ab54adee Fix native build paths for special characters (#266) 2026-09-29 20:01:03 +02:00
patchzyy a05c89739d Always refresh Retro-WFC payload with fallback (#264) 2026-09-28 21:01:40 +02:00
13 changed files with 192 additions and 72 deletions
+10 -2
View File
@@ -103,7 +103,7 @@ function Write-MkwBuildStep([string]$StepId, [string]$Message) {
function Reset-LocalDirectory([string]$Path) { function Reset-LocalDirectory([string]$Path) {
$full = [IO.Path]::GetFullPath($Path) $full = [IO.Path]::GetFullPath($Path)
$root = [IO.Path]::GetFullPath($Workspace).TrimEnd('\') + '\' $root = [IO.Path]::GetFullPath($Workspace).TrimEnd('\') + '\'
$installRoot = [IO.Path]::GetFullPath((Split-Path -Parent $Workspace)).TrimEnd('\') + '\' $installRoot = [IO.Path]::GetFullPath((Split-Path -Parent $realWorkspace)).TrimEnd('\') + '\'
# The caller-supplied output destinations are legitimate reset targets by # The caller-supplied output destinations are legitimate reset targets by
# definition, wherever the caller placed them: a fresh install's operation # definition, wherever the caller placed them: a fresh install's operation
# scratch lives beside the installation directory rather than inside it. # scratch lives beside the installation directory rather than inside it.
@@ -150,8 +150,16 @@ if ($Profile -eq 'both' -and [string]::IsNullOrWhiteSpace($BaseOutputDirectory))
if ($Profile -ne 'both' -and -not [string]::IsNullOrWhiteSpace($BaseOutputDirectory)) { if ($Profile -ne 'both' -and -not [string]::IsNullOrWhiteSpace($BaseOutputDirectory)) {
throw '-BaseOutputDirectory is valid only with -Profile both.' throw '-BaseOutputDirectory is valid only with -Profile both.'
} }
$realWorkspace = $Workspace.TrimEnd('\')
$Workspace = Get-MkwBuildSafePath $realWorkspace 'workspace' 'runtime\CMakeLists.txt'
# A selected package inside the install may also name the same Code.pul through the real path.
# Give it the workspace spelling before comparing it with the staged copy.
if (-not [string]::IsNullOrWhiteSpace($RetroRewindPackageDirectory) -and
$RetroRewindPackageDirectory.StartsWith($realWorkspace + '\', [StringComparison]::OrdinalIgnoreCase)) {
$RetroRewindPackageDirectory = $Workspace + $RetroRewindPackageDirectory.Substring($realWorkspace.Length)
}
$translator = Join-Path $Toolkit 'Translator\Translator.Cli.exe' $translator = Join-Path $Toolkit 'Translator\Translator.Cli.exe'
$toolchain = Get-MkwShellSafeToolchainRoot $Toolkit $toolchain = Get-MkwBuildSafePath $Toolkit 'toolchain' 'CMake\bin\cmake.exe'
$cmake = Join-Path $toolchain 'CMake\bin\cmake.exe' $cmake = Join-Path $toolchain 'CMake\bin\cmake.exe'
$ninja = Join-Path $toolchain 'Ninja\ninja.exe' $ninja = Join-Path $toolchain 'Ninja\ninja.exe'
$toolchainBin = Join-Path $toolchain 'llvm-mingw\bin' $toolchainBin = Join-Path $toolchain 'llvm-mingw\bin'
+29 -15
View File
@@ -40,41 +40,55 @@ function Get-MkwToolchainPath([string]$ToolchainRoot) {
) -join ';') ) -join ';')
} }
function Get-MkwShellSafeToolchainRoot([string]$ToolchainRoot) { function Get-MkwBuildSafePath([string]$Path, [string]$Kind, [string]$MarkerFile) {
if ([string]::IsNullOrWhiteSpace($ToolchainRoot)) { throw 'A toolchain root is required.' } <#
$full = [IO.Path]::GetFullPath($ToolchainRoot) The Windows native build passes workspace paths through CMake, Ninja response files and
clang, which do not all interpret quotes the same way. Keep those paths plain even when the
user's install directory contains an apostrophe, ampersand or other punctuation.
#>
if ([string]::IsNullOrWhiteSpace($Path)) { throw "A $Kind path is required." }
$full = [IO.Path]::GetFullPath($Path)
# A drive root keeps its separator: "C:" is relative to the current directory on that drive. # A drive root keeps its separator: "C:" is relative to the current directory on that drive.
if ($full -ne [IO.Path]::GetPathRoot($full)) { $full = $full.TrimEnd('\') } if ($full -ne [IO.Path]::GetPathRoot($full)) { $full = $full.TrimEnd('\') }
if ($full -notmatch '[()&^%!]') { return $full } if ($full -cmatch '^[A-Za-z0-9 ._\\:-]+$') { return $full }
Assert-File (Join-Path $full $MarkerFile) "$Kind marker"
$sha = [Security.Cryptography.SHA256]::Create() $sha = [Security.Cryptography.SHA256]::Create()
try { try {
$bytes = $sha.ComputeHash([Text.Encoding]::UTF8.GetBytes($full.ToLowerInvariant())) $bytes = $sha.ComputeHash([Text.Encoding]::UTF8.GetBytes($full.ToLowerInvariant()))
} finally { $sha.Dispose() } } finally { $sha.Dispose() }
$linkName = 'toolchain-' + ((($bytes[0..7]) | ForEach-Object { $_.ToString('x2') }) -join '') $linkName = "$Kind-" + ((($bytes[0..7]) | ForEach-Object { $_.ToString('x2') }) -join '')
$failures = @() $failures = @()
foreach ($base in @($env:ProgramData, $env:PUBLIC)) { foreach ($base in @($env:ProgramData, $env:PUBLIC)) {
if ([string]::IsNullOrWhiteSpace($base) -or $base -match '[()&^%! ]') { continue } if ([string]::IsNullOrWhiteSpace($base) -or $base -cnotmatch '^[A-Za-z0-9._\\:-]+$') { continue }
$link = Join-Path (Join-Path $base 'WiiCompiled') $linkName $link = Join-Path (Join-Path $base 'WiiCompiled') $linkName
try { try {
[IO.Directory]::CreateDirectory((Split-Path -Parent $link)) | Out-Null [IO.Directory]::CreateDirectory((Split-Path -Parent $link)) | Out-Null
# The name already identifies the target, so an existing junction that still resolves is $existing = Get-Item -LiteralPath $link -Force -ErrorAction SilentlyContinue
# this one; only a broken leftover is replaced. Directory.Delete removes the reparse if ($null -ne $existing) {
# point itself, where Remove-Item -Recurse would delete the toolchain it points at. # Never trust a directory just because it has the marker: it could point at a
if (-not (Test-Path -LiteralPath (Join-Path $link 'CMake\bin\cmake.exe') -PathType Leaf)) { # different installation. Nor may we remove a directory we did not create.
if (Test-Path -LiteralPath $link) { [IO.Directory]::Delete($link) } if ($existing.LinkType -ne 'Junction' -or
@($existing.Target).Count -ne 1 -or
-not [string]::Equals([IO.Path]::GetFullPath(@($existing.Target)[0]),
$full, [StringComparison]::OrdinalIgnoreCase)) {
throw "An existing path is not the expected junction: $link"
}
} else {
New-Item -ItemType Junction -Path $link -Target $full -ErrorAction Stop | Out-Null New-Item -ItemType Junction -Path $link -Target $full -ErrorAction Stop | Out-Null
} }
Write-Host "MKWCBUILD: Building through $link, because $full contains characters cmd.exe cannot parse" Assert-File (Join-Path $link $MarkerFile) "$Kind junction marker"
Write-Host "MKWCBUILD: Building the $Kind through $link, because $full contains characters the native build cannot quote reliably"
return $link return $link
} catch { } catch {
$failures += "$link ($($_.Exception.Message))" $failures += "$link ($($_.Exception.Message))"
} }
} }
throw ("The toolchain path $full contains a character (one of ( ) & ^ % !) that the compiler " + throw ("The $Kind path $full cannot be passed safely to the native build, and no junction " +
'cannot be invoked through, and no junction to it could be created: ' + ($failures -join '; ') + 'to it could be created: ' + ($failures -join '; ') + '. Install to a path of plain ' +
'. Install to a path without those characters.') 'letters, digits and spaces, or make a safe junction location available.')
} }
function Get-MkwProjectPins([string]$ProjectFile) { function Get-MkwProjectPins([string]$ProjectFile) {
+31 -8
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# Builds the redistributable precompiled aurora + third-party package for native Linux: aurora # Builds the redistributable precompiled aurora + third-party package for native Linux: aurora
# (~43% of local build CPU time per Prepare-NativePrebuilt.ps1) and vendored Crypto++ are identical # (~43% of local build CPU time per Prepare-NativePrebuilt.ps1), Crypto++ and mbed TLS are identical
# for every user under the pinned toolchain prepare-portable-tools.sh bundles, so this configures # for every user under the pinned toolchain prepare-portable-tools.sh bundles, so this configures
# runtime/ against that toolchain, builds just that closure, and harvests the archives plus a # runtime/ against that toolchain, builds just that closure, and harvests the archives plus a
# generated CMake description into an output package - the Linux counterpart to # generated CMake description into an output package - the Linux counterpart to
@@ -39,8 +39,7 @@ Usage: Prepare-NativePrebuilt.sh --arch {x86_64|aarch64} [options]
--reuse-stage Reuse an existing staging build directory (maintainer iteration aid: a --reuse-stage Reuse an existing staging build directory (maintainer iteration aid: a
re-harvest does not recompile aurora from scratch) re-harvest does not recompile aurora from scratch)
--parallel N Ninja build parallelism (default: nproc) --parallel N Ninja build parallelism (default: nproc)
--print-fingerprint-only Print the four provenance inputs (compiler_sha256, flag_fingerprint, --print-fingerprint-only Print the provenance inputs as "key=value" lines and
aurora_fingerprint, third_party_fingerprint) as "key=value" lines and
exit, without configuring/building/harvesting anything - lets a caller exit, without configuring/building/harvesting anything - lets a caller
(build-appimage.sh) decide whether an existing package is still current (build-appimage.sh) decide whether an existing package is still current
without paying for a full aurora rebuild just to find out. without paying for a full aurora rebuild just to find out.
@@ -131,6 +130,8 @@ fixed_configure_flags=(
-DCMAKE_DISABLE_FIND_PACKAGE_absl=ON -DCMAKE_DISABLE_FIND_PACKAGE_absl=ON
-DCMAKE_DISABLE_FIND_PACKAGE_PNG=ON -DCMAKE_DISABLE_FIND_PACKAGE_PNG=ON
-DCMAKE_DISABLE_FIND_PACKAGE_Freetype=ON -DCMAKE_DISABLE_FIND_PACKAGE_Freetype=ON
-DUSE_STATIC_MBEDTLS_LIBRARY=ON
-DUSE_SHARED_MBEDTLS_LIBRARY=OFF
# Freetype's own vendored CMakeLists.txt separately probes for system BZip2 (optional # Freetype's own vendored CMakeLists.txt separately probes for system BZip2 (optional
# bzip2-compressed-font support aurora-main never asked for) regardless of the Freetype # bzip2-compressed-font support aurora-main never asked for) regardless of the Freetype
# find_package disable above, since that only stops aurora's own outer find_package(Freetype) # find_package disable above, since that only stops aurora's own outer find_package(Freetype)
@@ -148,11 +149,10 @@ flag_fingerprint=$(printf '%s\n' "${fixed_configure_flags[@]}" | sha256sum | awk
aurora_fingerprint=$(fingerprint_tree "$aurora_source" extern build) aurora_fingerprint=$(fingerprint_tree "$aurora_source" extern build)
[[ -n "$aurora_fingerprint" ]] || fail "The aurora source tree could not be fingerprinted: $aurora_source" [[ -n "$aurora_fingerprint" ]] || fail "The aurora source tree could not be fingerprinted: $aurora_source"
# The harvested Crypto++ archive is consumed against this tree's headers, so it is fingerprinted # The harvested Crypto++ archive is consumed against this tree's headers, so it is fingerprinted.
# for the same reason as aurora above. No exclusions: unlike aurora's extern/, nothing under
# runtime/third_party is shipped separately.
third_party_fingerprint=$(fingerprint_tree "$runtime_source/third_party") third_party_fingerprint=$(fingerprint_tree "$runtime_source/third_party")
[[ -n "$third_party_fingerprint" ]] || fail "The vendored third-party tree could not be fingerprinted: $runtime_source/third_party" [[ -n "$third_party_fingerprint" ]] || fail "The vendored third-party tree could not be fingerprinted: $runtime_source/third_party"
mbedtls_fingerprint=$(sha256_of "$runtime_source/cmake/MbedTLSPin.cmake")
compiler_sha256=$(sha256_of "$clang_binary") compiler_sha256=$(sha256_of "$clang_binary")
@@ -161,6 +161,7 @@ if [[ "$print_fingerprint_only" -eq 1 ]]; then
printf 'flag_fingerprint=%s\n' "$flag_fingerprint" printf 'flag_fingerprint=%s\n' "$flag_fingerprint"
printf 'aurora_fingerprint=%s\n' "$aurora_fingerprint" printf 'aurora_fingerprint=%s\n' "$aurora_fingerprint"
printf 'third_party_fingerprint=%s\n' "$third_party_fingerprint" printf 'third_party_fingerprint=%s\n' "$third_party_fingerprint"
printf 'mbedtls_fingerprint=%s\n' "$mbedtls_fingerprint"
exit 0 exit 0
fi fi
@@ -361,6 +362,21 @@ while IFS='|' read -r name type file linkerfile; do
linker_file_to_reference["$linkerfile"]="@PKG@/$relative_linker" linker_file_to_reference["$linkerfile"]="@PKG@/$relative_linker"
fi fi
done < "$targets_txt" done < "$targets_txt"
mbedtls_refs=()
mbedtls_txt="$export_dir/mbedtls.txt"
assert_file "$mbedtls_txt" "Mbed TLS export targets list"
while IFS='|' read -r name linkerfile; do
[[ -n "$name" ]] || continue
linkerfile=$(normalize "$linkerfile")
ref=${linker_file_to_reference["$linkerfile"]:-}
[[ -n "$ref" ]] || fail "Mbed TLS archive was not harvested: $name ($linkerfile)"
mbedtls_refs+=("$ref")
done < "$mbedtls_txt"
[[ ${#mbedtls_refs[@]} -eq 3 ]] || fail "Expected three Mbed TLS archives, got ${#mbedtls_refs[@]}"
mbedtls_source_dir=$(get_meta mbedtls_source_dir)
assert_dir "$mbedtls_source_dir/include/mbedtls" "Mbed TLS headers"
mkdir -p "$output_dir/include/mbedtls"
cp -a "$mbedtls_source_dir/include/." "$output_dir/include/mbedtls/"
# Unlike Windows (SDL/zlib/libpng ship as DLLs by default), everything here was forced static above # Unlike Windows (SDL/zlib/libpng ship as DLLs by default), everything here was forced static above
# and Dawn's own Linux package (verified directly) ships libwebgpu_dawn.a, also static - so zero # and Dawn's own Linux package (verified directly) ships libwebgpu_dawn.a, also static - so zero
# shared imports is the expected, normal outcome, not a failure. # shared imports is the expected, normal outcome, not a failure.
@@ -426,6 +442,9 @@ for item in "${link_items[@]}"; do
if [[ "$item" = /* ]]; then item_abs=$(normalize "$item"); else item_abs=$(normalize "$stage_dir/$item"); fi if [[ "$item" = /* ]]; then item_abs=$(normalize "$item"); else item_abs=$(normalize "$stage_dir/$item"); fi
ref=${linker_file_to_reference["$item_abs"]:-} ref=${linker_file_to_reference["$item_abs"]:-}
if [[ -n "$ref" ]]; then if [[ -n "$ref" ]]; then
for mbedtls_ref in "${mbedtls_refs[@]}"; do
[[ "$ref" == "$mbedtls_ref" ]] && continue 2
done
package_link_items+=("$ref") package_link_items+=("$ref")
continue continue
fi fi
@@ -505,6 +524,9 @@ generated_cmake="$output_dir/native_prebuilt.cmake"
format_cmake_block MKW_NP_COMPILE_DEFINITIONS "${package_definitions[@]}" format_cmake_block MKW_NP_COMPILE_DEFINITIONS "${package_definitions[@]}"
format_cmake_block MKW_NP_COMPILE_OPTIONS "${package_compile_options[@]}" format_cmake_block MKW_NP_COMPILE_OPTIONS "${package_compile_options[@]}"
format_cmake_block MKW_NP_LINK_LIBRARIES "${package_link_items[@]}" format_cmake_block MKW_NP_LINK_LIBRARIES "${package_link_items[@]}"
format_cmake_block MKW_NP_MBEDTLS_LIBRARIES "${mbedtls_refs[@]}"
echo 'set(MKW_NP_MBEDTLS_INCLUDE_DIR "@PKG@/include/mbedtls")'
printf 'set(MKW_NP_MBEDTLS_FINGERPRINT "%s")\n' "$mbedtls_fingerprint"
format_cmake_block MKW_NP_AURORA_TARGETS "aurora::gx" "aurora::pad" "aurora::si" "aurora::vi" "aurora::mtx" format_cmake_block MKW_NP_AURORA_TARGETS "aurora::gx" "aurora::pad" "aurora::si" "aurora::vi" "aurora::mtx"
echo "" echo ""
printf 'set(MKW_NP_DAWN_CONFIG_DIR "%s")\n' "$dawn_config_token" printf 'set(MKW_NP_DAWN_CONFIG_DIR "%s")\n' "$dawn_config_token"
@@ -540,12 +562,12 @@ harvested_count=${#linker_file_to_reference[@]}
python3 - "$output_dir" "$compiler_sha256" "$compiler_version" "$flag_fingerprint" \ python3 - "$output_dir" "$compiler_sha256" "$compiler_version" "$flag_fingerprint" \
"$dawn_version" "$dawn_runtime_sha256" "$aurora_fingerprint" "$third_party_fingerprint" \ "$dawn_version" "$dawn_runtime_sha256" "$aurora_fingerprint" "$third_party_fingerprint" \
"$sdl3_target" "$harvested_count" <<'PY' "$sdl3_target" "$harvested_count" "$mbedtls_fingerprint" <<'PY'
import hashlib, json, os, sys, datetime import hashlib, json, os, sys, datetime
(output_dir, compiler_sha256, compiler_version, flag_fingerprint, dawn_version, (output_dir, compiler_sha256, compiler_version, flag_fingerprint, dawn_version,
dawn_runtime_sha256, aurora_fingerprint, third_party_fingerprint, sdl3_target, dawn_runtime_sha256, aurora_fingerprint, third_party_fingerprint, sdl3_target,
harvested_count) = sys.argv[1:] harvested_count, mbedtls_fingerprint) = sys.argv[1:]
contents = [] contents = []
for root, dirs, files in os.walk(output_dir): for root, dirs, files in os.walk(output_dir):
@@ -570,6 +592,7 @@ provenance = {
"DawnRuntimeSha256": dawn_runtime_sha256, "DawnRuntimeSha256": dawn_runtime_sha256,
"AuroraSourceFingerprint": aurora_fingerprint, "AuroraSourceFingerprint": aurora_fingerprint,
"ThirdPartySourceFingerprint": third_party_fingerprint, "ThirdPartySourceFingerprint": third_party_fingerprint,
"MbedTlsFingerprint": mbedtls_fingerprint,
"Sdl3Target": sdl3_target, "Sdl3Target": sdl3_target,
"HarvestedLibraryCount": int(harvested_count), "HarvestedLibraryCount": int(harvested_count),
"Contents": contents, "Contents": contents,
+27 -6
View File
@@ -127,18 +127,39 @@ internal static class Program
string? retroWfcOfflineDir = null; string? retroWfcOfflineDir = null;
if (downloadPayload) if (downloadPayload)
{ {
// Reused if a previous install already downloaded and it's still valid - matches
// Windows's own reuse-if-valid behavior instead of re-downloading on every install.
var cacheDir = Path.Combine(workspace, "generated", "retro-wfc-payload"); var cacheDir = Path.Combine(workspace, "generated", "retro-wfc-payload");
reporter.Progress(InstallStages.Validate, "Preparing the Retro-WFC payload", 1); reporter.Progress(InstallStages.Validate,
"Downloading the current Retro-WFC payload", 1);
try
{
// A valid signature authenticates a payload, but does not prove it is the latest
// signed revision. Always ask the fixed endpoint for the current snapshot; the
// downloader verifies it before atomically replacing the cache.
await RetroWfcPayload.DownloadRetroWfcPayloadAsync(
RetroWfcPayload.CurrentRetroWfcPayloadUri, cacheDir, token);
}
catch (Exception downloadFailure) when (!token.IsCancellationRequested &&
downloadFailure is HttpRequestException or TimeoutException
or IOException)
{
// Offline installs may continue with a previously authenticated snapshot. Do not
// use this path for a newly downloaded payload that failed signature validation:
// that must remain a hard failure instead of hiding possible endpoint tampering.
try try
{ {
RetroWfcPayload.ValidateStagedRetroWfcPayloadDirectory(cacheDir); RetroWfcPayload.ValidateStagedRetroWfcPayloadDirectory(cacheDir);
} }
catch (InvalidDataException) catch (Exception cacheFailure) when (cacheFailure is IOException or
UnauthorizedAccessException or InvalidDataException)
{ {
await RetroWfcPayload.DownloadRetroWfcPayloadAsync( throw new InvalidOperationException(
RetroWfcPayload.CurrentRetroWfcPayloadUri, cacheDir, token); "The current Retro-WFC payload could not be downloaded and no valid cached " +
$"payload is available ({cacheFailure.Message.TrimEnd('.')}).", downloadFailure);
}
reporter.Diagnostic(
"The current Retro-WFC payload could not be downloaded; using the previously " +
$"verified cached payload instead ({downloadFailure.Message.TrimEnd('.')}).");
} }
retroWfcOfflineDir = cacheDir; retroWfcOfflineDir = cacheDir;
} }
@@ -110,8 +110,7 @@ internal sealed class ProductRepairService
InputValidation.CurrentRetroWfcPayloadUri, payloadScratch, cancellationToken); InputValidation.CurrentRetroWfcPayloadUri, payloadScratch, cancellationToken);
} }
catch (Exception ex) when (!cancellationToken.IsCancellationRequested && catch (Exception ex) when (!cancellationToken.IsCancellationRequested &&
ex is HttpRequestException or IOException or InvalidDataException ex is HttpRequestException or TimeoutException or IOException)
or InvalidOperationException or OperationCanceledException)
{ {
payloadSnapshot = RecoverInstalledRetroWfcPayload(toolkitFingerprint, payloadSnapshot = RecoverInstalledRetroWfcPayload(toolkitFingerprint,
Path.Combine(scratchRoot, "retro-wfc-payload-recovered"), ex, cancellationToken); Path.Combine(scratchRoot, "retro-wfc-payload-recovered"), ex, cancellationToken);
+3 -2
View File
@@ -128,9 +128,9 @@ cp -a "$workspace/Launcher/artifacts/portable-tools/toolchain-$appimagetool_arch
# Precompiled aurora + third-party package (see Prepare-NativePrebuilt.sh) so a user's own # Precompiled aurora + third-party package (see Prepare-NativePrebuilt.sh) so a user's own
# local-build.sh never has to compile aurora itself (~43% of local build CPU time). Re-harvesting # local-build.sh never has to compile aurora itself (~43% of local build CPU time). Re-harvesting
# recompiles the whole aurora/Crypto++ closure with the toolchain above, so this is skipped unless # recompiles the aurora/Crypto++/mbed TLS closure with the toolchain above, so this is skipped unless
# --print-fingerprint-only (a fast, build-free check) says the existing package no longer matches # --print-fingerprint-only (a fast, build-free check) says the existing package no longer matches
# the current compiler/flags/aurora/third_party sources. # the current compiler, flags, source trees or mbed TLS pin.
native_prebuilt_dir="$workspace/Launcher/artifacts/native-prebuilt-$appimagetool_arch" native_prebuilt_dir="$workspace/Launcher/artifacts/native-prebuilt-$appimagetool_arch"
echo "Checking whether the precompiled aurora + third-party package ($appimagetool_arch) is current..." echo "Checking whether the precompiled aurora + third-party package ($appimagetool_arch) is current..."
current_fingerprint=$(bash "$script_dir/Prepare-NativePrebuilt.sh" --arch "$appimagetool_arch" --print-fingerprint-only) current_fingerprint=$(bash "$script_dir/Prepare-NativePrebuilt.sh" --arch "$appimagetool_arch" --print-fingerprint-only)
@@ -148,6 +148,7 @@ fields = {
"flag_fingerprint": "FlagFingerprint", "flag_fingerprint": "FlagFingerprint",
"aurora_fingerprint": "AuroraSourceFingerprint", "aurora_fingerprint": "AuroraSourceFingerprint",
"third_party_fingerprint": "ThirdPartySourceFingerprint", "third_party_fingerprint": "ThirdPartySourceFingerprint",
"mbedtls_fingerprint": "MbedTlsFingerprint",
} }
print(1 if all(provenance.get(v) == current.get(k) for k, v in fields.items()) else 0) print(1 if all(provenance.get(v) == current.get(k) for k, v in fields.items()) else 0)
PY PY
+19 -5
View File
@@ -77,26 +77,40 @@ if [[ -n "$retro_dir" ]]; then
# verify its pinned signature before publishing it into the local cache. # verify its pinned signature before publishing it into the local cache.
retro_wfc_dir="$support_root/RetroWfcPayload" retro_wfc_dir="$support_root/RetroWfcPayload"
retro_wfc_payload="$retro_wfc_dir/binary/payload.RMCPD00.bin" retro_wfc_payload="$retro_wfc_dir/binary/payload.RMCPD00.bin"
if [[ -f "$retro_wfc_payload" ]] && ! "$translator" validate-retro-wfc-payload --directory "$retro_wfc_dir"; then cached_payload_valid=0
if [[ -f "$retro_wfc_payload" ]]; then
if "$translator" validate-retro-wfc-payload --directory "$retro_wfc_dir"; then
cached_payload_valid=1
else
printf 'Discarding an invalid cached Retro-WFC payload...\n' >&2 printf 'Discarding an invalid cached Retro-WFC payload...\n' >&2
rm -f "$retro_wfc_payload" rm -f "$retro_wfc_payload"
fi fi
if [[ ! -f "$retro_wfc_payload" ]]; then fi
printf 'Downloading the Retro-WFC payload needed for online play...\n'
# A signed cache may still be an older vulnerable revision, so always attempt to replace it
# with the current signed snapshot. A transport failure may fall back to the verified cache;
# a downloaded snapshot with an invalid signature remains a hard failure.
printf 'Downloading the current Retro-WFC payload needed for online play...\n'
mkdir -p "$retro_wfc_dir" mkdir -p "$retro_wfc_dir"
payload_stage=$(mktemp -d "$retro_wfc_dir/.payload-download.XXXXXX") payload_stage=$(mktemp -d "$retro_wfc_dir/.payload-download.XXXXXX")
temporary_payload="$payload_stage/binary/payload.RMCPD00.bin" temporary_payload="$payload_stage/binary/payload.RMCPD00.bin"
mkdir -p "$(dirname "$temporary_payload")" mkdir -p "$(dirname "$temporary_payload")"
trap 'rm -rf "$payload_stage"' EXIT trap 'rm -rf "$payload_stage"' EXIT
/usr/bin/curl --fail --silent --show-error --connect-timeout 10 --max-time 30 \ if /usr/bin/curl --fail --silent --show-error --connect-timeout 10 --max-time 30 \
--retry 1 --output "$temporary_payload" \ --retry 1 --output "$temporary_payload" \
'https://rwfc.net/api/wfc/payload?g=RMCPD00' || fail 'could not download the Retro-WFC payload needed for online play' 'https://rwfc.net/api/wfc/payload?g=RMCPD00'; then
"$translator" validate-retro-wfc-payload --directory "$payload_stage" || \ "$translator" validate-retro-wfc-payload --directory "$payload_stage" || \
fail 'downloaded Retro-WFC payload failed signature validation' fail 'downloaded Retro-WFC payload failed signature validation'
mkdir -p "$retro_wfc_dir/binary" mkdir -p "$retro_wfc_dir/binary"
mv "$temporary_payload" "$retro_wfc_payload" mv "$temporary_payload" "$retro_wfc_payload"
rmdir "$payload_stage/binary" "$payload_stage" rmdir "$payload_stage/binary" "$payload_stage"
trap - EXIT trap - EXIT
elif (( cached_payload_valid )); then
printf 'Could not download the current Retro-WFC payload; using the previously verified cached payload.\n' >&2
rm -rf "$payload_stage"
trap - EXIT
else
fail 'could not download the current Retro-WFC payload and no valid cached payload is available'
fi fi
build_args+=(--profile both --base-output-dir "$products" --retro-rewind-package-dir "$retro_dir" --retro-wfc-offline-dir "$retro_wfc_dir") build_args+=(--profile both --base-output-dir "$products" --retro-rewind-package-dir "$retro_dir" --retro-wfc-offline-dir "$retro_wfc_dir")
fi fi
+8 -9
View File
@@ -113,11 +113,10 @@ endif()
# compiles cleanly for Android with nothing beyond a plain C toolchain (no perl/asm build-script # compiles cleanly for Android with nothing beyond a plain C toolchain (no perl/asm build-script
# dependency the way OpenSSL's build has), matching how this project already prefers toolchain- # dependency the way OpenSSL's build has), matching how this project already prefers toolchain-
# simple libraries (see Crypto++ above, similarly stripped of ASM/SIMD for portability). # simple libraries (see Crypto++ above, similarly stripped of ASM/SIMD for portability).
# Fetched at build time from a pinned upstream release tarball with a checked SHA-256, the same way # The from-source build fetches a pinned upstream tarball with a checked SHA-256.
# aurora-main's own dependencies (SDL, zlib, etc.) are pulled in - not committed as a vendored # The Linux native prebuilt package instead ships its compiled archives and headers.
# source tree, so the repository ships the compiled dependency rather than ~280 tracked upstream # Bump both values in cmake/MbedTLSPin.cmake when updating; the hash comes from
# files. Bump MKW_MBEDTLS_VERSION/MKW_MBEDTLS_SHA256 together when updating; the hash comes from # upstream's signed `mbedtls-<version>-sha256sum.txt` release asset.
# upstream's own signed `mbedtls-<version>-sha256sum.txt` release asset.
# #
# The alias exists on every platform so the link lines in cmake/PublicProducts.cmake stay # The alias exists on every platform so the link lines in cmake/PublicProducts.cmake stay
# platform-independent, but it is only populated where network_ssl.cpp actually compiles the mbed # platform-independent, but it is only populated where network_ssl.cpp actually compiles the mbed
@@ -128,14 +127,13 @@ endif()
add_library(mkw_mbedtls INTERFACE) add_library(mkw_mbedtls INTERFACE)
add_library(mkw::mbedtls ALIAS mkw_mbedtls) add_library(mkw::mbedtls ALIAS mkw_mbedtls)
if(NOT MKW_PLATFORM_WINDOWS) if(NOT MKW_PLATFORM_WINDOWS)
include("${CMAKE_CURRENT_LIST_DIR}/cmake/MbedTLSPin.cmake")
if(NOT MKW_NATIVE_PREBUILT_DIR)
include(FetchContent) include(FetchContent)
set(MKW_MBEDTLS_VERSION "3.6.7")
set(MKW_MBEDTLS_SHA256 "a7e8bcbec0e6f761b4af24f25677626b35f762f68eef79c08677a363212d11f6")
FetchContent_Declare(mkw_mbedtls_upstream FetchContent_Declare(mkw_mbedtls_upstream
URL "https://github.com/Mbed-TLS/mbedtls/releases/download/mbedtls-${MKW_MBEDTLS_VERSION}/mbedtls-${MKW_MBEDTLS_VERSION}.tar.bz2" URL "https://github.com/Mbed-TLS/mbedtls/releases/download/mbedtls-${MKW_MBEDTLS_VERSION}/mbedtls-${MKW_MBEDTLS_VERSION}.tar.bz2"
URL_HASH SHA256=${MKW_MBEDTLS_SHA256}) URL_HASH SHA256=${MKW_MBEDTLS_SHA256})
# Subproject mode already defaults ENABLE_TESTING off and skips codegen (GEN_FILES), but # Subproject mode already disables testing and codegen; it still enables programs.
# ENABLE_PROGRAMS defaults on and installation/package-config isn't wanted for a linked-in copy.
set(ENABLE_PROGRAMS OFF CACHE BOOL "" FORCE) set(ENABLE_PROGRAMS OFF CACHE BOOL "" FORCE)
set(ENABLE_TESTING OFF CACHE BOOL "" FORCE) set(ENABLE_TESTING OFF CACHE BOOL "" FORCE)
set(MBEDTLS_FATAL_WARNINGS OFF CACHE BOOL "" FORCE) set(MBEDTLS_FATAL_WARNINGS OFF CACHE BOOL "" FORCE)
@@ -143,6 +141,7 @@ if(NOT MKW_PLATFORM_WINDOWS)
FetchContent_MakeAvailable(mkw_mbedtls_upstream) FetchContent_MakeAvailable(mkw_mbedtls_upstream)
target_link_libraries(mkw_mbedtls INTERFACE MbedTLS::mbedtls MbedTLS::mbedx509 MbedTLS::mbedcrypto) target_link_libraries(mkw_mbedtls INTERFACE MbedTLS::mbedtls MbedTLS::mbedx509 MbedTLS::mbedcrypto)
endif() endif()
endif()
set(MKW_TRANSLATED_COMPILE_JOBS 0 CACHE STRING set(MKW_TRANSLATED_COMPILE_JOBS 0 CACHE STRING
"Cap on concurrently compiling translated shard TUs via a Ninja job pool (0 = uncapped). \ "Cap on concurrently compiling translated shard TUs via a Ninja job pool (0 = uncapped). \
+4
View File
@@ -0,0 +1,4 @@
# Keep the release and verified archive hash together. The Linux native prebuilt
# fingerprint includes this file, so changing either value forces a new harvest.
set(MKW_MBEDTLS_VERSION "3.6.7")
set(MKW_MBEDTLS_SHA256 "a7e8bcbec0e6f761b4af24f25677626b35f762f68eef79c08677a363212d11f6")
+22
View File
@@ -42,6 +42,28 @@ endfunction()
mkw_np_resolve(_mkw_np_includes ${MKW_NP_INCLUDE_DIRECTORIES}) mkw_np_resolve(_mkw_np_includes ${MKW_NP_INCLUDE_DIRECTORIES})
mkw_np_resolve(_mkw_np_links ${MKW_NP_LINK_LIBRARIES}) mkw_np_resolve(_mkw_np_links ${MKW_NP_LINK_LIBRARIES})
mkw_np_resolve(_mkw_np_dawn_config ${MKW_NP_DAWN_CONFIG_DIR}) mkw_np_resolve(_mkw_np_dawn_config ${MKW_NP_DAWN_CONFIG_DIR})
if(NOT MKW_PLATFORM_WINDOWS)
if(NOT MKW_NP_MBEDTLS_LIBRARIES OR NOT MKW_NP_MBEDTLS_INCLUDE_DIR)
message(FATAL_ERROR
"The Linux native prebuilt package has no Mbed TLS archives; regenerate it with Prepare-NativePrebuilt.sh")
endif()
file(SHA256 "${CMAKE_CURRENT_LIST_DIR}/MbedTLSPin.cmake" _mkw_np_current_mbedtls_fingerprint)
if(NOT MKW_NP_MBEDTLS_FINGERPRINT STREQUAL _mkw_np_current_mbedtls_fingerprint)
message(FATAL_ERROR "The native prebuilt Mbed TLS version differs from this workspace; regenerate the package")
endif()
mkw_np_resolve(_mkw_np_mbedtls_links ${MKW_NP_MBEDTLS_LIBRARIES})
mkw_np_resolve(_mkw_np_mbedtls_include ${MKW_NP_MBEDTLS_INCLUDE_DIR})
foreach(_archive IN LISTS _mkw_np_mbedtls_links)
if(NOT EXISTS "${_archive}")
message(FATAL_ERROR "The native prebuilt package is missing Mbed TLS archive: ${_archive}")
endif()
endforeach()
if(NOT IS_DIRECTORY "${_mkw_np_mbedtls_include}")
message(FATAL_ERROR "The native prebuilt package is missing Mbed TLS headers: ${_mkw_np_mbedtls_include}")
endif()
target_include_directories(mkw_mbedtls SYSTEM INTERFACE "${_mkw_np_mbedtls_include}")
target_link_libraries(mkw_mbedtls INTERFACE ${_mkw_np_mbedtls_links})
endif()
foreach(_dir IN LISTS _mkw_np_includes) foreach(_dir IN LISTS _mkw_np_includes)
if(NOT IS_DIRECTORY "${_dir}") if(NOT IS_DIRECTORY "${_dir}")
+14
View File
@@ -77,6 +77,9 @@ target_compile_features(mkw_np_probe PRIVATE cxx_std_20)
target_link_libraries(mkw_np_probe PRIVATE target_link_libraries(mkw_np_probe PRIVATE
aurora::gx aurora::pad aurora::si aurora::vi aurora::mtx aurora::gx aurora::pad aurora::si aurora::vi aurora::mtx
mkw::cryptopp) mkw::cryptopp)
if(NOT MKW_PLATFORM_WINDOWS)
target_link_libraries(mkw_np_probe PRIVATE mkw::mbedtls)
endif()
get_filename_component(_mkw_np_aurora_dir "${MKW_AURORA_DIR}" ABSOLUTE) get_filename_component(_mkw_np_aurora_dir "${MKW_AURORA_DIR}" ABSOLUTE)
mkw_collect_buildsystem_targets("${_mkw_np_aurora_dir}" _mkw_np_all_targets) mkw_collect_buildsystem_targets("${_mkw_np_aurora_dir}" _mkw_np_all_targets)
@@ -84,6 +87,16 @@ mkw_collect_buildsystem_targets("${_mkw_np_aurora_dir}" _mkw_np_all_targets)
# the scan above cannot see it; it is appended explicitly. The type and closure # the scan above cannot see it; it is appended explicitly. The type and closure
# checks below still apply to it. # checks below still apply to it.
list(APPEND _mkw_np_all_targets "mkw_cryptopp") list(APPEND _mkw_np_all_targets "mkw_cryptopp")
if(NOT MKW_PLATFORM_WINDOWS)
list(APPEND _mkw_np_all_targets mbedtls mbedx509 mbedcrypto)
# Keep the TLS archives separate from aurora's aggregate link interface.
string(CONCAT _mkw_np_mbedtls_lines
"mbedtls|$<TARGET_LINKER_FILE:MbedTLS::mbedtls>\n"
"mbedx509|$<TARGET_LINKER_FILE:MbedTLS::mbedx509>\n"
"mbedcrypto|$<TARGET_LINKER_FILE:MbedTLS::mbedcrypto>\n")
file(GENERATE OUTPUT "${MKW_NATIVE_PREBUILT_EXPORT_DIR}/mbedtls.txt"
CONTENT "${_mkw_np_mbedtls_lines}")
endif()
if(NOT _mkw_np_all_targets) if(NOT _mkw_np_all_targets)
message(FATAL_ERROR "No buildsystem targets were found under ${_mkw_np_aurora_dir}") message(FATAL_ERROR "No buildsystem targets were found under ${_mkw_np_aurora_dir}")
endif() endif()
@@ -136,6 +149,7 @@ string(REPLACE ";" "," _mkw_np_lib_targets_csv "${_mkw_np_lib_targets}")
file(WRITE "${MKW_NATIVE_PREBUILT_EXPORT_DIR}/meta.txt" file(WRITE "${MKW_NATIVE_PREBUILT_EXPORT_DIR}/meta.txt"
"aurora_dir=${_mkw_np_aurora_dir}\n" "aurora_dir=${_mkw_np_aurora_dir}\n"
"runtime_dir=${CMAKE_CURRENT_SOURCE_DIR}\n" "runtime_dir=${CMAKE_CURRENT_SOURCE_DIR}\n"
"mbedtls_source_dir=${mkw_mbedtls_upstream_SOURCE_DIR}\n"
"binary_dir=${CMAKE_BINARY_DIR}\n" "binary_dir=${CMAKE_BINARY_DIR}\n"
"dawn_config_dir=${_mkw_np_dawn_config_dir}\n" "dawn_config_dir=${_mkw_np_dawn_config_dir}\n"
"dawn_prebuilt_source_dir=${dawn_prebuilt_SOURCE_DIR}\n" "dawn_prebuilt_source_dir=${dawn_prebuilt_SOURCE_DIR}\n"
+2 -2
View File
@@ -294,7 +294,7 @@ inline double PpcLoadPairPsqFloatFastInline(uint32_t addr)
return PpcLoadPairPsqFloatFromHostInline(host); return PpcLoadPairPsqFloatFromHostInline(host);
} }
return PpcBitCastToDoubleInline( return PpcBitCastToDoubleInline(
PpcLoadPairPsqFloatBitsPackedInline(MemoryInline::Read64Slow(addr))); PpcLoadPairPsqFloatBitsPackedInline(Memory::Read64(addr)));
} }
inline double PpcLoadSinglePsqFloatFastInline(uint32_t addr) inline double PpcLoadSinglePsqFloatFastInline(uint32_t addr)
@@ -349,7 +349,7 @@ inline void PpcStorePairPsqFloatFastInline(uint32_t addr, double value)
PpcStorePairPsqFloatToHostInline(host, value); PpcStorePairPsqFloatToHostInline(host, value);
return; return;
} }
MemoryInline::Write64Slow( Memory::Write64(
addr, PpcStorePairPsqFloatBitsPackedInline(PpcBitCastToU64Inline(value))); addr, PpcStorePairPsqFloatBitsPackedInline(PpcBitCastToU64Inline(value)));
} }
+3 -2
View File
@@ -132,8 +132,9 @@ using CryptoEcdsa = CryptoPP::ECDSA<CryptoPP::EC2N, CryptoPP::SHA1>;
inline CryptoEcdsa::PrivateKey MakePrivateKey(const uint8_t* key) { inline CryptoEcdsa::PrivateKey MakePrivateKey(const uint8_t* key) {
CryptoPP::DL_GroupParameters_EC<CryptoPP::EC2N> parameters(CryptoPP::ASN1::sect233r1()); CryptoPP::DL_GroupParameters_EC<CryptoPP::EC2N> parameters(CryptoPP::ASN1::sect233r1());
const CryptoPP::Integer exponent(key, 30); // Wii keys need not be canonical scalars; reduction preserves their public key.
if (exponent <= CryptoPP::Integer::Zero() || exponent >= parameters.GetSubgroupOrder()) { const CryptoPP::Integer exponent = CryptoPP::Integer(key, 30) % parameters.GetSubgroupOrder();
if (exponent == CryptoPP::Integer::Zero()) {
throw std::invalid_argument("Wii ES private key is outside the sect233r1 subgroup"); throw std::invalid_argument("Wii ES private key is outside the sect233r1 subgroup");
} }