当前位置: 首页 > backend >正文

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文件需要进行以下修改,其中13161318行是新增的,否者编译的时候报错。

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

  1. 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 ../..
  1. 创一个文件,将其格式化为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 文档

http://www.xdnf.cn/news/3423.html

相关文章:

  • 三生原理的离散生成逻辑如何与复分析结合?
  • 2025大模型微调视频课程全套(附下载)
  • WPF之Image控件详解
  • Sentry 异常捕获
  • 第 2.3 节: 基于 Python 的关节空间与任务空间控制
  • AUTOSAR图解==>AUTOSAR_RS_TimingExtensions
  • Rerank详解
  • C++初阶-string类3
  • 补题 (Multiples of 5)
  • PostgreSQL运算符
  • 【JSON vs Python字典】核心区别与互操作指南
  • RPG_5.角色动画
  • C语言-函数的递归和迭代
  • Spring Boot 使用 WebMagic 爬虫框架入门
  • 腾讯云BI VS quickbi 企业选型(从企业实际功能使用和费用对比)
  • 在项目中如何对Map List等对象序列化及反序列化
  • 雅马哈SMT贴片机高效精密制造解析
  • 【数据结构】线性表--顺序表
  • 59常用控件_QComboBox的使用
  • 【C语言练习】015. 声明和初始化指针
  • 【Hive入门】Hive性能调优之资源配置:深入解析执行引擎参数调优
  • 欧拉计划 Project Euler62(立方数重排)题解
  • Allegro23.1新功能之如何加粗打印线宽操作指导
  • 跨域 iframe 内剪切板 Clipboard_API 报错
  • 网络安全零基础培训 L1-9 PHP连接MySQL数据库
  • d202551
  • QMK固件烧录指南:安全高效地更新您的机械键盘
  • Python结合QT进行开发
  • 西门子数字化研发设计制造一体化规划案例P87(87页PPT)(文末有下载方式)
  • 神经网络—损失函数