uboot 用c语言替换relocate.S

crt0.S

ENTRY(_main)

    @ldr    r0, [r9, #GD_RELOCADDR]        /* r0 = gd->relocaddr */
    @b    relocate_code
    b   do_relocate_code
here:

 xxxxxxx

......

 

drivers/gic/sunxi_gic.c

extern char __bss_start[];
extern char __bss_end[];
extern char __image_copy_start[];
extern char __image_copy_end[];
extern char __rel_dyn_start[];
extern char __rel_dyn_end[];
extern ulong _TEXT_BASE;    /* code start */

void do_copy_uboot2highaddr(void)
{     
    if( (gd->relocaddr - (ulong)__image_copy_start)  == 0x00 ){
        ;
    }else{      
        memcpy((char *)gd->relocaddr, __image_copy_start, __image_copy_end-__image_copy_start);       
    }
}


void do_fix_rel_dyn( void )   
{           
    ulong *rel_dyn_start;
    ulong *rel_dyn_end;
    ulong g_off = 0x00;
    int index;
    ulong temp1,target_pos; 
    rel_dyn_start = (ulong *)__rel_dyn_start;    
    rel_dyn_end   = (ulong *)__rel_dyn_end;
    int debug_output = 0x00;
    index = 0x00;

    debug( "\ng_off = %lx\n", g_off );
    debug( "gd->relocaddr = %lx\n", gd->relocaddr );
    debug( "__image_copy_start = %p\n", __image_copy_start );
    debug( "g_off = %lx\n", gd->relocaddr - (ulong)__image_copy_start );
    debug( "rel len       = %x\n", rel_dyn_end - rel_dyn_start );
    debug( "rel_dyn_start = %p\n", rel_dyn_start );
    debug( "rel_dyn_end   = %p\n",   rel_dyn_end   );
    
    g_off = gd->relocaddr - (ulong)__image_copy_start;
    //macdbg_dmphex((char *)rel_dyn_start, 0x100);
    //macdbg_dmphex((char *)rel_dyn_start+g_off, 0x100);

    while(1){
      if( index < 50 ){
             debug_output = 0;
      }else{
          debug_output = 0; 
      }
       
      #if 0
      ldr r0, =#biaohao
      ldr r0, [r0]
      ...
      biaohao:
         var:变量的绝对地址  4a000a14
      假设 var相对于 ldr指令的相对偏移位置为3 
      ldr r0, [pc+ 3] 
      r0即为变量的绝对地址
      然后 ldr r0, [r0] 取得变量的值
      
      代码重定向后 ldr r0, [pc+ 3] 
      取得的变量的绝对地址还是原来的 4a000a14
      所以需要 4a000a14 + g_off
      4a000a14 + g_off 需要设置到  biaohao位置
      作为他的新值

      白话理解就是:修正code段中的label值
      label值为 变量的绝对地址
      那重定向了 比如移动了1M位置 
      变量的绝对地址也需要 加1M,才能正确寻址到相应的变量

      先相对寻址 获取 label的地址
      这个由于是pc相对寻址的指令 重定向对他没有影响
      关键在于 label内的值的修正
      #endif
      
      if( (rel_dyn_start[index+1] & 0xff) == 0x17 ){
          target_pos = rel_dyn_start[index] + g_off;
          //重定向后的某一变量的地址的指针
          if( debug_output ){
              debug( "\ntarget_pos = %lx\n", target_pos );
              debug( "rel_dyn_start[index] = %lx\n", rel_dyn_start[index] );
          }
          temp1 = *(ulong *)target_pos;
          //重定向前某一变量的地址 

          if( debug_output ){
              debug( "temp1 = %lx\n", temp1 );
          }
          
          temp1 = temp1 + g_off;
          //地址重定向 + 偏移量 = 重定向后某一变量的地址

          if( debug_output ){
              debug( "temp11 = %lx\n", temp1 );
          }
          
          *(ulong *)target_pos = temp1;
          //把某一变量的重定向的地址值  存入重定向后的某一变量的地址的地址
      }
      index = index+2;
      if( index == (rel_dyn_end - rel_dyn_start) ){
          break;
      }
    }
}


void do_relocate_code( void )    
{       
    do_copy_uboot2highaddr();
    do_fix_rel_dyn();
}
    
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值