1.1 链接脚本 u-boot.lds 详解
编译过uboot之后会在uboot根目录下生成u-boot.lds文件,这是链接程序的脚本,从这里找程序的入口。重点代码如下:
ENTRY(_start) //当前代码入口点“_start”(在arch/arm/lib/vectors.S中定义,后面就是中断向量表)
.text :
{
*(.__image_copy_start)
*(.vectors) //vectors段保存中断向量表
arch/arm/cpu/armv7/start.o (.text*) //将arch/arm/cpu/armv7/start.s编译出的.o放到中断向量表后面
*(.text*) //其它代码段放在这
}
打开u-boot.map(该文件为uboot的映射文件,可以看到哪个文件或者函数链接到的地址),vscode中搜索,可以看到__image_copy_start链接到0X87800000也是.text和vectors段的起始地址。一些和地址有关的变量值如下:
__image_copy_start 0x87800000 uboot 拷贝的首地址
__image_copy_end 0x8785dd54 uboot 拷贝的结束地址
__rel_dyn_start 0x8785dd54 .rel.dyn 段起始地址
__rel_dyn_end 0x878668f4 .rel.dyn 段结束地址
_image_binary_end 0x878668f4 镜像结束地址
__bss_start 0x8785dd54 .bss 段起始地址
__bss_end 0x878a8e74 .bss 段结束地址
1.2 链接脚本 u-boot.lds 详解
1.2.1 reset 函数源码详解
“_start”在arch/arm/lib/vectors.S中,其中“b reset”开始跳转到reset函数(arch/arm/cpu/armv7/start.S),reset函数中“b save_boot_params”跳转到save_boot_params函数。再由“b save_boot_params_ret”跳转,save_boot_params_ret函数进行一些对于CPU的设置,调用了一些函数比如cpu_init_crit,_main等,cpu_init_crit其内部调用了lowlevel_init。
1.2.2 lowlevel_init函数详解
lowlevel_init在arch/arm/cpu/armv7/lowlevel_init.S定义,重要代码:
//设置SP指针指向CONFIG_SYS_INIT_SP_ADDR(在include/configs/mx6ullevk.h)
//其中定义了一些变量,比如IMX6ULL内部ocram的首地址和大小
ldr sp, =CONFIG_SYS_INIT_SP_ADDR
//对sp指针做8字节对齐处理
bic sp, sp, #7
//sp指针减去GD_SIZE(248)
sub sp, sp, #GD_SIZE
bic sp, sp, #7
mov r9, sp //将sp地址保存在r9寄存器
//s_init会判断CPU类型,对于IMX6ULL返回空
bl s_init
1.2.3 _main函数详解
来源于arch/arm/lib/crt0.S,重要代码:
ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) //设置sp指向0X0091FF00
//调用函数,参数为r0中的值=0X0091FF00
//作用是留出早期的malloc内存区域和gd内存区域
//返回值为新的top值==0X0091FA00
bl board_init_f_alloc_reserve
//用于初始化 gd,其实就是清零处理。
//设置了early malloc起始地址=0X0091FB00
bl board_init_f_init_reserve
//初始化DDR,定时器,完成代码拷贝等
//初始化gd的各个成员变量,这些成员变量使得uboot自己重定位到DRAM最后的地址区域给Linux腾出空间,生成一个内存“分配图”
bl board_init_f
//将uboot拷贝到新的地址
b relocate_code
//对中断向量表进行重定位
bl relocate_vectors
//清除BSS段,设置board_init_r等
bl c_runtime_cpu_setup
board_init_f最终内存分配结果:
1.2.4 uboot函数调用总结
1.2.5 bootz启动Linux内核过程详解
略,以后再看吧