2014-8-27 10:45:11
BeagleBoneBlack U-Boot 是如何引导系统的

连接到开发板

通过串口连接BeagleBone Black,参见Beagleboard:Terminal Shells
启动到U-Boot的时候,会看到

Hit any key to stop autoboot:0

按下任意键则放弃了自动引导,从而进入了U-Boot的命令行。
在这里你可以手动进行接下来系统的引导。但是我不会。
虽然不会,但是用于板子上的系统有自动引导,
我们可以分析自动引导,来了解U-Boot是如何引导系统的。


资料

在U-Boot的官网手册中看到了2个关键的环境变量和1个命令。
5.10. U-Boot Environment Variables

  • bootcmd: This variable defines a command string that is automatically >executed
         when the initial countdown is not interrupted.
         This command is only executed when the variable bootdelay is also defined!
  • bootargs: The contents of this variable are
         passed to the Linux kernel
         as boot arguments (aka “command line”).

5.9.6. Environment Variables Commands

5.9.6.4. run - run commands in an environment variable

bootcmd中的命令就是出现“Hit any key to stop autoboot”提示后,不按任意键,会自动运行的命令。
bootargs是传递给Linux内核的参数。
run是运行环境变量中的命令,bootcmd中包含run命令。


分析

所以分析引导过程要从bootcmd开始。

环境变量

在U-Boot的命令行中输入printenv可显示所有的环境变量,

U-Boot# printenv
arch=arm
baudrate=115200
board=am335x
board_name=A335BNLT
board_rev=t\
ue
boot_fdt=try
bootcmd=run findfdt; run mmcboot;setenv mmcdev 1; setenv bootpart 1:2; run mmcboot;run nandboot;
bootcount=2
bootdelay=1
bootdir=/boot
bootenv=uEnv.txt
bootfile=zImage
bootpart=0:2
console=ttyO0,115200n8
cpu=armv7
dfu_alt_info_emmc=rawemmc mmc 0 3751936
dfu_alt_info_mmc=boot part 0 1;rootfs part 0 2;MLO fat 0 1;MLO.raw mmc 100 100;u-boot.img.raw mmc 300 400;spl-os-args.raw mmc 80 80;spl-os-image.raw mmc 900 2000;spl-os-args fat 0 1;spl-os-image fat 0 1;u-boot.img fat 0 1;uEnv.txt fat 0 1
dfu_alt_info_ram=kernel ram 0x80200000 0xD80000;fdt ram 0x80F80000 0x80000;ramdisk ram 0x81000000 0x4000000
eth1addr=c8:a0:30:ac:87:2a
ethact=cpsw
ethaddr=c8:a0:30:ac:87:28
fdt_high=0xffffffff
fdtaddr=0x80F80000
fdtfile=undefined
findfdt=if test $board_name = A335BONE; then setenv fdtfile am335x-bone.dtb; fi; if test $board_name = A335BNLT; then setenv fdtfile am335x-boneblack.dtb; fi; if test $board_name = A33515BB; then setenv fdtfile am335x-evm.dtb; fi; if test $board_name = A335X_SK; then setenv fdtfile am335x-evmsk.dtb; fi; if test $fdtfile = undefined; then echo WARNING: Could not determine device tree to use; fi;
importbootenv=echo Importing environment from mmc ...; env import -t $loadaddr $filesize
loadaddr=0x80200000
loadbootenv=load mmc ${mmcdev} ${loadaddr} ${bootenv}
loadfdt=load mmc ${bootpart} ${fdtaddr} ${bootdir}/${fdtfile}
loadimage=load mmc ${bootpart} ${loadaddr} ${bootdir}/${bootfile}
loadramdisk=load mmc ${mmcdev} ${rdaddr} ramdisk.gz
mmcargs=setenv bootargs console=${console} ${optargs} root=${mmcroot} rootfstype=${mmcrootfstype}
mmcboot=mmc dev ${mmcdev}; if mmc rescan; then echo SD/MMC found on device ${mmcdev};if run loadbootenv; then echo Loaded environment from ${bootenv};run importbootenv;fi;if test -n $uenvcmd; then echo Running uenvcmd ...;run uenvcmd;fi;if run loadimage; then run mmcloados;fi;fi;
mmcdev=0
mmcloados=run mmcargs; if test ${boot_fdt} = yes || test ${boot_fdt} = try; then if run loadfdt; then bootz ${loadaddr} - ${fdtaddr}; else if test ${boot_fdt} = try; then bootz; else echo WARN: Cannot load the DT; fi; fi; else bootz; fi;
mmcroot=/dev/mmcblk0p2 ro
mmcrootfstype=ext4 rootwait
netargs=setenv bootargs console=${console} ${optargs} root=/dev/nfs nfsroot=${serverip}:${rootpath},${nfsopts} rw ip=dhcp
netboot=echo Booting from network ...; setenv autoload no; dhcp; tftp ${loadaddr} ${bootfile}; tftp ${fdtaddr} ${fdtfile}; run netargs; bootz ${loadaddr} - ${fdtaddr}
nfsopts=nolock
ramargs=setenv bootargs console=${console} ${optargs} root=${ramroot} rootfstype=${ramrootfstype}
ramboot=echo Booting from ramdisk ...; run ramargs; bootz ${loadaddr} ${rdaddr} ${fdtaddr}
ramroot=/dev/ram0 rw ramdisk_size=65536 initrd=${rdaddr},64M
ramrootfstype=ext2
rdaddr=0x81000000
rootpath=/export/rootfs
soc=am33xx
spiargs=setenv bootargs console=${console} ${optargs} root=${spiroot} rootfstype=${spirootfstype}
spiboot=echo Booting from spi ...; run spiargs; sf probe ${spibusno}:0; sf read ${loadaddr} ${spisrcaddr} ${spiimgsize}; bootz ${loadaddr}
spibusno=0
spiimgsize=0x362000
spiroot=/dev/mtdblock4 rw
spirootfstype=jffs2
spisrcaddr=0xe0000
static_ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}::off
stderr=serial
stdin=serial
stdout=serial
usbnet_devaddr=c8:a0:30:ac:87:2a
vendor=ti
ver=U-Boot 2014.04 (May 16 2014 - 16:42:23)Environment size: 3515/131067 bytes
U-Boot#

