0
点赞
收藏
分享

微信扫一扫

记录QEMU上模拟ARM运行环境(内核 2.6.30)


下载安装包

# gnu-gcc交叉编译链
sudo apt-get install gcc-arm-linux-gnueabi
# qume
sudo apt-get install qemu-system-arm
# Linux 2.6.30.4
wget https://mirrors.edge.kernel.org/pub/linux/kernel/v2.6/linux-2.6.30.4.tar.gz
# busybox-1.28.4
wget https://busybox.net/downloads/busybox-1.28.4.tar.bz2
# 其他环境
apt-get -y install g++-arm-linux-gnueabihf libexpat1-dev libncurses5-dev

注意​​Linux​​​和​​gcc​​版本匹配支持!

root@huawei linux-2.6.30.4 # find . -name "compiler-gcc*"                                                                                                                                                 [130]
./include/linux/compiler-gcc4.h
./include/linux/compiler-gcc.h
./include/linux/compiler-gcc3.h

运行环境

Linux huawei 5.4.0-100-generic #113-Ubuntu SMP Thu Feb 3 18:43:29 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux

设备平台:

  • 操作系统:​​Ubuntu​
  • 内核版本:​​5.4.0-100-generic​
  • 架构:​​x86_64​

新建目录​​qume-linux​

mkdir qume-linux
cd ./qume-linux
tar -xzvf linux-2.6.30.4.tar.gz

编译最小根文件系统

tar -jxvf busybox-1.28.4.tar.bz2
cd busybox-1.28.4
export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabi-
# 此处要安装图形库
make menuconfig # 选择Setting->Build Options [*]Build static binary(no shared libs)
make install

完成后会在目录中生成​​_install​​目录,本目录存放了编译好的文件系统需要的命令集合

此处有两种方法可以生成最小根文件系统,一种是使用虚拟内存文件系统,一种是直接新建物理节点(可见参考链接部分),下面 主要介绍使用虚拟内存文件系统

第一个方法

mkdir boot_demo
cd ./boot_demo
# 把busybox中的busybox文件复制到一个新的目录
cp -r /root/test_linux/busybox-1.35.0/_install/bin/busybox ./busybox
mkdir initramfs
cd ./initramfs/
mkdir bin
mv ../busybox .
mv ./busybox ./bin/
vim init
chmod +x init

其中​​init​​文件

#!/bin/busybox sh

/bin/busybox echo "Hello Linux"

/bin/busybox sh

最后写成​​makefile​​生成即可

initramfs:
cd ./initramfs_dir && find . -print0 | cpio -ov --null --format=newc | gzip -9 > ../initramfs.img

run:
qemu-system-arm \
-M vexpress-a9 \
-dtb vexpress-v2p-ca9.dtb \
-kernel zImage \
-initrd initramfs.img \
-m 1G \
-nographic \
-append "earlyprintk=serial,ttyS0 console=ttyS0"

第二个方法

我们使用ramfs的方式来为内核提供根文件系统,内核默认的配置没有支持ramfs设备,我们需要添加对应的支持(CONFIG_BLK_DEV_RAM=y)

make ARCH=arm menuconfig

Device Drivers
Block devices
BLK_DEV_RAM

内核支持了ramfs设备之后,我们通过给qemu传递参数指定本机的相关文件作为ramfs的文件系统传递到内核,修改qemu启动命令

qemu-system-aarch64 -machine virt       \
-cpu cortex-a53 \
-nographic \
-smp 1 \
-m 2048 \
-kernel linux-4.19.171/arch/arm64/boot/Image \
-append "root=/dev/ram0 rootfstype=ramfs rw init=/init" \
-initrd initramfs.cpio.gz

打包脚本​​mkinitramfs.sh​​内容:

#!/bin/sh

# Copyright 2006 Rob Landley <rob@landley.net> and TimeSys Corporation.
# Licensed under GPL version 2

