Files
vphone-cli/VPhoneKit
LakrandClaude Opus 5 a3d2382e2e Re-patch the firmware originals, so fw patch can be run again
The pipeline patched each boot-chain component in place: load the file,
run the patchers, save over the same path. A second run therefore handed
the patchers the first run's output, they found none of the shapes they
had already replaced, and the component died with `Patch site not found:
iBSS`. `fw prepare` refuses to re-extract over an existing restore tree,
so there was no way back either — a VM could be patched exactly once, for
its whole life, and turning a patch off in its PatchSelection.plist could
not change anything on disk.

The first run now copies each component into <vm>/FirmwareOriginals/,
mirroring its path, before anything is written, and every later run
patches those bytes. The shipped container also goes back immediately
before `loader.save`, because ContainerFirmwareLoader repackages whatever
IM4P it finds at the destination and would otherwise wrap the second
run's payload in the first run's container. Same VM and same plan now
produce the same file however many times fw patch runs.

A plan that selects nothing for a component — every patch blocked, or the
whole set dropped so no patcher is built — restores the unpatched image
instead of leaving the last run's patches stranded with nothing selecting
them. A component nobody ever patched is not rewritten, so it keeps the
modification date the restore gave it.

Filesystem and Manifest opt out. Both name BuildManifest.plist, but
neither is a patcher over that one file: one rewrites cryptex images
across the restore tree, the other rewrites hashes describing files other
steps produced, so putting the manifest back alone would describe a tree
that no longer exists. `.less` is excluded outright, so a `.less` run over
a patched VM cannot read "this variant builds no boot-chain patchers" as
"put the boot chain back".

A VM patched by an older build has no originals, so the first run would
otherwise adopt its already-patched bytes as pristine. If the component
then fails to patch, the copy is deleted and the error says to remove the
restore tree and run fw prepare again. fw prepare also deletes a stash
left over from previous firmware — AVPBooter's file name carries no
version, so a stale copy would be silently reused — and a slim export
leaves the originals out along with the restore tree they describe.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-30 17:58:06 +09:00
..