lds文件可以看出,程序入口函数为_start,下面从_start 开始分析start.s文件中有用的部分。
_start: b reset @do nothing, jump to save_boot_params b save_boot_params @do nothing,jump to save_boot_params_ret b save_boot_params_ret
接下来在运行save_boot_params_ret标号段的代码。
CONFIG_POSITION_INDEPENDENT 宏定义在配置选项中被设置,所以以下代码会被运行。
#if CONFIG_POSITION_INDEPENDENT adr x0, _start ands x0, x0, #0xfff b.eq 1f 0: wfi b 0b 1: pie_fixup: adr x0, _start ldr x1, _TEXT_base subs x9, x0, x1 beq pie_fixup_done adrp x2, __rel_dyn_start add x2, x2, #:lo12:__rel_dyn_start adrp x3, __rel_dyn_end add x3, x3, #:lo12:__rel_dyn_end pie_fix_loop: ldp x0, x1, [x2], #16 ldr x4, [x2], #8 cmp w1, #1027 bne pie_skip_reloc add x0, x0, x9 add x4, x4, x9 str x4, [x0] pie_skip_reloc: cmp x2, x3 b.lo pie_fix_loop pie_fixup_done: #endif
这段代码用于位置无关代码段的rel.dyn段,判断代码实际运行地址与链接地址是否相等,如果不相等,则需要吧rel_dyn段搬运到运行处对应的位置。
接下来根据实际运行的el等级,初始化异常向量表。
#if defined(CONFIG_ARMV8_SPL_EXCEPTION_VECTORS) || !defined(CONFIG_SPL_BUILD) .macro set_vbar, regname, reg msr regname, reg .endm adr x0, vectors #else .macro set_vbar, regname, reg .endm #endif switch_el x1, 3f, 2f, 1f 3: set_vbar vbar_el3, x0 mrs x0, scr_el3 orr x0, x0, #0xf msr scr_el3, x0 msr cptr_el3, xzr #ifdef COUNTER_FREQUENCY ldr x0, =COUNTER_FREQUENCY msr cntfrq_el0, x0 #endif b 0f 2: set_vbar vbar_el2, x0 mov x0, #0x33ff msr cptr_el2, x0 b 0f 1: set_vbar vbar_el1, x0 mov x0, #3 << 20 msr cpacr_el1, x0 0: isb
vectors是excecption.S文件中的代码,定义了异常向量表和中断函数。
至此,cpu进入了关闭mmu,cache,tlb的状态。
最后主cpu跳转到_main:
bl apply_core_errata bl lowlevel_init bl _main
而_main 是再crt0_64.S文件中。
综上,start.S里面做了以下事情:
(1)如果定义了CONFIG_POSITION_INDEPENDENT,则根据实际运行地址和链接地址来修正rel_dyn 段,参照arm位置无关代码。 (2)根据当前el等级,把中断向量表放到对应的el的寄存器中 (3)lowlevel_init中根据中断控制器的类型初始化中断控制器 (4)跳转到_main