if [ $# -ne 2 ]
then
echo "usage: mkinitramfs directory imagename.cpio.gz"
exit 1
fi

if [ -d "$1" ]
then
echo "creating $2 from $1"
(cd "$1"; find . | cpio -o -H newc | gzip) > "$2"
else
echo "First argument must be a directory"
exit 1
fi

./mkinitramfs.sh  rootfs/ initramfs.cpio.gz

第三个方法

创建rootfs根目录

mkdir -p rootfs/{dev,etc/init.d,lib}

把busybox-1.20.2中的文件复制到rootfs根目录下,主要是一些基本的命令

cp busybox-1.20.2/_install/* -r rootfs/

把交叉编译工具链中的库文件复制到rootfs根目录的lib文件夹下

sudo cp -P /usr/arm-linux-gnueabi/lib/* rootfs/lib/

制作根文件系统镜像 根文件系统镜像就相当于一个硬盘,就是把上面rootfs根目录中的所有文件复制到这个硬盘中。

# 生成512M大小的磁盘镜像
qemu-img create -f raw disk.img 512M
# 把磁盘镜像格式化成ext4文件系统
mkfs -t ext4 ./disk.img
# 将rootfs根目录中的所有文件复制到磁盘镜像中 操作步骤是:创建挂载点-挂载-复制文件-卸载。
mkdir tmpfs
sudo mount -o loop ./disk.img tmpfs/
sudo cp -r rootfs/* tmpfs/
sudo umount tmpfs
# 检查
file disk.img

此时启动命令为

# append表示传递给内核的参数 一般有根文件系统设备 文件系统类型 第一个进程名称
qemu-system-arm -M vexpress-a9 -m 512M -kernel ./linux-4.14.212/arch/arm/boot/zImage -dtb ./linux-4.14.212/arch/arm/boot/dts/vexpress-v2p-ca9.dtb -nographic -append "root=/dev/mmcblk0 rw console=ttyAMA0" -sd disk.img

如果选择的是虚拟内存文件系统,请在配置内核的时候打开支持​​Gneral setup​​​->​​initramfs/initrd​​​和​​Device Drivers​​​->​​Block devices​​​->​​Ram block device support​

编译内核

# ARCH:编译arch/目录下的哪一个子目录
# CROSS_COMPILE:即交叉编译器的前缀
make ARCH=arm CROSS_COMPILE=gcc-arm-linux-gnueabi-
make dtbs

模拟系统

qemu-system-arm 
-M vexpress-a9
-m 256M -kernel arch/arm/boot/zImage
-append "rdinit=/linuxrc console=ttyAMA0 loglevel=8"
-dtb arch/arm/boot/dts/vexpress-v2p-ca9.dtb
-nographic

# 以上命令中参数含义如下;
# -M:指定硬件芯片框架
# -m:指定运行内存大小
# -kernel:指定运行的内核镜像
# -dtb:指定具体芯片的配置信息
# -nographic:指定不使用图形界面

运行结果

# ...
1000a000.uart: ttyAMA1 at MMIO 0x1000a000 (irq = 38, base_baud = 0) is a PL011 rev1
1000b000.uart: ttyAMA2 at MMIO 0x1000b000 (irq = 39, base_baud = 0) is a PL011 rev1
1000c000.uart: ttyAMA3 at MMIO 0x1000c000 (irq = 40, base_baud = 0) is a PL011 rev1
rtc-pl031 10017000.rtc: registered as rtc0
rtc-pl031 10017000.rtc: setting system clock to 2022-09-14T14:39:19 UTC (1663166359)
amba 10020000.clcd: Fixing up cyclic dependency with 0-0039
drm-clcd-pl111 10020000.clcd: DVI muxed to daughterboard 1 (core tile) CLCD
drm-clcd-pl111 10020000.clcd: initializing Versatile Express PL111
drm-clcd-pl111 10020000.clcd: DVI muxed to daughterboard 1 (core tile) CLCD
drm-clcd-pl111 10020000.clcd: initializing Versatile Express PL111
drm-clcd-pl111 10020000.clcd: DVI muxed to daughterboard 1 (core tile) CLCD
input: AT Raw Set 2 keyboard as /devices/platform/bus@40000000/bus@40000000:motherboard-bus@40000000/bus@40000000:motherboard-bus@40000000:iofpga@7,00000000/10006000.kmi/serio0/input/input0
drm-clcd-pl111 10020000.clcd: initializing Versatile Express PL111
ALSA device list:
#0: ARM AC'97 Interface PL041 rev0 at 0x10004000, irq 32
drm-clcd-pl111 10020000.clcd: DVI muxed to daughterboard 1 (core tile) CLCD
Freeing unused kernel image (initmem) memory: 1024K
drm-clcd-pl111 10020000.clcd: initializing Versatile Express PL111
Run /linuxrc as init process
can't run '/etc/init.d/rcS': No such file or directory

Please press Enter to activate this console. input: ImExPS/2 Generic Explorer Mouse as /devices/platform/bus@40000000/bus@40000000:motherboard-bus@40000000/bus@40000000:motherboard-bus@40000000:iofpga@7,00000000/10007000.kmi/serio1/input/input2
drm-clcd-pl111 10020000.clcd: DVI muxed to daughterboard 1 (core tile) CLCD
drm-clcd-pl111 10020000.clcd: initializing Versatile Express PL111
ls
/ # ls
bin dev linuxrc root sbin usr
/ # pwd
/
/ # mkdir mnt
/ # ls
bin dev linuxrc mnt root sbin usr
/ #

我觉得可以写一个​​makefile​​​或者一个​​.sh​​来实现自动处理

踩过的坑

报错:​​can't open /dev/tty3: No such file or directory​​ 解决:

sudo mknod tty1 c 4 1
sudo mknod tty2 c 4 2
sudo mknod tty3 c 4 3
sudo mknod tty4 c 4 4

报错:​​---[ end Kernel panic - not syncing: No working init found. Try passing init= option to kernel. See Linux Documentation/init.txt for guidance.​​​ 解决:查看​​init​​文件格式与​​kernel​​文件格式匹配

报错:​​---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)​​ 解决:未安装文件系统

参考文章

  • ​​嵌入式linux:make 参数 ARCH与CROSS_COMPILE​​
  • ​​linux解压.xz文件​​
  • ​​教你编译一个基于arm的Linux内核,并用qemu模拟器测试​​
  • ​​arm系列的交叉编译器各版本的区别​​
  • ​​使用qemu进行arm64架构linux开发学习​​



举报

相关推荐

0 条评论