BeagleBone Black 3

摘自:http://jexbat.com/2016/BBB-Prepare-booting/


BeagleBone Black 從零到一 (3 Linux 鏡像、initramfs、Device Tree及根文件系統)

基於 Linux 3.8

內核啓動

BeagleBone Black 從零到一 (1 MLO、U-Boot) 這篇文章裏講到 U-Boot 啓動之後會運行 uEnv.txt 文件裏面 uenvcmd 指代的命令,我們也通常把加載鏡像文件等命令寫在這裏。

U-Boot 有很多方法能啓動內核,通常使用的是 bootm 或者 bootz 命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
U-Boot# help bootz
bootz - boot Linux zImage image from memory

Usage:
bootz [addr [initrd[:size]] [fdt]]
    - boot Linux zImage stored in memory
        The argument 'initrd' is optional and specifies the address
        of the initrd in memory. The optional argument ':size' allows
        specifying the size of RAW initrd.
        When booting a Linux kernel which requires a flat device-tree
        a third argument is required which is the address of the
        device-tree blob. To boot that kernel without an initrd image,
        use a '-' for the second argument. If you do not pass a third
        a bd_info struct will be passed instead

U-Boot# help bootm
bootm - boot application image from memory

Usage:
bootm [addr [arg ...]]
    - boot application image stored in memory
        passing arguments 'arg ...'; when booting a Linux kernel,
        'arg' can be the address of an initrd image
        When booting a Linux kernel which requires a flat device-tree
        a third argument is required which is the address of the
        device-tree blob. To boot that kernel without an initrd image,
        use a '-' for the second argument. If you do not pass a third
        a bd_info struct will be passed instead

For the new multi component uImage format (FIT) addresses
        must be extened to include component or configuration unit name:
        addr:<subimg_uname> - direct component image specification
        addr#<conf_uname>   - configuration specification
        Use iminfo command to get the list of existing component
        images and configurations.