我已经把相关的粘贴到了下面。
为方便阅读我添加了换行。

bootcmd

bootcmd=run findfdt; run mmcboot;setenv mmcdev 1; setenv bootpart 1:2; run mmcboot;run nandboot;

提前给出结论,
一共有6条,但通常前2条就可以启动了,
第3条是在mmcboot失败的情况下,切换mmc设备。
然后从新的mmc设备启动,
如果又失败,从nand启动。

findfdt 设置设备树文件

findfdt=if test $board_name = A335BONE; then setenv fdtfile am335x-bone.dtb; fi; if test $board_name = A335BNLT; then setenv fdtfile am335x-boneblack.dtb; fi; if test $board_name = A33515BB; then setenv fdtfile am335x-evm.dtb; fi; if test $board_name = A335X_SK; then setenv fdtfile am335x-evmsk.dtb; fi; if test $fdtfile = undefined; then echo WARNING: Could not determine device tree to use; fi;
board_name=A335BNLT

首先是运行findfdt中的命令,目的是通过board_name来设置fdtfile,
结果是fdtfile的值为 am335x-boneblack.dtb。
就是BeagleBone Black的设备树文件。


mmcboot 从mmc启动

接下来运行mmcboot中的命令。

mmcboot=mmc dev ${mmcdev}; if mmc rescan; then echo SD/MMC found on device ${mmcdev};if run loadbootenv; then echo Loaded environment from ${bootenv};run importbootenv;fi;if test -n $uenvcmd; then echo Running uenvcmd ...;run uenvcmd;fi;if run loadimage; then run mmcloados;fi;fi;
# 相关变量
mmcdev=0

"mmc dev 0"是将设备切换到0,通常有2个设备一个是SD卡,一个是eMMC。
mmc rescan 扫描当前mmc设备。


loadbootenv

loadbootenv=load mmc ${mmcdev} ${loadaddr} ${bootenv}
# 相关变量
mmcdev=0
loadaddr=0x80200000
bootenv=uEnv.txt

这应该是从设备0的第1个分区装载uEnv.txt到地址0x80200000。
当默认的环境变量不符合要求时,可以用uEnv.txt设置新的环境变量。
没有它也可以,先不用管,后面说。
如果装载成功,执行importbootenv。

importbootenv

importbootenv=echo Importing environment from mmc ...;env import -t $loadaddr $filesize

这是把uEnv.txt中的环境变量导入到U-Boot的环境变量中。
“filesize”没有在我的环境变量中指定。

uenvcmd

由于我没有“uenvcmd”这个环境变量,所以那个条件语句中的内容没有执行。
我记着Arch Linux好像用了那个,那个变量应该在uEnv.txt中。
于是直接到了loadimage。


loadimage 载入Linux内核

loadimage=load mmc ${bootpart} ${loadaddr} ${bootdir}/${bootfile}
# 相关变量
bootpart=0:2
loadaddr=0x80200000
bootdir=/boot
bootfile=zImage

这里和载入uEnv.txt是相似的, 都用了load命令。
“0:2”的意思是设备0的第2个分区。
如果不指定,为默认第一个分区,
载入uEnv.txt时就没有指定分区。

