关于uboot地址重定位

lucseven 2010-01-07 06:29:11
新手学习uboot,对于地址重定位的问题始终没有搞明白,请高手指点

Q1:start.s最初是在0x0000开始的地址处开始执行,中间有个过程是把自己以及uboot的其他代码搬移到0x3ff8 0000的位置,可是程序是怎么跳转到0x3ff8000处(或者所在的ram中)运行的呢?

以下是start.s的代码,高手能否告知是哪一条指令使pc跳转到ram中的?


#include <config.h>
#include <version.h>


/*
*************************************************************************
*
* Jump vector table as in table 3.1 in [1]
*
*************************************************************************
*/


.globl _start
_start: b reset
ldr pc, _undefined_instruction
ldr pc, _software_interrupt
ldr pc, _prefetch_abort
ldr pc, _data_abort
ldr pc, _not_used
ldr pc, _irq
ldr pc, _fiq

_undefined_instruction: .word undefined_instruction
_software_interrupt: .word software_interrupt
_prefetch_abort: .word prefetch_abort
_data_abort: .word data_abort
_not_used: .word not_used
_irq: .word irq
_fiq: .word fiq

.balignl 16,0xdeadbeef


/*
*************************************************************************
*
* Startup Code (reset vector)
*
* do important init only if we don't start from memory!
* relocate armboot to ram
* setup stack
* jump to second stage
*
*************************************************************************
*/

_TEXT_BASE:
.word TEXT_BASE

.globl _armboot_start
_armboot_start:
.word _start

/*
* These are defined in the board-specific linker script.
*/
.globl _bss_start
_bss_start:
.word __bss_start

.globl _bss_end
_bss_end:
.word _end

#ifdef CONFIG_USE_IRQ
/* IRQ stack memory (calculated at run-time) */
.globl IRQ_STACK_START
IRQ_STACK_START:
.word 0x0badc0de

/* IRQ stack memory (calculated at run-time) */
.globl FIQ_STACK_START
FIQ_STACK_START:
.word 0x0badc0de
#endif


/*
* the actual reset code
*/

reset:
/*
* set the cpu to SVC32 mode
*/
mrs r0,cpsr
bic r0,r0,#0x1f
orr r0,r0,#0xd3
msr cpsr,r0

/* turn off the watchdog */
#if defined(CONFIG_S3C2400)
# define pWTCON 0x15300000
# define INTMSK 0x14400008 /* Interupt-Controller base addresses */
# define CLKDIVN 0x14800014 /* clock divisor register */
#elif defined(CONFIG_S3C2410)
# define pWTCON 0x53000000
# define INTMSK 0x4A000008 /* Interupt-Controller base addresses */
# define INTSUBMSK 0x4A00001C
# define CLKDIVN 0x4C000014 /* clock divisor register */
#endif

#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)
ldr r0, =pWTCON
mov r1, #0x0
str r1, [r0]

/*
* mask all IRQs by setting all bits in the INTMR - default
*/
mov r1, #0xffffffff
ldr r0, =INTMSK
str r1, [r0]
# if defined(CONFIG_S3C2410)
ldr r1, =0x3ff
ldr r0, =INTSUBMSK
str r1, [r0]
# endif

/* FCLK:HCLK:PCLK = 1:2:4 */
/* default FCLK is 120 MHz ! */
ldr r0, =CLKDIVN
mov r1, #3
str r1, [r0]
#endif /* CONFIG_S3C2400 || CONFIG_S3C2410 */

/*
* we do sys-critical inits only at reboot,
* not when booting from ram!
*/
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_crit
#endif

#ifndef CONFIG_SKIP_RELOCATE_UBOOT
relocate: /* relocate U-Boot to RAM */
adr r0, _start /* r0 <- current position of code */
ldr r1, _TEXT_BASE /* test if we run from flash or RAM */
cmp r0, r1 /* don't reloc during debug */
beq stack_setup

ldr r2, _armboot_start
ldr r3, _bss_start
sub r2, r3, r2 /* r2 <- size of armboot */
add r2, r0, r2 /* r2 <- source end address */

copy_loop:
ldmia r0!, {r3-r10} /* copy from source address [r0] */
stmia r1!, {r3-r10} /* copy to target address [r1] */
cmp r0, r2 /* until source end addreee [r2] */
ble copy_loop
#endif /* CONFIG_SKIP_RELOCATE_UBOOT */

/* Set up the stack */
stack_setup:
ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */
sub r0, r0, #CFG_MALLOC_LEN /* malloc area */
sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */
#ifdef CONFIG_USE_IRQ
sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
sub sp, r0, #12 /* leave 3 words for abort-stack */

