[uboot]uboot如何引導系統


轉自:http://bbs.elecfans.com/jishu_455028_1_1.html


 如6410的bootcmd和bootargs默認存在於uboot1.1.6/include/configs/smdk6410.h

the older version's of u-boot used boot.scr to set boot parameter

setenv bootargs 'console=ttyS2,115200n8 root=/dev/mmcblk0p2 rw rootfstype=ext3 rootwait omapfb.mode=dvi:1280x1024MR-32 at 60 vram=12M' setenv bootcmd 'mmc init; fatload mmc 0 80000000 uImage; bootm 80000000'

boot

Newer version's of u-boot now look for a uEnv.txt file to set boot parameter

mpurate=1000
dvimode=800x600MR-16@60 
vram=4MB 
bootargs "console=ttyS2,115200n8 root=/dev/mmcblk0p2 rootwait ro 
vram=${vram} omapfb.mode=dvi:${dvimode} omapfb.vram=0:2M,1:2M mem=208M@0x80000000"
boot 

By default, the frame buffer is only allocated for /dev/fb0. Option vram should be specified in u-boot bootargs variable to allocate frame buffer for /dev/fb1. For example:   vram=8M omapfb.vram=4M,4M

---------------------------------------------------------------------------------------------------------------------------------------------

1.bootcmd和bootargs

通過串口連接BeagleBone Black,參見http://elinux.org/Beagleboard:Terminal_Shells
啟動到U-Boot的時候,會看到

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可顯示所有的環境變量,我已經把相關的粘貼到了下面。
為方便閱讀我添加了換行。

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

下面就分別從bootcmd內容說起:

2.1.findfdt

首先是運行findfdt中的命令,目的是通過board_name來設置fdtfile,結果是fdtfile的值為am335x-boneblack.dtb

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

2.2.mmcboot

"mmc dev 0"是將設備切換到0,通常有2個設備一個是SD卡,一個是eMMC

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

2.2.1.loadbootenv

這應該是從設備0的第1個分區裝載uEnv.txt到地址0x80200000
當默認的環境變量不符合要求時,可以用uEnv.txt設置新的環境變量。沒有它也可以,先不用管,后面說。

loadbootenv=load mmc ${mmcdev} ${loadaddr} ${bootenv}
loadaddr=0x80200000
bootenv=uEnv.txt

2.2.2.importbootenv

這是把uEnv.txt中的環境變量導入到U-Boot的環境變量中。“filesize”沒有指定。

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

由於我沒有“uenvcmd”這個環境變量,所以那個條件語句中的內容沒有執行。我記着Arch Linux好像用了那個,那個變量應該在uEnv.txt中。

2.2.3.loadimage

於是直接到了loadimage,這里和載入uEnv.txt是相似的,“0:2”的意思是設備0的第2個分區,而載入uEnv.txt時沒有指定分區,就默認第1分區了。
loadimage目的是將Linux內核載入內存。

loadimage=load mmc ${bootpart} ${loadaddr} ${bootdir}/${bootfile}
bootpart=0:2
bootdir=/boot
bootfile=zImage

2.2.4.mmcloados

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;

2.2.5.mmcargs

這個就是設置bootargs這一個環境變量而已,用於向內核傳遞參數。

mmcargs=setenv bootargs console=${console} ${optargs} root=${mmcroot} rootfstype=${mmcrootfstype}
console=ttyO0,115200n8
mmcroot=/dev/mmcblk0p2 ro
mmcrootfstype=ext4 rootwait

之前載入了Linux內核,這里載入了設備樹文件。
最后通過bootz后接2個地址就啟動了系統。

boot_fdt=try loadfdt=load mmc ${bootpart} ${fdtaddr} ${bootdir}/${fdtfile}
fdtaddr=0x80F80000

3.總結如下

這是默認環境變量的行為。而我們的系統可能與其不同。這就要修改環境變量。
我知道有2種方式,一種是在U-Boot的命令行中通過命令修改,另一種就是通過uEnv.txt了。

  • uboot命令方式
mmc dev 0;
load mmc 0:2 0x80200000 /boot/zImage
setenv bootargs concole=ttyO0,115200n8 root=mmcroot=/dev/mmcblk0p2 ro rootfstype=ext4 rootwait
load mmc 0:2 0x80F80000 /boot/am335x-boneblack.dtb
bootz 0x80200000 - 0x80F80000
  • uEnv.txt方式

這里介紹uEnv.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,也有其他方法,如init為指向systemd的軟鏈接。

這里是從設備0啟動系統,怎樣知道自己的系統位於哪個設備呢,也許有某種約定,比如如果有SD卡,那么SD卡是0
我不知道的話,可以在U-Boot的命令行中通過命令判斷。如,

U-Boot# mmc list OMAP SD/MMC: 0 OMAP SD/MMC: 1

列出mmc設備

U-Boot# mmc dev
mmc0 is current device

顯示當前是那個設備

U-Boot# mmc part
Partition Map for MMC device 0  --   Partition Type: DOS
Part    Start Sector    Num Sectors     UUID            Type
  1     2048            131072          29942d7e-01     0c Boot
  2     133120          15390720        29942d7e-02     83

顯示當前設備的分區信息

U-Boot# ls mmc 0:1
   100688   mlo
   308232   u-boot.img
      510   uenv.txt
3 file(s), 0 dir(s)

列出設備0第1個分區“/”目錄的文件,我沒有指定,默認為“/”。

附錄:printenv內容

OpenJTAG> printenv
bootcmd=nand read.jffs2 0x30007FC0 kernel; bootm 0x30007FC0
bootdelay=2
baudrate=115200
ethaddr=08:00:3e:26:0a:5b
netmask=255.255.255.0
mtdids=nand0=nandflash0
mtdparts=mtdparts=nandflash0:256k@0(bootloader),128k(params),2m(kernel),-(root)
ipaddr=192.168.1.66 //開發板ip地址 
 bootargs=root=/dev/nfs rw nfsroot=192.168.1.88:/home/book/Videos/rootfs/ ip=192.168.1.66 console=ttySAC0 mem=64M     //uboot中nfs文件系統參數192.168.1.88ubuntu系統ip地址
serverip=192.168.1.100 //xp中的ip地址

stdin=serial 
stdout=serial
stderr=serial
partition=nand0,0
mtddevnum=0
mtddevname=bootloader

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM