如何準備 sd.img (2016 版)
先前我們所準備的 sd.img 已經接近可以開機的階段,現在只要將開機核心及 bootloader
放至 sd.img 的第一個分割區即可進行開機。底下是 sd.img 的分割區及內容:
sd.img +- part1-+
| + MLO -> 不是每塊 ARM 版都有,主要適用於 TI OMAP 系列
| + u-boot -> 在編譯完之 u-boot-VERSION 目錄下
| + u-boot.bin -> 在編譯完之 u-boot-VERSION 目錄下
| + uImage -> 在編譯完之 linux-VERSION/arch/arm/boot 目錄下
+- part2-+
+ roofs -> 先前以 debootstrap 作出來的內容
把上述內容準備好之後,我們可以執行 runsd.sh,其內容如下:
MACHINE=vexpress-a9
SD_IMAGE=sd.img
MEMORY=256
qemu-system-arm -machine $MACHINE -m $MEMORY \
-nographic \
-drive file=./$SD_IMAGE,if=sd,format=raw,index=0 \
-kernel ./bootloader/u-boot-2016.09/u-boot \
然後將 sd.img 完全解除掛載,再執行 sh runsd.sh,我們可以先放著給它跑,最終會當掉,或是在倒數計時階段按 Enter 暫停下來。暫停後會出現 u-boot 的提示符號,如底下所示:
Hit any key to stop autoboot: 0
=>
請執行 bdinfo 如底下所示:
=> bdinfo
arch_number = 0x000008E0
boot_params = 0x60002000
DRAM bank = 0x00000000
-> start = 0x60000000
-> size = 0x10000000
DRAM bank = 0x00000001
-> start = 0x80000000
-> size = 0x00000004
eth0name = smc911x-0
ethaddr = 52:54:00:12:34:56
current eth = smc911x-0
ip_addr = <NULL>
baudrate = 38400 bps
TLB addr = 0x6FFF0000
relocaddr = 0x6FF7D000
reloc off = 0x0F77D000
irq_sp = 0x6FEDCEF0
sp start = 0x6FEDCEE0
我們可以看到版子資訊,在此可以看到 DRAM bank 0 的 start 位址是 0x60000000,待會我們以此位址來載入核心並開機試試,接下來可以執行 mmcinfo 如底下所示:
=> mmcinfo
Device: MMC
Manufacturer ID: aa
OEM: 5859
Name: QEMU!
Tran Speed: 25000000
Rd Block Len: 512
SD version 1.0
High Capacity: No
Capacity: 400 MiB
Bus Width: 1-bit
Erase Group Size: 512 Bytes
此時可以看到有一張 sd 卡,其容量是先前所定義的,以例來說為 400MB。接下來我們可以試著手動載入 linux 核心讓它開機,請執行:
=> fatload mmc 0:1 0x60000000 uImage
reading uImage
2438600 bytes read in 235 ms (9.9 MiB/s)
將 uImage 核心載入 0x60000000 位址,並使用 iminfo 來驗證:
=> iminfo 0x60000000
## Checking Image at 60000000 ...
Legacy image found
Image Name: Linux-3.18.44
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 2438536 Bytes = 2.3 MiB
Load Address: 60008000
Entry Point: 60008000
Verifying Checksum ... OK
驗證完沒問題的話可以使用 bootm 指令來開機,指令如下:
=> bootm 0x60000000
## Booting kernel from Legacy Image at 60000000 ...
Image Name: Linux-3.18.44
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 2438536 Bytes = 2.3 MiB
Load Address: 60008000
Entry Point: 60008000
Verifying Checksum ... OK
Loading Kernel Image ... OK
Starting kernel ...
之後會當掉,我們要修正這個問題。
開機故障排除
故障 1 訊息如下:
VFS: Cannot open root device "(null)" or unknown-block(0,0): error -6
Please append a correct "root=" boot option; here are the available partitions:
1f00 131072 mtdblock0 (driver?)
b300 409600 mmcblk0 driver: mmcblk
b301 25600 mmcblk0p1 58c7bb94-01
b302 382976 mmcblk0p2 58c7bb94-02
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
這是表示開機時的 bootargs 沒有設定好,以此例來說,系統找到的開機裝置為 mmcblk0,但是 bootargs 沒有設定好,我們可以在 u-boot 環境下執行底下指令來觀看 bootargs 的設定:
=> printenv bootargs
如果沒有設定或是設定錯誤的話,那麼開機就會失敗,請執行底下指令來設定 bootargs 環境變數:
=> setenv bootargs "root=/dev/mmcblk0p1 console=ttyAMA0"
此時再執行 printenv 來觀看環境變數設定可以看到正確的組態:
=> printenv bootargs
bootargs=root=/dev/mmcblk0p1 console=ttyAMA0
接著再重新執行載入核心及開機的流程:
=> fatload mmc 0:1 0x60008000 uimage
reading uimage
2438600 bytes read in 234 ms (9.9 MiB/s)
=> bootm 0x60008000
此時會出現新的錯誤訊息,如底下所示:
Kernel panic - not syncing: No working init found. Try passing init= option to kernel. See Linux Documentation/init.txt for guidance.
CPU: 0 PID: 1 Comm: swapper/0 Not tainted 3.18.44 #1
[<80014824>] (unwind_backtrace) from [<800116d0>] (show_stack+0x10/0x14)
[<800116d0>] (show_stack) from [<80477c64>] (dump_stack+0x98/0xac)
[<80477c64>] (dump_stack) from [<80475b10>] (panic+0x9c/0x200)
[<80475b10>] (panic) from [<80474040>] (cpu_die+0x0/0x80)
[<80474040>] (cpu_die) from [<00000000>] ( (null))
---[ end Kernel panic - not syncing: No working init found. Try passing init= option to kernel. See Linux Documentation/init.txt for guidance.
開機發生錯誤的解決方式:
開機時會有幾個錯誤訊息,最終會導致無法開機:
Timed out waiting for device dev-mmcblk0p1
Dependency failed for /boot.
Dependency failed for Local File Systems.
..
等錯誤
請編譯核心,在 General Setup 底下的設定打開:
[*] open by fhandle syscalls
然後再重新編譯一次核心,並且把編譯完的 uimage 複製至第一個分割區。