目录
- 前言
- 前置知识
- ARM Versatile Express开发板简介
- ARM处理器家族简介
- 安装qemu-system-arm
- 安装交叉编译工具
- 交叉编译ARM32 Linux内核
- 交叉编译ARM32 Busybox
- 使用busybox制作initramfs
- 使用QEMU启动ARM32 Linux内核
- 模拟vexpress-a9开发板
- 模拟vexpress-a15开发板
- 参考
前言
本文介绍采用 qemu 模拟ARM-32bit开发板(针对ARM-64bit有另外一篇文章介绍),并启动ARM32 Linux内核。大致思路是:
- 安装qemu-system-arm(ARM-32bit)模拟器;
- 安装arm-linux-gnueabi(ARM-32bit)交叉编译器;
- 交叉编译linux源码,得到ARM32 Linux内核镜像;
- 交叉编译busybox源码,使用busybox制作initramfs;
- 最后使用qemu-system-arm启用ARM32 Linux内核;
我的环境:
- 宿主机硬件平台:x86_64
- 宿主机操作系统:Ubuntu 20.04 (Linux 5.4.0-139-generic)
- QEMU版本:qemu-4.2.1
- 实验内核:linux-5.19
- busybox版本:busybox-1.35.0
前置知识
ARM Versatile Express开发板简介
本文将模拟ARM公司的vexpress开发板为例进行说明,vexpress系列(全称Versatile Express Family)是ARM自己推出的开发板,用于方便SOC厂商设计、验证和测试自己的芯片设计。在中国地区,各厂商可以通过米尔科技获得ARM授权的正版ARM Versatile Express开发板,硬件由“Express uATX主板(V2M)”和“CoreTile Express子板(V2P)子板”组成,Express uATX主板提供电源、外设,CoreTile Express子板提供CPU。
有关“Express uATX主板(V2M)”的详细资料:
- 米尔科技:ARM Versatile Express主板
- 官方文档:ARM Motherboard Express µATX Technical Reference Manual V2M-P1
有关“CoreTile Express子板(V2P)子板”的详细资料:
- 米尔科技:ARM Versatile Express处理器子板
- 官方文档:ARM CoreTile Express A9×4 Technical Reference Manual Cortex-A9 MPCore (V2P-CA9)
qemu官网也有对该开发板的详细介绍: Arm Versatile Express boards (vexpress-a9, vexpress-a15
CoreTile Express处理器子板支持的 ARM 处理器有:
- Cortex-A15 MPCore
- Cortex-A9 MPCore
- Cortex-A5 MPCore
ARM处理器家族简介
ARM处理器家族众多,哪些是32bit,哪些是64bit,可参考:
List_of_ARM_processors
很多厂家使用ARM核设计SOC芯片,这里罗列了很多,可参考:
List_of_products_using_ARM_processors
安装qemu-system-arm
安装:
$ sudo apt install qemu-system-arm
查看版本号:
$ qemu-system-arm --version
QEMU emulator version 4.2.1 (Debian 1:4.2-3ubuntu6.24)
Copyright (c) 2003-2019 Fabrice Bellard and the QEMU Project developers
qemu内置了很多ARM开发板,qemu官方文档中的 Arm System emulator 详细描述了每个支持的开发板规格文档(Board-specific documentation)。可以使用以下命令查看 qemu 支持的 ARM 开发板,本文将选择vexpress-a9和vexpress-a15开发板进行模拟:
$ qemu-system-arm -M 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)
canon-a1100 Canon PowerShot A1100 IS
cheetah Palm Tungsten|E aka. Cheetah PDA (OMAP310)
collie Sharp SL-5500 (Collie) PDA (SA-1110)
connex Gumstix Connex (PXA255)
cubieboard cubietech cubieboard (Cortex-A8)
emcraft-sf2 SmartFusion2 SOM kit from Emcraft (M2S010)
highbank Calxeda Highbank (ECX-1000)
imx25-pdk ARM i.MX25 PDK board (ARM926)
integratorcp ARM Integrator/CP (ARM926EJ-S)
kzm ARM KZM Emulation Baseboard (ARM1136)
lm3s6965evb Stellaris LM3S6965EVB
lm3s811evb Stellaris LM3S811EVB
mainstone Mainstone II (PXA27x)
mcimx6ul-evk Freescale i.MX6UL Evaluation Kit (Cortex A7)
mcimx7d-sabre Freescale i.MX7 DUAL SABRE (Cortex A7)
microbit BBC micro:bit
midway Calxeda Midway (ECX-2000)
mps2-an385 ARM MPS2 with AN385 FPGA image for Cortex-M3
mps2-an505 ARM MPS2 with AN505 FPGA image for Cortex-M33
mps2-an511 ARM MPS2 with AN511 DesignStart FPGA image for Cortex-M3
mps2-an521 ARM MPS2 with AN521 FPGA image for dual Cortex-M33
musca-a ARM Musca-A board (dual Cortex-M33)
musca-b1 ARM Musca-B1 board (dual Cortex-M33)
musicpal Marvell 88w8618 / MusicPal (ARM926EJ-S)
n800 Nokia N800 tablet aka. RX-34 (OMAP2420)
n810 Nokia N810 tablet aka. RX-44 (OMAP2420)
netduino2 Netduino 2 Machine
none empty machine
nuri Samsung NURI board (Exynos4210)
palmetto-bmc OpenPOWER Palmetto BMC (ARM926EJ-S)
raspi2 Raspberry Pi 2
realview-eb ARM RealView Emulation Baseboard (ARM926EJ-S)
realview-eb-mpcore ARM RealView Emulation Baseboard (ARM11MPCore)
realview-pb-a8 ARM RealView Platform Baseboard for Cortex-A8
realview-pbx-a9 ARM RealView Platform Baseboard Explore for Cortex-A9
romulus-bmc OpenPOWER Romulus BMC (ARM1176)
sabrelite Freescale i.MX6 Quad SABRE Lite Board (Cortex A9)
smdkc210 Samsung SMDKC210 board (Exynos4210)
spitz Sharp SL-C3000 (Spitz) PDA (PXA270)
swift-bmc OpenPOWER Swift BMC (ARM1176)
sx1 Siemens SX1 (OMAP310) V2
sx1-v1 Siemens SX1 (OMAP310) V1
terrier Sharp SL-C3200 (Terrier) 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
virt-2.10 QEMU 2.10 ARM Virtual Machine
virt-2.11 QEMU 2.11 ARM Virtual Machine
virt-2.12 QEMU 2.12 ARM Virtual Machine
virt-2.6 QEMU 2.6 ARM Virtual Machine
virt-2.7 QEMU 2.7 ARM Virtual Machine
virt-2.8 QEMU 2.8 ARM Virtual Machine
virt-2.9 QEMU 2.9 ARM Virtual Machine
virt-3.0 QEMU 3.0 ARM Virtual Machine
virt-3.1 QEMU 3.1 ARM Virtual Machine
virt-4.0 QEMU 4.0 ARM Virtual Machine
virt-4.1 QEMU 4.1 ARM Virtual Machine
virt QEMU 4.2 ARM Virtual Machine (alias of virt-4.2)
virt-4.2 QEMU 4.2 ARM Virtual Machine
witherspoon-bmc OpenPOWER Witherspoon BMC (ARM1176)
xilinx-zynq-a9 Xilinx Zynq Platform Baseboard for Cortex-A9
z2 Zipit Z2 (PXA27x)
一个开发板往往支持不同cpu,查看某个开发板(以vexpress-a9为例)支持的cpu列表:
$ qemu-system-arm -M vexpress-a9 --cpu help
Available CPUs:
arm1026
arm1136
arm1136-r2
arm1176
arm11mpcore
arm926
arm946
cortex-a15
cortex-a7
cortex-a8
cortex-a9
cortex-m0
cortex-m3
cortex-m33
cortex-m4
cortex-r5
cortex-r5f
max
pxa250
pxa255
pxa260
pxa261
pxa262
pxa270-a0
pxa270-a1
pxa270
pxa270-b0
pxa270-b1
pxa270-c0
pxa270-c5
sa1100
sa1110
ti925t
安装交叉编译工具
我们是在x86平台下进行的开发,目标平台是arm架构,需要安装交叉编译工具链。有关arm-linux的交叉编译器主要有:
- 针对ARM-32bit的arm-linux-gnueabi和arm-linux-gnueabihf。
- 针对ARM-64bit的aarch64-linux-gnu。
交叉编译器各版本的区别可参考《arm系列交叉编译器各版本区别》。
这里只安装ARM-32bit的arm-linux-gnueabi版本:
$ sudo apt install gcc-arm-linux-gnueabi
查看版本:
$ arm-linux-gnueabi-gcc --version
arm-linux-gnueabi-gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
交叉编译ARM32 Linux内核
$ mkdir ~/kvm-arm
$ cd ~/kvm-arm/
$ wget https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/snapshot/linux-5.19.tar.gz
$ tar -xf linux-5.19.tar.gz
$ cd linux-5.19/
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- O=build vexpress_defconfig
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- O=build -j8
说明:
- ARCH:指定目标CPU架构;
- CROSS_COMPILE:指定交叉编译器;
- O=build:O是Out的缩写,表示编译输出文件放在build目录,不跟源码混在一起,保持源码的整洁性。
- 要模拟vexpress开发板,所以选择vexpress_defconfig配置文件(对应原厂默认内核配置文件arch/arm/configs/vexpress_defconfig),make 的过程会根据原厂默认配置文件生成可直接用于编译的内核配置文件.config。
看到以下日志就表示编译成功:
Kernel: arch/arm/boot/zImage is ready
查看下内核编译出来的原始内核文件vmlinux,是ARM 32-bit版本。
$ file build/vmlinux
build/vmlinux: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, BuildID[sha1]=7c27ffc92ea9a8e90b84cd79b13b974857ca0b76, not stripped
vmlinux不能直接引导Linux系统启动,能引导Linux系统启动的是bzImage文件,由vmlinux经objcopy处理后的二进制内核映像,下文用到的内核镜像就是bzImage:
$ file build/arch/arm/boot/zImage
build/arch/arm/boot/zImage: ARM OpenFirmware FORTH Dictionary, Text length: -509607936 bytes, Data length: -509607936 bytes, Text Relocation Table length: -369098747 bytes, Data Relocation Table length: 24061976 bytes, Entry Point: 0x00000000, BSS length: 5141592 bytes
同时也会生成多个vexpress 开发板的设备树文件,分别对应前文ARM Versatile Express提到的三种开发板:
$ ls -ls build/arch/arm/boot/dts/vexpress*.dtb
20 -rw-rw-r-- 1 kaoya kaoya 18587 3月 1 22:38 build/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dtb
16 -rw-rw-r-- 1 kaoya kaoya 13024 3月 1 22:38 build/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dtb
16 -rw-rw-r-- 1 kaoya kaoya 12602 3月 1 22:38 build/arch/arm/boot/dts/vexpress-v2p-ca5s.dtb
16 -rw-rw-r-- 1 kaoya kaoya 14081 3月 1 22:38 build/arch/arm/boot/dts/vexpress-v2p-ca9.dtb
交叉编译ARM32 Busybox
$ mkdir ~/kvm-arm
$ cd ~/kvm-arm/
$ wget https://busybox.net/downloads/busybox-1.35.0.tar.bz2
$ tar -xf busybox-1.35.0.tar.bz2
$ cd busybox-1.35.0/
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- menuconfig
# 修改配置,选中如下项目,静态编译
# Settings –> Build Options –> [*] Build static binary(no share libs)
# 反选如下项目,否则后续qemu执行会提示 /bin/sh:can't access tty;job control turned off
# Shells ---> [ ] Job control
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- -j 8
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- install
装完后会 默认安装到源码目录的 _install/ 目录下:
$ ls _install/
bin linuxrc sbin usr
最关键的就是_install/bin/busybox,其他都是链接文件。
$ file _install/bin/busybox
_install/bin/busybox: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, BuildID[sha1]=c0f615b2d6018047e05dc0e11b1ac9707ffb5a75, for GNU/Linux 3.2.0, stripped
编译的过程中如果出现如下提示,可忽略:
Trying libraries: m resolv rt
Library m is needed, can't exclude it (yet)
Library resolv is needed, can't exclude it (yet)
Library rt is not needed, excluding it
Library m is needed, can't exclude it (yet)
Library resolv is needed, can't exclude it (yet)
Final link with: m resolv
使用busybox制作initramfs
使用busybox快速制作initramfs。
创建虚拟rootfs中的inti启动脚本,并赋予可执行权限:
$ cd ~/kvm-arm/busybox-1.35.0/_install/
$ touch init
$ chmod +x init
脚本内容:
#!/bin/sh
# 挂载一些必要的文件系统
mkdir /proc && mount -t proc none /proc
mkdir /sys && mount -t sysfs none /sys
mkdir /tmp && mount -t tmpfs none /tmp
echo
echo "Hello 32-bit ARM Linux"
# 显示开机消耗时间
echo "This boot took $(cut -d' ' -f1 /proc/uptime) seconds"
echo
# 停留在控制台
exec /bin/sh
制作initramfs文件,它是多个文件通过cpio打包和gzip压缩的文件,是一个cpio格式的内存文件系统。
$ find . -print0 | cpio --null -ov --format=newc | gzip -9 > ../initramfs.cpio.gz
使用QEMU启动ARM32 Linux内核
ARM Linux内核镜像和initramfs都准备好,就可以使用QEMU启动linux内核了。
模拟vexpress-a9开发板
vexpress-a9开发板,其处理器是32-bit的Cortex-A9,4核。
以字符界面方式启动QEMU(不启动图形界面),同时日志输出到控制台:
$ qemu-system-arm \
-M vexpress-a9 \
-cpu cortex-a9 \
-smp 4 \
-m 1G \
-nographic \
-kernel ./linux-5.19/build/arch/arm/boot/zImage \
-dtb ./linux-5.19/build/arch/arm/boot/dts/vexpress-v2p-ca9.dtb \
-initrd ./busybox-1.35.0/initramfs.cpio.gz \
-append "init=/init console=ttyAMA0"
QEMU参数说明(更多可参考:Standard options):
- -M:指定模拟的开发板,可通过qemu-system-arm -M help查看。
- -cpu:指定模拟的cpu,可通过qemu-system-arm -M vexpress-a9 --cpu help查看。
- -smp:指定cpu核数量,启动后可以使用nproc命令核对, vexpress-a9最多只支持4核,可少不可多,超过启动会报错。
- -m:指定内存大小,vexpress-a9最大支持1GB,可少不可多 ,超过启动会报错,启动后可以使用free -h命令核对。
- -kernel:指定启动的内核镜像;
- -initrd:指定启动的内存文件系统;
- -append:传递给内核的启动参数;启动后可使用cat /proc/cmdline命令核对。
- -nographic:启动字符界面(不启动图形界面),输出重定向到宿主机命令行,与参数 console=ttyAMA0 组合使用;
图形界面操作使用工具栏菜单即可,字符界面操作使用快捷键如下所示(更多可参考:Keys in the character backend multiplexer):
C-a h print this help
C-a x exit emulator
C-a s save disk data back to file (if -snapshot)
C-a t toggle console timestamps
C-a b send break (magic sysrq)
C-a c switch between console and monitor
C-a C-a sends C-a
启动后核对下各种参数:
# cat /proc/cpuinfo
processor : 0
model name : ARMv7 Processor rev 0 (v7l)
BogoMIPS : 915.86
Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpd32
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x0
CPU part : 0xc09
CPU revision : 0
processor : 1
model name : ARMv7 Processor rev 0 (v7l)
BogoMIPS : 513.63
Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpd32
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x0
CPU part : 0xc09
CPU revision : 0
processor : 2
model name : ARMv7 Processor rev 0 (v7l)
BogoMIPS : 915.86
Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpd32
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x0
CPU part : 0xc09
CPU revision : 0
processor : 3
model name : ARMv7 Processor rev 0 (v7l)
BogoMIPS : 921.60
Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpd32
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x0
CPU part : 0xc09
CPU revision : 0
Hardware : ARM-Versatile Express
Revision : 0000
Serial : 0000000000000000
/ #
/ # free -h
total used free shared buff/cache available
Mem: 1002.9M 11.2M 986.7M 2.0M 5.0M 982.2M
Swap: 0 0 0
/ #
/ # nproc
4
启动如何有报错:
pulseaudio: set_sink_input_volume() failed
pulseaudio: Reason: Invalid argument
pulseaudio: set_sink_input_mute() failed
pulseaudio: Reason: Invalid argument
这是有关pulseaudio音频服务的错,可以忽略它。使用高版本的qemu(如qemu-7.2.0)就不会报这个错。
模拟vexpress-a15开发板
以字符界面方式启动QEMU(不启动图形界面),同时日志输出到控制台:
$ qemu-system-arm \
-M vexpress-a15 \
-cpu cortex-a15 \
-smp 2 \
-m 2G \
-nographic \
-kernel ./linux-5.19/build/arch/arm/boot/zImage \
-dtb ./linux-5.19/build/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dtb \
-initrd ./busybox-1.35.0/initramfs.cpio.gz \
-append "init=/init console=ttyAMA0"
说明:
- vexpress-a15 的CPU数最多支持2核,-smp配置超过启动不会报错,但启动后只能看到2核。
- vexpress-a15 的内存最大支持2G,-m配置超过启动不会报错,但启动后只能看到2G内存。
以图形界面的方式启动QEMU:
# 日志输出和shell在窗口上
qemu-system-arm \
-M vexpress-a15 \
-cpu cortex-a15 \
-smp 2 \
-m 2G \
-kernel ./linux-5.19/build/arch/arm/boot/zImage \
-dtb ./linux-5.19/build/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dtb \
-initrd ./busybox-1.35.0/initramfs.cpio.gz \
-append "init=/init"
# 日志输出和shell在本地控制台
qemu-system-arm \
-M vexpress-a15 \
-cpu cortex-a15 \
-smp 2 \
-m 2G \
-serial mon:stdio \
-kernel ./linux-5.19/build/arch/arm/boot/zImage \
-dtb ./linux-5.19/build/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dtb \
-initrd ./busybox-1.35.0/initramfs.cpio.gz \
-append "init=/init console=ttyAMA0"
参考
- Arm System emulator
- Arm Versatile Express boards (vexpress-a9, vexpress-a15)
- List_of_products_using_ARM_processors
- List_of_ARM_processors
- Qemu使用及常见开发板的模拟
- qemu-system-aarch64使用和相关参数介绍