omapl138移植uboot系列之uboot SPL代码分析(第三篇)

    单纯的从源码开始分析uboot是一件十分令人头疼的事,因为uboot不只是针对你是用的芯片架构,你在分析源码时所遇到的那些条件编译你很难去找到它定义的地方,更别说这个宏到底有没有被定义,我个人比较喜欢对照着反汇编去分析源代码。

    在顶层目录下执行:

make omapl138_lcdk_defconfig

make

  1. MEMORY { .sram : ORIGIN = 0x80000000, LENGTH = 131072 }
  2. OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
  3. OUTPUT_ARCH(arm)
  4. ENTRY(_start)
  5. SECTIONS
  6. {
  7.  . = 0x00000000;
  8.  . = ALIGN(4);
  9.  .text :
  10.  {
  11.  __start = .;
  12.    *(.vectors)
  13.    arch/arm/cpu/arm926ejs/start.o (.text*)
  14.    *(.text*)
  15.  } >.sram
  16.  . = ALIGN(4);
  17.  .rodata : { *(SORT_BY_ALIGNMENT(.rodata*)) } >.sram
  18.  . = ALIGN(4);
  19.  .data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram
  20.  . = ALIGN(4);
  21.  .u_boot_list : { KEEP(*(SORT(.u_boot_list*))); } >.sram
  22.  . = ALIGN(4);
  23.  .rel.dyn : {
  24.   __rel_dyn_start = .;
  25.   *(.rel*)
  26.   __rel_dyn_end = .;
  27.  } >.sram
  28.  .bss :
  29.  {
  30.   . = ALIGN(4);
  31.   __bss_start = .;
  32.   *(.bss*)
  33.   . = ALIGN(4);
  34.   __bss_end = .;
  35.  } >.sram

编译完成后,在目录spl下找到我们生成的u-boot-spl.lds链接脚本:

    由链接脚本我们可以得出以下信息:

      1.程序的入口地址在_start处

      2._start入口函数在arch/arm/cpu/arm926ejs/start.S处定义

  执行arm-linux-objdump -D u-boot-spl > u-boot-spl.dis

 

  1. 80000000 <__start>:
  2. 80000000: ea000016   b   80000060 <reset>
  3. 80000004: e59ff014   ldr pc, [pc, #20]  ; 80000020 <_undefined_instruction>
  4. 80000008: e59ff014   ldr pc, [pc, #20]  ; 80000024 <_software_interrupt>
  5. 8000000c: e59ff014   ldr pc, [pc, #20]  ; 80000028 <_prefetch_abort>
  6. 80000010: e59ff014   ldr pc, [pc, #20]  ; 8000002c <_data_abort>
  7. 80000014: e59ff014   ldr pc, [pc, #20]  ; 80000030 <_not_used>
  8. 80000018: e59ff014   ldr pc, [pc, #20]  ; 80000034 <_irq>
  9. 8000001c: e59ff014   ldr pc, [pc, #20]  ; 80000038 <_fiq>

 

  即生成u-boot-spl的反汇编文件:

  1. 80000060 <reset>:
  2. 80000060: e10f0000   mrs r0, CPSR
  3. 80000064: e3c0001f   bic r0, r0, #31
  4. 80000068: e38000d3   orr r0, r0, #211   ; 0xd3
  5. 8000006c: e129f000   msr CPSR_fc, r0
  6. 80000070: eb000228   bl  80000918 <_main>

 

    可以看出,SPL的链接地址为0x80000000,即omapl138的SHARERAM中,在0x80000000处程序直接无返回的跳到了reset处,即0x80000060地址。

reset处,ARM处理器切换到SVC模式,然后跳到\arch\arm\lib\crt0.S_main处运行。

  1. 80000918 <_main>:
  2. 80000918: e59fd054   ldr sp, [pc, #84]  ; 80000974 <clbss_l+0x1c>
  3. 8000091c: e3cdd007   bic sp, sp, #7
  4. 80000920: e1a0000d   mov r0, sp
  5. 80000924: eb0001a8   bl  80000fcc <board_init_f_alloc_reserve>
  6. 80000928: e1a0d000   mov sp, r0
  7. 8000092c: e1a09000   mov r9, r0
  8. 80000930: eb0001a8   bl  80000fd8 <board_init_f_init_reserve>
  9. 80000934: e3a00000   mov r0, #0
  10. 80000938: eb000011   bl  80000984 <board_init_f>
  11. 8000093c: eb000058   bl  80000aa4 <spl_relocate_stack_gd>
  12. 80000940: e3500000   cmp r0, #0
  13. 80000944: 11a0d000   movne  sp, r0
  14. 80000948: 11a09000   movne  r9, r0
  15. 8000094c: e59f0024   ldr r0, [pc, #36]  ; 80000978 <clbss_l+0x20>
  16. 80000950: e59f1024   ldr r1, [pc, #36]  ; 8000097c <clbss_l+0x24>
  17. 80000954: e3a02000   mov r2, #0

 

一开始就设置了栈地址并且8byte对齐,因为如果没有设置栈是不能调用C语言函数的,接下来就可以调用C语言函数啦,跳转到第一个C函数board_init_f_alloc_reserve

  1.  80000fcc <board_init_f_alloc_reserve>:
  2. 80000fcc: e24000a8   sub r0, r0, #168   ; 0xa8
  3. 80000fd0: e3c0000f   bic r0, r0, #15
  4. 80000fd4: e12fff1e   bx  lr

 

对照C函数

  1. ulong board_init_f_alloc_reserve(ulong top)
  2. {
  3.     /* Reserve early malloc arena */
  4. #if defined(CONFIG_SYS_MALLOC_F)
  5.     top -= CONFIG_SYS_MALLOC_F_LEN;
  6. #endif
  7.     /* LAST : reserve GD (rounded up to a multiple of 16 bytes) */
  8.     top = rounddown(top-sizeof(struct global_data), 16);
  9.  
  10.     return top;
  11. }

 

  1.  80000984 <board_init_f>:
  2. 80000984: e12fff1e   bx  lr

 

自刚开始设置的sp栈地址处开始往下168Byte空间存放u-bootglobal data,函数返回后,继续跳转到board_init_f_init_reserve初始化该数据结构,再次返回后跳转至board_init_f函数:

  1. 80000aa4 <spl_relocate_stack_gd>:
  2. 80000aa4: e3a00000   mov r0, #0
  3. 80000aa8: e12fff1e   bx  lr

 

该函数什么也没做,直接返回

最后最关键的board_init_r函数,由于该函数篇幅太长,这里不再贴出,该函数完成了omapl138系统时钟的设置,串口控制台的配置等,从启动介质中加载uboot的imag镜像置DDR,然后启动uboot,SPL任务完成。

猜你喜欢

转载自blog.csdn.net/weixin_42314225/article/details/80459596