some progress:
Today I learned how the ML boot process works. I can boot the firmware by just directly jumping into the ROM, but of course I need to start my own task before I let the camera take control. The problem is I don't understand the 5dc boot process enough yet to know how to do this.
Here is the ML boot process (my interpretation[omitted some stuff]) outlined. Refer to copy_and_restart() in boot-hack.c:
- bootloader copies our code to 0x800000
- we copy a portion of the firmware from ROM into RAM. All we need to copy is from the start of the ROM up until the BL jump to cstart. For example, in the 500d, this bl call is at 0xFF012AE8. Subtract the start of the rom (0xFF010000) from this and we get 0x12AE8. This is all that we need to copy, so a safe number (used in ML) for RELOCSIZE is 0x3000. As long as the RELOCSIZE is at least as big as ([cstart bl call location] - [rom start address]), we are good.
blob_memcpy( new_image, firmware_start, firmware_start + firmware_len );
- in the RAM copy of the firmware, the jump to cstart is replaced with a return instruction so that it doesn't try to run cstart until we call it ourselves later.
INSTR( HIJACK_INSTR_BL_CSTART ) = RET_INSTR;
- next, we fix some branch instructions in cstart so that they point to the ROM locations of the functions and not the RAM ones (we want to eventually be executing from ROM and not our RAM copy of the firmware). This is done on bzero32 and create_init_task. Also, we replace DryOS's init_task (passed as an arg to create_init_task) to point to our init task (which starts ML). Our init task will call dryos' init task so everything works out in the end.
FIXUP_BRANCH( HIJACK_FIXBR_BZERO32, bzero32 );
FIXUP_BRANCH( HIJACK_FIXBR_CREATE_ITASK, create_init_task );
INSTR( HIJACK_INSTR_MY_ITASK ) = (uint32_t) my_init_task;
- next we execute the RAM copy of the firmware. Remember we patched the call to cstart to just return, so once execution reaches that point it will stop and return (it returns to nobody). Think of RELOCADDR as the location of the RAM copy of the firmware, so if we call that, then the firmware starts executing (up until cstart like I said above)
thunk reloc_entry = (thunk)( RELOCADDR + 0xC );
reloc_entry();
- Now we execute the RAM version of cstart. Remember we modified it to call the ROM functions for bzero32 and create_init_task, so after create_init_task is called, execution is now running from the ROM and no longer from the RAM copy.
void (*ram_cstart)(void) = (void*) &INSTR( cstart );
ram_cstart();
This is my understanding, if anyone has anything to contribute please do