[Firefly-RK3399] Bootloader各个引导阶段直至加载Kernel的过程

Posted Neutionwei

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Firefly-RK3399] Bootloader各个引导阶段直至加载Kernel的过程相关的知识,希望对你有一定的参考价值。

1、BOOTROM阶段

BOOTROM的代码是Rockchip原厂芯片出厂时已烧录的代码,目的是从各个存储媒介中加载miniloader(tpl + spl),以下摘自RK3399芯片手册:

从图中可以看出BOOTROM会依次从Nor Flash、Nand Flash、eMMC、SD/MMC中校验ID BLOCK,由此便知道BOOTROM的存储媒介启动顺序为Nor Flash > Nand Flash > eMMC > SD/MMC。

2、SPL阶段

SPL阶段是U-Boot的前一级,SPL的目的也是加载U-Boot到内存,至于在加载哪一个存储媒介的U-Boot到内存,这个取决于dts的u-boot,spl-boot-order结点,以下来自uboot/arch/arm/dts/rk3399-firefly.dts

        chosen {
                stdout-path = &uart2;
                u-boot,spl-boot-order = &sdmmc, &sdhci;
        };

我们看到既有sdmmc,也有sdhci,其实在dts中,sdmmc就代表SD/MMC、sdhci就代表eMMC,这里sdmmc放得比sdhci靠前,自然优先级就是SD/MMC > eMMC,也就是如果eMMC与SD/MMC存储媒介中都有U-Boot,则会优先加载SD/MMC中的U-Boot,这就是为什么我们一插进SD卡后,会直接加载SD卡的镜像。

注意:eMMC与SD/MMC存储媒介均有镜像,那么这个SPL本身是从eMMC中加载到内存的。

3、U-Boot阶段

U-Boot的根本目的是加载内核,同时给内核传参。RK3399加载内核是通过依次执行三条命令实现,以下来自uboot/include/configs/rockchip-common.h

#define RKIMG_BOOTCOMMAND			\\
	"boot_android ${devtype} ${devnum};"	\\
	"bootrkp;"				\\
	"run distro_bootcmd;"

我们看到RK3399首先执行boot_android命令,这个命令是启动Android的Kernel使用的,当然这里的Android必须是GPT分区,以往Firefly-RK3399的Android 7.1是RK分区,这个命令不支持这种方式;第二条命令是bootrkp,这个是启动Linux的Kernel使用的,最后一条是run distro_bootcmd,我们来看一下distro_bootcmd环境变量的定义,来自uboot/include/config_distro_bootcmd.h

	"distro_bootcmd=" BOOTENV_SET_SCSI_NEED_INIT                      \\
		"for target in ${boot_targets}; do "                      \\
			"run bootcmd_${target}; "                         \\
		"done\\0"

我们可以看到它就相当于依次执行bootcmd_${target}环境变量的内容,到目前为止,博主未使用过这个命令加载内核,只知道它是主线U-Boot加载Kernel的方式。

注意:U-Boot一旦加载Kernel成功便不会再返回,因此上述三条命令有且只有一条命令加载Kernel成功,否则U-Boot就会加载Kernel失败,然后进入U-Boot shell。

以上是关于[Firefly-RK3399] Bootloader各个引导阶段直至加载Kernel的过程的主要内容,如果未能解决你的问题,请参考以下文章

[Firefly-RK3399] ADB命令使用

[Firefly-RK3399] U-Boot shell中增加saveenv命令

[Firefly-RK3399] U-Boot配置使用键盘与2.4G无线遥控

[Firefly-RK3399] Bootloader各个引导阶段直至加载Kernel的过程

[Firefly-RK3399] U-Boot配置U盘启动

[Firefly-RK3399] U-Boot适配红外遥控器IR