HI3516DV300_15_Uboot详解


一、分段式uboot的生成过程解析

1.0 与以往Uboot不同的

两段式的Uboot:直接编译的Uboot不能用,还得经过一次编译生成Uboot-z才行,还要进行二次制作;也就是,先编译生成一个Gzip工具,再结合那个excel表格生成一个.reg文件,最终生成最终文件;现在很多平台,比如全志,也都会采用这种两段式的Uboot的方式。

1.1 顺着顶层Makefile的u-boot-z目标去找

  • 首先在顶层的Makefile里面找到u-boot-z

依赖于uboot目录下的u-boot.bin文件

由u-boot.bin叠加reg文件生成u-boot-z.bin

  • 分析如何由u-boot.bin生成u-boot-z.bin

其实就是进入到下面这个目录去执行下面这个目录的Makefile,并且是执行默认目标

  • 分析以上Makefile

找到要执行生成的目标文件.bin

找到目标文件.bin的依赖:.tmp,.regfile

.regfile:看名字就知道是生成的.reg文件,下面就是判断Uboot顶层文件夹有没有reg文件,或reg文件有没有错误

.tmp:依赖于tmp文件
tmp这个依赖文件又依赖于u-boot.elf
u-boot.elf有依赖于image_data.gzip
image_data.gzip又依赖于BINIMAGE,这个BINIMAGE就是上级传过来的u-boot.bin

SRC, START, COBJS

SRC,来自于SSRC

SSRC

一定是先解压到老版本的U-Boot到DDR里面去,再执行老版本的U-Boot,所以以下部分的源码是不能压缩的

所以分析到这里就知道:elf的依赖里面:

第一个依赖就是:压缩之后的老版本的Uboot
后面二个就是:没有压缩的那一部分

后面2个:START,COBJS

这里面也都是一些与解压相关的,只是语法的问题,并不是重复了

.tmp:由上述uboot.elf生成了.tmp文件

uboot.bin:由 .tmp文件 + regfile一起生成uboot.bin文件

1.2 中间的生成过程,其实是可以去分析的

1.2.1 elf文件时怎么来的

调用链接器的代码

-Bstatic:表示静态链接
-T u-boot.lds:表示指定链接脚本
链接的规则就是: u-boot.lds
链接脚本的路径如下图所示:

从链接脚本中可以看出:ENTRY(_ start)
链接的时候:start.o也是在最前面的,所以会把Start.S放在最前面

-Ttext:指定我们的目标地址,这就是程序的链接地址,这个链接地址是:$(TEXTBASE),即为:

TEXTBASE这个地址,就是我们整个系统的DDR的地址

$(START),$(COBJS):就是一些依赖文件

$(BOOT).map:生成一个map文件,就是用于查符号表之类的

$(OBJDUMP),:生成了一个反汇编文件,如果符号表要查阅反汇编文件,查阅这里就行了

1.2.2 image_data.gzip是压缩包,既然是压缩包的话,那是怎样链接的

其实很简单,就是往压缩包里面塞文件

具体看链接的规则: u-boot.lds

这些都是来源于Source里面的那些东西,并且全部是.o

整个没有被压缩的这段代码,长度必须小于0x6000,也就是必须小于24K Byte

也就是Uboot启动的第一阶段的代码,不能大于24K Byte

系统在启动的时候,会自动从eMMC读取一段固定大小的内容到内部sRAM中,然后跳转去执行它,这部分的内容就是U-Boot的第一阶段,也就是上面列出来的内容,这里面的函数,在第一阶段,会被加载进去;在海思里面,这段sRAM的大小就是24K Byte

就在下面这一部分,往压缩包里面添加东西的了

压缩完成之后,它的属性就设置为.image了,这个是看段属性的

整个步骤完成了之后,就会生成.elf

1.2.3 .tmp文件是如何生成的呢

这个从.elf到.tmp的过程就和以前从.elf到bin的过程差不多

这个从.elf到.tmp的的过程:执行的是OBJCOPY

1.2.4 由.tmp以及regfile文件生成bin文件

tmp就已经是二进制文件了,其实就已经是镜像了

具体如何添加上regfile呢?

首先来分析前三行

第一行:从tmp里面读取前64个字节到tmp1中
第二行:从regfile里面读取8192个字节(其实就是8K)到tmp2中(.reg文件本来是没有8K Byte的,但是在这里,被填充到8K Byte了);这样做是因为:想把reg文件固定一个范围,不想把它设定为一个动态的大小。
第三行:从tmp文件拷贝到输出文件,输出文件跳过前8256字节,生成tmp3

所以:

tmp1就是:tmp的前64个字节;就是一些符号位,相当于一些头部。
tmp2就是:.reg文件被吹大到8192字节(8K Byte);就是寄存器配置的主体。
tmp3就是:tmp文件拷贝到输出文件,输出文件跳过前8256字节,生成tmp3;tmp3文件大小就是tmp文件的大小 + 8256字节;就是:未压缩的Uboot的第一阶段 + 原始Uboot的压缩版。

后面:

把tmp1,tmp2,tmp3合并在一起,就申城额Uboot-z.bin文件
最后的bin文件,其实就是tmp1+tmp2+tmp3,分为3段,这个就是最终的uboot.bin了
可以发现,为什么要腾出8256字节,是因为:8192+64=8256,为了方便放置前面的2个文件
镜像大小:64+8192+temp3大小 = 8256+temp3大小

1.3 分析过程的关键记录

  • image_data.gzip:其实就是第一次编译出来的老版本u-boot.bin进过gzip压缩后的压缩文件

分析:以前老版本的U-boot是编译完就直接丢进去运行了,这里呢,还进行了压缩,可以解释的一个原因就是U-boot太大了

  • 分析:uboot.bin被压缩肯定带来2个问题:

    1.uboot执行时肯定要解压缩再执行

2.最终烧录到emmc中去执行的uboot,肯定有一段是未经过压缩的;肯定有一段解压代码在外部,没有进行压缩。

  • 最终版本的uboot是链接到0x80700000地址的

    所以将来最终版本的U-boot一定要被加载到这个地址去运行,否则就会出现运行地址和链接地址不正确,导致运行不了

  • uboot.elf的内容:前面都是未经压缩的uboot第一阶段,后面是被压缩的原版uboot镜像

    前面:eMMC直接Load 24K的文件

后面:后面是因为第二阶段才会被拉过来用

  • 所以:

    tmp1就是:tmp的前64个字节;就是一些符号位,相当于一些头部。
    tmp2就是:.reg文件被吹大到8192字节(8K Byte);就是寄存器配置的主体。
    tmp3就是:tmp文件拷贝到输出文件,输出文件跳过前8256字节,生成tmp3;tmp3文件大小就是tmp文件的大小 + 上8256字节;就是:未压缩的Uboot的第一阶段 + 原始Uboot的压缩版。

  • 后面:

    把tmp1,tmp2,tmp3合并在一起,就申城额Uboot-z.bin文件
    最后的bin文件,其实就是tmp1+tmp2+tmp3,分为3段,这个就是最终的uboot.bin了
    可以发现,为什么要腾出8256字节,是因为:8192+64=8256,为了方便放置前面的2个文件
    镜像大小:64+8192+temp3大小 = 8256+temp3大小


Author: Ruimin Huang
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source Ruimin Huang !
  TOC