轉自: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