欢迎光临
我们一直在努力

linux 系统移植(第六期)--Uboot移植(5)--bootcmd 和 bootargs 环境变量-- Ubuntu20.04

文章目录

前言

一、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 命令来运行 findfdtfindfdt NXP 自行添加的环境变量,findfdt 是用来查找开发板对应的设备树文件(.dtb)IMX6ULL EVK 的设备树文件为 imx6ull-14×14-evk.dtbfindfdt 内容如下:

"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_fileboard_nameboard_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 netbootnetboot

也是一个自定义的环境变量,这个变量是从网络启动 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。

3rootfstype

此选项一般配置 root 一起使用,rootfstype 用于指定根文件系统类型,如果根文件系统为ext 格式的话此选项无所谓。如果根文件系统是 yaffs、jffs 或 ubifs 的话就需要设置此选项,指定根文件系统的类型。


总结

学习两个重要的环境变量 bootcmd bootargs。

赞(0)
未经允许不得转载:171主机测评 » linux 系统移植(第六期)--Uboot移植(5)--bootcmd 和 bootargs 环境变量-- Ubuntu20.04
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址