loadimage的目的是将Linux内核载入内存。
到目前为止,主要做了2件事:

  • 设置设备树文件
  • 载入Linux内核

成功后执行 mmcloados。


mmcloados

mmcloados=run mmcargs;if test ${boot_fdt} = yes || test ${boot_fdt} = try;thenif run loadfdt;thenbootz ${loadaddr} - ${fdtaddr};elseif test ${boot_fdt} = try;thenbootz;elseecho WARN: Cannot load the DT;fi;fi;elsebootz;fi;

首先执行mmcargs

mmcargs=setenv bootargs console=${console} ${optargs} root=${mmcroot} rootfstype=${mmcrootfstype}
# 相关变量值
console=ttyO0,115200n8
mmcroot=/dev/mmcblk0p2 ro
mmcrootfstype=ext4 rootwait

目的就是设置bootargs这个环境变量而已,用于向内核传递参数。

然后判断 boot_fdt 的值决定下一步,

# 相关变量
boot_fdt=try

判断通过,执行 loadfdt:

loadfdt=load mmc ${bootpart} ${fdtaddr} ${bootdir}/${fdtfile}
# 相关变量
bootpart=0:2
fdtaddr=0x80F80000
bootdir=/boot
# fdtfile的值为第一步执行findfdt设置的am335x-boneblack.dtb

这里载入了设备树文件,和载入Linux内核是很像的。

至此又做了2件事:

  • 设置Linux内核启动参数
  • 载入设备树文件

启动Linux需要的东西就齐了:

  • Linux内核启动参数
  • Linux内核文件
  • 设备树文件

如果载入设备树成功,
通过bootz后接2个地址就启动了系统。


总结如下

# 切换到启动设备
mmc dev 0;
# 载入Linux内核
load mmc 0:2 0x80200000 /boot/zImage
# 设置Linux内核启动参数
setenv bootargs concole=ttyO0,115200n8 root=mmcroot=/dev/mmcblk0p2 ro rootfstype=ext4 rootwait
# 载入设备树
load mmc 0:2 0x80F80000 /boot/am335x-boneblack.dtb
# 启动Linux
bootz 0x80200000 - 0x80F80000

这是默认环境变量的行为。
而我们的系统可能与其不同。这就要修改环境变量。
我知道有2种方式,
一种是在U-Boot的命令行中通过命令修改,
另一种就是通过uEnv.txt了。

uEnv.txt

使用eEnv.txt更加方便点。就是个文本文件。
先列出我uEnv.txt的内容,不用详细看,看我下面的说明。

bootfile=uImage
loadfdt=load mmc ${bootpart} ${fdtaddr} ${bootdir}/dts/${fdtfile}
mmcloados=run mmcargs; if test ${boot_fdt} = yes || test ${boot_fdt} = try; then if run loadfdt; then bootm ${loadaddr} - ${fdtaddr}; else if test ${boot_fdt} = try; then bootz; else echo WARN: Cannot load the DT; fi; fi; else bootz; fi;
mmcroot=/dev/mmcblk0p2 rw
mmcargs=setenv bootargs console=${console} ${optargs} root=${mmcroot} rootfstype=${mmcrootfstype} init=/usr/lib/systemd/systemd

一共6行,最后一行空白。

  • bootfile修改了内核名字,
  • loadfdt中只是在目录中加了“dts/”,
  • mmcloados主要是把bootz改成bootm。
  • mmcroot把只读改成了可读写。
  • mmcargs只是在后面指定了init为systemd。也有其他方法,比如在Linux系统中将init设置成指向systemd的软链接。

U-Boot常用命令

上面是从设备0启动系统,怎样知道自己的系统位于哪个设备呢,
也许有某种约定,比如如果有SD卡,那么SD卡是0。
我不知道的话,可以在U-Boot的命令行中通过命令判断。如,

# 列出 mmc 设备。
U-Boot# mmc list
OMAP SD/MMC: 0
OMAP SD/MMC: 1
# 显示当前是哪个设备。
U-Boot# mmc dev
mmc0 is current device
# 显示当前设备的分区信息。
U-Boot# mmc partPartition Map for MMC device 0  --   Partition Type: DOSPart    Start Sector    Num Sectors     UUID            Type1     2048            131072          29942d7e-01     0c Boot2     133120          15390720        29942d7e-02     83
# 列出设备0第1个分区"/"目录的文件,我没有指定,默认为“/”。
U-Boot# ls mmc 0:1100688   mlo308232   u-boot.img510   uenv.txt3 file(s), 0 dir(s)

