0
点赞
收藏
分享

微信扫一扫

Android系统10 RK3399 init进程启动(八) u-boot启动逻辑

说明

系统:Android10.0

设备: FireFly RK3399 (ROC-RK3399-PC-PLUS)

前言

         上一篇讲到了u-boot编译完成之后,会生成各种镜像, 本章节重点介绍u-boot各个镜像生成的基本流程, 通过了解文件, 来辅助理解rk3399 u-boot启动基本过程。

一,编译u-boot的一般步骤

如果不考虑现有源码中的各种脚本, 比如不管make.sh, 编译u-boot的源码的一般步骤有以下通用步骤:

1,设置交叉工具链,一般修改Makefile

        ARCH=arm
        CROSS_COMPILE=../prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-

或者在make命令后面直接传递参数。

2, 选择芯片配置文件, 如rk3399, 其实是将configs/xxx_defconfig拷贝到顶层目录.config

        make rk3399_defconfig

3,  make编译

二, u-boot.bin文件生成

可以通过编译的调试信息中发现如下结果:

 /mnt/ext-disk2/RK/rk3399_Android10.0/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-objcopy --gap-fill=0xff  -j .text -j .secure_text -j .secure_data -j .rodata -j .data -j .u_boot_list -j .rela.dyn -j .got -j .got.plt -j .dtb.init.rodata -j .efi_runtime -j .efi_runtime_rel -O binary  u-boot u-boot-nodtb.bin
 

 cat u-boot-nodtb.bin dts/dt.dtb > u-boot-dtb.bin
  cp u-boot-dtb.bin u-boot.bin
  truncate -s "%8" u-boot.bin  #直接设置成一定大小文件


 最终发现,Makefile中通过objcopy, 将elf格式的u-boot转换成u-boot-nodtb.bin。

三, uboot.img文件生成

注意, 这个镜像叫做uboot.img 而在同一级目录下有个叫做u-boot.img , 镜像是由如下脚本生成的:

/mnt/ext-disk2/RK/rk3399_Android10.0/u-boot/scripts/uboot.sh --load 0x00200000

 load addr is 0x200000!
pack input u-boot.bin
pack file size: 1028816(1004 KB)
crc = 0xdbf2d111
uboot version: U-Boot 2017.09 (Nov 15 2021 - 17:03:41)
pack uboot.img success!
pack uboot okay! Input: u-boot.bin
 

在uboot.sh脚本中,实际是调用了:

./tools/loaderimage --pack --uboot u-boot.bin uboot.img ${LOAD_ADDR} ${SIZE}

rk3399平台执行的脚本为:

        ./tools/loaderimage --pack --uboot u-boot.bin uboot.img 0x00200000    

通过名字大体可以猜测到,应该就是在u-boot.bin上增加一个入口地址0x00200000 , 这个地址就是u-boot.bin被加载到内存的地址。

其他镜像如下:

 ./tools/mkimage -f auto -A arm -T firmware -C none -O u-boot -a 0x00200000 -e 0 -n "U-Boot 2017.09"" for evb_rk3399 board" -E -b arch/arm/dts/rk3399-evb.dtb -d u-boot-nodtb.bin u-boot-dtb.img

 ./tools/mkimage -f auto -A arm -T firmware -C none -O u-boot -a 0x00200000 -e 0 -n "U-Boot 2017.09"" for evb_rk3399 board" -E -b arch/arm/dts/rk3399-evb.dtb -d u-boot-nodtb.bin u-boot.img 

这么看 u-boot-dtb.img和u-boot.img 是一样的, 都是通过在u-boot-nodtb.bin加上一个头部信息, 类似内核zImage和uImage的差别。

四, rk3399_loader_v1.24.126.bin生成

打包loader镜像是通过make.sh loader来完成的, 最终执行如下:

 rk3399对应的脚本为:

u-boot/scripts/loader.sh --ini   ../rkbin/RKBOOT/RK3399MINIALL.ini

而../rkbin/RKBOOT/RK3399MINIALL.ini配置文件是:

[CHIP_NAME]
NAME=RK330C
[VERSION]
MAJOR=1
MINOR=26
[CODE471_OPTION]
NUM=1
Path1=bin/rk33/rk3399_ddr_800MHz_v1.24.bin
Sleep=1
[CODE472_OPTION]
NUM=1
Path1=bin/rk33/rk3399_usbplug_v1.26.bin
[LOADER_OPTION]
NUM=2
LOADER1=FlashData
LOADER2=FlashBoot
FlashData=bin/rk33/rk3399_ddr_800MHz_v1.24.bin
FlashBoot=bin/rk33/rk3399_miniloader_v1.26.bin
[OUTPUT]
PATH=rk3399_loader_v1.24.126.bin

