《u-boot.lds分析》

u-boot.lds (~/board/smdk2410/u-boot.lds)

/*指定输出可执行文件是elf格式,32位ARM指令,小端*/
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/

/*指定输出可执行文件的平台为ARM*/
OUTPUT_ARCH(arm)

/*指定输出可执行文件的起始代码段为_start*/
ENTRY(_start)
SECTIONS
{
   /*指定可执行image文件的全局入口点,通常这个地址都放在ROM(flash)0x0位置。必须使编译器知道这个地址,通常都是修改此处来完成*/
    . = 0x00000000;/*;从0x0位置开始*/

    . = ALIGN(4);/*代码以4字节对齐*/
    .text:
    {
    /*代码的第一个代码部分*/  
      cpu/arm920t/start.o    (.text)
      *(.text)
    }

    . = ALIGN(4);
    .rodata : { *(.rodata) } /*指定只读数据段*/

    . = ALIGN(4);
    .data : { *(.data) }/* 可读写数据段,所有的可读写数据段都放在这里*/

    . = ALIGN(4);
    .got : { *(.got) }/*指定got段, got段是uboot自定义的一个段, 非标准段*/

    . = .;
    __u_boot_cmd_start = .;  /*把__u_boot_cmd_start赋值为当前位置, 即起始位置*/
    .u_boot_cmd : { *(.u_boot_cmd) } /*指定u_boot_cmd段, uboot把所有的uboot命令放在该段.*/
    __u_boot_cmd_end = .;/*把__u_boot_cmd_end赋值为当前位置,即结束位置*/

    . = ALIGN(4);
    __bss_start = .; /*把__bss_start赋值为当前位置,即bss段的开始位置*/
    .bss : { *(.bss) }
    _end = .;/*把_end赋值为当前位置,即bss段的结束位置*/
}

  以上是smdk2410中的u-boot.lds。

  U-boot中那段relocate代码就是通过adr实现当前程序是在RAM中还是flash中:
  relocate:/* 把U-Boot重新定位到RAM*/
  adr r0, _start /* r0是代码的当前位置*/

  /*adr伪指令,汇编器自动通过当前PC的值算出这条指令中"_start"的值,执行到_start时PC的值放到r0中:当此段在flash中执行时r0= _start = 0;当此段在RAM中执行时_start=_TEXT_BASE(在board/smdk2410/config.mk中指定的值为0x33F80000,即u-boot在把代码拷贝到RAM中去执行的代码段的开始)*/

  上面start.o中的代码装载地址和运行地址都为0x00000000,但是在start.o中会有一个u-boot自拷贝及重定位过程,start.o执行到最后时,整个u-boot已经被复制到了内    存的TEXT_BASE(0x33f80000)位置,开始执行下面的跳转语句:
  ldr pc, _start_armboot  /*将标号_start_armboot的值传给pc,实际上是将start_armboot函数的首地址传给pc但是此时的start_armboot应该是在内存中,因为start_armboot一定是在4kB之后,而nandflash4kB之后的代码是无法直接访问的,必须先读入内存。而这时候u-boot的代码已经被拷贝并重定位到内存中,所以此处加在到pc的地址应当是内存中的地址,即33f800之后的某一地址*/_start_armboot: .word start_armboot

  

猜你喜欢

转载自www.cnblogs.com/zhuangquan/p/11431280.html