查看: 8095|回复: 1

U-Boot是如何引导系统的

[复制链接]
  • TA的每日心情
    奋斗
    2016-9-30 17:07
  • 签到天数: 87 天

    连续签到: 1 天

    [LV.6]常住居民II

    发表于 2014-8-27 10:45:11 | 显示全部楼层 |阅读模式
    分享到:
    本帖最后由 alienspy 于 2015-11-22 13:17 编辑

    通过串口连接BeagleBone Black,参见http://elinux.org/Beagleboard:Terminal_Shells
    启动到U-Boot的时候,会看到
    1. Hit any key to stop autoboot:0
    复制代码
    按下任意键则放弃了自动引导,从而进入了U-Boot的命令行。
    在这里你可以手动进行接下来系统的引导。但是我不会。
    虽然不会,但是用于板子上的系统有自动引导,
    我们可以分析自动引导,来了解U-Boot是如何引导系统的。



    在U-Boot的官网手册中看到了2个关键的环境变量和1个命令。
    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").

    run    - run commands in an environment variable


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

    所以分析引导过程要从bootcmd开始。
    在U-Boot的命令行中输入printenv可显示所有的环境变量,我已经把相关的粘贴到了下面。
    为方便阅读我添加了换行。
    1. bootcmd=
    2.   run findfdt;
    3.   run mmcboot;
    4.   setenv mmcdev 1;
    5.   setenv bootpart 1:2;
    6.   run mmcboot;
    7.   run nandboot;

    8. findfdt=
    9.   if test $board_name = A335BONE;
    10.   then
    11.     setenv fdtfile am335x-bone.dtb;
    12.   fi;
    13.   if test $board_name = A335BNLT;
    14.   then
    15.     setenv fdtfile am335x-boneblack.dtb;
    16.   fi;
    17.   if test $board_name = A33515BB;
    18.   then
    19.     setenv fdtfile am335x-evm.dtb;
    20.   fi;
    21.   if test $board_name = A335X_SK;
    22.   then
    23.     setenv fdtfile am335x-evmsk.dtb;
    24.   fi;
    25.   if test $fdtfile = undefined;
    26.   then
    27.     echo WARNING: Could not determine device tree to use;
    28.   fi;

    29. board_name=A335BNLT
    复制代码
    首先是运行findfdt中的命令,目的是通过board_name来设置fdtfile,结果是fdtfile的值为am335x-boneblack.dtb。

    1. mmcboot=
    2.   mmc dev ${mmcdev};
    3.   if mmc rescan;
    4.   then
    5.     echo SD/MMC found on device ${mmcdev};
    6.     if run loadbootenv;
    7.     then
    8.       echo Loaded environment from ${bootenv};
    9.       run importbootenv;
    10.     fi;
    11.     if test -n $uenvcmd;
    12.     then
    13.       echo Running uenvcmd ...;
    14.       run uenvcmd;
    15.     fi;
    16.     if run loadimage;
    17.     then
    18.       run mmcloados;
    19.     fi;
    20.   fi;

    21. mmcdev=0

    复制代码
    "mmc dev 0"是将设备切换到0,通常有2个设备一个是SD卡,一个是eMMC。

    1. loadbootenv=load mmc ${mmcdev} ${loadaddr} ${bootenv}

    2. loadaddr=0x80200000

    3. bootenv=uEnv.txt

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

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

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

    1. loadimage=load mmc ${bootpart} ${loadaddr} ${bootdir}/${bootfile}

    2. bootpart=0:2

    3. bootdir=/boot

    4. bootfile=zImage

    复制代码
    由于我没有“uenvcmd”这个环境变量,所以那个条件语句中的内容没有执行。我记着Arch Linux好像用了那个,那个变量应该在uEnv.txt中。
    于是直接到了loadimage,这里和载入uEnv.txt是相似的,“0:2”的意思是设备0的第2个分区,而载入uEnv.txt时没有指定分区,就默认第1分区了。
    loadimage的目的是将Linux内核载入内存。

    1. mmcloados=
    2.     run mmcargs;
    3.     if test ${boot_fdt} = yes || test ${boot_fdt} = try;
    4.     then
    5.         if run loadfdt;
    6.         then
    7.             bootz ${loadaddr} - ${fdtaddr};
    8.         else
    9.             if test ${boot_fdt} = try;
    10.             then
    11.                 bootz;
    12.             else
    13.                 echo WARN: Cannot load the DT;
    14.             fi;
    15.         fi;
    16.     else
    17.         bootz;
    18.     fi;

    复制代码
    1. mmcargs=setenv bootargs console=${console} ${optargs} root=${mmcroot} rootfstype=${mmcrootfstype}

    2. console=ttyO0,115200n8

    3. mmcroot=/dev/mmcblk0p2 ro

    4. mmcrootfstype=ext4 rootwait
    复制代码
    这个就是设置bootargs这一个环境变量而已,用于向内核传递参数。

    1. boot_fdt=try

    2. loadfdt=load mmc ${bootpart} ${fdtaddr} ${bootdir}/${fdtfile}

    3. fdtaddr=0x80F80000
    复制代码
    之前载入了Linux内核,这里载入了设备树文件。
    最后通过bootz后接2个地址就启动了系统。


    总结如下
    1. mmc dev 0;

    2. load mmc 0:2 0x80200000 /boot/zImage

    3. setenv bootargs concole=ttyO0,115200n8 root=mmcroot=/dev/mmcblk0p2 ro rootfstype=ext4 rootwait

    4. load mmc 0:2 0x80F80000 /boot/am335x-boneblack.dtb

    5. bootz 0x80200000 - 0x80F80000
    复制代码
    这是默认环境变量的行为。而我们的系统可能与其不同。这就要修改环境变量。
    我知道有2种方式,一种是在U-Boot的命令行中通过命令修改,另一种就是通过uEnv.txt了。
    这里介绍uEnv.txt的方式。先列出我uEnv.txt的内容,不用详细看,看我下面的说明。
    1. bootfile=uImage

    2. loadfdt=load mmc ${bootpart} ${fdtaddr} ${bootdir}/dts/${fdtfile}

    3. mmcloados=run mmcargs; if test ${boot_fdt} = yes || test ${boot_fdt} =
    4. try; then if run loadfdt; then bootm ${loadaddr} - ${fdtaddr}; else if
    5. test ${boot_fdt} = try; then bootz; else echo WARN: Cannot load the DT;
    6. fi; fi; else bootz; fi;

    7. mmcroot=/dev/mmcblk0p2 rw

    8. 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,也有其他方法,如init为指向systemd的软链接。

    这里是从设备0启动系统,怎样知道自己的系统位于哪个设备呢,也许有某种约定,比如如果有SD卡,那么SD卡是0。
    我不知道的话,可以在U-Boot的命令行中通过命令判断。如,
    1. U-Boot# mmc list
    2. OMAP SD/MMC: 0
    3. OMAP SD/MMC: 1
    复制代码
    列出mmc设备。
    1. U-Boot# mmc dev
    2. mmc0 is current device
    复制代码
    显示当前是哪个设备。
    1. U-Boot# mmc part

    2. Partition Map for MMC device 0  --   Partition Type: DOS

    3. Part    Start Sector    Num Sectors     UUID            Type
    4.   1     2048            131072          29942d7e-01     0c Boot
    5.   2     133120          15390720        29942d7e-02     83
    复制代码
    显示当前设备的分区信息。
    1. U-Boot# ls mmc 0:1
    2.    100688   mlo
    3.    308232   u-boot.img
    4.       510   uenv.txt

    5. 3 file(s), 0 dir(s)
    复制代码
    列出设备0第1个分区“/”目录的文件,我没有指定,默认为“/”。

    回复

    使用道具 举报

  • TA的每日心情
    开心
    2015-10-10 20:28
  • 签到天数: 8 天

    连续签到: 1 天

    [LV.3]偶尔看看II

    发表于 2014-9-10 15:35:23 | 显示全部楼层
    对我有用,谢谢楼主
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /5 下一条

    手机版|小黑屋|与非网

    GMT+8, 2024-12-22 20:10 , Processed in 0.141127 second(s), 17 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.