300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > 为 QEMU ARM 仿真器编译 Linux 内核:QEMU 模拟 ARM 环境

为 QEMU ARM 仿真器编译 Linux 内核:QEMU 模拟 ARM 环境

时间:2021-05-22 17:36:41

相关推荐

为 QEMU ARM 仿真器编译 Linux 内核:QEMU 模拟 ARM 环境

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 autoconfsudo apt install libsdl2-dev -y # 不安装可能会出现 VNC Server running ":1:5900"

解压

tar -xvf qemu-4.2.0.tar.xz

为了防止编译后文件比较乱,选择创建 build 目录作为编译中间目标路径

cd qemu-4.2.0/mkdir build

配置、编译并安装 qemu

./configure --prefix=./build --target-list=arm-softmmu,arm-linux-user --enable-debugmake -j$(nproc)make install

–target-list 指定要编译的target(guest),arm-softmmu 表示要编译 system mode 的 arm qemu;arm-linux-user 表示要编译 user mode 的 arm qemu。

如果要重新编译,请删除原先的编译中间文件

sudo make cleansudo make distclean

查看 qemu 支持的开发板

qemu-system-arm -M help

0x20 编译内核

下载内核,这里推荐几个下载内核源码的镜像站点:

https://mirrors./pub/linux/kernel/

http://ftp./sites//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- allscripts/kconfig/conf --syncconfig KconfigCALL scripts/checksyscalls.shCALL scripts/atomic/check-atomics.shCHKinclude/generated/compile.hKernel: arch/arm/boot/Image is readyKernel: arch/arm/boot/zImage is readyMODPOST 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_defconfigmake 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 helpSupported machines are:akitaSharp SL-C1000 (Akita) PDA (PXA270)ast2500-evbAspeed AST2500 EVB (ARM1176)ast2600-evbAspeed AST2600 EVB (Cortex A7)borzoiSharp SL-C3100 (Borzoi) PDA (PXA270)...tosa Sharp SL-6000 (Tosa) PDA (PXA255)verdexGumstix Verdex (PXA270)versatileabARM Versatile/AB (ARM926EJ-S)versatilepbARM Versatile/PB (ARM926EJ-S)vexpress-a15 ARM Versatile Express for Cortex-A15vexpress-a9ARM Versatile Express for Cortex-A9...

0x23 方案三:手动配置内核源码并编译

make vexpress_defconfig ARCH=arm O=./objectmake ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- menuconfig -j4 O=./object

生成以下两个我们需要的文件

arch/arm/boot/zImagearch/arm/boot/dts/vexpress-v2p-ca9.dtb

0x30 QEMU 加载内核

使用方案二生成的内核压缩文件

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 -kernel linux-5.6.6/arch/arm/boot/zImage -dtb linux-5.6.6/arch/arm/boot/dts/vexpress-v2p-ca9.dtb -append "console=ttyAMA0" -serial stdio

参数说明

-M 指定开发板-m 指定内存大小-kernel 指定内核文件-dtb 指定dtb文件-nographic 指定不需要图形界面-append 指定扩展显示界面,串口或者LCD,“console=ttyAMA0” 内核启动参数,这里告诉内核vexpress单板运行,串口设备是哪个tty

0x31 不开启图形终端

为了在图形窗口中显示,我们需要传递console=tty1内核参数。这个内核参数将会被 qemu 通过-append选项传递给 Linux。如果不指定-nographic,上述命令会打开 qemu 并打开一个黑色的控制台窗口,通过一个 Tuxlogo 来显示图形能力。启动信息将会在这个图形窗口显示。

内核成功启动,如下图,不过我们还没有指定根文件系统,所以报错

0x32 重定向模拟系统的串口

-nographic是为了让系统直接输出,不要可视化界面,但是这样的话,要关闭 qemu 模拟的系统,只能通过kill方式。qemu 可以重定向主机上的模拟系统的串口,使用选项-serial stdio,则 Linux 可以通过传递console=ttyAMA0作为内核参数而在第一个串口中显示它的信息。

qemu-system-arm -M versatilepb -m 256M -kernel linux-5.6.6/arch/arm/boot/zImage \-dtb linux-5.6.6/arch/arm/boot/dts/versatile-pb.dtb \-append "console=ttyAMA0" \-serial stdio \

0x33 开启远程登录

-nographic还可以用-serial telnet::,server,nodelay替代,这样可以另开一个终端,通过输入telnet 127.0.0.1 的方式连接到 qemu 虚拟机,此方法会有三个终端存在

emu-system-arm -M versatilepb -m 256M -kernel linux-5.6.6/arch/arm/boot/zImage \-dtb linux-5.6.6/arch/arm/boot/dts/versatile-pb.dtb \-append "console=ttyAMA0" \-serial telnet::,server,nodelay

0x34 后续操作

后续就是加上 -initrd 参数选项指定固件中的根文件系统,就可以仿真固件。如果你觉得命令过于复杂,写出脚本就可以了

# boot.sh#! /bin/shqemu-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 内核挂载根文件系统

内核运行成功后,需要根文件系统的支撑,才能形成一个完整的系统。这里,我们使用 busybox 制作一个最小根文件系统,加深我们对根文件系统的理解。

0x41 使用 busybox 制作根文件系统

1 下载和编译 busybox

从 busybox 官网 下载 busybox ,解压

tar -jxvf busybox-1.31.1.tar.bz2 cd busybox-1.31.1/

