u-boot移植(二)---修改前工作:代码流程分析1

一、代码执行总体流程图

1.1 代码路径 

  • U-boot.lds (arch\arm\cpu)
  • vectors.S (arch\arm\lib)
  • start.S (arch\arm\cpu\arm920t)
  • lowlevel_init.S (board\samsung\jz2440)
  • crt0.S (arch\arm\lib)
  • relocate.S (arch\arm\lib)
  • Board_init.c (common\init)
  • Board_f.c (common)
  • Jz2440.h (include\configs)
  • Generic-asm-offsets.h (include\generated)

1.2 启动代码流程图

  分析完后补上。

二、链接文件

  目录:u-boot-2017.03/arch/arm/cpu

  文件:u-boot.lds

  编写好的 .lds 文件,在用 arm-Linux-ld 连接命令时带 -Tfilename 来调用执行,如:arm-linux-ld-Tnand.lds x.o y.o -o xy.o

  也用-Ttext参数直接指定连接地址,如 arm-linux-ld-Ttext 0x30000000 x.o y.o -oxy.o

  既然程序有了两种地址,就涉及到一些跳转指令的区别。 
  ARM汇编中,常有两种跳转方法:b跳转指令、ldr指令向PC赋值。 
??要特别注意这两条指令的意思: 
  1> b step:b跳转指令是相对跳转,依赖当前PC的值,偏移量是通过该指令本身的bit[23:0]算出来的,这使得使用b指令的程序不依赖于要跳到的代码的位置,只看指令本身。 
  2> ldr pc, =board_init_r :该指令是一个伪指令编译后会生成以下代码:ldr pc, [pc, #8]

    从内存中的某个位置读出数据并赋给PC,同样依赖当前PC的值,所以可以用它实现从Flash到RAM的程序跳转。

  2种方式指明程序地址,这里分析下第二种方式,在根目录 Makefile文件有如下一行:

  

  在文件 include/configs/jz2440.h 有定义:

  

  我们在这里可以用下面的命令生成 u-boot.dis文件(注意交叉编译器的名字):

  arm-2440-linux-gnueabi-objdump -D -m arm u-boot > u-boot.dis

  

  在0 地址执行的是 _start.S文件,然后跳转到reset执行,接着定义异常向量表:

  

  在u-boot.lds 脚本中并没有指定基地址, 根目录下的 u-boot 脚本是由 arch/arm/cpu/u-boot.lds 在编译的时候生成的,所以如果要修改u-boot.lds 需要找到正确的地方。

  u-boot.lds 分析:  1 #include <config.h>

  2 /* 指定输出可执行文件是elf格式,32位ARM指令,小端模式  */
  3 OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
  4 OUTPUT_ARCH(arm) /* 指定输出文件的的平台体系为ARM */
  5 ENTRY(_start)    /* 指定可执行映像文件的起始段的段名是 _start,这里跳转到vector.S执行 */
  6 SECTIONS
  7 {
  8     /DISCARD/ : { *(.rel._secure*) }
  9     /* 指定可执行的 image 文件的全局入口点,通常这个地址都发给你法rom(flash)0x0位置。
 10      * 必须使编译器知道这个地址,一般不修改此处,而是修改其它地方的宏定义*/
 11     . = 0x00000000;
 12     . = ALIGN(4);
 13     .text :
 14     {
 15         /* 映像文件赋值起始地址,它在文件 arch/arm/lib/sections.c 中定义:
 16          * char __image_copy_start[0] __attribute__((section(".__image_copy_start")));*/
 17         *(.__image_copy_start)
 18         /* arch/arm/lib/vectors.S 里有一句:.section ".vectors"  */
 19         /* 这里的 vectors 是让vector.S 链接的二进制文件的开头部分 */
 20         *(.vectors)
 21         CPUDIR/start.o (.text*)        /* 执行 start.S */
 22         *(.text*)                    /* 其他代码 */
 23     }
 24
 25     . = ALIGN(4);
 26     /* 只读数据段,所有的只读数据段都放在这个位置  */
 27     .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
 28
 29     . = ALIGN(4);
 30     /* 可读写数据段,所有的可读写数据段都放在这个位置 */
 31     .data : {
 32         *(.data*)
 33     }
 34
 35     . = ALIGN(4);
 36
 37     . = .;
 38
 39     . = ALIGN(4);     /* U-BOOT命令段 */
 40     .u_boot_list : {
 41         KEEP(*(SORT(.u_boot_list*)));
 42     }
 43
 44     . = ALIGN(4);
 45
 46     .image_copy_end :
 47     {
 48         *(.__image_copy_end)
 49     }
 50     /* 相对动态信息段 */
 51     .rel_dyn_start :
 52     {
 53         *(.__rel_dyn_start)
 54     }
 55
 56     .rel.dyn : {
 57         *(.rel*)
 58     }
 59
 60     .rel_dyn_end :
 61     {
 62         *(.__rel_dyn_end)
 63     }
 64
 65     .end :
 66     {
 67         *(.__end)
 68     }
 69
 70     _image_binary_end = .;
 71
 72     /*
 73      * Deprecated: this MMU section is used by pxa at present but
 74      * should not be used by new boards/CPUs.
 75      */
 76     . = ALIGN(4096);
 77     .mmutable : {
 78         *(.mmutable)
 79     }
 80
 81 /*
 82  * Compiler-generated __bss_start and __bss_end, see arch/arm/lib/bss.c
 83  * __bss_base and __bss_limit are for linker only (overlay ordering)

     * bss段,里面放置的是初始值为0的全局变量和静态变量,这些变量不会保存在
        * 二进制文件中

 84  */
 85
 86     .bss_start __rel_dyn_start (OVERLAY) : {
 87         KEEP(*(.__bss_start));
 88         __bss_base = .;
 89     }
 90
 91     .bss __bss_base (OVERLAY) : {
 92         *(.bss*)
 93          . = ALIGN(4);
 94          __bss_limit = .;
 95     }
 96
 97     .bss_end __bss_limit (OVERLAY) : {
 98         KEEP(*(.__bss_end));
 99     }
100
101     .dynsym _image_binary_end : { *(.dynsym) }
102     .dynbss : { *(.dynbss) }
103     .dynstr : { *(.dynstr*) }
104     .dynamic : { *(.dynamic*) }
105     .plt : { *(.plt*) }
106     .interp : { *(.interp*) }
107     .gnu.hash : { *(.gnu.hash) }
108     .gnu : { *(.gnu*) }
109     .ARM.exidx : { *(.ARM.exidx*) }
110     .gnu.linkonce.armexidx : { *(.gnu.linkonce.armexidx.*) }
111 }

  链接执行,首先是进入到arch/arm/vector.S 中执行,在其中执行 _start.S ,_start.S 的首行就跳转到 start.S 中的 reset 中去执行了。

  这里没有执行SPL,若要加上SPL,则还需要加上 nandflash

  链接脚本暂时的流程为:

  

  跳转A处,A代码在Vector.S中,执行_start.S代码,下一节看 _start.S的代码,并分析其过程。

备注:后续会更新此文档

时间: 2024-12-12 15:09:25

u-boot移植(二)---修改前工作:代码流程分析1的相关文章

nova boot代码流程分析(三):nova与neutron的交互(2)

继续<nova boot代码流程分析(三):nova与neutron的交互(1)>的分析. #/nova/virt/libvirt/driver.py:LibvirtDriver # NOTE(ilyaalekseyev): Implementation like in multinics # for xenapi(tr3buchet) def spawn(self, context, instance, image_meta, injected_files, admin_password,

nova boot代码流程分析(五):VM启动从neutron-dhcp-agent获取IP与MAC

1.   network和subnet创建代码流程 [[email protected] ~(keystone_user1)]# neutron net-create demo-net [[email protected] ~(keystone_user1)]# neutron subnet-create  demo-net 1.1.1.0/24 --name demo-subnet --gateway 1.1.1.1 --enable_dhcp true 这里,我们主要分析上面两个命令的代码流

u-boot移植(三)---修改前工作:代码流程分析2

一.vectors.S 1.1 代码地址 vectors.S (arch\arm\lib) 1.2 流程跳转 跳转符号 B 为 start.S 中的 reset 执行代码,暂且先不看,先看看 vector.S 中的执行. 1.3 代码分析 ldr{条件} 目的寄存器 <存储器地址> 1 _start: 2 3 #ifdef CONFIG_SYS_DV_NOR_BOOT_CFG 4 .word CONFIG_SYS_DV_NOR_BOOT_CFG 5 #endif 6 /* LDR{条件} 目的

u-boot移植(三)---修改前工作:代码流程分析3---代码重定位

一.重定位 1.以前版本的重定位 2.新版本 我们的程序不只涉及一个变量和函数,我们若想访问程序里面的地址,则必须使用SDRAM处的新地址,即我们的程序里面的变量和函数必须修改地址.我们要修改地址,则必须知道程序的地址,就需要在链接的时候加上PIE选项: 加上PIE选项后,链接时候的地址就会生成,然后存储在段里面,如下段(u-boot.lds): 然后我们根据这些地址的信息来修改代码,程序就可以复制到SDRAM的任何地方去. 二.代码流程 start.S中执行到了 bl _main,跳转到_ma

nova boot代码流程分析(二):nova-scheduler主机选择

本篇文章将分析nova-scheduler服务在创建VM时如何进行主机的选择.完整来说,nova-scheduler主机选择的过程主要分为以下几个阶段: 1. nova.scheduler.rpcapi.SchedulerAPI发出RPC请求到nova.scheduler.manager.SchedulerManager. 2. 从SchedulerManager到调度器(类SchedulerDriver). 3. 从SchedulerDriver到Filters. 4. 从Filters到权重

nova boot代码流程分析(一):Claim机制

nova boot创建VM的流程大致为: 1. novaclient发送HTTP请求到nova-api(这里内部细节包括keystone对用户的验证及用户从keystone获取token和endpoints等信息,具体参考<keystone WSGI流程>). 2. nova-api通过rpc调用到nova-conductor. 3. nova-conductor调用rpc进入nova-scheduler进行compute节点的选择,nova-scheduler将compute节点选择的信息的

分享一个ASP.NET开发中经常碰到的小问题,修改好的js代码保存生成后,在运行调试时却还是修改前的代码

记得刚开始学ASP.NET的时候就遇到过这个问题,各种无语,明明本地代码改了,保存生成了N遍,甚至重开VS,清浏览器缓存,都没用,调试起来就还是修改之前的js代码,上网查了半天也没查到解释,倒是有人提同样的问题,但是没人能给出答案. 于是那段时间很悲剧的只能每次出现这个问题,就重新建一个Web项目,把代码粘过去... 后来我尝试了下把VS升级到了2013,之后似乎就没出现过这个问题了,于是就以为就是VS2010的bug. 最近到了一家新公司,公司统一用VS2010,于是这个问题就又出现了..但是

六、uboot 代码流程分析---start.S

6.1 _start 入口函数 6.1.1 vectors.S (arch\arm\lib) 从上一节可以知道,uboot 的入口函数为 _start .此 函数定义在 vectors.S (arch\arm\lib) 中. 在此文件中,定义了异常向量表,及其操作函数._start 开始后,直接跳入  reset 复位中执行启动. 1 /* 头文件包含,包含架构和配置相关的头文件,自动生成的 */ 2 #include <config.h> 3 4 /* 5 * A macro to allo

Struts2代码流程分析

以一个修改的小例子来阐述Struts2的工作流程 页面from表单     <form action="ModifyPassword.action" method="post">     <table cellspacing="0" cellpadding="5" width="100%" align="left">      <tr>     <