Sub-commands to do part of the bootm sequence.  The sub-commands must be
issued in the order below (it's ok to not issue all sub-commands):
        start [addr [arg ...]]
        loados  - load OS image
        ramdisk - relocate initrd, set env initrd_start/initrd_end
        fdt     - relocate flat device tree
        cmdline - OS specific command line processing/setup
        bdt     - OS specific bd_t processing
        prep    - OS specific prep before relocation or go
        go      - start OS

bootz 啓動存儲在內存中的 zImage ,支持 device-tree,其中一些參數:
addr:內核地址
initrd:ramdisk 鏡像地址,如果沒有指定的 initrd 需要傳遞一個 - 給啓動指令。什麼是 ramdisk 鏡像呢?我們下面會講到。
fdt: flat device tree 地址,如果沒有指定 fdt 地址,會傳入一個 bd_info 結構體。什麼是 Device Tree 呢?我們下面也會講到。

Linux 啓動需要的文件

Linux 啓動的時候需要掛載根文件系統來運行初始化程序,再總結 bootz 命令,所以 U-Boot 啓動 Linux 內核需要以下文件:
內核鏡像、initrd 文件(ramdisk 鏡像)、DTB(Device Tree Binary)、根文件系統
不是必要但是也是需要的文件:
System.map

Linux 內核鏡像

vm 代表 Virtual Memory,Linux 支持虛擬內存,因此得名 vm。Linux 內核按引導程序的不同分不同的格式,主要有:

  • vmlinux : 最原始的內核靜態鏈接後可執行的文件格式 ELF,沒有壓縮,不可啓動的內核鏡像,可能在調試階段纔會用到。
  • vmlinux.bin : 和 vmlinux 類似不過是可啓動的 RAW Binary 格式。所有的標誌和重定位信息都被丟棄,由 vmlinux 通過命令 objcopy -O binary vmlinux vmlinux.bin 生成。
  • vmlinuz : 經過壓縮過的 vmlinux 可啓動鏡像。可啓動表示有能力加載操作系統到內存中運行,vmlinuz 通常由 zImage 和 bzImage 拷貝而來。
  • zImage : 比zImage 是 ARM linux 常用的一種壓縮鏡像文件,它是由 vmlinux 加上解壓代碼經 gzip 壓縮而成,通常放在小尺寸 ROM 中(小於 512K),zImage 解壓縮內核到低容量內存(640K)。由命令 make zImage生成。
  • bzImage : bz 表示 big zImage,其格式與 zImage 類似,但採用了不同的壓縮算法。bzImage 需要解壓縮內核到高容量內存(1M以上)。由命令 make bzImage 生成。
  • uImage : uImage 是 uboot 專用的鏡像文件,它是在 zImage 之前加上一個長度爲 0x40 的頭信息(tag),在頭信息內說明了該鏡像文件的類型、加載 位置、生成時間、大小等信息。其 0x40 之後與 zImage 沒區別。

編譯及生成:

BeagleBone 的內核鏡像託管在 Github
編譯之前可能需要安裝的庫

1
2
➜ sudo apt-get install lzop
➜ sudo apt-get install libncurses5-dev libncursesw5-dev

源碼裏面已經包含了 BeagleBone 的配置文件:

1
2
3
4
5
6
➜ git clone git://github.com/beagleboard/linux.git
➜ cd linux
➜ git checkout 3.8
➜ make distclean
➜ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- bb.org_defconfig 
➜ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage dtbs -j4

編譯完成後會在 arch/arm/boot 目錄下面生成 zImage 鏡像和 dtbs 文件。
或者也可以使用 make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- menuconfig 或者 make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- xconfig 來自己配置需要編譯的內容。
如果使用 make xconfig 則需要安裝 qt 和一些依賴,如果使用虛擬機不能使用 ssh 的方式遠程編譯,需要打開虛擬的圖形界面進行編譯。
xconfig 的一些依賴:

1
2
3
➜ sudo apt-get update
➜ sudo apt-get install libqt4-dev pkg-config
➜ sudo apt-get install g++

initrd、initramfs

Linux kernel 在自身初始化完成之後,需要能夠找到並運行第一個用戶程序(這個程序通常叫做 “init” 程序)。用戶程序存在於文件系統之中,因此,內核必須找到並掛載一個文件系統纔可以成功完成系統的引導過程。根文件系統(rootfs) 所在的儲存裝置很可能極難尋找,比方說 SCSI 裝置就需要複雜且耗時的程序,若用 RAID 系統更是需要看配置情況而定,同樣的問題也發生在 USB storage 上,因爲 kernel 得花上更長的等待與配置時間,又或者需要遠端掛載 rootfs,不僅得處理網路裝置的問題,甚至還得考慮相關的伺服器認證、通訊往返時間等議題。爲解決此問題,Linux kernel 提出了一個 RAM disk 的解決方案,把一些啓動所必須的用戶程序和驅動模塊放在 RAM disk 中,這個 RAM disk 看上去和普通的 disk 一樣,有文件系統,有 cache,內核啓動時,首先把 RAM disk 掛載起來,等到 init 程序和一些必要模塊運行起來之後,再切到真正的文件系統之中。更重要的是,有了 initrd(init ram disk) 我們可在放置某些特別的程式,一來作爲掛載 rootfs 作準備,比方說硬體初始化、解密、解壓縮等等,二來提示使用者或系統管理員目前的狀態,這對於消費性電子產品來說,有很大的意義。
整體來說,如果能增加開機的彈性(比方說配合簡單的shell script 即​​可達成USB/SCSI 初始化動作,若透過 kernel code 實做,恐怕上百千行是免不掉的),又能適度降低 kernel image 本身的設計複雜度與空間使用量,採取 initrd 是很不錯的方式,所以幾乎各大Linux distribution 都有提供 initrd,以解決在不同硬體、不同裝置上開機的技術議題。
如果仔細考慮一下,initrd 雖然解決了問題但並不完美。 比如,disk 有 cache 機制,對於 RAM disk 來說,這個 cache 機制就顯得很多餘且浪費空間;disk 需要文件系統,那文件系統(如 ext2 等)必須被編譯進 kernel 而不能作爲模塊來使用。
Linux 2.6 kernel 提出了一種新的實現機制,即 initramfs。顧名思義,initramfs 只是一種 RAM filesystem 而不是 disk。initramfs 實際是一個 cpio 歸檔,啓動所需的用戶程序和驅動模塊被歸檔成一個文件。因此,不需要 cache,也不需要文件系統。

引用:關於 initramfs

The only purpose of an initramfs is to mount the root filesystem. The initramfs is a complete set of directories that you would find on a normal root filesystem. It is bundled into a single cpio archive and compressed with one of several compression algorithms.
initramfs 的唯一用途就是掛載根文件系統。initramfs 就是一個普通文件系統目錄的完整的集合。它用幾個壓縮算法打包成 cpio 格式。
There are only four primary reasons to have an initramfs in the LFS environment: loading the rootfs from a network, loading it from an LVM logical volume, having an encrypted rootfs where a password is required, or for the convenience of specifying the rootfs as a LABEL or UUID. Anything else usually means that the kernel was not configured properly.
在 LFS (Linux From Scratch) 中 initramfs 的存在主要有四個主要的原因:從網絡加載根文件系統、從 LMM 邏輯卷加載的根文件系統、加密過的需要密碼的根文件系統或者方便的指定根文件系統爲 LABLE 或者 UUID。還有別的通常意味着內核配置不正確。
For most distributions, kernel modules are the biggest reason to have an initramfs. In a general distribution, there are many unknowns such as file system types and disk layouts. In a way, this is the opposite of LFS where the system capabilities and layout are known and a custom kernel is normally built. In this situation, an initramfs is rarely needed.
對於大多數分發版本來說,需要 initramfs 最大的原因是內核模塊。在一般的分發中,有很多未知的文件系統和磁盤分佈,在某種程度下,這是在系統能力和佈局未知的情況。 如果說系統能力和佈局已知,內核已經建立的情況下很少需要 initramfs。

上面提到的 RAM DISK 爲 image-initrd,RAM filesystem 爲 cpio-initrd,內核啓動的時候會先判斷是否爲 cpio 格式,如果不是的話會當作 image-initrd 處理。

cpio-initrd 和 image-initrd 處理流程可以參考:Linux2.6 內核的 Initrd 機制解析

編譯及生成:

Linux 2.6 以來都是默認使用 initramfs(”General setup” 的子項目 “Initial RAM filesystem and RAM disk (initramfs/initrd) suppot” 是默認勾選的) ,只是編譯的輸出很多還沿襲傳統使用 initrd 的名字。編譯的時候會生成 usr/initramfs_data.cpio 文件,內核編譯的時候會把這個文件編譯進內核。如果配置選項裏面 “Initramfs source file” 爲空(不指定 CONFIG_INITRAMFS_SOURCE),會默認編譯出一個空的 initramfs 包(沒有 init 文件)。
這樣一來 Linux 內核編譯的時候如果按默認方式編譯(勾選 “initial RAM filesystem and RAM disk (initramfs/initrd) suppot”) 則有四種方法生成 initramfs 文件:
1. 不指定 CONFIG_INITRAMFS_SOURCE 則會編譯出一個空的 initramfs
2. 爲 CONFIG_INITRAMFS_SOURCE 指定一個現有的 initramfs 文件

如果你有一個現有的 initramfs_data.cpio.gz 文件,可以指定給 CONFIG_INITRAMFS_SOURCE ,內核編譯時會自動檢測文件類型然後鏈接到內核鏡像中去。
3. 爲 CONFIG_INITRAMFS_SOURCE 指定一個現有的根文件系統目錄
如果爲 CONFIG_INITRAMFS_SOURCE 指定一個目錄,編譯的時候會自動把此目錄打包成 cpio 文件,但是不是用的標準的 cpio 命令打包,內核編譯時會在指定的目錄生成一個描述目錄結構的文本文件 gen_initramfs_list.sh,然後給 gen_init_cpio 程序(在 usr 目錄下)調用,就會生成 cpio 包。
4. 使用 initramfs_list 配置文件配置
這就是剛剛第三種方法講的配置文件 gen_initramfs_list.sh,不過我們這裏是手動創建配置文件而不是自動生成。手動創建後放入一個目錄中,然後指定 CONFIG_INITRAMFS_SOURCE 爲那個目錄編譯的時候就可以生成相應的 cpio 包。
例子:

gen_initramfs_list.sh
1
2
file /init usr/hello 500 0 0
dir /dev 755 0 0

這個內容表示把 usr/hello 指定爲文件系統中的 init 文件,權限爲 500,uid 和 gid 都爲0,並且創建 /dev文件夾,權限爲 755,uid 和 gid 都爲 0。
詳細使用方法請看:Tech Tip: How to use initramfs.

值得注意的是我們按照這個方法制作出來的內核鏡像實際上比原來的大了許多,這是因爲我們是將 initramfs 根文件系統直接合併到內核鏡像裏邊了。這樣,啓動內核時的參數就不需要添加 initrd=…… 來指定 initramfs 的位置了(或者配置內核的時候直接不勾選 “Initial RAM filesystem and RAM disk (initramfs/initrd) suppot”,但是爲了可擴展性一般默認勾選)。
啓動命令爲:

1
bootz ${loadaddr} - ${fdtaddr};

當然如果想指定外部的 initramfs 文件來啓動 Linux,首先直接指定 CONFIG_INITRAMFS_SOURCE 爲空,這樣就會鏈接一個空的 initramfs (一百多字節)進內核,然後指定外部 initramfs 的位置來啓動。
命令爲:

1
bootz ${loadaddr} ${rdaddr}:${rdsize}  ${fdtaddr};

手動生成 initramfs 文件:

1
2
3
4
5
6
➜ mkdir sub   
➜ cp hello sub/init
➜ cd sub
➜ find . | cpio -o -H newc | gzip > ../initramfs_data.cpio.gz
➜ cd ..
➜ rm -rf sub

System.map

System.map 是一個特定內核的內核符號表。它是你當前運行的內核的符號鏈接。Linux 內核是一個很複雜的代碼塊,有許許多多的全局符號。內核並不使用符號名。它是通過變量或函數的地址(指針)來使用變量或函數的,而不是使用 size_t BytesRead,內核更喜歡使用(例如) c0343f20 來引用這個變量。
當你編譯一個新內核時,各個符號名的地址要發生變化,你的老的 System.map 具有的是錯誤的符號信息。每次內核編譯時產生一個新的 System.map,你應當用新的System.map 來取代老的 System.map。
雖然內核本身並不真正使用 System.map,但其它程序比如 klogd, lsof 和 ps 等軟件需要一個正確的 System.map。如果你使用錯誤的或沒有 System.map,klogd 的輸出將是不可靠的,這對於排除程序故障會帶來困難。沒有 System.map,你可能會面臨一些令人煩惱的提示信息。
另外少數驅動需要 System.map 來解析符號,沒有爲你當前運行的特定內核創建的System.map 它們就不能正常工作。
Linux 的內核日誌守護進程 klogd 爲了執行名稱-地址解析,klogd 需要使用System.map。System.map 應當放在使用它的軟件能夠找到它的地方。執行:man klogd 可知,如果沒有將 System.map 作爲一個變量的位置給 klogd,那麼它將按照下面的順序,在三個地方查找 System.map:
/boot/System.map
/System.map
/usr/src/linux/System.map
System.map 也有版本信息,klogd 能夠智能地查找正確的映象(map)文件。

編譯及生成:

System.map 文件在編譯內核的時候會自動生成在源碼根目錄下,每次重新編譯內核都要替換掉相應的 System.map。

Device Tree 機制

Kernel 3.x 版本之後開始支持 Device Tree 機制。
在早期的ARM Linux Kernel中,板級細節(BSP)使用代碼形式,存放在 arch/arm/ 目錄。名字通常爲:plat-xxxx 或者 mach-xxxx,相當多數的代碼只是在描述板級細節,而這些板級細節對於內核來講,不過是垃圾。板級代碼只對相應開發板有用,每次升級 Kernel 都需要對板級代碼進行升級和測試,ARM 對應的開發板又種類繁多所以這些代碼越來越臃腫龐大。
引入了 Device Tree 之後,改變了原來用硬編碼的方式把板級代碼嵌入在內核裏面,改用通過 Bootloader 傳遞 DB 文件的方式把硬件信息傳遞給 Kernel,實現了內核和板級代碼的低耦合,減少內核代碼的臃腫降低維護人員的成本。
Uboot 的主線代碼從 v1.1.3 開始就支持 DT 了,其對ARM的支持和 Kernel 對 Device Tree 的支持是同期完成的,在 Uboot 中需要在配置文件中加入 #define CONFIG_OF_LIBFDT 配置項即可,當我們將 DTB 文件在 Uboot 里加載到內存中後,通過 fdt addr 0xnnnnnnnn 命令來設置 DTB 文件對應地址,這樣就可以使用 fdt resizefdt print 等命令對 DTB 文件進行操作了。對於 ARM,使用 bootz ${loadaddr} ${rdaddr}:${rdsize} ${fdtaddr} 命令來啓動 Kernel。
更多背景介紹:Device Tree 背景介紹

編譯及生成:

DTS:Device Tree Source 位於目錄 linux/arch/arm/boot/dts
DTC:Device Tree Compiler 位於目錄 linux/scripts/dtc/dtc
DTB:Device Tree Binary 生成在 linux/arch/arm/boot/dts
DTB 是由 DTS 通過 DTC 編譯而成。
在構建內核的時候可以使用 make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- dtbs 生成。
Device Tree Binary 在編譯 linux 內核的時候自動根據 arch/arm/boot/dts/Makefile 指定的方式生成,也可以通過 dtc 手動編譯:

1
➜ ./scripts/dtc/dtc -I dts -O dtb -o ./devicetree.dtb ./beaglebone.dts

DTS 組成和結構專門寫一篇文章來講。

根文件系統

根文件系統是內核掛載的第一個文件系統,根文件系統爲分層文件樹的頂點。它包含對於系統操作很關鍵的文件和目錄,包括設備目錄和用於引導系統的程序。根文件系統還包含可安裝文件系統以連接到根文件系統層次結構的安裝點。
Linux 只有一個文件樹,整個文件系統是以一個樹根 “/“ 爲起點的,所有的文件和外部設備都以文件的形式掛結在這個文件樹上,包括硬盤、軟盤、光驅、調制解調器等,這和以 “驅動器盤符” 爲基礎的Windows系統是大不相同的。

編譯及生成:

根文件系統的製作可以自己建立各個系統文件夾添加需要的庫和啓動文件然後打包成可分發的鏡像。
目前一般使用 buildroot 或者 busybox 來製作根文件系統,buildroot 比 busybox 更強大並且包含了 busybox 。

下載 buildroot 源碼:

1
➜ git clone git://git.buildroot.net/buildroot

爲 Beaglebone 配置 buildroot:

1
➜ make beaglebone_defconfig

如果只編譯文件系統,需要做一些修改:

1
➜ make menuconfig

取消勾選 Kernel --> Linux Kernel,這裏不編譯內核;
取消勾選 bootloaders --> u-boot,也不編譯 u-boot;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

Target options --->:
    Floating point strategy (NEON)
    ARM instruction set (Thumb2)
Toolchain --->
    Toolchain type (External toolchain)
    Toolchain (Linaro ARM 2014.08)
    Toolchain origin (Toolchain to be downloaded and installed) //讓 buildroot 自己下載
Target packages --->
    Networking applications --->
        [*] dhcpcd
        [*] openssh
    Text editors and viewers --->
        [*] nano
Filesystem images --->
    ext2/3/4 variant (ext4) --->
        (X) ext4

保存然後:

1
➜ make

make 的時候 buildroot 會聯網下載一些編譯工具或者依賴包。最後會在 output 文件夾中生成相應的文件系統,把生成的文件系統燒寫進 SD 卡中:

1
➜ sudo dd if=buildroot/output/images/rootfs.ext4 of=/dev/sdc2

值得注意的是用以上命令燒寫之後可以看到 SD 卡使用率變成 100%,沒有空間寫別的文件進去了。
這是因爲使用 dd 命令不僅僅把文件而是把整個文件系統都燒寫到 SD 卡中了,包括磁盤使用率的 metadata 描述。雖然 SD 卡上還有很多剩餘空間,但是剩餘空間還沒有合併到特定的分區上,隱藏在 SD 卡分區的末尾。
這個時候使用 resize 命令就能合併了(在 ext2、ext3和ext4上都能使用,並且執行命令的時候會提示使用 e2fsck 檢查下文件系統,按提示操作即可):

1
➜ sudo resize2fs /dev/sda99

如果我們在 buildroot 中的 toolchain 指定外部編譯工具爲之前在 Ubuntu 上面 apt-get 的交叉編譯器,那麼編譯的時候則會出現錯誤信息:

Distribution toolchains are unsuitable for use by Buildroot,
as they were configured in a way that makes them non-relocatable,
and contain a lot of pre-built libraries that would conflict with
the ones Buildroot wants to build.

這是因爲 Ubuntu 得到的交叉編譯器被配置成不可重定位的,而且包含了一些與 buildroot 相沖突的庫,官方解釋:

Distro toolchains, i.ie. toolchains coing with distributions, will
almost invariably be unsuitable for use with Buildroot:

  • they are mostly non-relocatable;
    • their sysroot is tainted with a lot of extra libraries.

Especially, the toolchains coming with Ubuntu (really, all the Debian
familly of distros) are configured with –sysroot=/ which makes them
non-relocatable, and they already contain quite some libraries that
conflict (in any combination of version, API or ABI) with what Buildroot
wants to build (i.e. extra libraries, some not even present in
Buildroot…) but also their mere preence when Buildroot does not expect
them to be already built (so that a package would enable features when
it should not).

所以我們要自己下載交叉編譯工具或者讓 buildroot 自動下載。

開始完整啓動 Linux

準備:

  • SD 卡已經分好兩個區,區 1 爲 FTA 格式,區 2 爲 EXT4 格式,區 1 前面留有 1 MB 的空間供 U-Boot 使用
  • U-Boot 已經編譯好並把 MLO 和 uboot.img 文件燒寫到 SD 卡的前 1M 起始位置,以便處理器用 RAW Mode 啓動 U-boot,具體請看BeagleBone Black 從零到一 (1 MLO、U-Boot)
  • Linux 已經編譯好並且生成了 zImage、System.map;
  • initramfs 已經制作好並且生成了 initrd.img;(如果沒有特殊的啓動前要求此項可以忽略);
  • 文件系統已經制作好並且燒入到 SD 卡的 ext4 分區中;

新建 boot 目錄:

1
➜ mkdir boot

拷貝內核編譯出來的 zImage 和 System.map 至 boot 目錄並重命名:

1
2
3
➜ cp zImage  ~/boot/
➜ cp System.map ~/boot/
➜ mv ~/boot/zImage ~/boot/vmlinuz

把 initrd.img 和 dtb 文件拷貝到 boot 文件夾,再把整個 boot 文件夾拷貝到 ext4 分區的根目錄。
在 FTA 分區中新建 uEnv.txt 文件,讓 U-Boot 啓動之後自動運行相應的指令啓動 Linux:

uEnv.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
## uEnv.txt 可以引用默認的環境變量,在 include/configs/xxx.h 裏面定義
## 因爲 SDRAM 的地址是從 0x80000000開始的,這裏設置鏡像、dtb、initrd加載到的地址分別爲 0x82000000、0x88000000、0x88080000
loadaddr=0x82000000
fdtaddr=0x88000000
rdaddr=0x88080000
## 設置
initrd_high=0xffffffff
fdt_high=0xffffffff

## 設置命令爲先打印 debug 信息,然後從第 0 個 MMC 設備的第 2 個分區裏面的boot 文件夾中的 vmliuz 文件加載到 loadaddr 處
loadximage=echo debug: [/boot/vmlinuz] ... ; load mmc 0:2 ${loadaddr} /boot/vmlinuz}
## 同樣的加載 dtb 文件
loadxfdt=echo debug: [/boot/{fdtfile}] ... ;load mmc 0:2 ${fdtaddr} /boot/${fdtfile}
## 加載 initrd
loadxrd=echo debug: [/boot/initrd.img] ... ; load mmc 0:2 ${rdaddr} /boot/initrd.img; setenv rdsize ${filesize}
## 加載第二個分區的 uEnv.txt 文件
loaduEnvtxt=load mmc 0:2 ${loadaddr} /boot/uEnv.txt ; env import -t ${loadaddr} ${filesize};
## 檢查 ${dtb} 字符串長度是否不爲 0,如果不爲 0 就賦值給 fdtfile
check_dtb=if test -n ${dtb}; then setenv fdtfile ${dtb};fi;
## 運行前面指定的命令
loadall=run loaduEnvtxt; run check_dtb; run loadximage; run loadxrd; run loadxfdt;

