uboot 中有两个非常重要的环境变量 bootcmd 和 bootargs。
bootcmd 保存着 uboot 默认命令,uboot 倒计时结束以后就会执行 bootcmd 中的命令。这些命令一般都是用来启动 Linux 内核的,比如读取 EMMC 或者 NAND Flash 中的 Linux 内核镜像文件和设备树文件到 DRAM 中,然后启动 Linux 内核。
bootargs 保存着 uboot 传递给 Linux 内核的参数,通过在设备树中插入chose节点将bootargs的值传递给内核。
目录
1.bootcmd环境变量
uboot的所有默认环境变量在 include/env_default.h文件中
如上图所示 "bootcmd=" CONFIG_BOOTCOMMAND ,而CONFIG_BOOTCOMMAND 在各个开发板的配置头文件中,比如im6ullevk.h
#define CONFIG_BOOTCOMMAND \
"run findfdt;" \
"mmc dev ${mmcdev};" \
"mmc dev ${mmcdev}; if mmc rescan; then " \
"if run loadbootscript; then " \
"run bootscript; " \
"else " \
"if run loadimage; then " \
"run mmcboot; " \
"else run netboot; " \
"fi; " \
"fi; " \
"else run netboot; fi"
#endif
首先运行findfdt命令确定设备树文件的名字,然后切换到emmc,接下来执行loadimage加载内核镜像,最后执行mmcboot,也就是加载设备树文件,并执行bootz命令启动内核
简化后最终如下
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-hyq-emmc.dtb;" \
"bootz 0x80800000 - 0x83000000;"
或者可以直接在 uboot 中设置 bootcmd 的值,这个值就是保存到 EMMC 中的,命令如下:
setenv bootcmd 'mmc dev 1; fatload mmc 1:1 80800000 zImage; fatload mmc 1:1 83000000 imx6ull-hyq-emmc.dtb; bootz 80800000 - 83000000;'
saveenv
2.bootargs环境变量
在 include/env_default.h文件中
"bootargs=" CONFIG_BOOTARGS
但是我们在im6ullevk.h的头文件中并没有找到CONFIG_BOOTARGS 此宏的定义,在上一小节中boofcmd命令最后执行了mmcboot命令,mmcboot命令如下
"mmcboot=echo Booting from mmc ...; " \
"run mmcargs; " \
"if test ${boot_fdt} = yes || test ${boot_fdt} = try; then " \
"if run loadfdt; then " \
"bootz ${loadaddr} - ${fdt_addr}; " \
"else " \
"if test ${boot_fdt} = try; then " \
"bootz; " \
"else " \
"echo WARN: Cannot load the DT; " \
"fi; " \
"fi; " \
"else " \
"bootz; " \
"fi;\0" \
首先运行的是mmcarg环境变量,如下
"mmcargs=setenv bootargs console=${console},${baudrate} " \
CONFIG_BOOTARGS_CMA_SIZE \
"root=${mmcroot}\0" \
展开后
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
启动以后 I.MX6ULL 的串口 1 在 linux 下的设备文件就是/dev/ttymxc0,在 Linux 下,一切皆文
件。
ttymxc0 后面有个“,115200”,这是设置串口的波特率,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。
root 后面有“rootwait rw”,rootwait 表示等待 mmc 设备初始化完成以后再挂载,否则的话
mmc 设备还没初始化完成就挂载根文件系统会出错的。rw 表示根文件系统是可以读写的,不加
rw 的话可能无法在根文件系统中进行写操作,只能进行读操作。
3.启动Linux
- 从 EMMC 启动 Linux 系统
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-hyq-emmc.dtb; bootz 80800000 - 83000000;'
saveenv
- 从网络启动 Linux
配置网络环境变量
setenv ipaddr 192.168.1.50
setenv ethaddr 00:04:9f:04:d2:35
setenv gatewayip 192.168.1.1
setenv netmask 255.255.255.0
setenv serverip 192.168.1.250
saveenv
setenv bootargs 'console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw'
setenv bootcmd 'tftp 80800000 zImage; tftp 83000000 imx6ull-hyq-emmc.dtb; bootz 80800000 - 83000000'
saveenv
- NFS文件系统挂载
setenv bootargs "console=tty1 console=ttymxc0,115200 root=/dev/nfs rw nfsroot=192.168.0.105:/home/hyq/linux/nfs/rootfs ip=192.168.0.50:192.168.0.105:192.168.0.1:255.255.255.0::eth0:off"
saveenv
设置调试信息到LCD和终端一起输出
- 网络开机自启动设置
从EMMC启动Linux系统,在测试网络的时候可能会发现网络不能用,这并不是因为我们将系统烧写到 EMMC 中以后网络坏了。仅仅是因为网络没有打开,我们用 NFS 挂载根文件系统的时候因为要使用 NFS服务,因此 Linux 内核会打开 eth0 这个网卡,现在我们不使用 NFS 挂载根文件系统,因此 Linux内核也就不会自动打开 eth0 网卡了。我们可以手动打开网卡,首先输入“ifconfig -a”命令查看一下 eth0 和 eth1 是否都存在。
以打开 eth0 网卡为例,输入如下命令打开 eth0并设置IP地址
ifconfig eth0 up
ifconfig eth0 192.168.1.251 netmask 255.255.255.0
route add default gw 192.168.1.1
设置开机自动开启网卡,将命令添加到/etc/init.d/rcS 文件中,如下:
#!/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/lib:/usr/lib
export PATH LD_LIBRARY_PATH runlevel
#网络开机自启动设置
ifconfig eth0 up
#udhcpc -i eth0
ifconfig eth0 192.168.1.251 netmask 255.255.255.0
route add default gw 192.168.1.1