文章目录
前言
[二、环境变量 bootcmd](#二、环境变量 bootcmd)
[三、环境变量 bootargs](#三、环境变量 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-9x9-evk.dtb; fi; " \
"if test ${board_name} = SDB && test ${board_rev} = 14X14; then " \
"setenv fdt_file imx6ull-14x14-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
#ifdef CONFIG_ENV_CALLBACK_LIST_DEFAULT
ENV_CALLBACK_VAR "=" CONFIG_ENV_CALLBACK_LIST_DEFAULT "\0"
#endif
#ifdef CONFIG_ENV_FLAGS_LIST_DEFAULT
ENV_FLAGS_VAR "=" CONFIG_ENV_FLAGS_LIST_DEFAULT "\0"
#endif
#ifdef CONFIG_BOOTARGS
"bootargs=" CONFIG_BOOTARGS "\0"
#endif
#ifdef CONFIG_BOOTCOMMAND
"bootcmd=" CONFIG_BOOTCOMMAND "\0"
#endif
#ifdef CONFIG_RAMBOOTCOMMAND
"ramboot=" CONFIG_RAMBOOTCOMMAND "\0"
#endif
#ifdef CONFIG_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
#ifdef CONFIG_LOADS_ECHO
"loads_echo=" __stringify(CONFIG_LOADS_ECHO) "\0"
#endif
#ifdef CONFIG_ETHPRIME
"ethprime=" CONFIG_ETHPRIME "\0"
#endif
#ifdef CONFIG_IPADDR
"ipaddr=" __stringify(CONFIG_IPADDR) "\0"
#endif
#ifdef CONFIG_SERVERIP
"serverip=" __stringify(CONFIG_SERVERIP) "\0"
#endif
#ifdef CONFIG_SYS_AUTOLOAD
"autoload=" CONFIG_SYS_AUTOLOAD "\0"
#endif
#ifdef CONFIG_PREBOOT
"preboot=" CONFIG_PREBOOT "\0"
#endif
#ifdef CONFIG_ROOTPATH
"rootpath=" CONFIG_ROOTPATH "\0"
#endif
#ifdef CONFIG_GATEWAYIP
"gatewayip=" __stringify(CONFIG_GATEWAYIP) "\0"
#endif
#ifdef CONFIG_NETMASK
"netmask=" __stringify(CONFIG_NETMASK) "\0"
#endif
#ifdef CONFIG_HOSTNAME
"hostname=" __stringify(CONFIG_HOSTNAME) "\0"
#endif
#ifdef CONFIG_BOOTFILE
"bootfile=" CONFIG_BOOTFILE "\0"
#endif
#ifdef CONFIG_LOADADDR
"loadaddr=" __stringify(CONFIG_LOADADDR) "\0"
#endif
#ifdef CONFIG_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
#ifdef CONFIG_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
#ifdef CONFIG_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-14x14-evk.dtb,findfdt 内容如下:
"findfdt="\
"if test $fdt_file = undefined; then " \
"if test $board_name = EVK && test $board_rev = 9X9; then " \
"setenv fdt_file imx6ull-9x9-evk.dtb; fi; " \
"if test $board_name = EVK && test $board_rev = 14X14; then " \
"setenv fdt_file imx6ull-14x14-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=9x9 的话 fdt_file就为 imx6ull-9x9-evk.dtb。如果 board_name 为 EVK 并且 board_rev=14x14 的话 fdt_file 就设置为 imx6ull-14x14-evk.dtb。因此 IMX6ULL EVK 板子的设备树文件就是 imx6ull-14x14-evk.dtb,因此 run findfdt 的结果就是设置 fdt_file 为 imx6ull-14x14-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-14x14-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。