## 設置傳遞給內核的參數,其中 cmdline 是在第二個分區也就是放置 linux 鏡像的分區內的 boot 文件夾中的 uEnv.txt 加載的
mmcargs=setenv bootargs console=tty0 console=${console} ${optargs} ${cape_disable} ${cape_enable} root=/dev/mmcblk0p2 rootfstype=${mmcrootfstype} ${cmdline}

##  根據前面幾篇文章 U-Boot 的配置,啓動後會運行 uenvcmd
uenvcmd=run loadall; run mmcargs; echo debug: [${bootargs}] ... ; echo debug: [bootz ${loadaddr} ${rdaddr}:${rdsize} ${fdtaddr}] ... ; bootz ${loadaddr} ${rdaddr}:${rdsize} ${fdtaddr};

SD 卡中 ext4 分區中 boot 文件夾中再創建一個 uEnv.txt,這邊的 uEnv.txt 便於向 U-Boot 傳遞一些內核參數之類的,不用每次換了內核之類的都去修改 U-Boot 那邊的文件:

uEnv.txt
1
2
3
4
uname_r=3.8.13-bone79
#uuid=
#dtb=
cmdline=coherent_pool=1M quiet init=/lib/systemd/systemd cape_universal=enable

都設置好了之後,把 SD 卡插入 beaglebone 中並且按住 S2 鍵上電就能從 SD 卡中啓動了。

參考:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章