uboot系列之-----代码重定位(源码)
2013-01-06 20:56
232 查看
从上一篇我们知道,board_init_f函数的最后返回到relocate_code,调用该函数的原型是
Relocate_code(addr_sp,id,addr),再讲一下三个参数的意义:
addr_sp是地址空间里面堆栈的首地址
id是存储gd_t类型全局参数的首地址
addr是uboot的重定位地址,也就是加载地址
这三个参数的值都是在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,r1和r2分别对应上面所讲的三个参数
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是该条指令的地址,x是PC与_start标号之间的偏移量(_start-PC),_start永远位于代码的最开始,当PC>_start时,x为负值,否则x为正值。所以当代码此时还在flash中时,_start为0(内部ram),PC+x(x<0)=PC+_start-PC
= _start=0,即r0=0,如果代码此时已经在SDRAM中了(即已经拷贝过了),_start
= TEXT_BASE,r0 = TEXT_BASE。所以接下来就比较r0与r6(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指明的地址)
Relocate_code(addr_sp,id,addr),再讲一下三个参数的意义:
addr_sp是地址空间里面堆栈的首地址
id是存储gd_t类型全局参数的首地址
addr是uboot的重定位地址,也就是加载地址
这三个参数的值都是在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,r1和r2分别对应上面所讲的三个参数
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是该条指令的地址,x是PC与_start标号之间的偏移量(_start-PC),_start永远位于代码的最开始,当PC>_start时,x为负值,否则x为正值。所以当代码此时还在flash中时,_start为0(内部ram),PC+x(x<0)=PC+_start-PC
= _start=0,即r0=0,如果代码此时已经在SDRAM中了(即已经拷贝过了),_start
= TEXT_BASE,r0 = TEXT_BASE。所以接下来就比较r0与r6(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指明的地址)
相关文章推荐
- UBOOT之源码分析(X4412)——代码重定位
- js调试系列 源码定位与调试[基础篇]
- ReactiveSwift源码解析(九) SignalProducerProtocol延展中的Start、Lift系列方法的代码实现
- uboot系列之-----命令的处理过程(源码)
- Uboot 源码分析----代码整体结构分析
- uboot搬移部分和重定位部分的代码分析
- 【dubbo源码解读系列】之二 dubbo代码启动入口解析(自定义main方法)
- 《zw版·Halcon-delphi系列原创教程》航母舰载机·视觉定位标志的识别代码
- [源码、文档、分享] iOS/iPhone学习系列、代码教程----~~~持续更新中~~~
- uboot重定位代码分析(转)
- [译]在VS 2010中搜索定位代码新招盘点 (VS 2010 和.NET 4.0 系列博文)
- js调试系列: 源码定位与调试[基础篇]
- Silverlight实用窍门系列:20.后台CS代码中创建四种常用的动画效果【附带源码实例】
- uboot系列之-----命令的处理过程(源码)
- uboot系列之------CPU初始化概述(源码)
- uboot重定位代码分析(转)
- uboot系列之-----板级初始化(源码)
- js调试系列 源码定位与调试[基础篇]
- uboot系列之-----板级初始化(源码)
- 【代码】Android 客户端GPS定位源码