Not exactly "ML style", yet heavily inspired by ML and chdk (big thanks especially to reyalp, kitor and names_are_hard!), here a rather unpolished, highly experimental proof-of-concept that works around the PushAF bug of Canon XF605 stock firmware:
https://chdk.setepontos.com/index.php?action=dlattach;topic=14803.0;attach=1811120230915_workaround_pushaf_bug.zip.asc
-----BEGIN PGP SIGNATURE-----
iHUEABYIAB0WIQTuqjGte1kC77493zByb9iJKwGigAUCZQTGyQAKCRByb9iJKwGi
gPz8AP9EFSsDRlV0WWxZVNnKd9E8/H2i6mOFK+rzRIAbYyvV2AEAuZY5sCANCLtq
dleLZ7A5Nr0v6l09fAGsKIK8cue7FgE=
=taaw
-----END PGP SIGNATURE-----
This version supports the following XF605 firmware versions:
FW "real version" displayed as
100390 1.0.0(3.9.0) 1.0.0.1
100392 1.0.0(3.9.2) 1.0.0.1
101416 1.0.0(4.1.6) 1.0.1.1
CompileE.g., to compile for the oldest supported firmware version, use:
make FW=100390
The "clean" target can be run with
any valid firmware version, e.g.:
make clean FW=100390
How does it work?The Makefile compiles two binaries: resident.bin and afterwards autoexec.bin, which contains resident.bin as binary blob.
When a XF605 with BOOTFLAG enabled is switched on, the first-stage bootloader checks both SD-card slots whether an SD-card is present and whether it is marked bootable. If that is the case, it assumes that autoexec.bin exists on it and loads its content into memory (at 0x00800000) and jumps there (assuming valid thumb code).
autoexec.bin is created from start_autoexec.S, autoexec.c, crc32.c and the corresponding stubs_*.S file.
start_autoexec.S places a single jump instruction in the .init section which is designated to comprise the very beginning of autoexec.bin. Furthermore, it stores resident.bin as binary blob alongside its length and some easy-to-spot marker.
autoexec.c contains the code being jumped to from start_autoexec.S and is entered in our_main. It checks for a compatible first-stage bootloader, second-stage bootloader and ICU firmware version by calculating and comparing the CRC32 of the respective flash memory region. If possible, commenting debug strings are output to the serial console using first-stage bootloader functions.
It copies the resident.bin blob to a lower RAM address, choosen such that the binary blob ends close to the address that marks the end of what appears to be the heap used by the original firmware.
It appends a copy of the position-independent code that comprises the original second-stage bootloader. The second-stage bootloader copy gets patched to return to the resident.bin copy instead of directly advancing into the code it copies into RAM.
Finally the patched second-stage bootloader copy gets executed and finally jumps to resident.bin.
resident.bin is created from start_resident.S, resident.c and the corresponding stubs_*.S file.
start_resident.S places a single jump instruction in the .init section which is designated to comprise the very beginning of resident.bin. Furthermore, it defines a label called _posts_to_swhack_msgq_hook which marks a "function" carefully written in assembler.
resident.c contains the code being jumped to from start_resident.S and is entered in on_return_from_canon. It patches the code that the second-stage bootloader copied from flash to RAM: The heap size is being reduced such that the carefully placed resident.bin copy is never overwritten by the original firmware. Furthermore, it hooks into a button-handling function of the original firmware and redirects the control flow to the "function" carefully written in assembler. It does so by moving eight bytes from the target function containing only position-independent instructions into placeholders within the destination function and overwriting the source with a jump there. The destination function essentially adds a call to a C function in resident.c containing logic to work around the PushAF bug.
The workaround consists in overriding AF_mode while PushAF is being pressed if AF-boosted MF would be in action otherwise.