我在移植ixp425 arm芯片的时候,用的u-boot版本为2011.06,中间搬移代码到sdram中的地址是由board_init_f一步步计算出来的,而CONFIG_SYS_TEXT_BASE是在板子目录下的config.mk中定义的,也就是说程序在sdram中的运行地址应该就是CONFIG_SYS_TEXT_BASE中指定的数字,但board_init_f程序执行后的搬移地址与CONFIG_SYS_TEXT_BASE不一致,那么搬移到sdram中后,程序怎么可能运行成功呢?我也没看见使用mmu的什么高级功能,进行remap,那程序肯定跑飞。不知道新版本uboot为什么这么设计,望执教!谢谢大家。
在我知识里,CONFIG_SYS_TEXT_BASE指定的地址应该是运行地址,如果搬移地址与运行地址不一致,程序肯定跑飞呀!神呀,救救我吧,我被这问题折磨惨了。
另贴上uboot2011.03关于重定位(relocate)处的相关源代码(在arch/arm/cpu/ixp/start.S中):
跳转如下:
/* Set initial stackpointer in SDRAM to call board_init_f */
call_board_init_f:
ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
ldr r0,=0x00000000
bl board_init_f
/*------------------------------------------------------------------------------*/
/*
* void relocate_code (addr_sp, gd, addr_moni)
*
* This "function" does not return, instead it continues in RAM
* after relocating the monitor 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 */
/* Set up the stack */
stack_setup:
mov sp, r4
adr r0, _start
cmp r0, r6
beq clear_bss /* skip relocation */
mov r1, r6 /* r1 <- scratch for copy_loop */
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
#ifndef CONFIG_PRELOADER
/*
* fix .rel.dyn relocations
*/
ldr r0, _TEXT_BASE /* r0 <- Text base */
sub r9, r6, r0 /* r9 <- relocation offset */
ldr r10, _dynsym_start_ofs /* r10 <- sym table ofs */
add r10, r10, r0 /* r10 <- sym table in FLASH */
ldr r2, _rel_dyn_start_ofs /* r2 <- rel dyn start ofs */
add r2, r2, r0 /* r2 <- rel dyn start in FLASH */
ldr r3, _rel_dyn_end_ofs /* r3 <- rel dyn end ofs */
add r3, r3, r0 /* r3 <- rel dyn end in FLASH */
fixloop:
ldr r0, [r2] /* r0 <- location to fix up, IN FLASH! */
add r0, r0, r9 /* r0 <- location to fix up in RAM */
ldr r1, [r2, #4]
and r7, r1, #0xff
cmp r7, #23 /* relative fixup? */
beq fixrel
cmp r7, #2 /* absolute fixup? */
beq fixabs
/* ignore unknown type of fixup */
b fixnext
fixabs:
/* absolute fix: set location to (offset) symbol value */
mov r1, r1, LSR #4 /* r1 <- symbol index in .dynsym */
add r1, r10, r1 /* r1 <- address of symbol in table */
ldr r1, [r1, #4] /* r1 <- symbol value */
add r1, r1, r9 /* r1 <- relocated sym addr */
b fixnext
fixrel:
/* relative fix: increase location by offset */
ldr r1, [r0]
add r1, r1, r9
fixnext:
str r1, [r0]
add r2, r2, #8 /* each rel.dyn entry is 8 bytes */
cmp r2, r3
blo fixloop
#endif
clear_bss:
#ifndef CONFIG_PRELOADER
ldr r0, _bss_start_ofs
ldr r1, _bss_end_ofs
mov r4, r6 /* reloc addr */
add r0, r0, r4
add r1, r1, r4
mov r2, #0x00000000 /* clear */
clbss_l:str r2, [r0] /* clear loop... */
add r0, r0, #4
cmp r0, r1
bne clbss_l
bl coloured_LED_init
bl red_LED_on
#endif
/*
* We are done. Do not return, instead branch to second part of board
* initialization, now running from RAM.
*/
ldr r0, _board_init_r_ofs
adr r1, _start
add lr, r0, r1
add lr, lr, r9
/* setup parameters for board_init_r */
mov r0, r5 /* gd_t */
mov r1, r6 /* dest_addr */
/* jump to it ... */
mov pc, lr
。。。
就跳转到c程序board_init_r,其它哪儿也没有重定位的代码了!
另一个问题,board_init_f、boar_init_r都是位置相关的c语言程序,这uboot版本代码真是搞不懂了!以前的老版本uboot还搞的懂,在执行c代码之前始终是在start.S汇编代码中执行,并且搬移代码也在start.S中完成,重定位地址在board/***/config.mk中定义TEXT_BASE,把uboot放在sdram的高端地址就可以了,而且搬移地址也是这地址;新版本的uboot搬移地址是board_init_f函数中算出来的,随便怎么样,这地址也不可能是config.mk中人工自己定义的一样,因此确实看不懂了。望哪位大侠给予指点。
另我下载了另一个版本的uboot为2011.3的版本,start.S中在跳转到board_init_f之前有一部分代码如下:
/* copy */
mov r0, #0
mov r4, r0
add r2, r0, #CONFIG_SYS_MONITOR_LEN
mov r1, #0x10000000
mov r5, r1
30:
ldr r3, [r0], #4
str r3, [r1], #4
cmp r0, r2
bne 30b
不知道是什么意思,不成了两次搬移代码了吗?