clear_bss:
ldr r0, _bss_start /* find start of bss segment */
ldr r1, _bss_end /* stop here */
mov r2, #0x00000000 /* clear */

clbss_l:str r2, [r0] /* clear loop... */
add r0, r0, #4
cmp r0, r1
ble clbss_l

#if 0
/* try doing this stuff after the relocation */
ldr r0, =pWTCON
mov r1, #0x0
str r1, [r0]

/*
* mask all IRQs by setting all bits in the INTMR - default
*/
mov r1, #0xffffffff
ldr r0, =INTMR
str r1, [r0]

/* FCLK:HCLK:PCLK = 1:2:4 */
/* default FCLK is 120 MHz ! */
ldr r0, =CLKDIVN
mov r1, #3
str r1, [r0]
/* END stuff after relocation */
#endif

ldr pc, _start_armboot

_start_armboot: .word start_armboot
...全文
673 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
lucseven 2010-01-17
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 dairyman000 的回复:]
这个是因为链接的时候,函数的地址都被增加了TEXT_BASE。你可以在代码中搜索一下TEXT_BASE的值定义为多少,看看就明白了。  这个值往往也就是u-boot被拷贝到内存,内存的起始值。
[/Quote]
uboot的哪个文件使链接的时候函数地址都增加了TEXT_BASE?
lucseven 2010-01-12
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 lucseven 的回复:]
引用 2 楼 dairyman000 的回复:
跳转发生在
ldr pc, _start_armboot
start_armboot 的值为TEXT_BASE加上start_armboot的实际偏移值。

完成代码拷贝后,start.S做了一些诸如开启MMU,设置堆栈,清除bss的工作后,就开始执行C语言函数start_armboot. 也正是在这里,完成了向SDRAM的跳转。

谢谢,回复
_start_armboot 里的值是_start,编译的时候_start代表值不是0x0000?如果编译的时候 _start =0x0000,那么运行ldr pc, _start_armboot时岂不是跳到0x0了?
希望高手指正
[/Quote]

我之前说的不对_start_armboot 里的值是void start_armboot()函数的地址,根据uboot的lds文件看,所有的代码都放在0x000开始的区域。程序怎么回调转到3ff80000左右的地址处运行呢?
dairyman000 2010-01-12
  • 打赏
  • 举报
回复
这个是因为链接的时候,函数的地址都被增加了TEXT_BASE。你可以在代码中搜索一下TEXT_BASE的值定义为多少,看看就明白了。 这个值往往也就是u-boot被拷贝到内存,内存的起始值。
lucseven 2010-01-11
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 dairyman000 的回复:]
跳转发生在
ldr pc, _start_armboot
start_armboot 的值为TEXT_BASE加上start_armboot的实际偏移值。

完成代码拷贝后,start.S做了一些诸如开启MMU,设置堆栈,清除bss的工作后,就开始执行C语言函数start_armboot. 也正是在这里,完成了向SDRAM的跳转。
[/Quote]
谢谢,回复
_start_armboot 里的值是_start,编译的时候_start代表值不是0x0000?如果编译的时候 _start =0x0000,那么运行ldr pc, _start_armboot时岂不是跳到0x0了?
希望高手指正
dairyman000 2010-01-09
  • 打赏
  • 举报
回复
uboot开启MMU只有愿不愿开启和能不能开启(硬件不支持MMU)的问题,不存在敢不敢开启的问题。
uboot自身完全可以运行在虚拟地址空间,上面提到开启MMU,设置堆栈,清除bss都是针对Uboot而言的。
Arnold9009 2010-01-08
  • 打赏
  • 举报
回复
mark
期待高手出现
TheSaviour 2010-01-08
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 dairyman000 的回复:]
……
完成代码拷贝后,start.S做了一些诸如开启MMU,……
[/Quote]

赫赫,uboot里可不敢开启mmu,那是kernel自己要做的事情。
dairyman000 2010-01-07
  • 打赏
  • 举报
回复

跳转发生在
ldr pc, _start_armboot
start_armboot 的值为TEXT_BASE加上start_armboot的实际偏移值。

完成代码拷贝后,start.S做了一些诸如开启MMU,设置堆栈,清除bss的工作后,就开始执行C语言函数start_armboot. 也正是在这里,完成了向SDRAM的跳转。
lucseven 2010-01-07
  • 打赏
  • 举报
回复
有热心高手讲几句么?

21,597

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 驱动开发/核心开发
社区管理员
  • 驱动开发/核心开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