文章目录
前言
一、bootcmd和bootargs环境变量
二、环境变量 bootcmd
三、环境变量 bootargs
总结
前言
上一期我们已经把uboot 的驱动部分就修改完成了,uboot 移植也完成了,uboot 的最终目的就是启动 Linux 内核,所以需要通过启动 Linux 内核来判断 uboot 移植是否成功。在启动 Linux 内核之前我们先来学习两个重要的环境变量 bootcmd 和 bootargs。
一、bootcmd和bootargs环境变量
uboot 中有两个非常重要的环境变量 bootcmd 和 bootargs,接下来看一下这两个环境变量。bootcmd 和 bootagrs 是采用类似 shell 脚本语言编写的,里面有很多的变量引用,这些变量其实 都是环境变量,有很多是 NXP 自 己 定 义 的 。 文 件 mx6ull_alientek_emmc.h 中的宏 CONFIG_EXTRA_ENV_SETTINGS 保存着这些环境变量的默认值,内容如下:
#ifdef CONFIG_SYS_BOOTMENU
#define CONFIG_EXTRA_ENV_SETTINGS \\
CONFIG_MFG_ENV_SETTINGS \\
"fdt_addr=0x83000000\\0" \\
"panel=ATK4384\\0" \\
"fdt_high=0xffffffff\\0" \\
"bootz ${loadaddr} – ${fdt_addr}\\0"
#else
#define CONFIG_EXTRA_ENV_SETTINGS \\
CONFIG_MFG_ENV_SETTINGS \\
"image=Image\\0" \\
"console=ttymxc0\\0" \\
"fdt_high=0xffffffff\\0" \\
"initrd_high=0xffffffff\\0"
…
"findfdt=" \\
"if test ${fdt_file} = undefined; then " \\
"if test ${board_name} = EVK && test ${board_rev} = 9X9; then " \\
"setenv fdt_file imx6ull-9×9-evk.dtb; fi; " \\
"if test ${board_name} = SDB && test ${board_rev} = 14X14; then " \\
"setenv fdt_file imx6ull-14×14-evk.dtb; fi; " \\
"if test ${fdt_file} = undefined; then " \\
"echo WARNING: Could not determine dtb to use; fi; " \\
"fi;\\0"
宏 CONFIG_EXTRA_ENV_SETTINGS 是个条件编译语句,使用 NAND 和 EMMC 的时候
宏 CONFIG_EXTRA_ENV_SETTINGS 的值是不同的。
二、环境变量 bootcmd
bootcmd 是U-Boot 启动 Linux 内核的核心命令载体,倒计时结束后自动执行。
支持手动修改,无存储值时会读取env_default.h中的默认配置(首次运行必用)。
核心功能是从存储介质读取内核 / 设备树文件到内存并启动 Linux。
打开文件
include/env_default.h
,在此文件中有如下所示内容:
#ifdef DEFAULT_ENV_INSTANCE_EMBEDDED
env_t environment __PPCENV__ = {
ENV_CRC,/* CRC Sum */
#ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT
1,/* Flags: valid */
#endif
{
#elif defined(DEFAULT_ENV_INSTANCE_STATIC)
static char default_environment[] = {
#else
const uchar default_environment[] = {
#endif
#ifdefCONFIG_ENV_CALLBACK_LIST_DEFAULT
ENV_CALLBACK_VAR "=" CONFIG_ENV_CALLBACK_LIST_DEFAULT "\\0"
#endif
#ifdefCONFIG_ENV_FLAGS_LIST_DEFAULT
ENV_FLAGS_VAR "=" CONFIG_ENV_FLAGS_LIST_DEFAULT "\\0"
#endif
#ifdefCONFIG_BOOTARGS
"bootargs="CONFIG_BOOTARGS"\\0"
#endif
#ifdefCONFIG_BOOTCOMMAND
"bootcmd="CONFIG_BOOTCOMMAND"\\0"
#endif
#ifdefCONFIG_RAMBOOTCOMMAND
"ramboot="CONFIG_RAMBOOTCOMMAND"\\0"
#endif
#ifdefCONFIG_NFSBOOTCOMMAND
"nfsboot="CONFIG_NFSBOOTCOMMAND"\\0"
#endif
#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
"bootdelay="__stringify(CONFIG_BOOTDELAY)"\\0"
#endif
#if defined(CONFIG_BAUDRATE) && (CONFIG_BAUDRATE >= 0)
"baudrate="__stringify(CONFIG_BAUDRATE)"\\0"
#endif
#ifdefCONFIG_LOADS_ECHO
"loads_echo="__stringify(CONFIG_LOADS_ECHO)"\\0"
#endif
#ifdefCONFIG_ETHPRIME
"ethprime="CONFIG_ETHPRIME"\\0"
#endif
#ifdefCONFIG_IPADDR
"ipaddr="__stringify(CONFIG_IPADDR)"\\0"
#endif
#ifdefCONFIG_SERVERIP
"serverip="__stringify(CONFIG_SERVERIP)"\\0"
#endif
#ifdefCONFIG_SYS_AUTOLOAD
"autoload="CONFIG_SYS_AUTOLOAD"\\0"
#endif
#ifdefCONFIG_PREBOOT
"preboot="CONFIG_PREBOOT"\\0"
#endif
#ifdefCONFIG_ROOTPATH
"rootpath="CONFIG_ROOTPATH"\\0"
#endif
#ifdefCONFIG_GATEWAYIP
"gatewayip="__stringify(CONFIG_GATEWAYIP)"\\0"
#endif
#ifdefCONFIG_NETMASK
"netmask="__stringify(CONFIG_NETMASK)"\\0"
#endif
#ifdefCONFIG_HOSTNAME
"hostname="__stringify(CONFIG_HOSTNAME)"\\0"
#endif
#ifdefCONFIG_BOOTFILE
"bootfile="CONFIG_BOOTFILE"\\0"
#endif
#ifdefCONFIG_LOADADDR
"loadaddr="__stringify(CONFIG_LOADADDR)"\\0"
#endif
#ifdefCONFIG_CLOCKS_IN_MHZ
"clocks_in_mhz=1\\0"
#endif
#if defined(CONFIG_PCI_BOOTDELAY) && (CONFIG_PCI_BOOTDELAY > 0)
"pcidelay="__stringify(CONFIG_PCI_BOOTDELAY)"\\0"
#endif
#ifdefCONFIG_ENV_VARS_UBOOT_CONFIG
"arch="CONFIG_SYS_ARCH"\\0"
"cpu="CONFIG_SYS_CPU"\\0"
"board="CONFIG_SYS_BOARD"\\0"
"board_name="CONFIG_SYS_BOARD"\\0"
#ifdef CONFIG_SYS_VENDOR
"vendor="CONFIG_SYS_VENDOR"\\0"
#endif
#ifdef CONFIG_SYS_SOC
"soc="CONFIG_SYS_SOC"\\0"
#endif
#endif
#ifdefCONFIG_EXTRA_ENV_SETTINGS
CONFIG_EXTRA_ENV_SETTINGS
#endif
"\\0"
#ifdef DEFAULT_ENV_INSTANCE_EMBEDDED
}
#endif
};
上段代码中指定了很多环境变量的默认值,比如 bootcmd 的默认值CONFIG_BOOTCOMMAND,bootargs 的默认值就是 CONFIG_BOOTARGS,我们可以在mx6ull_alientek_emmc.h 文件中通过设置宏 CONFIG_BOOTCOMMAND 来设置 bootcmd 的默认值,NXP 官方设置的 CONFIG_BOOTCOMMAND 值如下:
204 #define CONFIG_BOOTCOMMAND \\
205 "run findfdt;" \\
206 "mmc dev ${mmcdev};" \\
207 "mmc dev ${mmcdev}; if mmc rescan; then " \\
208 "if run loadbootscript; then " \\
209 "run bootscript;" \\
210 "else " \\
211 "if run loadimage; then " \\
212 "run mmcboot;" \\
213 "else run netboot; " \\
214 "fi; " \\
215 "fi; " \\
216 "else run netboot; fi"
第205行:run findfdt;使用的是 uboot 的 run 命令来运行 findfdt,findfdt 是 NXP 自行添加的环境变量,findfdt 是用来查找开发板对应的设备树文件(.dtb)。IMX6ULL EVK 的设备树文件为 imx6ull-14×14-evk.dtb,findfdt 内容如下:
"findfdt="\\
"if test $fdt_file = undefined; then " \\
"if test $board_name = EVK && test $board_rev = 9X9; then " \\
"setenv fdt_file imx6ull-9×9-evk.dtb; fi; " \\
"if test $board_name = EVK && test $board_rev = 14X14; then " \\
"setenv fdt_file imx6ull-14×14-evk.dtb; fi; " \\
"if test $fdt_file = undefined; then " \\
"echo WARNING: Could not determine dtb to use; fi; " \\
"fi;\\0" \\
findfdt 里面用到的变量有 fdt_file,board_name,board_rev,这三个变量内容如下:
fdt_file=undefined,board_name=EVK ,board_rev=14X14
findfdt 做的事情就是判断,fdt_file 是否为 undefined,如果 fdt_file 为 undefined 的话那就要 根据板子信息得出所需的.dtb 文件名。此时 fdt_file 为 undefined,所以根据 board_name 和 board_rev 来判断实际所需的.dtb 文件,如果 board_name 为 EVK 并且 board_rev=9×9 的话 fdt_file就为 imx6ull-9×9-evk.dtb。如果 board_name 为 EVK 并且 board_rev=14×14 的话 fdt_file 就设置为 imx6ull-14×14-evk.dtb。因此 IMX6ULL EVK 板子的设备树文件就是 imx6ull-14×14-evk.dtb,因此 run findfdt 的结果就是设置 fdt_file 为 imx6ull-14×14-evk.dtb。
第206行,mmc dev ${mmcdev}用于切换 mmc 设备,mmcdev 为 1,因此这行代码就是:mmc
dev 1,也就是切换到 EMMC 上。
第 207 行,先执行 mmc dev ${mmcdev}切换到 EMMC 上,然后使用命令 mmc rescan 扫描
看有没有 SD 卡或者 EMMC 存在,如果没有的话就直接跳到 216 行,执行 run netboot,netboot
也是一个自定义的环境变量,这个变量是从网络启动 Linux 的。如果 mmc 设备存在的话就从
mmc 设备启动。
第
208
行,运行
loadbootscript
环境变量,此环境变量内容如下:
loadbootscript=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script};
其中
mmcdev=1
,
mmcpart=1
,
loadaddr=0x80800000
,
script= boot.scr
,因此展开以后就是:
loadbootscript=fatload mmc 1:1 0x80800000 boot.scr;
loadbootscript 就是从 mmc1 的分区 1 中读取文件 boot.src 到 DRAM 的 0X80800000 处。但
是 mmc1 的分区 1 中没有 boot.src 这个文件,可以使用命令“ls mmc 1:1”查看一下 mmc1 分区
1 中的所有文件,看看有没有 boot.src 这个文件。
第
209
行,如果加载
boot.src
文件成功的话就运行
bootscript
环境变量,
bootscript
的内容如
下:
bootscript=echo Running bootscript from mmc …;
source
因为
boot.src
文件不存在,所以
bootscript
也就不会运行。
第 211 行,如果 loadbootscript 没有找到 boot.src 的话就运行环境变量 loadimage,loadimage 就是从 mmc1 的分区中读取 zImage 到内存的 0X80800000 处,而 mmc1 的分区 1 中存在zImage。
第 212 行,加载 linux 镜像文件 zImage 成功以后就运行环境变量 mmcboot,否则的话运行
netboot 环境变量。
其实就是为了从 EMMC 中读取 zImage 镜像文件和设备树文件。精华只有4行:
mmc dev 1 //切换到 EMMC
fatload mmc 1:1 0x80800000 zImage //读取 zImage 到 0x80800000 处
fatload mmc 1:1 0x83000000 imx6ull-14×14-evk.dtb //读取设备树到 0x83000000 处
bootz 0x80800000 – 0x83000000 //启动 Linux
NXP
官方将
CONFIG_BOOTCOMMAND
写的这么复杂只有一个目的:为了兼容多个板子
当我们明确知道我们所使用的板子的时候就可以大幅简化宏CONFIG_BOOTCOMMAND 的 设 置 , 比 如 我 们 要 从 EMMC 启动,那么宏CONFIG_BOOTCOMMAND 就可简化为:
#define CONFIG_BOOTCOMMAND \\
"mmc dev 1;" \\
"fatload mmc 1:1 0x80800000 zImage;" \\
"fatload mmc 1:1 0x83000000 imx6ull-alientek-emmc.dtb;" \\
"bootz 0x80800000 – 0x83000000;"
三、环境变量 bootargs
bootargs 保存着 uboot 传递给 Linux 内核的参数,bootargs 环境变量是由 mmcargs 设置的,mmcargs 环境变量如下:
mmcargs=setenv bootargs console=${console},${baudrate} root=${mmcroot}
其中
console=ttymxc0
,
baudrate=115200
,
mmcroot=/dev/mmcblk1p2 rootwait rw
,因此将
mmcargs
展开以后就是:
mmcargs=setenv bootargs console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw
可以看出环境变量 mmcargs 就是设置 bootargs 的值为“console= ttymxc0, 115200 root=
/dev/mmcblk1p2 rootwait rw”,bootargs 就是设置了很多的参数的值,这些参数 Linux 内核会使
用到,常用的参数有:
1
、
console
console 用来设置 Linux 终端(控制台),也就是通过什么设备来和 Linux 进行交互,比如串口还是 LCD 屏幕。如果是串口的话,需要指定具体串口号。这里设置串口作为 Linux 终端,这样我们就可以在电脑上通过 SecureCRT 和 Linux 交互。
此处 console 被设置为 ttymxc0,因为 Linux 启动后,IMX6ULL 的串口 1 在 Linux 中的设备文件就是 /dev/ttymxc0,在 Linux 中,一切皆文件。
console=ttymxc0,115200 表示:使用 ttymxc0(串口 1)作为 Linux 的终端,并且串口波特率设置为 115200。
2. root
root 用来设置根文件系统的位置,root=/dev/mmcblk1p2 表示根文件系统存放在 mmcblk1 设备的分区 2 中。
在 EMMC 版本的核心板启动 Linux 后,会存在 /dev/mmcblk0、/dev/mmcblk1、/dev/mmcblk0p1、/dev/mmcblk0p2、/dev/mmcblk1p1 和 /dev/mmcblk1p2 这样的文件。其中 /dev/mmcblkX(X=0~n) 表示 mmc 设备,而 /dev/mmcblkXpY(X=0~n,Y=1~n) 表示 mmc 设备 X 的分区 Y。
在 I.MX6U-ALPHA 开发板中,/dev/mmcblk1 表示 EMMC,而 /dev/mmcblk1p2 表示 EMMC 的分区 2。
3、rootfstype
此选项一般配置 root 一起使用,rootfstype 用于指定根文件系统类型,如果根文件系统为ext 格式的话此选项无所谓。如果根文件系统是 yaffs、jffs 或 ubifs 的话就需要设置此选项,指定根文件系统的类型。
总结
学习两个重要的环境变量 bootcmd 和 bootargs。




