4 SPL 代码分析2(CRT0_64.S) _main的代码如下: - ENTRY(_main)
- /*
- * Set up initial C runtime environment and call board_init_f(0).
- */
- #if defined(CONFIG_TPL_BUILD) && defined(CONFIG_TPL_NEEDS_SEPARATE_STACK) (1)
- ldr x0, =(CONFIG_TPL_STACK)
- #elif defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
- ldr x0, =(CONFIG_SPL_STACK)
- #else
- ldr x0, =(CONFIG_SYS_INIT_SP_ADDR)
- #endif
- bic sp, x0, #0xf /* 16-byte alignment for ABI compliance */ (2)
- mov x0, sp (3)
- bl board_init_f_alloc_reserve (4)
- mov sp, x0 (5)
- /* set up gd here, outside any C code */
- mov x18, x0 (6)
- bl board_init_f_init_reserve (7)
- mov x0, #0 (8)
- bl board_init_f (9)
- #if !defined(CONFIG_SPL_BUILD) (10)
- /*
- * Set up intermediate environment (new sp and gd) and call
- * relocate_code(addr_moni). Trick here is that we'll return
- * 'here' but relocated.
- */
- ldr x0, [x18, #GD_START_ADDR_SP] /* x0 <- gd->start_addr_sp */
- bic sp, x0, #0xf /* 16-byte alignment for ABI compliance */
- ldr x18, [x18, #GD_BD] /* x18 <- gd->bd */
- sub x18, x18, #GD_SIZE /* new GD is below bd */
- adr lr, relocation_return
- ldr x9, [x18, #GD_RELOC_OFF] /* x9 <- gd->reloc_off */
- add lr, lr, x9 /* new return address after relocation */
- ldr x0, [x18, #GD_RELOCADDR] /* x0 <- gd->relocaddr */
- b relocate_code
- relocation_return:
- /*
- * Set up final (full) environment
- */
- bl c_runtime_cpu_setup /* still call old routine */
- #endif /* !CONFIG_SPL_BUILD */
- #if defined(CONFIG_SPL_BUILD) (11)
- bl spl_relocate_stack_gd /* may return NULL */ (12)
- /*
- * Perform 'sp = (x0 != NULL) ? x0 : sp' while working
- * around the constraint that conditional moves can not
- * have 'sp' as an operand
- */
- mov x1, sp (13)
- cmp x0, #0 (14)
- csel x0, x0, x1, ne (15)
- mov sp, x0 (16)
- #endif
- /*
- * Clear BSS section
- */
- ldr x0, =__bss_start /* this is auto-relocated! */ (17)
- ldr x1, =__bss_end /* this is auto-relocated! */
- clear_loop: (18)
- str xzr, [x0], #8 (19)
- cmp x0, x1 (20)
- b.lo clear_loop (21)
- /* call board_init_r(gd_t *id, ulong dest_addr) */
- mov x0, x18 /* gd_t */ (22)
- ldr x1, [x18, #GD_RELOCADDR] /* dest_addr */ (23)
- b board_init_r /* PC relative jump */ (24)
- /* NOTREACHED - board_init_r() does not return */
- ENDPROC(_main)
(1)将配置文件中设置的栈指针地址加载到x0寄存器中,在spl中应该是CONFIG_SPL_STACK的值,它一般位于include/configs/xxx中。
(2)将x0寄存器中的值清除低4位,使其16字节对齐,然后将它存入栈指针寄存器sp中,在armv8中栈指针寄存器为x31。
(3)由于sp中的值是做过对齐操作的,因此将其保存到x0中作为函数传参,在armv8中x0 - x7寄存器可以用于函数传参,其中x0为第一个参数。
(4)调用board_init_f_alloc_reserve函数,它定义在common/init/board_init.c中,代码如下。即若定义了early malloc功能,则为malloc预留一些内存,其中top就是通过x0传入的参数,由于栈是向低地址伸展的,因此将高地址留给early malloc,只需要将栈地址往下移即可。在保留过之后,继续将新的指针做16字节对齐。该函数是一个c语言实现,由于c语言需要栈的支持,而上面的第二步已经设置了栈指针,因此调用该函数不会有问题。
|