转载自https://blog.csdn.net/qq_28877125/article/details/120785133
0. 前言
bootcmd uboot 倒计时结束以后就会执行 bootcmd 中的命令
bootargs 保存着 uboot 传递给 Linux 内核的参数
uboot中的环境变量
- bootdelay:执行自动启动的等候秒数
- baudrate:串口控制台的波特率
- netmask: 以太网接口的掩码
- ethaddr: 以太网卡的网卡物理地址
- bootfile: 缺省的下载文件
- bootargs:传递给内核的启动参数
- bootcmd:自动启动时执行的命令
- serverip: 服务器端的ip地址
- ipaddr: 本地ip 地址
- stdin: 标准输入设备
- stdout: 标准输出设备
- stderr: 标准出错设备
以上是一些基本的环境变量。uboot中一般会有一些缺省的环境变量。在启动uboot后会将参数放在特定的FLASH区域,之后由kernel去获取解析。还有另一种方法设置环境变量就是在uboot启动后进入命令行模式,设置环境变量,然后执行saveenv后,会将设置的环境变量保存到特定区域的FLASH中,由kernel去获取解析。
其中bootargs和bootcmd相对比较重要。
1. bootcmd
uboot上电启动后会自动倒数bootdelay秒,如果没有人按下回车打断启动,则uboot会自动执行bootcmd启动命令来启动内核。
这个参数包含了一些命令,这些命令将在u-boot进入主循环后执行。
示例:
bootcmd=boot_logo;nand read 1000000 3c0000 300000;bootm 1000000
意思是启动u-boot后,执行boot_logo显示logo信息,然后从nand flash中读内核映像到内存,然后启动内核。
来做个小实验:set bootcmd printenv,然后saveenv;然后重启则会看到启动倒数bootdelay秒后自动执行printenv命令打印出环境变量。这个小实验说明充分说明开机自动执行了bootcmd这个环境变量。
灵活的写法–参考通用脚本语法
- 写法一:
setenv bootcmd 'setenv bootm_boot_mode sec; load mmc 0:1 0x41000000 zImage; load mmc 0:1 0x48000000 sun8i-h3-nanopi-m1-plus.dtb; bootz 0x41000000 - 0x48000000;'
- 写法二:
setenv bootcmd 'setenv bootm_boot_mode sec; fatload mmc 0:1 0x41000000 zImage; fatload mmc 0:1 0x48000000 sun8i-h3-nanopi-m1-plus.dtb; bootz 0x41000000 - 0x48000000;'
2. bootargs
2.1 NOR Flash示例
console=ttyS0,115200 earlyprintk panic=5 rootwait mtdparts=spi32766.0:1M(uboot)ro,64k(dtb)ro,4M(kernel)ro,-(rootfs) root=31:03 rw rootfstype=jffs2
解释:
- console=ttyS0,115200 表示终端为ttyS0,串口波特率为115200
- earlyprintk
- panic=5
- rootwait
- root=31:03 rw 表示根文件系统在第3分区
- rootfstype=jffs2 表示根文件系统的类型是jffs2
- mem=35M 表示内存大小为35M
mtdparts=spi32766.0:1M(uboot)ro,64k(dtb)ro,4M(kernel)ro,-(rootfs)
告诉内核MTD分区情况,它在内核目录/drivers/mtd/cmdlinepart.c
文件中有介绍:
2.2 NAND Flash示例
console=ttyS0,115200 root=/dev/mtdblock5 rootfstype=jffs2 mem=35M mtdparts=nand.0:3840k(u-boot),4096k(kernel),123136k(filesystem)
其中:
- console=ttyS0,115200 表示终端为ttyS0,串口波特率为115200
- root=/dev/mtdblock5 表示根文件系统在第五分区
- rootfstype=jffs2 表示根文件系统的类型是jffs2
- mem=35M 表示内存大小为35M
- mtdparts告诉内核MTD分区情况,它在内核目录/drivers/mtd/cmdlinepart.c文件中有介绍:
2.3 SD/EMMC 示例
console=tty0 ttyS0,115200 panic=5 rootwait root=/dev/mmcblk0p1 rootfstype=ext4 rw earlyprintk vt.global_cursor_default=0
解释:
- root=/dev/mtdblock5 表示根文件系统在第五分区
- rootfstype=jffs2 表示根文件系统的类型是jffs2
- console=ttyS0,115200 表示终端为ttyS0,串口波特率为115200
- mem=35M 表示内存大小为35M
- mtdparts告诉内核MTD分区情况,它在内核目录/drivers/mtd/cmdlinepart.c文件中有介绍:
2.4 console 参数
console 用来设置 linux 终端(或者叫控制台),也就是通过什么设备来和 Linux 进行交互,是串口还是 LCD 屏幕?如果是串口的话应该是串口几等等。这里设置 console 为 ttymxc0,因为 linux启动以后 I.MX6ULL
的串口 1 在 linux 下的设备文件就是/dev/ttymxc0
。
ttymxc0 后面有个“,115200”,这是设置串口的波特率,console=ttymxc0,115200 综合起来就是设置 ttymxc0(也就是串口 1)作为 Linux 的终端,并且串口波特率设置为 115200。
1. ttyS
串行端口终端(/dev/ttySn)
串行端口终端(Serial Port Terminal)是使用计算机串行端口连接的终端设备。计算机把每个串行端口都看作是一个字符设备。有段时间这些串行端口设备通常被称为终端设备,因为 那时它的最大用途就是用来连接终端。这些串行端口所对应的设备名称是/dev/tts/0(或/dev/ttyS0), /dev/tts/1(或/dev/ttyS1)等,设备号分别是(4,0), (4,1)等,分别对应于DOS系统下的COM1、COM2等。若要向一个端口发送数据,可以在命令行上把标准输出重定向到这些特殊文件名上即可。例如, 在命令行提示符下键入:echo test > /dev/ttyS1会把单词”test”发送到连接在ttyS1(COM2)端口的设备上。
2. ttySAC
PC上的串口一般是ttyS,板子上Linux的串口一般叫做ttySAC,如果你发觉串口不能用,可以看看你是不是用的调试串口或者你用的串口是不是内核启动时给初始化成其他用途了
3. tty
控制终端(/dev/tty)
如果当前进程有控制终端(Controlling Terminal)的话,那么/dev/tty就是当前进程的控制终端的设备特殊文件。可以使用命令”ps –ax”来查看进程与哪个控制终端相连。对于你登录的shell,/dev/tty就是你使用的终端,设备号是(5,0)。使用命令”tty”可以查看它 具体对应哪个实际终端设备。/dev/tty有些类似于到实际所使用终端设备的一个联接。
4. ttyn
控制台终端(/dev/ttyn, /dev/console)
在Linux 系统中,计算机显示器通常被称为控制台终端 (Console)。它仿真了类型为Linux的一种终端(TERM=Linux),并且有一些设备特殊文件与之相关联:tty0、tty1、tty2 等。当你在控制台上登录时,使用的是tty1。使用Alt+[F1—F6]组合键时,我们就可以切换到tty2、tty3等上面去。tty1–tty6等 称为虚拟终端,而tty0则是当前所使用虚拟终端的一个别名,系统所产生的信息会发送到该终端上(这时也叫控制台终端)。因此不管当前正在使用哪个虚拟终端,系统信息都会发送到控制台终端上。
/dev/console即控制台,是与操作系统交互的设备,系统将一些信息直接输出到控制台上。目前只有在单用户模式下,才允许用户登录控制台。
可以查看Documentation/serial-console.txt找到相关描述。
2.5 root 参数
root 用来设置根文件系统的位置 它的参数与存储介质相关:
存储介质 | 大小 | 标识 | 描述 | 举例 | |
---|---|---|---|---|---|
nor flash | 16MByte~32MByte | mtdX | |||
nand Flash | 128MByte+ | mtdblockX(X:0,1,2,3…) | root=/dev/mtdblock1 rw root=/dev/mtdblock2 rw | ||
emmc | ~ | mmcblkXpY(X=0~ n,Y=1~ n具体要看系统识别出来哪些) | root=/dev/mmcblk0p1 rw root=/dev/mmcblk0p2 rw | ||
SD/TF卡 | ~ | mmcblkXpY(X=0~ n,Y=1~ n具体要看系统识别出来哪些) | SD/TF卡本质上就是emmc | root=/dev/mmcblk0p1 rw | root=/dev/mmcblk0p2 rw |
内存 | ~ | ram | 内存文件系统 | ||
网络 | 网络文件系统 |
root=/dev/mmcblk1p2
用于指明根文件系统存放在mmcblk1 设备的分区 2 中。
/dev/mmcblkxpy(x=0n,y=1n)
表示 mmc 设备x 的分区 y。在 I.MX6U-ALPHA 开发板中/dev/mmcblk1 表示EMMC,而/dev/mmcblk1p2 表示EMMC 的分区 2。
root 后面有“rootwait rw”,rootwait 表示等待 mmc 设备初始化完成以后再挂载,否则的话mmc 设备还没初始化完成就挂载根文件系统会出错的。rw 表示根文件系统是可以读写的,不加 rw 的话可能无法在根文件系统中进行写操作,只能进行读操作。
root=/dev/nfs
在文件系统为基于nfs的文件系统的时候使用。当然指定root=/dev/nfs之后,还需要指定nfsroot=serverip:nfs_dir
,即指明文件系统存在那个主机的那个目录下面。
目前很多新的开发板都是使用FLASH作为存储。因为很多都直接使用MTD驱动程序。MTD 驱动程序的主要优点在于 MTD 驱动程序是专门为基于闪存的设备所设计的,所以它们通常有更好的支持、更好的管理和基于扇区的擦除和读写操作的更好的接口。Linux 下的 MTD 驱动程序接口被划分为两类模块:用户模块和硬件模块。
有两个流行的用户模块可启用对闪存的访问: MTD_CHAR 和 MTD_BLOCK 。
MTD_CHAR
提供对闪存的原始字符访问,而MTD_BLOCK
将闪存设计为可以在上面创建文件系统的常规块设备(象 IDE 磁盘)。与MTD_CHAR
关联的设备是/dev/mtd0
、mtd1、mtd2(等等),而与MTD_BLOCK
关联的设备是/dev/mtdblock0
、mtdblock1(等等)。由于MTD_BLOCK
设备提供象块设备那样的模拟,通常更可取的是在这个模拟基础上创建象 FTL 和 JFFS2 那样的文件系统。
2.6 rootfstype 参数
此选项一般配合 root 一起使用,rootfstype 用于指定根文件系统类型,如果根文件系统为ext2格式的话此选项无所谓。如果根文件系统是 yaffs、jffs 或 ubifs 的话就需要设置此选项,指定根文件系统的类型。
2.7 init 参数
init指定的是内核启起来后,进入系统中运行的第一个脚本,一般init=/linuxrc, 或者init=/etc/preinit,preinit的内容一般是创建console,null设备节点,运行init程序,挂载一些文件系统等等操作。请注意,很多初学者以为init=/linuxrc是固定写法,其实不然,/linuxrc指的是/目录下面的linuxrc脚本,一般是一个连接罢了。
2.8 mmcblkXpY 参数
2.9 mtdparts 参数
mtdparts=fc000000.nor_flash:1920k(linux),128k(fdt),20M(ramdisk),4M(jffs2),38272k(user),256k(env),384k(uboot)
要想这个参数起作用,内核中的mtd驱动必须要支持,即内核配置时需要选上Device Drivers —> Memory Technology Device (MTD) support —> Command line partition table parsing
mtdparts的格式如下:
mtdparts=[;
:= :[,]
:= [@offset][][ro]
:= unique id used in mapping driver/device
:= standard linux memsize OR “-” to denote all remaining space
:= (NAME)
因此你在使用的时候需要按照下面的格式来设置:
mtdparts=mtd-id:@(),@()
这里面有几个必须要注意的:
a. mtd-id
必须要跟你当前平台的flash的mtd-id
一致,不然整个mtdparts会失效
b. size在设置的时候可以为实际的size(xxM,xxk,xx)
,也可以为-
这表示剩余的所有空间。
举例:
假设flash 的mtd-id是sa1100,那么你可以使用下面的方式来设置:
mtdparts=sa1100:- → 只有一个分区
mtdparts=sa1100:256k(ARMboot)ro,-(root) → 有两个分区
可以查看drivers/mtd/cmdlinepart.c中的注释找到相关描述。
2.9 initrd, noinitrd 参数
当你没有使用ramdisk启动系统的时候,你需要使用noinitrd这个参数,但是如果使用了的话,就需要指定initrd=r_addr,size
r_addr表示initrd在内存中的位置,size表示initrd的大小。
3. 更改环境变量
(1)新建一个环境变量,使用:set var value
(2)更改一个环境变量,使用:set var value
(3)删除一个环境变量,使用:set var
(4)保存环境变量,使用:saveenv
uboot中,saveenv/save命令不带参数,直接执行,作用是将内存中的环境变量的值同步保存到Flash中环境变量的分区。
注意:环境变量的保存是整体的覆盖保存,也就是说内存中所有的环境变量都会整体的将Flash中环境变量分区中原来的内容整体覆盖。要彻底更改一个环境变量的值,需要2步:
第一步set命令来更改内存中的环境变量,第二步用save命令将其同步到Flash中环境变量的分区。(环境变量如何参与程序运行呢?环境变量有2份,一份在Flash中,另一份在内存中,如DDR。uboot开机时一次性从Flash中读取全部环境变量到DDR中作为环境变量的初始化值,然后使用过程中都是用DDR中这一份,用户可以用saveenv指令将DDR中的环境变量重新写入Flash中去更新Flash中环境变量。下次开机时又会从Flash中再读一次)。
有时候我们只是想测试下这个环境变量,不希望影响到下一次开机,那就只set不save,这样set后当前本次运行的uboot已经起效果了,只不过没save下一次开机还是会恢复到原来的状况。
4. 其他写法
写法类似脚本
fdt_addr=0x18000000
loadaddr=0x12000000
bootcmd=ext4load mmc 2:1 ${loadaddr} zImage;ext4load mmc 2:1 ${fdt_addr} imx6q-sabresd.dtb;setenv bootargs root=PARTUUID=8cb74943-02 vt.global_cursor_default=0 console=null rootwait rw;bootz ${loadaddr} - ${fdt_addr};
使用变量:${var_name}
5. 其他例子
5.1 内核引导之bootcmd参数设置
要设置bootloader的serverip=192.168.1.102(Linux服务器的IP地址,保证和开发板的IP在同一网段)
通过tftp服务引导内核
setenv bootcmd 'tftp 0x30008000 uImage;bootm 0x30008000'
通过NFS服务引导内核
setenv bootcmd 'nfs 0x30007FC0 192.168.1.102:/home/tshwang/arm_linux/nfs/uImage;bootm 0x30007FC0'
通过nand引导内核
setenv bootcmd 'nand read.jffs2 0x30007FC0 kernel; bootm 0x30007FC0'
5.2 挂载根文件系统之bootargs参数设置
通过Nand读取挂载根文件系统
set bootargs noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0 rootfstype=yaffs
通过NFS挂载根文件系统
set bootargs noinitrd root=/dev/nfs nfsroot=192.168.1.102:/home/tshwang/arm_linux/nfs/rootfs/myfirst_rootfs ip=192.168.1.117:192.168.1.102:192.168.1.1:255.255.255.0::eth0:off init=/linuxrc console=ttySAC0 rootfstype=yaffs
6. 其他例子二
bootargs 保存着 uboot 传递给 Linux 内核的参数。
bootargs 环境变量设置:
EMMC 启动:setenv bootargs ‘console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw’EMMC 启动:setenv bootargs ‘console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw’
参数 | 含义 |
---|---|
console=ttymxc0 | 设置 linux 终端,串口 1 的设备文件是/dev/ttymxc0 |
115200 | 设置串口的波特率 |
root=/dev/mmcblk1p2 | 根文件系统存放在 mmcblk1 设备的分区 2 ,即EMMC 的分区 2 。/dev/mmcblkx(x=0~n)表示 mmc 设备,而/dev/mmcblkxpy(x=0n,y=1n)表示 mmc 设备 x 的分区 y |
rootwait | 表示等待 mmc 设备初始化完成以后再挂载,否则的话 mmc 设备还没初始化完成就挂载根文件系统会出错的。 |
rw | 表示根文件系统是可以读写的,不加 rw 的话可能无法在根文件系统中进行写操作,只能进行读操作。 |
网络启动:
setenv bootargs 'console=ttymxc0,115200 root=/dev/nfs nfsroot=192.168.137.18:/home/pjw/linux/nfs/rootfs,proto=tcp rw ip=192.168.137.20:192.168.137.18:192.168.1.1:255.255.255.0::eth0:off'
参数 | 含义 |
---|---|
console=ttymxc0 | 设置 linux 终端,串口 1 的设备文件是/dev/ttymxc0 |
115200 | 设置串口的波特率 |
root=/dev/nfs | 根文件系统存放在 nfs 挂载目录 |
nfsroot=192.168.137.18:/home/pjw/linux/nfs/rootfs | 服务器 IP 地址:根文件系统存放路径 |
proto=tcp rw | 使用 TCP 协议 |
rw | 表示挂载的根文件系统是可以读写的 |
ip=192.168.137.20 | 客户端 IP 地址 |
192.168.137.18:192.168.1.1:255.255.255.0 | 服务器 IP 地址,网关地址,子网掩码 |
eth0 | 设备名 |
off | 自动配置,一般不使用,所以设置为 off。 |
bootcmd 保存着 uboot 默认命令。
bootcmd 环境变量设置:
EMMC 启动:setenv bootcmd ‘mmc dev 1; fatload mmc 1:1 80800000 zImage; fatload mmc 1:1 83000000 imx6ull-alientek-emmc.dtb; bootz 80800000 - 83000000;’
网络启动:setenv bootcmd ‘tftp 80800000 zImage; tftp 83000000 imx6ull-alientek-emmc.dtb; bootz 80800000 - 83000000;’
参数 | 含义 |
---|---|
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 |
评论 (0)