uboot系列之-----代码重定位(源码)

从上一篇我们知道,board_init_f函数的最后返回到relocate_code,调用该函数的原型是

Relocate_code(addr_sp,id,addr),再讲一下三个参数的意义:

addr_sp是地址空间里面堆栈的首地址

id是存储gd_t类型全局参数的首地址

addruboot的重定位地址,也就是加载地址

这三个参数的值都是在board_init_f函数里面定义好了的(具体可以参看上一篇日志《uboot系列之-----板级初始化(源码)》)。

现在跳到arch/arm/cpu/armv7/start.s中的relocate_code代码标号处。

 

.globl         relocate_code

relocate_code:

         mov  r4, r0 /*save addr_sp */

         mov  r5, r1 /*save addr of gd */

         mov  r6, r2 /*save addr of destination */

这里面r0,r1r2分别对应上面所讲的三个参数

r0 – addr_sp

r1 – id

r2 – addr

         /* Setup the stack*/

stack_setup:

       mov sp,r4

        

设置堆栈指针

adr   r0,_start 

#ifndef CONFIG_PRELOADER 

         cmp r0,r6

         beq clear_bss   /*skip relocation*/

        

#endif

adr是小范围的地址读取伪指令,这条指令也可以理解成ldr r0,=PC+x,PC是该条指令的地址,xPC_start标号之间的偏移量(_start-PC),_start永远位于代码的最开始,当PC>_start时,x为负值,否则x为正值。所以当代码此时还在flash中时,_start0(内部ram),PC+x(x<0)=PC+_start-PC = _start=0,r0=0,如果代码此时已经在SDRAM中了(即已经拷贝过了),_start = TEXT_BASE,r0 = TEXT_BASE。所以接下来就比较r0r6(r6存储的重定位地址),如果相等,就说明已经拷贝过了,就跳过重定位代码,否则,就要执行重定位代码。我们这里是需要重定位的。

      mov r1,r6       /*r1<-scratch for copy_loop*/

     ldr r2,_TEXT_BASE

     ldr r3,_bss_start_ofs

     add  r2,r0,r3   /*r2<-source end address*/

copy_loop:

        ldmia  r0!,{r9-r10}    /*copy from source address [r0]*/

        stmia  r1!,{r9-r10}   /**copy to target address[r1]/

       cmp r0,r2     /*until source end address[r2]*/

       blo copy_loop

       

_TEXT_BASE标号处存放的是CONFIG_SYS_TEXT_BAE,改变量定义在/board/samsung/smdk4212/config.mk 值为0xc3e0_0000,不过在这段程序中好像没什么用,addr r2,r0,r3  使得r2 =r3(因为r0=0),即BSS段的开始地址,也就是代码段的结束地址。整个copy_loop循环就是将uboot代码拷贝到重定位地址处(即addr指明的地址)

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值