执行完 board_init_f 后,重新跳转回 _main 中执行。
10.1 relloc_code 前
10.1.1 gd 设置
在调用board_init_f()完成板卡与全局结构体变量 gd 的初始化后将其拷贝到在代码段下重新分配的全局结构体中。接下来进行sp的重新设置,将r9指向重新分配的全局变量gd,然后进行代码的重定位。
/* 将 sp 指针指向全局gd的gd->start_addr_sp,即栈底 */ 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 */
10.1.2 relocate_vectors
当执行未 GD 的设置后,跳转到 relocate_vectors 中去执行向量初始化
1 adr lr, here
1 here: 2 /* 3 * now relocate vectors 4 */ 5 6 bl relocate_vectors
relocate_vectors 主要是进行异常向量表的重定位,将异常向量表拷贝到正确的地址中去,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)
10.1.3 relocate_code
紧接着设置重定位的开始和结束地址。设置完成后跳转到 relocate_code(relocate.S) 中执行
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
拷贝代码段和动态连接段
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)
10.1.4 relocate_code 后
运行C环境,清理 BSS,执行点灯等操作,然后跳转到 board_init_r 中执行第二阶段初始化
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