an analysis of generated "autoexec", here with
ROMBASEADDR = 0xFF010000 RESTARTSTART = 0x0008B000
compared to reboot.c and 5d-hack.c
800000 EXPORT _start 800000 _start 800000 B loc_80000C 800000 ; ---------------------------------- 800004 aGaonisoy DCB "gaonisoy" 80000C ; ---------------------------------- 0000C 80000C loc_80000C 80000C MRS R0, CPSR 800010 BIC R0, R0, #0x3F 800014 ORR R0, R0, #0xD3 800018 MSR CPSR_cf, R0 80001C MOV SP, #0x1900 800020 MOV R11, #0 800024 B cstart 800024 ; End of function _start |
Makefile autoexec: reboot.o -e _start -Ttext=0x800000 asm( ".text\n" ".globl _start\n" "_start:\n" " b 1f\n" ".ascii \"gaonisoy\"\n" // 0x124, 128 "1:\n" "MRS R0, CPSR\n" "BIC R0, R0, #0x3F\n" // Clear I,F,T "ORR R0, R0, #0xD3\n" // Set I,T, M=10011 == supervisor "MSR CPSR, R0\n" " ldr sp, =0x1900\n" // 0x130 " mov fp, #0\n" " b cstart\n" ); |
00800028 ALIGN 0x1000 00801000 |
reboot.c /** Include the relocatable shim code */ extern uint8_t blob_start; extern uint8_t blob_end; asm( ".text\n" ".align 12\n" // 2^12 == 4096 bytes ".incbin \"magiclantern.bin\"\n" // |
801000 blob_start DATA XREF: _start+2E018 801000 801000 B loc_801004 801004 801004 loc_801004 801004 LDR R2, =0xB7F00 801008 LDR R3, =0xD0680 80100C CMP R2, R3 801010 BCS loc_801024 801014 MOV R1, #0 801018 801018 loc_801018 801018 STR R1, [R2],#4 80101C CMP R2, R3 801020 BCC loc_801018 801024 801024 loc_801024 blob_start+10 |
5d-hack.c extern uint32_t _bss_start[], _bss_end[]; static inline void zero_bss( void ) { uint32_t *bss = _bss_start; while( bss < _bss_end ) *(bss++) = 0; } void __attribute__((noreturn,noinline,naked)) copy_and_restart( int offset ) { zero_bss(); |
801024 loc_801024 801024 LDR R2, =0xC85F4 801028 RSBS R1, R0, #1 80102C MOVCC R1, #0 801030 STR R1, [R2] |
// Set the flag if this was an autoboot load autoboot_loaded = (offset == 0); |
801034 LDR R12, =0xB7F00 801038 MOV R2, 0xFF010000 801040 801040 loc_801040 801040 ADD R1, R12, R2 801044 LDR R0, [R2],#4 801048 ADD R1, R1, #0xFF0000 80104C CMN R2, #0xFE0000 801050 STR R0, [R1] 801054 LDR R1, =0xB7F00 801058 BNE loc_801040 |
arm-mcr.h static inline void blob_memcpy( void * dest_v, const void * src_v, const void * end ) 5d-hack.c // Copy the firmware to somewhere safe in memory const uint8_t * const firmware_start = (void*) ROMBASEADDR; const uint32_t firmware_len = RELOCSIZE; uint32_t * const new_image = (void*) RELOCADDR; blob_memcpy( new_image, firmware_start, firmware_start + firmware_len ); |
INSTR( HIJACK_INSTR_BL_CSTART ) = RET_INSTR; /* * in cstart() (0xff010ff4) make these changes: * calls bzero(), then loads bs_end and calls * create_init_task */ // Reserve memory after the BSS for our application INSTR( HIJACK_INSTR_BSS_END ) = (uintptr_t) _bss_end; // Fix the calls to bzero32() and create_init_task() FIXUP_BRANCH( HIJACK_FIXBR_BZERO32, bzero32 ); FIXUP_BRANCH( HIJACK_FIXBR_CREATE_ITASK, create_init_task ); // Set our init task to run instead of the firmware one INSTR( HIJACK_INSTR_MY_ITASK ) = (uint32_t) my_init_task; | |
8010C4 MOV R0, #0 8010C8 8010C8 loc_8010C8 8010C8 MOV R1, R0,LSL#30 8010CC MOV R3, #0 8010D0 8010D0 loc_8010D0 8010D0 ORR R2, R1, R3 8010D4 MCR p15, 0, R2,c7,c14, 2 8010D8 ADD R3, R3, #0x20 8010DC CMP R3, #0x400 8010E0 BNE loc_8010D0 8010E4 ADD R0, R0, #1 8010E8 CMP R0, #4 8010EC BNE loc_8010C8 8010F0 SUB R3, R3, #0x400 |
static inline void clean_d_cache( void ) { uint32_t segment = 0; do { uint32_t line = 0; for( ; line != 0x400 ; line += 0x20 ) { asm( "mcr p15, 0, %0, c7, c14, 2" : : "r"( line | segment ) ); } } while( segment += 0x40000000 ); } |
8010F4 MOV R3, #0 8010F8 MCR p15, 0, R3,c7,c5 8010FC MOV R3, #0 801100 MCR p15, 0, R3,c7,c6 801104 MCR p15, 0, R3,c7,c10, 4 |
static inline void flush_caches( void ) { uint32_t reg = 0; asm( "mov %0, #0\n" "mcr p15, 0, %0, c7, c5, 0\n" // entire I cache "mov %0, #0\n" "mcr p15, 0, %0, c7, c6, 0\n" // entire D cache "mcr p15, 0, %0, c7, c10, 4\n" // drain write buffer : : "r"(reg) ); } |
00801108 LDR R3, =0xB7F0C 0080110C MOV LR, PC 00801110 BX R3 |
// We enter after the signature, avoiding the // relocation jump that is at the head of the data thunk reloc_entry = (thunk)( RELOCADDR + 0xC ); reloc_entry(); |
00801114 LDR R2, =0x8B168 00801118 LDR R3, =0x193C 0080111C STR R2, [R3] |
// Install our task creation hooks task_dispatch_hook = my_task_dispatch_hook; |
801120 LDR R2, =0xFF011028 801124 LDR R3, =0x10A7F00 801128 ADD R3, R2, R3 80112C MOV LR, PC 801130 BX R3 801134 801134 loc_801134 801134 B loc_801134 |
void (*ram_cstart)(void) = (void*) &INSTR( cstart ); ram_cstart(); // Unreachable while(1) |
82E000 EXPORT blob_end 82E000 blob_end |
reboot.c ".align 12\n" "blob_end:\n" ".globl blob_end\n" ); |
82E000 MOV R0, PC 82E000 ; find_offset 82E004 LDR R3, =loc_82E008 82E008 82E008 loc_82E008 82E008 82E008 RSB R0, R3, R0 82E00C BX LR |
static int __attribute__((noinline)) find_offset( void ) { uintptr_t pc; asm __volatile__ ( "mov %0, %%pc" : "=&r"(pc) ); return pc - 8 - (uintptr_t) find_offset; } |
82E014 EXPORT cstart 82E014 cstart 82E014 BL blob_end 82E018 LDR R4, =blob_start 82E01C LDR LR, =blob_end 82E020 RSB LR, R4, LR 82E024 MOVS LR, LR,ASR#2 82E028 ADD R4, R4, R0 82E02C BEQ loc_82E054 82E030 MOV R3, #0 82E034 MOV R2, R3 82E038 82E038 loc_82E038 82E038 LDR R12, [R4,R3] 82E03C ADD R2, R2, #1 82E040 ADD R1, R3, #0x8B000 82E044 CMP LR, R2 82E048 STR R12, [R1] 82E04C ADD R3, R3, #4 82E050 BHI loc_82E038 |
void __attribute__((noreturn)) cstart( void ) { ssize_t offset = find_offset(); blob_memcpy( (void*) RESTARTSTART, &blob_start + offset, &blob_end + offset ); |
82E054 loc_82E054 82E054 MOV R12, #0 82E058 82E058 loc_82E058 82E058 MOV R1, R12,LSL#30 82E05C MOV R3, #0 82E060 82E060 loc_82E060 82E060 ORR R2, R3, R1 82E064 MCR p15, 0, R2,c7,c14, 2 82E068 ADD R3, R3, #0x20 82E06C CMP R3, #0x400 82E070 BNE loc_82E060 82E074 ADD R12, R12, #1 82E078 CMP R12, #4 82E07C BNE loc_82E058 82E080 MOV R3, #0 82E084 MOV R3, #0 82E088 MCR p15, 0, R3,c7,c5 82E08C MOV R3, #0 82E090 MCR p15, 0, R3,c7,c6 82E094 MCR p15, 0, R3,c7,c10, 4 |
clean_d_cache(); flush_caches(); |
82E098 MOV R3, #0x8B000 82E09C MOV LR, PC 82E0A0 BX R3 |
// Jump into the newly relocated code void __attribute__((noreturn))(*copy_and_restart)(int) = (void*) RESTARTSTART; void __attribute__((noreturn))(*firmware_start)(void) = (void*) ROMBASEADDR; if( 1 ) copy_and_restart(offset); else firmware_start(); // Unreachable while(1) |