Adding support for new firmware version of an existing port
Adding support for new canon firmware versions of an existing port - posted 22-Aug-2009 by reyalP 
"I thought I'd post how I did the SX1 and SD990. This is not necessarily the best or most efficient way, it's just how I did it."
Create the platform/<camera>/sub/<firmware>/* for your new canon firmware.
- A working CHDK source tree and build environment
- IDA with ARM support. Not strictly required, but assumed in the instructions below.
- A working knowledge of C and assembler
- firmware dump (PRIMARY.BIN) files for an existing, working port of the same camera, and the new version you are trying to support. These should be loaded into IDA with the appropriate FLIRT sigs applied and IDC scripts run.
- Copy the most closely related (i.e. numerically closest version) sub to a sub named for your new firmware. (e.g. 200h -> 201a)
- Build the new sub, with the PRIMARY.BIN in place. This will obviously not be a working port, you just want to generate stubs_entry.S
- Diff the newly generated stubs_entry.S and the one for the already supported firmware.
- In the diff, find the numerically lowest address that has changed, and the numerically highest address that has not changed. Write them down. If lots of addresses have changed, you may not want to use this technique. After this point, I assume relatively few, high valued addresses have changed. You can also note the difference between the old and new addresses. This will help you sanity check later on. In the firmwares I've done, there is say 64 bytes added somewhere in the firmware, and everything else is just shifted down by that amount. That means if you are looking for a function that is at X in the old firmware, you can start by jumping to X+64 in the new one, and chances are it will be there.
- Now you are ready to start updating files. I suggest keeping notes of which files you changed and what you did.
- Open the PRIMARY.BIN for your new firmware in IDA, and go to the start of the firmware, and find the two loops that copy the canon initialized DATA and BSS (these are the first two loops in the firmware, with data preceding BSS), it looks something like this:
LDR R0, =unk_FFB74B98 ; canon initialized data source LDR R1, =0x1900 ; canon initialized data destination LDR R3, =0xFE80 ; canon initialized data end loc_FF81013C CMP R1, R3 ; while p != end LDRCC R2, [R0],#4 ; *p++ = *src++ STRCC R2, [R1],#4 BCC loc_FF81013C ; end while LDR R1, =0xE8B40 ; bss end MOV R2, #0 loc_FF810154 CMP R3, R1 ; while p != end STRCC R2, [R3],#4 ; *p=0 BCC loc_FF810154 ; end while
- Open boot.c, find boot(), and compare the values there with the loops in the firmware dump. Update the code corresponding to the loops above. The start of initialized data has probably moved. If the sizes of the data and BSS have not changed, it's a good indication that the addresses of variables used by CHDK have not changed.
- Now scan through the assembler in boot.c, and the corresponding code in IDA. You don't really have to really examine every line, you are mostly looking for calls to functions that have an address higher than highest unchanged address noted above. If you find one, compare it with what's in IDA, and update as needed. Also keep an eye out for variables that might have moved.
- Follow the same procedure for the capt_seq.c and movie_rec.c
- If one of the functions you have to update is has moved, you probably want to copy the assembler from scratch rather than trying to correct it.
- lib.c: If no variables have moved, you probably don't have to do anything here. You can sanity check by searching for the constants in both dumps, and making sure they are referenced by identical code (use "search for a sequence of bytes"). Hardware addresses are unlikely to have changed.
- stubs_min.S: pretty much the same as lib.c, except FlashParamsTable which will probably have moved by the same amount as the canon data.
- stubs_entry_2.S: Scan through for addresses that are higher than highest unchanged address, and correct as needed.
- makefile.inc: MEMISOSTART will need updating if the size of canon DATA + BSS has changed.
- That's it, you are done. Build it (from scratch with clean !) and find someone to try it it out...
- OK, you weren't actually quite done yet. Assuming it works, update the toplevel makefile to include your new sub, and commit or submit a patch.
"Note that some of the assumptions above (like variables not moving) are just educated guesses. Canon could have changed the order of variables or functions but had them come out the same size."