BeagleBoneBlack的U-Boot是如何引导系统的相关推荐

  1. 学习 Linux,101: 引导系统

    2019独角兽企业重金招聘Python工程师标准>>> 系列文章: http://www.ibm.com/developerworks/cn/views/linux/libraryv ...

  2. 虚拟启动光盘-从ISO光盘镜像引导系统

    这是一款神奇的小工具,它可以引导ISO文件,就像开机启动CDROM光盘一样效果. 以前有过能够从软盘映像文件启动系统的工具;虚拟启动软盘程序和WinGrub,但由于软盘映像文件体积限制,无法在这个映像 ...

  3. U盘安装LINUX系统,拔除U盘后无法引导系统

    U盘安装LINUX系统,拔除U盘后无法引导系统 问题描述: 使用U盘安装LINUX操作系统,排除U盘后,无法正常引导系统,必须插入U盘才可以进入系统. 原因分析: GRUB全.称为.Grand Uni ...

  4. UEFI安装win7过程的另类引导系统

    朋友的新买的联想笔记本,固态硬盘,自带win10,因为某个行业软件兼容性问题需要安装windows 7. 折腾了许久,无法在此笔记本UEFI GPT分区上成功引导Ghost  win 7,期间使用引导 ...

  5. 在DOS下让ISO文件引导系统 实现无光驱安装系统

    首先把网上收集的资料发上来参考一下. 免软驱DOS下引导硬盘ISO文件 ---------------------------------------------------------------- ...

  6. 从U盘启动Linux后拔出U盘,U盘安装LINUX系统,拔除U盘后无法引导系统

    U盘安装LINUX系统,拔除U盘后无法引导系统 1 问题描述: 使用U盘安装LINUX操作系统,拔除U盘后,无法正常引导系统,必须插入U盘才可以进入系统. 2 原因分析: GRUB全.称为.Grand ...

  7. 操作系统启动过程——硬件自检+系统引导+系统加载+系统登录

    以下的内容都是在网上搜集并整理的,希望有问题的朋友在提问之前能先在这里看一看,不要浪费了众多为网络奉献的众多网友的心血! 电脑及操作系统的启动过程是一个很复杂的过程,对于我们大多数只是希望把电脑玩的更 ...

  8. Linux内核错误(引导系统)Deepin用户手册在/etc/sysctl.conf文件中加入kernel.panic = 20,在/etc/sysctl.conf中kernel.sysrq=1内存

    Linux内核错误(引导系统)- 系统管理 -Deepin深度系统用户手册 Power By Baidu Ai 00:00 00:00 目录 1 简介 2 问题分析 3 案例分析 此文章约为4327字 ...

  9. 基于结构光测量技术和3D物体识别技术开发的机器人3D视觉引导系统

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达本文转自|新机器视觉 基于结构光测量技术和3D物体识别技术开发的机器 ...

最新文章

  1. org.json.JSONException: A JSONObject text must begin with #39;{#39; at character 1 of {解决方法...
  2. 一款美轮美奂的JavaScript 小项目
  3. android网络游戏开发实战pdf_Python项目开发实战+第2版PDF高清文档下载
  4. 1026 程序运行时间 (15 分)(c语言)
  5. 阿里巴巴为什么主推HSF?比Dubbo有哪些优势?
  6. SAP CRM和Hybris里的Product Variant
  7. java中的args参数
  8. 浅谈Opencl四大模型之Platform model
  9. 主从reactor 多线程模型
  10. 电脑主板线路连接图解_教你如何连接主板路线图文教程
  11. ESP8266-Arduino编程实例-BME280环境传感器驱动
  12. 微信小程序实现简单下拉加载更多
  13. Perfect Triples(思维/规律)
  14. Percona-toolkit的安装和配置-杨建荣的学习笔记
  15. BootCamp Intel Mac上安装Windows全教程
  16. web开发框架_Web开发的最佳PHP框架
  17. 关于采样率位深码率无损的一些心得
  18. 计算机相关的专刊,计算机 | 1区SCI期刊专刊信息1条
  19. RT-Thread-设备(fal)
  20. matlab/simulink石良臣,《MATLAB/Simulink系统仿真超级学习手册》——2.6 MATLAB的图形绘制...

热门文章

  1. Excel单列内容分多列
  2. java dragged_Java 检验 dragged
  3. 割点和桥的模板(割点和割边)
  4. python输出到语音播放_python将文本转化成语音并播放
  5. 麻省理工学院计算机系正教授,我校教授应邀赴美国麻省理工学院等高校做主题演讲并访问交流...
  6. 基于条纹投影的结构光3D成像的研究分享
  7. 限位开关、接近开关、光电传感器、压力传感器等是否有UL认证?
  8. MySQL WorkBench8.0(64Bit) 汉化xml
  9. 计算机技术比武活动方案,计算机操作技能比赛方案
  10. 红米note9 android10,红米note10和note9哪个更好 红米note10和note9性价比详解