qemu(4) -- qemu-system-arm使用
1. 前言
参考网上的资料,使用qemu中的vexpress_a9
板子,跑一下Linux环境。
2. 源码
2.1 u-boot
可以到U-Boot官网下载对应的源码,我下载的是u-boot-2025.04-rc5.tar.gz,大约24MB。
3.2 linux
可以到The Linux Kernel Archives官网下载对应的源码,我下载的是linux-5.15.180.tar.xz,大约121MB。最新的是linux-6.14.4.tar.xz,qemu开启lcd时,6.14
提示Guest has not initialized the display (yet)
,不清楚为什么就切换为5.15
的版本了。
4.3 busybox
可以到BUSYBOX官网下载对应的源码,我下载的是busybox-1.37.0.tar.bz2,大约2.4MB。1.37.0
版本有些bug,busybox-1.37.0/libbb/hash_md5_sha.c
文件需要进行以下修改,其中1316
和1318
行是新增的,否者编译的时候报错。
1316 # if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
1317 || ctx->process_block == sha1_process_block64_shaNI
1318 #endif
4.4 rootfs
构建rootfs
时需要手动添加一些文件。
$ tree rootfs
rootfs/
└── vexpress_a9├── dev│ ├── console│ ├── null│ ├── tty1│ ├── tty2│ ├── tty3│ └── tty4├── etc│ ├── fstab│ ├── init.d│ │ └── rcS│ ├── inittab│ ├── profile│ └── sysconfig│ └── HOSTNAME├── mnt├── proc├── root├── sys├── tmp└── var
3. 依赖
安装编译所需要的依赖包。
# gnutls-dev,编译u-boot时需要
# libmpc-dev,编译内核时需要
sudo apt install gnutls-dev libmpc-dev
3. 编译
设置交叉编译所需要的环境变量,也可以将这些变量写到make
命令后面,这样就不需要定义为环境变量。
export ARCH=arm
export CROSS_COMPILE=arm-none-linux-gnueabihf-
# 获取主机的cpu核心数,后面命令行中会需要
JOBS=$(nproc)
3.1 u-boot
# 进入u-boot源码目录
cd u-boot-2025.04-rc5
# “O=”指定编译输出目录,使用vexpress_ca9x4板子的配置
make O=../build/uboot_vexpress_a9 vexpress_ca9x4_defconfig
# about 1min
make O=../build/uboot_vexpress_a9 -j${JOBS}
# 将编译出的mkimage程序拷贝到PATH目录中,后面linux制作uImage时会用到它
cp ../build/uboot_vexpress_a9/tools/mkimage ~/bins
# 将u-boot的镜像拷贝到images目录,之后qemu启动时使用
cp ../build/uboot_vexpress_a9/u-boot ../build/images
# 退出u-boot源码目录
cd ..
3.2 busybox
# 进入busybox源码目录
cd busybox-1.37.0
# 使用默认的配置
make O=../build/busybox_vexpress_a9 defconfig
# 执行menconfig修改一些配置项,修改的内容都在“Settings --->”下面
# [*] Build static binary (no shared libs),表示使用静态链接,不使用动态库
# (./_install)Destination path for 'make install' => ../rootfs_vexpress_a9,表示修改安装目录,此处的目录是相对于编译目录而言的
# [*] vi-style line editing commands (New),启用vi命令
make O=../build/busybox_vexpress_a9 menuconfig
# about 1min,此处install会先编译后安装
make O=../build/busybox_vexpress_a9 install -j${JOBS}
# 可以看到busybox已经创建 好了目录结构
ls ../build/rootfs_vexpress_a9/
# 退出busybox源码目录
cd ..
3.3 linux
# 进入linux源码目录
cd linux-5.15.180
# 使用vexpress的配置
make O=../build/linux_vexpress_a9 vexpress_defconfig
# about 6min,编译kernel镜像,zImage表示压缩镜像
make O=../build/linux_vexpress_a9 zImage -j${JOBS}
# 编译设备树
make O=../build/linux_vexpress_a9 dtbs
# 编译模块文件
make O=../build/linux_vexpress_a9 modules
# 使用u-boot-2025.04-rc5编译出的mkimage程序制作uImage,LOADADDR指定uImage中的头信息
make O=../build/linux_vexpress_a9 uImage LOADADDR=0x60003000
# 将内核镜像zImage拷贝到images目录
cp ../build/linux_vexpress_a9/arch/arm/boot/zImage ../build/images
# 将内核镜像uImage拷贝到boot目录,之后通过u-boot加载内核时,从boot目录读取该文件
cp ../build/linux_vexpress_a9/arch/arm/boot/uImage ../build/rootfs_vexpress_a9/boot
# 将设备树拷贝到images和boot目录,前者用于直接启动,后者用于u-boot启动
cp ../build/linux_vexpress_a9/arch/arm/boot/dts/vexpress-v2p-ca9.dtb ../build/images
cp ../build/linux_vexpress_a9/arch/arm/boot/dts/vexpress-v2p-ca9.dtb ../build/rootfs_vexpress_a9/boot
# 退出linux源码目录
cd ..
3.4 rootfs
busybox
已经构建了一部分rootfs的内容,还需要手动补充一些文件。
# 进入创建的根目录
$ cd build/rootfs_vexpress_a9
# 查看当前的目录结构
$ ls
bin linuxrc sbin usr
# 执行脚本完善文件系统的内容
$ ../../rootfs/vexpress_a9.sh
# 查看当前的目录结构
$ ls
bin boot dev etc linuxrc mnt proc root sbin tmp usr var
# 退出根目录
cd ../..
- 创一个文件,将其格式化为ext4,然后挂载到主机中,将根目中的内容复制进去。
# 进入images目录
cd build/images
# 创建一个32MB的文件rootfs.ext4,使用0填充
dd if=/dev/zero of=rootfs.ext4 bs=1M count=32
# 将rootfs.ext4文件格式化成ext4文件系统
mkfs.ext4 rootfs.ext4
# 创建一个临时目录作为挂载点
mkdir temp/
# 将文件rootfs.ext4挂载到temp/目录上,mount会自动识别文件系统格式,需要管理员权限,-o loop表示挂载的是一个文件虚拟的块设备
sudo mount rootfs.ext4 temp/ -o loop
# 将根目中的文件拷贝到temp/目录中
sudo cp ../rootfs_vexpress_a9/* temp/ -r
# 取消挂载,此时rootfs.ext4就是一个根文件系统镜像了,其文件系统格式为ext4,且拥有../rootfs_vexpress_a9/目录下的所有文件
sudo umount temp
# 退出images目录
cd ../..
4. 启动
4.1 linux
qemu可以直接启动linux。
# 进入images目录
$ cd build/images
# 无窗口启动,启动日志会直接输出到控制台,先按下CTRL+a再按下x可以退出qemu
$ qemu-system-arm -M vexpress-a9 -m 512M -kernel zImage -dtb vexpress-v2p-ca9.dtb -sd rootfs.ext4 -append "root=/dev/mmcblk0 rw console=ttyAMA0" -nographic
....(此处省略许多日志,日志中ALSA等信息是可声卡有关的错误,暂时可以先不理会)
-----------------------------------
*****welcome to vexpress board*****
-----------------------------------Please press Enter to activate this console.(此处按下回车即可登录到控制台)
# 进入linux控制台
[root@vexpress ~]$ ls
bin etc mnt sbin var
boot linuxrc proc tmp
dev lost+found root usr
# 有窗口启动,可以看到qemu弹出了gui窗口,等待一段时间会在窗口上出现小企鹅,启动日志会输出到gui窗口
$ qemu-system-arm -M vexpress-a9 -m 512M -kernel zImage -dtb vexpress-v2p-ca9.dtb -sd rootfs.ext4 -append "root=/dev/mmcblk0 rw console=tty0"
# 退出images目录
cd ../..
有窗口启动时,鼠标单击窗口即可进行输入交互,我在两个电脑上运行过,有个电脑gui窗口交互有些问题,输入的命令总是收的不全,另一台电脑正常。鼠标点进窗口后就不能点击qemu窗口的菜单栏了,根据窗口标题提示,需要先按下Ctrl+Alt+g,表示将鼠标的焦点退出控制台,然后才能点击窗口的菜单栏,通过菜单栏的【Machine】》【Quit】可以退出qemu。
4.2 u-boot
qemu可以直接运行u-boot,然后通过u-boot加载内核。
# 进入images目录
$ cd build/images
# 无窗口启动,启动日志会直接输出到控制台,rootfs.ext4会被映射为u-boot的mmc 0,先按下CTRL+a再按下x可以退出qemu
$ qemu-system-arm -M vexpress-a9 -m 512M -kernel u-boot -sd rootfs.ext4 -nographic
# 进入u-boot命令行,加载uImage文件到内存0x60003000位置
=> ext4load mmc 0 0x60003000 boot/uImage
# 加载设备树文件到内存0x60500000位置,确保不覆盖uImage即可
=> ext4load mmc 0 0x60500000 boot/vexpress-v2p-ca9.dtb
# 设置启动参数
=> setenv bootargs "root=/dev/mmcblk0 rw console=ttyAMA0"
# 启动linux,两个地址分别指向内核和设备树的位置
=> bootm 0x60003000 - 0x60500000
...(此处省略许多日志,日志中ALSA等信息是可声卡有关的错误,暂时可以先不理会)
-----------------------------------
*****welcome to vexpress board*****
-----------------------------------Please press Enter to activate this console.(此处按下回车即可登录到控制台)
[root@vexpress ~]$ ls
bin etc mnt sbin var
boot linuxrc proc tmp
dev lost+found root usr
# 退出images目录
cd ../..
上一篇:qemu(3) – qemu-arm使用
下一篇:qemu(4) – qemu-system-arm使用
目录:全部文章合集
参考
QEMU教程
U-Boot 文档