- Upload errors were silently cleared by refresh() before the alert
could fire; fix by setting self.error after refresh()
- Unreadable local files were skipped silently; now surfaces an error
- Upload loop continued past failures unlike downloads; now breaks early
- Drag-and-drop with no resolvable URLs was silent; now shows an error
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Introduce a kernel debug port option and wire it through the CLI and VM configuration. Adds a --kernelDebugPort CLI option (default 5909), a kernelDebugPort field in VPhoneVirtualMachine.Options, and validation (1..65535) that throws VPhoneError.invalidKernelDebugPort on invalid values. Configure the VM to use a fixed host GDB debug stub port when possible (with system-assigned fallback) and print the chosen stub info from the AppDelegate. Also include a small menu styling tweak (comma-style) in VPhoneMenuBattery.
Add ramdisk-specific kernel snapshot and build logic so the installer ramdisk can boot with a conservative kernel while the restore target keeps the fully JB-patched kernel. Changes:
- research/patch_comparison_all_variants.md: document the Ramdisk Kernel Split and intent.
- scripts/fw_patch_jb.py: snapshot the base/dev-patched kernel before applying JB extensions (new helper and constants).
- scripts/ramdisk_build.py: build krnl.ramdisk.img4 from the snapshot and krnl.img4 from the restore kernel when a snapshot exists; factor kernel IMG4 creation into build_kernel_img4.
- scripts/ramdisk_send.sh: prefer krnl.ramdisk.img4 when present, falling back to krnl.img4; fail early if no kernel image found.
This improves /dev/disk1s1 remount reliability during CFW/install by keeping the restore kernel JB-patched but booting the installer ramdisk with a more conservative kernel variant.
Use _VZMacSyntheticBatterySource to inject a virtual power source into the
guest VM. The guest kernel's AppleVirtualPlatformPowerSource driver picks it
up automatically via VirtIO, giving iOS a real battery indicator without any
guest-side changes.
- Default: 100% charge, charging state
- Runtime-adjustable via setBattery(charge:connectivity:)
- Battery menu in menu bar with level presets and charging toggle
Ensure target mountpoint exists and verify mounts succeed in remote_mount across cfw_install scripts: create the directory with mkdir -p, short-circuit if already mounted, attempt mount_apfs, and fail with a clear error if the mount did not occur. Also replace the grep|head pipeline with an awk extraction to safely pick the first com.apple.os.update snapshot when renaming to orig-fs.
These were used for per-patch kernel JB debugging (C23 bisect,
single-patch boot test, batch testing). No longer needed now that
A2, C23, and C24 are all boot-tested and fixed.
Three bugs caused NOT_BOOT (timeout):
1. Wrong sysent table base: first _nosys match is entry 428, not entry 0.
Entry 0 is the indirect syscall handler. Fixed with backward scan.
2. Raw VA written to chained fixup pointer slot: struct.pack("<Q", cave_va)
corrupts the fixup chain from sysent[439] onward. Fixed with proper
auth rebase encoding (_encode_chained_auth_ptr).
3. Missing PAC parameters: dispatch uses BLRAA X8, X17 with X17=0xBCAD.
Chained fixup must encode diversity=0xBCAD, key=IA, addrDiv=0.
Chain 'next' field preserved from original entry.
Boot-tested OK via testing ramdisk.
Root cause: find_string("vnode_getattr") matched "%s: vnode_getattr: %d"
format string inside an AppleImage4 function. The old code then took that
function as vnode_getattr itself, causing BL to call into AppleImage4 with
wrong arguments → PAC failure on indirect branch at a2+48.
Fix: _find_vnode_getattr_via_string() now scans backward from the string
ref for a BL instruction and extracts its target — the real vnode_getattr
(sub_FFFFFE0007CCD1B4 at foff 0xCC91B4).
Bisection confirmed: variants A (stack frame) and B (+ tpidr_el1) boot OK,
variant C (+ BL vnode_getattr) panics with old resolution, boots OK with fix.
Boot-tested: full C23 patch with corrected vnode_getattr — BOOTS OK.
Ops table pointer modification breaks chained fixup integrity in the
fileset kernelcache, causing PAC failures in unrelated kexts (e.g.,
AppleImage4). The fixup diversity (0xEC79) also doesn't match the
dispatch discriminator.
New approach: replace PACIBSP at hook function entry with B cave.
Cave runs relocated PACIBSP, ownership propagation shellcode, then
B hook+4 to resume. Uses only PC-relative branches — no PAC, no
chained fixup modification. Also fixes branch offsets in shellcode
to ensure all registers are properly restored in error/skip paths.
Root cause: backward branch search found PAC validation B.EQ (target fell
within error region range) instead of the kernel_map guard B.NE. New approach
walks backward from panic string ADRP to find CMP+B.cond where the branch
goes forward past the panic, then makes it unconditional. Also enables B6
and B8 in find_all(). Boot-tested: PASS.
Old approach patched vnode-type assertion BLs (CBZ→panic). New approach
scans backward from function end for the shared MOV W0,#1 kill return
before the LDP x29,x30 epilogue and changes it to MOV W0,#0. Single
instruction converts all 5+ kill paths to success. Boot-tested OK.
Root cause: "most-called BL target" heuristic in _proc_info picked copyio
(4 calls, 0x28C bytes) over the real _proc_security_policy (2 calls,
0x134 bytes). Lowered size filter threshold from 0x300 to 0x200 to
correctly exclude utility functions like copyio. Boot-tested: PASS.
Old approach patched vnode-type assertion BLs (CBZ→panic). New approach
scans backward from function end for the shared MOV W0,#1 kill return
before the LDP x29,x30 epilogue and changes it to MOV W0,#0. Single
instruction converts all 5+ kill paths to success. Boot-tested OK.
Root cause: "most-called BL target" heuristic in _proc_info picked copyio
(4 calls, 0x28C bytes) over the real _proc_security_policy (2 calls,
0x134 bytes). Lowered size filter threshold from 0x300 to 0x200 to
correctly exclude utility functions like copyio. Boot-tested: PASS.