uboot 2014以后的版本已经加入了支持快速启动的spl模式,本文用iMX6Q-SDP开发板做个简单讲解
在官方的yocot中下载fsl-L4.9.11_1.0.0-ga版本代码并编译,提取出uboot、kernel和rootfs做为SPL模式的示范
看一下uboot官方对SPL和过去对比的描述
如下是denx对spl的描述
如下是SPL模式的简易时序图
如下针对iMX6Q Sabresd SD开发板打开SPL模式
uboot部分
开发板对应的配置文件为mx6qsabresd_defconfig
打开SPL模式需要在配置文件加入一个宏CONFIG_SPL=y
此时的defconfig配置文件已经打开SPL模式了,能够完成boot_rom --> SPL --> uboot --> kernel 的过程了
但此时还没达到快速启动的目的,需要跳过uboot直达kernel才行:boot_rom --> SPL --> kernel
为此查看uboot/README的SPL framework部分
CONFIG_SPL
Enable building of SPL globally.
此项我们在defconfig中已经打开
CONFIG_SPL_OS_BOOT
Enable booting directly to an OS from SPL.
See also: doc/README.falcon
有一项说明了从SPL跳转到kernel需要打开此宏
在include/configs/mx6_common.h中加入定义#define CONFIG_SPL_OS_BOOT,然后编译
得到如下明确的错误提示
在uboot/README or 查阅未定义的宏得知具体含义
CONFIG_SYS_SPL_ARGS_ADDR Address in RAM where the parameters must be copied by SPL.
In most cases, it is <start_of_ram> + 0x100
CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR,
CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTORS
Sector and number of sectors to load kernel argument
parameters from when MMC is being used in raw mode
(for falcon mode)
CONFIG_SYS_MMCSD_RAW_MODE_KERNEL_SECTOR
Sector to load kernel uImage from when MMC is being
used in raw mode (for Falcon mode)
含义非常明确
具体是多少需要算一下,此处只要求kernel的地址信息,隐藏了uboot和SPL的地址信息,由此我们可以根据SPL和uboot的地址,算出允许kernel和dtb写入的安全地址
SPL的位置是由boot_rom指定的位于mmc的0x400位置,不可更改
uboot位置则在include/configs/imx6_spl.h中指定
/* MMC support */
#if defined(CONFIG_SPL_MMC_SUPPORT)
#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR 138 /* offset 69KB */
#define CONFIG_SYS_U_BOOT_MAX_SIZE_SECTORS 800 /* 400 KB */
#define CONFIG_SYS_MMCSD_FS_BOOT_PARTITION 1
#define CONFIG_SYS_MONITOR_LEN (CONFIG_SYS_U_BOOT_MAX_SIZE_SECTORS/2*1024)
#endif
此宏CONFIG_SPL_MMC_SUPPORT跟随全局SPL变量CONFIG_SPL打开
位于include/configs/mx6sabresd.h
#ifdef CONFIG_SPL
#define CONFIG_SPL_LIBCOMMON_SUPPORT
#define CONFIG_SPL_MMC_SUPPORT
#include "imx6_spl.h"
#endif
由此我们计算下kernel和dtb的安全地址
image / bin | addr begin | addr end | size (bytes) |
SPL | addr = 0x400 / sector = 2 | addr = 0x9000 | 35840 |
u-boot | addr = 11400 / sector = 138 | addr = 0x64754 | 340820 |
由此可知,dtb和kernel的位置需要在addr = 0x64754之后,为了方便按照如下直接取整
image / bin | addr begin | addr end | size (bytes) |
dtb | addr = 0x200000 / sector = 4096 | addr = 0x20c574 | 50548 |
kernel | addr = 0x400000 / sector = 8192 | addr = 0xaea368 | 7250792 |
可得到如下的定义
/* Falcon Mode - MMC support: args@2MB kernel@4MB */
#define CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR 0x1000 // 2M
#define CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTORS (CONFIG_CMD_SPL_WRITE_SIZE / 512)
#define CONFIG_SYS_MMCSD_RAW_MODE_KERNEL_SECTOR 0x2000 /* 4MB */
现在已经将SPL跳转到kernel所需的所有地址信息全部填充完毕,还记得在最开始的时候,有一个条件选项
boot_rom --> SPL ---- > uboot
\ --- > kernel
在SPL我们是可以选择进入uboot或者是kernel的,当然也可以写死,如果不写死就是要重载该函数spl_start_uboot
该函数在doc/README.falcon有描述
Function that a board must implement
------------------------------------
void spl_board_prepare_for_linux(void) : optional
Called from SPL before starting the kernel
spl_start_uboot() : required
Returns "0" if SPL should start the kernel, "1" if U-Boot must be started.
可在board/freescale/mx6sabresd/mx6sabresd.c文件中重载spl_start_uboot,当前直接写死SPL--> kernel,可手动改为return 0试试结果如何变化
#ifdef CONFIG_SPL_OS_BOOT
int spl_start_uboot(void)
{
/* Only enter in Falcon mode if KEY_VOL_UP is pressed */
return 0;
}
#endif
kernel 部分
kernel部分非常简单
该开发板对应的defconfig为imx_v7_defconfig
source environment
make imx_v7_defconfig
export LOADADDR=0x10800000
make uImage
得到两个文件uImage和imx6q-sabresd.dtb
但是直接使用默认的defconfig是无法跑起来的,通过uboot给kernel指定参数或者编译选项来指定,采用SPL引导kernel之后无法通过uboot给kernel传递参数了,可用如下的编译选项来指定根目录文件系统:
CONFIG_CMDLINE="noinitrd console=ttymxc0,115200 root=/dev/mmcblk2p1 rootfstype=ext4 rw"
ext4的由来是yocto编译默认生成的fsl-image-qt5-imx6qsabresd-20171114030630.rootfs.ext4
mmcblk2p1的由来可能有多种方法,此处是根据kernel运行后,未加入文件系统时,得到的log提示,因为开发板另有一块emmc也会被识别到(可通过变更SD卡分区表的方式识别出SD卡设备节点和emmc的设备节点)
修改完后再重新成uImage和imx6q-sabresd.dtb
rootfs部分
该部分主要是计算文件系统分区
官方某配置的文件系统fsl-image-qt5-imx6qsabresd-20171114030630.rootfs.ext4大小为1,677,721,600 bytes
之前的SPL,uboot,dtb,kernel所占用的地址大约在15MB的地方,大概预留一些空间此处预留200MB,从409600扇区开始
image / bin | addr begin | addr end | size (bytes) |
rootfs.ext4 | addr = / sector = 409600 | addr = / sector = 3686399 | 1,677,721,600 |
算好文件系统分区后,使用分区工具进行分区,如fdisk
将文件系统刷入SD卡
sudo dd if=fsl-image-qt5-imx6qsabresd-20171114030630.rootfs.ext4 of=/dev/sdh bs=512 seek=409600
制作启动mmc卡
sudo dd if=SPL of=/dev/sdh bs=1k seek=1
sudo dd if=u-boot.img of=/dev/sdh bs=512 seek=138
sudo dd if=imx6q-sabresd.dtb of=/dev/sdh bs=512 seek=4096
sudo dd if=uImage of=/dev/sdh bs=512 seek=8192
如下链接有编译好的SPL u-boot.img imx6q-sabresd.dtb uImage rootfs文件,因为原有的rootfs太大,裁减了一个小的,没得验证过,可以重新制作文件系统分区后验证一下
https://download.csdn.net/download/bgk112358/10493706