# Firmware 9.60 capability-probe offline evidence Date: 2026-07-17. No PS5 connection, transfer, deployment, or execution was performed. ## Artifact identity | Field | Value | |---|---| | Artifact | `chimera-gfx-capability-probe-0.1.0-fw-9.60-offline-audit-only.elf` | | Size | 110424 bytes | | SHA-256 | `4be1c17b4964f2b68c39b5145bc4af4619c32512d60269ecf5c39728b390fa63` | | Source commit | `ba8f6a40cf37dff628254caa9b11d83a73957cf8` | | SDK | PS5 Payload SDK v0.41, commit `d2e2e585740362976a39fdd5ccf390f199a7bc37` | | Build type | Release, C11, warnings as errors | | Phase-1 VideoOut | explicitly `OFF`; target not built or linked | | Transfer / execution | false / false | | Execution eligibility | **false** | Two clean builds around an audit-tool-only commit produced the same size and SHA-256. The tracked manifest is `manifests/artifacts/chimera-gfx-capability-probe-0.1.0-fw-9.60.json`. ## Firmware gate The checked-in discovery allowlist is exactly `["9.60"]`; CMake still defaults to `NONE`. Configure rejects `9.61`. The Phase-1 target rejects `9.60` and every other non-`NONE` value. The ELF embeds `9.60` and requires exactly these application arguments: ```text --firmware 9.60 --acknowledge-read-only-probe ``` Disassembly places `chimera_gfx_firmware_gate_allows` at `main+0x7f`, before `chimera_gfx_ps5_make_loader_ops` at `main+0xa5` and the probe call at `main+0xb2`. This is only a comparison against an operator-supplied string; it does not independently attest the console firmware. SDK startup occurs before `main` and therefore before this gate. ## Complete dynamic import inventory Undefined symbols (`prospero-nm -u`), exact set: - `__stderrp` - `__stdoutp` - `fprintf` - `fwrite` - `snprintf` - `strcmp` `DT_NEEDED` modules (`llvm-readelf-18 --dynamic-table`), exact set: - `libkernel_web.sprx` - `libSceLibcInternal.sprx` - `libSceNet.sprx` There are zero direct `sce*`, GNM, VideoOut, SDL, draw, dispatch, submit, or flip imports. `libSceVideoOut.sprx` text is present only because the SDK rtld statically includes a general sysmodule-name table; there is no corresponding import or call. `INIT_ARRAYSZ` and `FINI_ARRAYSZ` are both zero. ## Project-requested functions Before the firmware gate, project `main` uses only argument checks, `strcmp`, and a refusal log on error. After the gate, the complete project path is: 1. `chimera_gfx_ps5_make_loader_ops`; 2. `chimera_gfx_ps5_probe_symbols`; 3. internal `log_line`/`write_log` callbacks for boolean JSON events; 4. loader callback `open_module`, which calls `dlopen("libSceGnmDriver.sprx", RTLD_LAZY | RTLD_LOCAL)`; 5. loader callback `resolve_symbol` 21 times; it calls `dlerror`, `dlsym`, then `dlerror`; every returned address is reduced to a boolean and discarded; 6. `snprintf` plus `fprintf`/compiler-selected `fwrite` for boolean JSON lines; 7. loader callback `close_module`, which calls `dlclose`; 8. `chimera_gfx_status_string` and a final summary log. No resolved GNM pointer is cast to a callable type or invoked. The 21 exact names are machine-checked against `manifests/ps5_gnm_symbols.json`. ## SDK startup and loader side effects Pinned-source review plus disassembly proves this pre-`main` success path: 1. `_start` clears payload BSS. 2. `__crt_syscall_init`, `__kernel_init`, and `__klog_init` initialize SDK state from loader-supplied arguments. 3. libc `__isthreaded` is set to one. 4. `__patch_init` reads current process credentials, calls `kernel_set_ucred_caps` and `kernel_set_ucred_attrs`, and performs two `kernel_copyin` writes that change the process syscall-address bounds. 5. `__rtld_init` initializes SPRX/SO/payload/dlfcn support and may call `sceKernelLoadStartModule` for `libSceSysmodule.sprx` if it is absent. 6. payload dependencies are opened and relocations modify payload memory; payload init/fini arrays themselves are empty. After the project gate, SDK `dlopen` first checks loaded modules through SDK kernel reads. If GNM is absent it can call `sceKernelLoadStartModule`. It then uses `kernel_copyout` to copy module metadata, symbol tables, and string tables into allocated user memory. The pinned SPRX-specific `init` callback is empty, but the internal behavior of the system load/start call is unknown. These facts mean the ELF is non-rendering at project level but is not globally non-mutating. The pre-`main` kernel writes violate the project's userland-only execution boundary. ## Cleanup audit The bounded project loop attempts `dlclose` after all lookups and on lookup or format failures. SDK `dlclose` calls rtld fini, close, and destroy. The pinned SPRX `fini` callback is empty. If this open loaded the module, `sprx_close` calls `sceKernelStopUnloadModule`, then frees copied tables and clears local state. Cleanup is not guaranteed: - there is no documented cancellation or bounded timeout around loader calls; - a crash or hang can bypass `dlclose`; - a stop/unload failure can leave the module loaded while SDK bookkeeping is destroyed; - the CRT's credential/syscall-permission changes have no matching restoration path in the pinned source; - a `libSceSysmodule.sprx` load during rtld initialization has no observed matching unload in this call chain. ## Offline verification results - Windows MSVC Debug: 11/11 tests passed. - WSL Clang 18 with clang-tidy and formatting: 12/12 tests passed. - Strict artifact audit: six exact undefined symbols, three exact `DT_NEEDED` modules, empty init/fini arrays, all 21 manifest names, zero direct Sce/GNM imports. - SDK runtime source audit: passed and concluded execution eligibility false. - Negative configure tests: firmware `9.61` rejected; Phase-1 with `9.60` rejected. - Artifact-manifest digest/size verification: passed. - Secret scan and `git diff --check`: passed. ## Remaining blockers The exact system-module initialization effects, runtime argument delivery, firmware attestation, loader timeout behavior, and partial-failure recovery are unproven. More decisively, the SDK v0.41 CRT performs prohibited kernel writes before the project firmware gate. This exact artifact must not be transferred or executed.