U-Boot源码分析6—启动过程分析_main
- 1 `_main`函数
- 2 `board_init_f_alloc_reserve`函数
- 3 `board_init_f_init_reserve`函数
- 4 `board_init_f`函数
-
- 4.1 `initcall_run_list`函数
- 4.2 `init_sequence_f`初始化序列
-
- 4.2.1 `setup_mon_len`
- 4.2.2 `fdtdec_setup`
- 4.2.3 `initf_malloc`
- 4.2.4 `initf_bootstage`
- 4.2.5 `initf_console_record`
- 4.2.6 `arch_cpu_init`
- 4.2.7 `mach_cpu_init`
- 4.2.8 `initf_dm`
- 4.2.9 `arch_cpu_init_dm`
- 4.2.10 `timer_init`
- 4.2.11 `env_init`
- 4.2.12 `init_baud_rate`
- 4.2.13 `serial_init`
- 4.2.14 `console_init_f`
- 4.2.15 `display_options`
- 4.2.16 `display_text_info`
- 4.2.17 `print_cpuinfo`
- 4.2.18 `show_board_info`
- 4.2.19 `announce_dram_init`
- 4.2.20 `dram_init`
- 4.2.21 `setup_dest_addr`
- 4.2.22 `reserve_round_4k`
- 4.2.23 `reserve_mmu`
- 4.2.24 `reserve_video`
- 4.2.25 `reserve_trace`
- 4.2.26 `reserve_uboot`
- 4.2.27 `reserve_malloc`
- 4.2.28 `reserve_board`
- 4.2.29 `setup_machine`
- 4.2.30 `reserve_global_data`
- 4.2.31 `reserve_fdt`
- 4.2.32 `reserve_bootstage`
- 4.2.33 `reserve_arch`
- 4.2.34 `reserve_stacks`
- 4.2.35 `dram_init_banksize`
- 4.2.36 `show_dram_config`
- 4.2.37 `display_new_sp`
- 4.2.38 `reloc_fdt`
- 4.2.39 `reloc_bootstage`
- 4.2.40 `setup_reloc`
- 5 `spl_relocate_stack_gd`
- 6 `board_init_r`
1 _main函数
根据上一章分析,启动过程运行到_main函数,通过查找,可知arch/arm/lib/crt0.S和arch/arm/lib/crt0_64.S文件中均有_main函数的定义,再通过查看arch/arm/lib/Makefile文件中内容

由宏定义CONFIG_ARM64=y,可知编译链接的是arch/arm/lib/crt0_64.S文件中的_main函数,下面进行分析
第72行~81行,首先还是根据宏定义设置堆栈,然后使用bl指令跳转至board_init_f_alloc_reserve,即调用board_init_f_alloc_reserve函数

2 board_init_f_alloc_reserve函数
查找可知board_init_f_alloc_reserve函数位于common/init/board_init.c文件中
这里board_init_f_alloc_reserve函数有1个输入参数top,由汇编代码可知这里传入的是x0寄存器的值,即栈顶指针(目前为堆栈的起始位置,即CONFIG_SPL_STACK=LOW_LEVEL_SRAM_STACK=0x00008000,为SRAM的结束地址,因为此时还未初始化DDR,仍使用的SRAM)
第49行~51行,将top减去早先预留的空间(这里减去的值为0x400即1024字节)。这里需要说明的是SYS_MALLOC_F是u-boot为了给串口等设备进行初始化预分配的malloc池,因为此时还没有进行内存的初始化(也就是后续所说的重定向),所有的代码运行、变量等均存于SRAM中,而SRAM空间很小,因此需要额外注意SRAM空间的使用
第53行,计算global_data需要预留的空间,并进行16字节对齐,并更新top的值。
第55行,返回top的值,这个值将保存在x0寄存器中
回到_main函数中,第82行,将board_init_f_alloc_reserve函数返回值即上述top的值存入sp寄存器;第84行,将此值保存在x18寄存器中(即后面说的全局变量gd的起始地址),然后第85行调用board_init_f_init_reserve函数,传入参数仍为x0寄存器的值,即上述top

3 board_init_f_init_reserve函数
board_init_f_init_reserve函数同样位于common/init/board_init.c文件中
这里board_init_f_init_reserve函数有1个输入参数base,由汇编代码可知这里传入的是x0寄存器的值,目前为board_init_f_alloc_reserve函数计算后得到的值,即为global_data结构体预留空间且进行了16字节对齐的地址
第102行~111行,定义一个叫做gd_ptr的global_data结构体指针,并将此地址指针作为其起始地址,然后进行清零
第117行,计算16字节对齐后剩余空间的起始地址,并将其保存在全局变量gd中,在arch/arm/include/asm/global_data.h中定义,即为gd_t结构体的指针,且其内容保存在X18寄存器中,而使用volatile关键字表明gd的内容可能会被意想不到的改变,因此在编译时不对任何使用gd的代码进行优化

gd_t结构体位于include/asm-generic/global_data.h中,保存一些关键的全局数据
board_init_f_init_reserve函数第126行,将后续可用于malloc的首地址保存在全局结构体中gd->malloc_base
在_main函数中,第87行将X0寄存器清零,然后使用bl指令跳转至board_init_f,即调用board_init_f函数
4 board_init_f函数
这里从u-boot.map的记录可以看出,board_init_f函数位于common/board_f.c文件中,传入参数为0,即gd->flags的值为0

第908行,通过调用函数initcall_run_list来运行init_sequence_f初始化序列中的所有函数,这里先看看initcall_run_list函数
4.1 initcall_run_list函数
initcall_run_list函数位于lib/initcal.c中,其功能十分简单,即调用初始化序列中所有函数,并判断其运行返回值

第17行开始的for循环,遍历init_seq


7021

被折叠的 条评论
为什么被折叠?



