[ARM Linux系统移植] U-Boot 启动 Linux 测试

在 u-boot 移植完毕后,就可以测试 u-boot 能否正常启动 linux 系统。再次之前我们需要了解两个重要的环境变量:bootcmdbootargs

bootcmd 变量里附带了 u-boot “倒计时” 结束之后执行的指令;bootargs 变量里附带了 u-boot 需要传递给 linux 的命令行变量。

1. bootcmd 变量

先说 bootcmd 变量,变量里面附带的指令核心就是读取 zImage 和设备树文件,然后执行 bootz 命令,以此引导 linux。下面我们来梳理一下 i.Mx 官网定义的 bootcmd 变量。

在文件 include/env_default.h 中,我们可以看到,如果没有自行设置相关的环境变量,就会使用一组默认的环境变量。第 32 行定义了默认的 bootargs 变量;第 35 行定义了默认的 bootcmd 变量。

include/env_default.h
  1. #ifdef DEFAULT_ENV_INSTANCE_EMBEDDED
  2. env_t environment __PPCENV__ = {
  3.     ENV_CRC,    /* CRC Sum */
  4. #ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT
  5.     1,      /* Flags: valid */
  6. #endif
  7.     {
  8. #elif defined(DEFAULT_ENV_INSTANCE_STATIC)
  9. static char default_environment[] = {
  10. #else
  11. const uchar default_environment[] = {
  12. #endif
  13. #ifdef  CONFIG_ENV_CALLBACK_LIST_DEFAULT
  14.     ENV_CALLBACK_VAR "=" CONFIG_ENV_CALLBACK_LIST_DEFAULT "\0"
  15. #endif
  16. #ifdef  CONFIG_ENV_FLAGS_LIST_DEFAULT
  17.     ENV_FLAGS_VAR "=" CONFIG_ENV_FLAGS_LIST_DEFAULT "\0"
  18. #endif
  19. #ifdef  CONFIG_BOOTARGS
  20.     "bootargs=" CONFIG_BOOTARGS         "\0"
  21. #endif
  22. #ifdef  CONFIG_BOOTCOMMAND
  23.     "bootcmd="  CONFIG_BOOTCOMMAND      "\0"
  24. #endif

默认 bootcmd 变量的内容宏 CONFIG_BOOTCOMMAND 在文件 mx6ullevk.h 中定义。

include/configs/mx6ullevk.h
  1. #define CONFIG_BOOTCOMMAND \
  2.        "run findfdt;" \
  3.        "mmc dev ${mmcdev};" \
  4.        "mmc dev ${mmcdev}; if mmc rescan; then " \
  5.            "if run loadbootscript; then " \
  6.                "run bootscript; " \
  7.            "else " \
  8.                "if run loadimage; then " \
  9.                    "run mmcboot; " \
  10.                "else run netboot; " \
  11.                "fi; " \
  12.            "fi; " \
  13.        "else run netboot; fi"
  14. #endif

bootcmd 中,首先会执行 findfdt 函数(第 214 行),来确认设备树文件的名称。findfdt 函数内容如下所示,逻辑比较简单:依据 board_nameboard_rev 的变量值,来设置 fdt_file 的变量值。像目前自己手头烧写的 u-boot 中,board_name=EVKboard_rev=14X14,因此就会选择到 imx6ull-14x14-evk.dtb

include/configs/mx6ullevk.h : findfdt
  1. "findfdt="\
  2.     "if test $fdt_file = undefined; then " \
  3.         "if test $board_name = EVK && test $board_rev = 9X9; then " \
  4.             "setenv fdt_file imx6ull-9x9-evk.dtb; fi; " \
  5.         "if test $board_name = EVK && test $board_rev = 14X14; then " \
  6.             "setenv fdt_file imx6ull-14x14-evk.dtb; fi; " \
  7.         "if test $fdt_file = undefined; then " \
  8.             "echo WARNING: Could not determine dtb to use; fi; " \
  9.     "fi;\0" \

接着第 215 至 216 行,bootcmd 中会切换 emmc 设备(自测环境中 mmcdev=0),再进行扫描检测 emmc 设备是否存在。自己手头环境中是存在 emmc 设备的,所以流程走到第 217 至 224 行的分支,其中首先执行 loadbootscript 函数。

loadbootscript 函数的内容如下所示,只有一条 fatload 指令。当前环境中,mmcdev=0mmcpart=1loadaddr=0x80800000script=boot.scr,即从 emmc0 的第 1 个分区中加载 boot.scr 文件到地址 0x80800000 处。

include/configs/mx6ullevk.h : loadbootscript
  1. "loadbootscript=" \
  2.     "fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script};\0" \

自测环境中没有 boot.scr 这个文件,因此之后会执行到第 220 至 223 行这个分支。首先执行的是第 220 行中的 loadimage 函数,它的内容如下。作用为从 emmc0 的第 1 个分区中加载 zImage 文件(image=zImage)到地址 0x80800000 处。

include/configs/mx6ullevk.h : loadimage
  1. "loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}\0" \

因为 emmc 中 zImage 文件存在,所以最后会调用第 221 行的 mmcboot 函数。其内容如下所示,第 164 行首先调用 mmcargs 函数,它的作用是设置 bootargs 变量内容,这将在第 2 章中再进行说明。因为 boot_fdt=try,所以会执行 loadfdt 函数。loadfdt 函数从 emmc0 的第 1 个分区中加载设备树文件到地址 0x83000000 处(fdt_addr=0x83000000)。最后执行 bootz 命令。

include/configs/mx6ullevk.h : mmcboot
  1. "loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdt_file}\0"
  2. "mmcboot=echo Booting from mmc ...; " \
  3.     "run mmcargs; " \
  4.     "if test ${boot_fdt} = yes || test ${boot_fdt} = try; then " \
  5.        "if run loadfdt; then " \
  6.            "bootz ${loadaddr} - ${fdt_addr}; " \
  7.        "else " \
  8.            "if test ${boot_fdt} = try; then " \
  9.               "bootz; " \
  10.            "else " \
  11.               "echo WARN: Cannot load the DT; " \
  12.            "fi; " \
  13.        "fi; " \
  14.     "else " \
  15.        "bootz; " \
  16.     "fi;\0" \

至此,bootcmd 内容的分析就结束了。因为为了兼容性考虑,官方加载过程会显得比较繁琐,“浓缩”关键的内容就如下 4 行指令:

  • mmc dev 0
  • fatload mmc 0:1 0x80800000 zImage
  • fatload mmc 0:1 0x83000000 imx6ull-14x14-evk.dtb
  • bootz 0x80800000 - 0x83000000

第一句切换到 emmc 设备,第二句加载 zImage 文件,第三句加载设备树文件,第四句执行 bootz 命令。

2. bootargs 变量

在第 1 章中已经了解到,bootargs 变量是通过 mmcargs 函数设置的。其中 console=ttymxc0,即设置控制台对应串口设备;baudrate=115200,即指定串口的波特率;CONFIG_BOOTARGS_CMA_SIZECONFIG_MFG_NAND_PARTITION 宏都为空;root=/dev/mmcblk0p2 rootwait rw,即设置根文件系统位于 emmc0 的第二个分区,后面的 rootwait 表示等待 emmc 设备初始化完成以后再挂载,rw 表示系统是可读可写的。

include/configs/mx6ullevk.h : mmcargs
  1. "mmcargs=setenv bootargs console=${console},${baudrate} " \
  2.     CONFIG_BOOTARGS_CMA_SIZE \
  3.     CONFIG_MFG_NAND_PARTITION \
  4.     "root=${mmcroot}\0" \

3. 启动 linux 测试

bootcmdbootargs 两个变量说明完毕之后,就可以开始测试移植的 u-boot 能否正常启动 linux。下面我们测试从 emmc 中以及从网络启动 linux。

3.1 从 emmc 中启动

由于目前还不知道如何将需要的文件烧写到 emmc 中,所以我们先直接使用之前体验开发板功能时烧写到 emmc 中的现成内容。我们先在 u-boot 命令行下查看当前 emmc1 中的文件:

  • > fatls mmc 1:1
  • 38823    imx6ull-14x14-emmc-4.3-480x272-c.dtb
  • 38823    imx6ull-14x14-emmc-4.3-800x480-c.dtb
  • 38823    imx6ull-14x14-emmc-7-1024x600-c.dtb
  • 38823    imx6ull-14x14-emmc-7-800x480-c.dtb
  • 39655    imx6ull-14x14-emmc-hdmi.dtb
  • 39563    imx6ull-14x14-emmc-vga.dtb
  • 6786272    zimage

其中已经有了 zImage 文件和设备树文件,因为当前自己的显示屏是 4.3 寸 800x480 的,所以选择以上第二份设备树文件。因此在 u-boot 命令行中执行以下命令,再重启:

  • > setenv bootargs 'console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw'
  • > setenv bootcmd 'mmc dev 1; fatload mmc 1:1 80800000 zImage; fatload mmc 1:1 83000000 imx6ull-14x14-emmc-4.3-800x480-c.dtb; bootz 80800000 - 83000000;'
  • > saveenv

因为是之前体验烧写的版本,所以只要开发板正常显示桌面界面就证明 linux 系统启动成功了。

3.2 从网络启动

从网络启动 linux 系统主要是为了便于调试,这边通过 tftp 服务传输 zImage 文件和设备树文件。tftp 服务的配置在文章 [ARM Linux系统移植] U-Boot 网络命令 中有介绍。在 u-boot 命令行中执行以下命令,即可设置从网络启动:

  • > setenv bootargs 'console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw'
  • > setenv bootcmd 'tftp 80800000 zImage; tftp 83000000 imx6ull-14x14-emmc-4.3-800x480-c.dtb; bootz 80800000 - 83000000'
  • > saveenv