可以得知依赖的文件有:DDR相关的bin/rk33/rk3399_ddr_800MHz_v1.24.bin、USB相关的bin/rk33/rk3399_usbplug_v1.26.bin、miniloader(瑞芯微自己写的不开源的bootloader)相关的bin/rk33/rk3399_miniloader_v1.26.bin。
boot_merger将这三个bin文件最后合并成rk3399_loader_v1.24.126.bin。

五, trust.img生成

make.sh trust: 打包trust.img镜像, 实际调用:

   ${SCRIPT_ATF} --ini ${INI_TRUST} ${PLAT_SHA} ${PLAT_RSA} ${PLAT_TRUST_SIZE}

  rk3399对应的脚本为:

        u-boot/scripts/atf.sh --ini  ../rkbin/RKTRUST/RK3399TRUST.ini

 atf 是arm trust firmware缩写, atf.sh脚本负责将几个和trust zone相关的二进制合并在一起:

[VERSION]
MAJOR=1
MINOR=0
[BL30_OPTION]
SEC=0
[BL31_OPTION]
SEC=1
PATH=bin/rk33/rk3399_bl31_v1.35.elf
ADDR=0x00040000
[BL32_OPTION]
SEC=1
PATH=bin/rk33/rk3399_bl32_v2.01.bin
ADDR=0x08400000
[BL33_OPTION]
SEC=0
[OUTPUT]
PATH=trust.img

六, rk3399上电启动u-boot逻辑

1、板卡上电,cpu从片内0xffff0000(bootrom)启动,将外部存储(spi flash, emmc, sd/tf等)中读取的MiniLoaderAll.bin复制到内部SRAM中,完成对关键部分进行初始化, 如时钟,中断, 外部内存,usb设备等的初始化.(u-boot代码也可能做同样的事情)

2、MiniLoaderAll从外部存储(spi flash, emmc, sd/tf等)中读取parameter.txt,并进行解析,解析出来各个分区信息;

3、根据分区信息在外部存储的指定位置寻找trust.img镜像,并执行trust zone相关安全认证代码, 认证完毕就加载u-boot.img到指定的地址(0x00200000)运行

4, u-boot在内存中执行, 并解析bootcmd代码,启动内核

七, make.sh脚本主要执行步骤

了解了上面的过程, 大家也可以对make.sh脚本进行分析, 这里将主要的结果步骤大体列举一下, 总共会经历12条指令, 大家可以通过set -x 和 set +x对脚本进行调试查看。

process_args $*
prepare
select_toolchain
select_chip_info
fixup_platform_configure
select_ini_file
handle_args_late
sub_commands
clean_files
make V=1 CROSS_COMPILE=${TOOLCHAIN_GCC} all #--jobs=${JOB}
pack_images
finish
 

第一条指令:process_args $* 
 #实际就是process_args rk3399, 结果就是分析各种参数, 同时执行make rk3399_defconfig -j${JOB}

第二条指令:prepare  获取rkbin工具路径, 并且根据是否64位设置对应的ARM64_TRUSTZONE="y" (是有的), 以及PLAT_TYPE="FIT"(没有)

第三条指令:select_toolchain 设置交叉工具链

,64位和32位分分别在:
TOOLCHAIN_ARM32=../prebuilts/gcc/linux-x86/arm/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin
TOOLCHAIN_ARM64=../prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin

第四条指令:select_chip_info 从.config文件获取芯片信息

        根据.config中的芯片名字, 在表格CHIP_TYPE_FIXUP_TABLE中找loader, trust, label的名字,对于rk399而言, 表格中并没有对应单项

第五条指令:fixup_platform_configure 在表格中通过芯片名字选择平台配置

        比如配置rsa加密算法和sha签名算法版本, 32位和64位对应的uboot, trust镜像大小和个数

而表格中并没有rk3399的配置, 所以都是用默认的-, 使用默认的uboot镜像大小, trust镜像大小

第六条指令:select_ini_file:选择ini配置文件
    minibootloader的配置文件:../rkbin/RKBOOT/RK3399MINIALL.ini
    trust镜像配置文件:        ../rkbin/RKTRUST/RK3399TRUST.ini    

第七条指令:补充部分编译参数

第八条指令:处理子命令, 如make.sh uboot, make.sh trust等

第9条指令:clean_files, 删除目标文件, 如 u-boot, tpl/u-boot-tpl.dtb等我呢间

第10条指令:直接make 编译

第11条指令: pack_images 打包

        主要是打包uboot.img, trust.img , rk3399_loader_v1.24.126.bin

第12调指令finish :结束, 只是打印信息

六,总结

u-boot编译的相关镜像是如何生成的, 以及上电之后, RK3399做了什么事情,这块大家需要心里有个大体的概念, 此处并没有涉及到代码层面, 所以更多的是梳理流程和理解逻辑, 我们在了解整个RK3399 启动Android 的过程的时候, 就应该从上电开始, 这样才能形成一个整体。


举报

相关推荐

0 条评论