After executing board_init_f, jump back to _main for execution.
9.1 Before relloc_code
9.1.1 gd settings
After calling board_init_f() to complete the initialization of the board and the global structure variable gd, copy it to the global structure reassigned under the code segment. Next, reset the sp, point r9 to the reassigned global variable gd, and then relocate the code.
/* Point the sp pointer to gd->start_addr_sp of the global gd, that is, the bottom of the stack */ ldr r0, [r9, #GD_START_ADDR_SP] /* sp = gd->start_addr_sp */ bic r0, r0, # 7 /* 8-byte alignment for ABI compliance */ mov sp, r0 ldr r9, [r9, #GD_BD] /* r9 = gd->bd */ sub r9, r9, #GD_SIZE /* new GD is below bd */
9.1.2 relocate_vectors
After performing the settings without GD, jump to relocate_vectors to perform vector initialization
1 adr lr, here
1 here: 2 /* 3 * now relocate vectors 4 */ 5 6 bl relocate_vectors
relocate_vectors is mainly to relocate the exception vector table, copy the exception vector table to the correct address, relocate.S (arch\arm\lib)
1 ENTRY(relocate_vectors) 2 /* 3 * Copy the relocated exception vectors to the 4 * correct address 5 * CP15 c1 V bit gives us the location of the vectors: 6 * 0x00000000 or 0xFFFF0000. 7 */ 8 ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */ 9 mrc p15, 0, r2, c1, c0, 0 /* V bit (bit[13]) in CP15 c1 */ 10 ands r2, r2, #(1 << 13) 11 ldreq r1, =0x00000000 /* If V=0 */ 12 ldrne r1, =0xFFFF0000 /* If V=1 */ 13 ldmia r0!, {r2-r8,r10} 14 stmia r1!, {r2-r8,r10} 15 ldmia r0!, {r2-r8,r10} 16 stmia r1!, {r2-r8,r10} 17 bx lr 18 19 ENDPROC(relocate_vectors)
9.1.3 relocate_code
This is followed by setting the start and end addresses of the relocation. After setting, jump to relocate_code to execute
1 ldr r0, [r9, #GD_RELOC_OFF] /* r0 = gd->reloc_off */ 2 add lr, lr, r0 3 ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */ 4 b relocate_code
Copy code segment and dynamic link segment
1 ENTRY(relocate_code) 2 ldr r1, =__image_copy_start /* r1 <- SRC &__image_copy_start */ 3 subs r4, r0, r1 /* r4 <- relocation offset */ 4 beq relocate_done /* skip relocation */ 5 ldr r2, =__image_copy_end /* r2 <- SRC &__image_copy_end */ 6 7 /* 拷贝代码到 SDRAM 中去,.__image_copy_start = 0; */ 8 copy_loop: 9 ldmia r1!, {r10-r11} /* copy from source address [r1] */ 10 stmia r0!, {r10-r11} /* copy to target address [r0] */ 11 cmp r1, r2 /* until source end address [r2] */ 12 blo copy_loop 13 14 /* 15 * fix .rel.dyn relocations 16 * 重定位 .rel.dyn 段 17 */ 18 ldr r2, =__rel_dyn_start /* r2 <- SRC &__rel_dyn_start */ 19 ldr r3, =__rel_dyn_end /* r3 <- SRC &__rel_dyn_end */ 20 fixloop: 21 ldmia r2!, {r0-r1} /* (r0,r1) <- (SRC location,fixup) */ 22 and r1, r1, #0xff 23 cmp r1, #R_ARM_RELATIVE 24 bne fixnext 25 26 /* relative fix: increase location by offset */ 27 add r0, r0, r4 28 ldr r1, [r0] 29 add r1, r1, r4 30 str r1, [r0] 31 fixnext: 32 cmp r2, r3 33 blo fixloop 34 35 relocate_done: 36 37 /* ARMv4- don't know bx lr but the assembler fails to see that */ 38 39 #ifdef __ARM_ARCH_4__ 40 mov pc, lr 41 #else 42 bx lr 43 #endif 44 45 ENDPROC(relocate_code)
9.1.4 relocate_code 后
Run the C environment, clean up the BSS, perform operations such as lighting, and then jump to board_init_r to perform the second-stage initialization
1 /* Set up final (full) environment */ 2 3 bl c_runtime_cpu_setup /* we still call old routine here */ 4 #endif 5 #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_FRAMEWORK) 6 ldr r0, =__bss_start /* this is auto-relocated! */ 7 8 /* 清理 BSS */ 9 #ifdef CONFIG_USE_ARCH_MEMSET 10 ldr r3, =__bss_end /* this is auto-relocated! */ 11 mov r1, #0x00000000 /* prepare zero to clear BSS */ 12 13 subs r2, r3, r0 /* r2 = memset len */ 14 bl memset 15 #endif 16 17 #if ! defined(CONFIG_SPL_BUILD) 18 bl coloured_LED_init 19 bl red_led_on 20 #endif 21 /* call board_init_r(gd_t *id, ulong dest_addr) */ 22 mov r0, r9 /* gd_t */ 23 ldr r1, [r9, #GD_RELOCADDR] /* dest_addr */ 24 /* call board_init_r */ 25 ldr pc, =board_init_r /* this is auto-relocated! */ 26 /* we should not return here. */ 27 #endif