方法一:静态编译

编译,busybox 编译的方式与内核编译类似,在配置文件中,建议选择静态编译

make distcleanmake menuconfig ARCH=arm# menuconfig beginSettings -->[*] Build static binary (no shared libs)# menuconfig endmake ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- all install

方法二:动态链接

如果你嫌麻烦,可以直接使用默认配置,默认配置是使用动态链接的方式进行编译

make distcleanmake defconfigmake ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- all install

busybox 默认安装到./_install目录下

lys@kali:~/Documents/busybox-1.31.1/_install$ lsbin linuxrc sbin usr

2 创建 rootfs 目录

busybox 装完成后,会在 busybox 目录下生成 _install 目录,该目录下的程序就是单板运行所需要的命令。

拷贝该目录下的文件

rm linuxrc # 此文件可删除cp -r * ~/Documents/rootfs/

3 复制动态链接库

从交叉编译器中拷贝所需要的动态链接库,复制到 lib 库目录下(如果 busybox 是静态编译的话,可以忽略此步骤

lys@kali:~/Documents/rootfs$ mkdir liblys@kali:~/Documents/rootfs$ sudo cp -r /usr/arm-linux-gnueabi/lib/* ./lib/

4 测试目标二进制程序是否能够运行

使用 qemu-user 模式测试 busybox 是否能够运行。新版 kali 没有内置 user 模式的 qemu ,需要我们下载安装之后,再进行测试

sudo apt-get install qemu-user

qemu-arm 测试 busybox

测试成功之后,需要新建终端,因为刚刚的export QEMU命令已经修改了系统的库目录路径,为了重新设置环境变量,需要新建终端,再进行后续的操作步骤

5 创建 4 个 tty 终端设备

mknod 用于创建 linux 中的字符设备和块设备,tty1 是设备的名字,c 是指块设备,4 是主设备号 /dev/devices 里面记录现有的设备,1 表示第一个子设备

$ mkdir ./dev$ sudo mknod ./dev/tty1 c 4 1$ sudo mknod ./dev/tty2 c 4 2$ sudo mknod ./dev/tty3 c 4 3$ sudo mknod ./dev/tty4 c 4 4

6 生成映象文件

lys@kali:~/Documents$ dd if=/dev/zero of=a9rootfs.ext3 bs=1M count=16

像 /dev/nul l一样,/dev/zero 也是一个伪文件,但它实际上产生连续不断的 null 的流(二进制的零流,而不是ASCII型的)。写入它的输出会丢失不见,/dev/zero主要的用处是用来创建一个指定长度用于初始化的空文件,像临时交换文件。

格式化生成 ext3 文件系统

mkfs.ext3 a9rootfs.ext3

7 将 rootfs 挂载到制作的 ext3 文件系统映象

方法一:

sudo mkdir tmpfs# -o loop=:使用 loop 模式用来将一个档案当成硬盘分割挂上系统。sudo mount -t ext3 a9rootfs.ext3 tmpfs/ -o loopsudo cp -r rootfs/* tmpfs/sudo umount tmpfs

方法二:

sudo mount -t ext3 a9rootfs.ext3 rootfs/ -o loopsudo umount rootfs

0x42 挂载根文件系统

在挂在根文件系统之前,先使用上一章的方法启动内核,看看内核中支持的块设备的名称

以 versatile 开发板为例,支持的设备以及文件系统如上所示,可以看到,只支持 ext2 ,而非我们刚刚制作的 ext3,重新制作个根文件系统就好了。或者使用 vexpress 开发板,这个开发板功能更为高级,支持挂载 ext3 文件系统。

sudo qemu-system-arm -M versatilepb -m 256M -kernel linux-5.6.6/arch/arm/boot/zImage -dtb linux-5.6.6/arch/arm/boot/dts/versatile-pb.dtb -append "root=/dev/ram0 ttyAMA0" -serial stdio -sd a9rootfs.ext2

root=/dev/..就是上图中,开发板硬件某个设备的名称。经过验证,verstaile 开发板较老,不能很好的支持我们制作的根文件系统,改换 vexpress,重新编译内核和文件系统,挂载成功。

qemu-system-arm -M vexpress-a9 -m 512M -kernel linux-5.6.6/arch/arm/boot/zImage \-dtb linux-5.6.6/arch/arm/boot/dts/vexpress-v2p-ca9.dtb \-append "root=/dev/mmcblk0 console=ttyAMA0" \-sd a9rootfs.ext3 -serial stdio

系统成功启动

0x50 Q&A 可能遇到的问题

0x51 编译内核

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/benh@.cert.pem"

0x52 编译 busybox

Trying libraries: m resolv

这个其实代表编译成功,因为没有打印 make error

0x53 加载文件系统

error while loading shared libraries

在加载 init 文件时出错,此类错误多数是因为符号链接的问题,跟库有关系,建议重新编译 busybox,注意要用静态链接的方式编译。

Kernel panic - not syncing: No working init found

原因一:最小文件系统制作有问题,注意是否生成了目标平台的 busybox

原因二:应用程序通过eabi接口编译,内核需要支持这种接口。因此需要重新编译内核,在 Kernel Feture下选中 Use the ARM EABI to compile the kernel

0x60 总结

使用 qemu 模拟硬件设备,运行内核,并不是我们的最终目的,后续要做的是提取根文件系统,并将其挂在,这样就可以实现一个完整的设备模拟。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。