I suggest you look at my initial project for the 5dc:
www.bitbucket.org/coutts/5dplusEverything starts in entry.S. First use a dumper tool to extract the firmware image from a canon firmware update file (see the build_scripts/eos_tools_v11 folder in that project linked above). Use decrypt_fw and then dissect_fw to split the FIR up. See this wiki page for more details:
http://magiclantern.wikia.com/wiki/Packing_FIR_FilesAfter you analyze the firmware dump using a program like IDA Pro (or the free
ARM Console created by Alex) to see how the camera boots/works, then attempt to boot a custom FIR file running user code. Use the assemble_fw perl script in the eos_tools directory to assemble a new FIR file with your usercode (compiled autoexec.bin) instead of canon's payload. The final step is to run decrypt_fw again on this fir to sign it for the camera to accept it. (Note: this step may or may not be necessary, depends on the camera. Try both if one doesn't work). Start by just blinking an LED or something basic to know your code runs. You don't need to boot the main firmware to blink an LED.
If 40d is similar to the 5dc, then you won't be able to run any practical code from a FIR (including calling the EnableBootDisk function or booting the firmware/camera) so you will need to write some code that scans the bootloader area (0xFFFF0000-0xFFFFFFFF) for function signatures to identify the read/write bootflag functions. This will allow you to set the camera's bootflag, to boot an autoexec.bin file with a prepared card, and development takes off from there (you will be able to boot the firmware and do anything from autoexec). I created this bootdisk code from the 350d method, using the 400d bootloader to find the signatures I needed. Only modification you will need is to change are the references to these:
read_bootflag = (ft_read_bootflag)0xFFFF8AE0;
write_bootflag = (ft_write_bootflag)0xFFFF89F0;
https://bitbucket.org/coutts/5dplus/src/e486f2e53796/bootdisk.cThe 5dc took me many hours to get going, I dumped many memory addresses through LED blinks in binary, you should be prepared to do the same. Here is some code that you can use to blink out the contents of a memory address if you know the red/blue LED addresses:
https://bitbucket.org/coutts/5dplus/src/a1cc964de4af/init.cYou can use this to write code to search for specific signatures of the read_bootflag and write_bootflag functions. Some signatures would be instructions like:
MOVEQ R7, #0xF8000000
which is assembled and looks like this in memory:
0x03A0733E
Use the 5dc bootloader (I can send you it) to know what signatures you're looking for (unique instructions that would only appear in the read/write bootflag functions). After you find a signature and have a match at some spot in the BL area (0xFFFF0000-0xFFFFFFFF), use this address and search in reverse (going backwards in memory to lower addresses) until you find the nearest PUSH (STMFD) instruction, this will be the address of the start of the function so that you can call it / use it.
I'll just tell you the signatures to find.
First, for
write_bootflag. Here is a small snippet from that function, the first 5 instructions:
ROM:FFFF89F0 STMFD SP!, {R4-R8,LR}
ROM:FFFF89F4 MOV R5, R1
ROM:FFFF89F8 MOV R4, #0
ROM:FFFF89FC CMP R0, #0
ROM:FFFF8A00 MOVNE R7, #0xF8000000
If you were scanning memory, these 5 instructions would look like this(starting at 0xFFFF89F0 on the left and ending on 0xFFFF8A00 on the right):
0xE92D41F0 0xE1A05001 0xE3A04000 0xE3500000 0x13A0733E
So, look for the signature for the
MOVNE R7, #0xF8000000 instruction, then once you find it, search backwards for the STMFD (push) instruction signature, and you will have located
write_bootflag in the 40d bootloader. Chances are the functions will probably be identical, but take caution to verify at least 3 times that you have located the correct function and it seems the same / similar to the 5dc one (remember we are working blind here).
Now,
read_bootflag. First 5 instructions look like:
ROM:FFFF8AE0 STR LR, [SP,#var_4]!
ROM:FFFF8AE4 CMP R0, #0
ROM:FFFF8AE8 MOVNE R3, #0xF8000000
ROM:FFFF8AEC ADDNE R3, R3, #0x2000
ROM:FFFF8AF0 MOVNE R2, #0x40
And in memory would look like this (same thing as before, starting at 0xFFFF8AE0 on left and ending at 0xFFFF8AF0 on the right):
0xE52DE004 0xE3500000 0x3E33A013 0x12833A02 0x13A02040
Note: there isn't a STMFD (push) instruction in read_bootflag. The 400d bootloader is like this too, so chances are the 40d is as well.
NOTE: you may need to reverse endianness of the assembled instructions above to see them in memory, but maybe not, I can't remember

So, once you have located read_bootflag() and write_bootflag(), you will be able to really start developing.

This may seem confusing, and I'm sorry, but I hope you will see how valuable this information is (I had to figure it all out on my own). The 350d people dumped the bootloader using a photo diode and the LED to blink the code in binary to a computer, I couldn't figure that out so I did it this way. Let me know if you have any questions, I can probably help a lot. Do you use gmail?