前情提要
上一篇提到,設定實習環境的目標有:
- 可以使用ARM 平台。一方面追求流行,一方面我不想再開x86這個副本
- 可以方便地建立ARM平台的Linux Rootfs和kernel版本
- 可以方便地更改指定要編譯的Kernel版本
- 透過Qemu ,使用2的Rootfs和kernel開機
- 透過Qemu和搭配的工具可以分析Linux kernel的run time 行為
今天就是來解決3 的項目。更細分的話,這次目標是
- 使用官方Linux kernel 編譯Vexpress 平台kernel及產生Buildroot支援的開發版device tree
- 編譯出來的kernel binary可以在Qemu上順利載入
- 編譯出來的kernel binary可以順利的載入buildroot產生的rootfs,以及網路介面和相關設備
目錄
測試環境
做組裝的最重要的原則之一就是要能夠reproduce,所以交代測試環境是一定要的
1 2 3 4 5 6 7 8 9 |
|
- buildroot 版本
- commit hash:
14b24726a81b719b35fee70c8ba8be2d682a7313
- commit hash:
下載Linux Kernel Source
沒啥好講的,就剪貼指令吧
1
|
|
設定和編譯
東西下載完不是就閉著眼睛開幹,因為我們在開始編譯前需要
- 切換到你想要研究的版本
- 如果不是x86,你需要指定平台
- 細項Kernel config設定
那麼就來見招拆招吧
切換版本
非常簡單,先git tag
,切過去就好。我要切到4.4.2就是
1 2 3 |
|
設定ARM Vexpress預設config
先講結論
1
|
|
開始沒人要看的解釋吧。基本上也亂看找出來的,簡單講一下當初的「脈絡」
- 我知道我們平台是vexpress,所以就
find | grep vexpress
。從一堆檔案中我看到有趣的檔案./arch/arm/configs/vexpress_defconfig
。 - 接下來就是要找make 的時候怎麼和這個檔案勾起來。網路上找一下會發現一個變數
ARCH
,剩下就試看看make ARCH=arm vexpress_defconfig
,能不能動,可以動所以打完收工。
然後你就知道
- Linux kernel source中有些平台會提供default config
- 透過
ARCH
可以讓make時自動參考這些檔案產生config
更改Kernel Config讓Qemu使用
建議不要把buildroot compile cache打開。我花了很多時間在kernel 編譯後Qemu還是沒有使用編譯後的kernel的問題,最後發現關閉buildroot compile cache問題就消失了。
如果閉著眼睛開始編譯,你會很高興地發現可以開機了,但是接下來就會很失望的發現出現mount完rootfs找不到/dev/ttyAMA0
,以至於沒辦法進入login畫面。這是因為雖然serial driver偵測到設備,但是/dev下面沒有相對的device node。解法就是確認下面kernel option有開啟。想要知道真正的原因手冊這邊有提到,請參考Dynamic using devtmpfs only
段落。
- Device Drivers -> Generic Driver Options ->
- Maintain a devtmpfs filesystem to mount at /dev
- Automount devtmpfs at /dev, after the kernel mounted the rootfs
建議順便巡一下其他kernel選項,用不到的可以關一下。比如說一堆有的沒的網卡,音效支援之類的。
編譯
Buildroot
make menuconfig
- Toolchain -> Custom kernel headers series
- 改成你現在Linux 版本
- Toolchain -> Custom kernel headers series
make
Linux kernel
指令如下
1
|
|
這其實就是make bzImage
的囉唆版,多了
ARCH=arm
- 指定ARM平台
CROSS_COMPILE=..
- Cross compile prefix,既然我們使用buildroot內建toolchain,就用他們來編譯kernel
V=1
- 身為組裝工,沒看到編譯指令訊息跳出來就會沒安全感
產生Device tree binary
由於Kernel的演進,可以存放平台硬體相關設定讓kernel啟動時存取。此方式稱為device tree,詳細資訊可以參考這份簡介(pdf投影片)。
以論述文來說,儘量先說結論再解釋。因此懶人包如下,假設在kernel top 目錄中:
1 2 |
|
沒人要看的說明如下,懶得看推論的就剪貼上面就好
對於組裝工來說,我關心的是
- Kernel 軟體包中是否有存在已經有的device tree?
- 有的話,我要選那一個?
- 怎麼產生出最後成果?
- Qemu怎麼使用device tree?
要回上面的問題,最簡單的方式就是回顧buildroot中啟動qemu Vepress的命令參數,你就會發現有個東西似乎和我們關心的device tree有關聯
-dtb output/images/vexpress-v2p-ca9.dtb
這邊顯示了幾個資訊
- 有一個檔案叫dtb
- 檔名的v2p-ca9有可能和平台有關係
那麼我們在Kernel中找一下檔名中有vexpress-v2p-ca9的檔案
1 2 |
|
這邊一樣透露了這是一個和dtb
很類似的檔案,那麼我們進一步做一些確認
1 2 3 4 5 6 7 8 9 |
|
剩下就是估狗大法,發現需要編譯器才能把dts轉換成dtb檔案。 所以就用上面的方式產稱dtb檔囉。
測試
剩下就剪貼了
我在buildroot top目錄執行的,你要嘛就切到buildroot目錄下,要嘛就指定-drive file
到你自己rootfs的路徑
1
|
|
提出來兩個參數表示這是我編譯出來的kernel而不是buildroot的
-kernel /tmp/kernel/linux-stable/arch/arm/boot/zImage
-dtb /tmp/kernel/linux-stable/vexpress-v2p-ca9.dtb
開機畫面節錄如下
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 |
|
參考資料
附錄
使用Buildroot 內建套件指定編譯Linux kernel 4.2.2
當初會去做這個主要是因為開始編譯獨立的Linux kernel前要先驗證buildroot自己編的Linux 4.4.2是否可以用qemu開機。另外的好處的就是buildroot編譯出來的kernel config (在output/build/linux-4.4.2/.config) 可以和你自己的kernel config比對。這邊只要在buildroot中make menuconfig中和kernel有關設定指定4.4.2即可,比Versatile簡單太多了故省略,如果有人遇到問題我再補上這邊說明。