QEMU 是一套由法布里斯·貝拉(Fabrice Bellard)所編寫的以 GPL 許可證分發源碼的模擬處理器,在GNU/Linux 平臺上使用廣泛。簡單來說,QEMU 是一個虛擬機,與常見的 Vmware/VirtualBox 不同的是,QEMU 可以模擬不同平臺的硬件,使得我們在 x86 設備上可以運行其他架構的程序。
本文主要講述如何編譯符合 qemu 要求的內核,使用 qemu 成功運行內核。我們需要在 Linux 環境下安裝交叉編譯工具鏈,用於在 x86 平臺上編譯 arm 架構的內核;也要解決其中的依賴問題;如果有需要,還要升級系統自帶的 qemu(系統自帶版本較高,可以不用重新安裝)。如果能夠成功的運行內核,後續還可以在 qemu 模擬的環境中,掛在相應的根文件系統,這樣就可以完整的運行一個 arm 架構的 linux 系統。
0x10 前期準備
0x11 編譯內核需要的依賴及工具
下載配置內核需要的依賴
sudo apt-get install ncurses-devel libncurses-devel flex bison bc
安裝交叉工具編譯鏈
sudo apt-get install gcc-arm-linux-gnueabi
# 此工具用來編譯生成 arm32 可執行程序
0x12 安裝 QEMU
Ubuntu 以及 Kali 自帶了 qemu,如果你想升級 qemu 的版本,可以源碼安裝。
安裝依賴
sudo apt-get install zlib1g-dev libglib2.0-0 libglib2.0-dev libtool libsdl1.2-dev autoconf
解壓
tar -xvf qemu-4.2.0.tar.xz
爲了防止編譯後文件比較亂,選擇創建 build 目錄作爲編譯中間目標路徑
cd qemu-4.2.0/
mkdir build
cd build/
配置、編譯並安裝 qemu
../configure --target-list=arm-softmmu --audio-drv-list=
make
make install
0x20 編譯內核
下載內核,這裏推薦一個下載內核源碼的鏡像站點:https://mirrors.edge.kernel.org/pub/linux/kernel/
0x21 方案一:編譯生成與平臺無關的內核
進入源碼根目錄,配置和編譯
#(1)清除原有的配置與中間文件
make distclean
#(2)配置內核,並生成配置文件
make menuconfig ARCH=arm
#(3)編譯內核
make uImage ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- all
編譯內核的時候,既可以選擇 uImage,也可以不填此選項,這樣編譯的時候,會提示用戶,選擇使用哪種內核壓縮模式。筆者在這裏選擇的是 zImage,最後生成的文件如下
~/Documents/linux-5.6.6$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- all
scripts/kconfig/conf --syncconfig Kconfig
CALL scripts/checksyscalls.sh
CALL scripts/atomic/check-atomics.sh
CHK include/generated/compile.h
Kernel: arch/arm/boot/Image is ready
Kernel: arch/arm/boot/zImage is ready
MODPOST 17 modules
也就是說,arch/arm/boot/zImage
就是我們編譯好的內核。
0x22 方案二:編譯生成特定硬件下(qemu)運行的內核
使用 arch/arm/configs/versatile_defconfig
文件的配置,versatile_defconfig 的內容將被 copy 到 .config 中,這樣生成的內核文件可以直接使用 qemu 進行仿真。
#(1)清除原有的配置與中間文件
make distclean
#(2)配置內核,並生成配置文件
make ARCH=arm versatile_defconfig # vexpress_defconfig
make menuconfig ARCH=arm # 可運行可不運行
#(3)編譯內核
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- all
versatile_defconfig
是指 ARM Versatile Express 開發板的配置,我們也可以用其他硬件仿真。qemu -m
命令可查看當前 qemu 支持仿真的硬件平臺,即開發板
lys@kali:~/Documents$ qemu-system-arm -machine help
Supported machines are:
akita Sharp SL-C1000 (Akita) PDA (PXA270)
ast2500-evb Aspeed AST2500 EVB (ARM1176)
ast2600-evb Aspeed AST2600 EVB (Cortex A7)
borzoi Sharp SL-C3100 (Borzoi) PDA (PXA270)
...
tosa Sharp SL-6000 (Tosa) PDA (PXA255)
verdex Gumstix Verdex (PXA270)
versatileab ARM Versatile/AB (ARM926EJ-S)
versatilepb ARM Versatile/PB (ARM926EJ-S)
vexpress-a15 ARM Versatile Express for Cortex-A15
vexpress-a9 ARM Versatile Express for Cortex-A9
...
0x23 方案三:手動配置內核源碼並編譯
make vexpress_defconfig ARCH=arm O=./object
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- menuconfig -j4 O=./object
生成以下兩個我們需要的文件
arch/arm/boot/zImage
arch/arm/boot/dts/vexpress-v2p-ca9.dtb
0x30 QEMU 加載內核
使用方案二生成的內核壓縮文件
sudo qemu-system-arm -M versatilepb -m 256M -kernel linux-5.6.6/arch/arm/boot/zImage -nographic -dtb linux-5.6.6/arch/arm/boot/dts/versatile-pb.dtb -append "console=ttyAMA0"
用方案三生成的內核壓縮文件以及配置文件
qemu-system-arm -M vexpress-a9 -m 512M -kernellinux-5.6.6/arch/arm/boot/zImage -dtb linux-5.6.6/arch/arm/boot/dts/versatile-pb.dtb -nographic -append "console=ttyAMA0"
參數說明
- -M 指定開發板
- -m 指定內存大小
- -kernel 指定內核文件
- -dtb 指定dtb文件
- -nographic 指定不需要圖形界面
- -append 指定擴展顯示界面,串口或者LCD
內核成功啓動,如下圖,不過我們還沒有指定根文件系統,所以報錯
後續就是加上 -initrd 參數選項指定固件中的根文件系統,就可以仿真固件。如果你覺得命令過於複雜,寫出腳本就可以了
# boot.sh
#! /bin/sh
qemu-system-arm \
-M vexpress-a9 \
-m 512M \
-kernel ~/qemu/zImage \
-dtb ~/qemu/vexpress-v2p-ca9.dtb \
-nographic \
-append "root=/dev/mmcblk0 rw console=ttyAMA0" \
-sd rootfs.ext3
0x40 Q&A 可能遇到的問題
fatal error: openssl/opensslv.h: No such file or directory
這是由於沒有下載 openssl 庫,下載安裝即可
sudo apt-get install libssl-dev
/bin/sh: 1: bc: not found
這是由於缺少計算器程序 bc 造成的,下載安裝
sudo apt-get install bc
No rule to make target ‘debian/certs/debian-uefi-certs.pem’
打開 .config 文件,註釋下面這一句話
CONFIG_SYSTEM_TRUSTED_KEYS="debian/certs/[email protected]"
0x50 總結
使用 qemu 模擬硬件設備,運行內核,並不是我們的最終目的,後續要做的是提取根文件系統,並將其掛在,這樣就可以實現一個完整的設備模擬。