在BOOT标题uboot.lds分析中可知boot的编译地址的基地址为0x9fc00000(记住编译地址并不等同于运行地址)。那么难道boot启动的起始地址就是0x9fc00000吗?
这样看上去没什么道理,因为大家都知道设备上电后在flash的起始地址开始运行,在uboot.lds中我们指定了代码段的起始入口为_start接口,那么_start的编译地址为
0x9fc00000,但是在flash上的运行地址为0x00000000。设备一上电就会找到_start入口开始执行,该入口在start.S文件中,也是boot启动的第一部分。
start.S:
这里我们可以看见_start
_start: 执行RVECENT这个宏,那么我们来看看这个宏都做了什么
这个宏执行无条件跳转b跳转到reset
reset:
/* Initialize GOT pointer.
*********************************
初始化GOT Global Offset Table(GOT全局偏移量表) 指针
编译器在数据段开始的地方创建了一个表.叫做全局偏移量表(global offset table.GOT)。
GOT包含每个被这个目标模块引用的全局数据目标的表目。
编译器还为GOT中每个表目生成一个重定位记录。在加载时,动态链接器会重定位GOT中的每个表目,
使得它包含正确的绝对地址。
跳转到下面标签1,执行,并把返回地址保存到ra寄存器。
最后定义了1个字, 值 == _GLOBAL_OFFSET_TABLE_
标号_GLOBAL_OFFSET_TABLE_可能驻留在.got section的中间,允许负的和非负
的下标索引这个数组。
*********************************
*/
bal 1f /*转移指令*/
nop
.word _GLOBAL_OFFSET_TABLE_
1:
move gp, ra
lw t1, 0(ra)
move gp, t1
.set reorder
/* Initialize CS, enable cache.
初始化时钟,使能cache
*/
JAL_KSEG1(board_earlyinit)
/*这里我们可以看到JAL_KSEG1的宏定义
#define JAL_KSEG1(x) LA t9,x ; or t9,K1BASE; jalr t9; nop
通过该宏可知,跳转到board_earlyinit | K1BASE 的地址行去并保存返回地址
那么K1BASE是怎么得到的。