主题 : uboot关于重定位与搬移地址冲突的疑问 复制链接 | 浏览器收藏 | 打印
级别: 新手上路
UID: 74804
精华: 0
发帖: 8
金钱: 40 两
威望: 8 点
贡献值: 0 点
综合积分: 16 分
注册时间: 2012-07-29
最后登录: 2012-09-19
楼主  发表于: 2012-08-05 17:07

 uboot关于重定位与搬移地址冲突的疑问

我在移植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
不知道是什么意思,不成了两次搬移代码了吗?
级别: 侠客
UID: 11034
精华: 0
发帖: 71
金钱: 355 两
威望: 71 点
贡献值: 0 点
综合积分: 142 分
注册时间: 2009-11-25
最后登录: 2018-02-08
1楼  发表于: 2012-08-06 17:00
你是NAND启动还是NOR启动的?上面的那个代码只是NOR启动的
级别: 新手上路
UID: 74804
精华: 0
发帖: 8
金钱: 40 两
威望: 8 点
贡献值: 0 点
综合积分: 16 分
注册时间: 2012-07-29
最后登录: 2012-09-19
2楼  发表于: 2012-08-07 20:32
nor启动的,是我们公司自己开发的eoc哈!只要nor。
级别: 侠客
UID: 11034
精华: 0
发帖: 71
金钱: 355 两
威望: 71 点
贡献值: 0 点
综合积分: 142 分
注册时间: 2009-11-25
最后登录: 2018-02-08
3楼  发表于: 2012-08-08 09:45
光看你这些信息,我没能分析出问题的 你试下反汇编跟踪看下地址是怎么跳的
位置相关倒是可以通过自己指定分配地址和去掉arch/arm里的 LDFLAGS_u-boot += -pie 这个就可以了