感謝Scott 大大糾正,選錯平台,這篇使用了ARMv4指令集的測試平台。請大家忽略,正確的版本將會之後更新!
前情提要
上一篇提到,設定實習環境的目標有:
- 可以使用ARM 平台。一方面追求流行,一方面我不想再開x86這個副本
- 可以方便地建立ARM平台的Linux Rootfs和kernel版本
- 可以方便地更改指定要編譯的Kernel版本
- 透過Qemu ,使用2的Rootfs和kernel開機
- 透過Qemu和搭配的工具可以分析Linux kernel的run time 行為
今天就是來解決3 的項目。更細分的話,這次目標是
- 使用官方Linux kernel 編譯Versatile
- 編譯出來的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 Versatile預設config
先講結論
1
|
|
開始沒人要看的解釋吧。基本上也亂看找出來的,簡單講一下當初的「脈絡」
- 我知道我們平台是versatile,所以就
find | grep versatile
。從一堆檔案中我看到有趣的檔案./arch/arm/configs/versatile_defconfig
。 - 接下來就是要找make 的時候怎麼和這個檔案勾起來。網路上找一下會發現一個變數
ARCH
,剩下就試看看make ARCH=arm versatile_defconfig
,能不能動,可以動所以打完收工。
然後你就知道
- Linux kernel source中有些平台會提供default config
- 透過
ARCH
可以讓make時自動參考這些檔案產生config
設定Qemu VM支援的硬體
建議不要把buildroot compile cache打開。我花了很多時間在kernel 編譯後Qemu還是沒有使用編譯後的kernel的問題,最後發現關閉buildroot compile cache問題就消失了。
如果閉著眼睛開始編譯,你會很高興地發現可以開機了,但是接下來就會很失望的發現kernel panic,原因是認不出開機的disk。
之所以會發生這樣的原因是因為Linux kernel 提供的default config選項和buildroot 給Qemu的kernel 選項不同(參考),比對buildroot 開機畫面,會發現他們有偵測到兩個硬體,分別是
- SCSI 控制器,用來辨認rootfs
- Realtek 8139 網路卡,不用我解釋吧
那麼我們這邊直接把這兩個加上去就收工沒錯吧?答案是對也不對,因為這兩個東西會和其他的部份有關。
以下是我用笨方式一個一個試出來需要開啟的東西,不一定最簡潔甚至正確,但是他可以開機就是了。要注意不要編成module,編譯的細節我假設讀者都知道,如果完全不懂可能要找一下新手入門資訊了。另外我列出的選項是Kernel 4.4.2
下的選項,請自行斟酌。
記得請用make ARCH=arm menuconfig
更改設定
- PCI bus,原因是SCSI控制器和網路卡是PCI bus介面,不開就沒有不會看到這些選項。
- SCSI 包括
- SSCI device
- Disk
- 我有開Generic,懶得關掉看會不會出問題了
- SCSI low-level drivers -> SYM53C8XX Version 2 SCSI support
- Network device support
- Ethernet driver suppor -> Realtek devices
- RealTek RTL-8139 C+ PCI Fast Ethernet Adapter support
- Ethernet driver suppor -> Realtek devices
- 要支援buildroot預設的device node管理方式。有興趣的可以看這邊
- Device Drivers -> Generic Driver Options ->
- Maintain a devtmpfs filesystem to mount at /dev
- Automount devtmpfs at /dev, after the kernel mounted the rootfs
- Device Drivers -> Generic Driver Options ->
- File system 要支援ext2,原因是buildroot產生的是ext2檔案格式
- tmpfs要開啟
- File systems -> Pseudo filesystems
- Tmpfs virtual memory file system support (former shm fs)
- File systems -> Pseudo filesystems
建議順便巡一下其他kernel選項,用不到的可以關一下。比如說MTD
,一堆有的沒的網卡,音效支援之類的。
編譯
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
- 身為組裝工,沒看到編譯指令訊息跳出來就會沒安全感
測試
這邊卡關的原因是預設的buildroot (Linux kernel 4.7)使用qemu載入的時候需要指定device tree檔案。但是在Linux 4.4.2下面指定device tree檔案反而無法順利開機。我怎麼知道到的?撈git commit log去看的。
剩下就剪貼了
我在buildroot top目錄執行的,你要嘛就切到buildroot目錄下,要嘛就指定-drive file
到你自己rootfs的路徑
1
|
|
單純提出來一個參數表示這是我編譯出來的kernel而不是buildroot的
-kernel /tmp/kernel/linux-stable/arch/arm/boot/zImage
開機節錄畫面如下
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 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
|
參考資料
附錄
使用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 4.4.x的kernel config
前篇有提到make qemu_arm_versatile_defconfig
這個指令和buildroot/board/qemu/arm-versatile
這個目錄。我們進一步去看一下這個目錄
1 2 3 4 |
|
直接破梗
- readme.txt 告訴你怎麼用qemu 開機
- linux-4.7.config 是Linux kernel config
所以我會去git log .
,撈看看有沒有Linux kernel 4.4.x的資料。果然給我看到一個commit
1 2 3 4 5 6 7 |
|
剩下就是使用git切到該commit,撈出資料,另存新檔。我把他存在
/tmp/linux-4.4.config
更改buildroot config指定使用Linux 4.4.2
- make menuconfig
- Kernel -> Kernel version -> Custom version
- Kernel -> Kernel version: 填 4.4.2
- Kernel -> Kernel configuration -> Using a custom (def)config file
- Kernel -> Configuration file path: 填
/tmp/linux-4.4.config
- make
測試驗證
根據buildroot/board/qemu/arm-versatile中4.4.2版時的readme.txt,qemu指令執行如下,基本上就是不去載入device tree檔案。
1
|
|
以下是開機畫面
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 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
|