Updated settings for current dumps:
- load
ROM1.BIN on [DIGIC 2...6], or
ROM0.BIN on [DIGIC 7]
- [DIGIC 2...5] select ARM processor, architecture ARMv5TEJ (we have ARMv5TE on all models from DIGIC 2 to DIGIC 5)
- [DIGIC 6...7] select ARM processsor, architecture ARMv7 A&R (most likely Cortex
R4 on D6 and
A9 on D7)
- uncheck 'Delete instructions with no xrefs' (we have plenty of those)
- uncheck 'Perform no-return analysis' (IDA usually gets it wrong)
- RAM section: 0, size 0x100000 (we can always add more later)
- ROM1 start address: 0xFF800000 for 8MB dumps, 0xFF000000 for 16MB dumps, 0xFE000000 for 32MB dumps, ROMBASEADDR for old non-fullsize dumps
- ROM0 start address: 0xE0000000 on [DIGIC 7], 0xF0000000 on [DIGIC 2..5] (data only)
- ROM1 size: 0x7FFFFC or 0xFFFFFC or 0x1FFFFFC (off-by-one bug in IDA; I have an older version, so YMMV)
- ROM0 size: actual file size
- File load address / size: same as ROM.
- [DIGIC 2...5] go to FFFF0000 and press C (that's the bootloader)
- [DIGIC 2...5] go to ROMBASEADDR (usually FF810000 or FF010000 or FF0C0000) and press C (that's the main firmware)
- [DIGIC 6] [optional, may slow down IDA]: Load Additional Binary, ROM1.BIN, loading segment 0, offset FC000000, num. bytes 0x1FFFFFC (only if your IDA has the off-by-one bug)
- [DIGIC 6] go to FC000000 or FE000000 to find the start address (32-bit); go there and press C (that's the bootloader)
- [DIGIC 6] go to ROMBASEADDR (usually FE0A0000) and press C (that's the main firmware)
- [DIGIC 7] go to E0000000 and press C (that's the bootloader)
- [DIGIC 7] go to E0040000, set the Thumb bit (ALT+G, T=1) and press C (that's the main firmware)
- [DIGIC 7] first instruction configures the reset vector (VBAR); interrupts are executed in Thumb mode
After loading the ROM, you will most likely need to load additional blobs, copied by Canon firmware from ROM into RAM and executed from there. You can find these by running the ROM in QEMU with "-d romcpy" (or just look them up
in the QEMU test suite log).
./run_canon_fw.sh 60D,firmware="boot=0" -d romcpy
[ROMCPY] 0xFFFF0000 -> 0x0 size 0x40 at 0xFFFF05FC
[ROMCPY] 0xFFFF2A3C -> 0x100000 size 0xD1A8 at 0xFFFF12EC
[ROMCPY] 0xFF66A010 -> 0x1900 size 0x34B24 at 0xFF01000C
[ROMCPY] 0xFF0101E4 -> 0x4B0 size 0x214 at 0xFF010150
dd if=ROM1.BIN of=60D.0x4B0.bin bs=1 skip=$((0x101E4)) count=$((0x214))
Then, run the firmware in QEMU to get an initial IDC script with all the functions called during emulation:
./run_canon_fw.sh 60D,firmware="boot=0" -d idc
...
60D.idc saved.
Getting around:
- find out where the bootloader code jumps to main firmware
- follow the startup code in main firmware until you find "cstart" (it calls bzero32, then passes init_task as parameter to create_init_task)
- look up something that resembles a debug message, passed as third argument (in R2) to a function called thousands of times (that's DebugMsg)
- look up something that resembles a task name (e.g. GuiMainTask, CSMgrTask) and find task_create
- look up AllocateMemory (usually prints NG AllocateMemory and calls GetMemoryInformation on failure)
- look up the "Illegal inter" string and find out who calls it (you'll find the interrupt handler; there's one for each DryOS core in the firmware)
- look up some more functions with the
Finding Stubs tutorial.
You should now have the basics to start browsing around. Have fun!