通过qemu仿真树莓派系统调试IoT固件和程序
本文将介绍如何使用 QEMU 模拟器在 x86 架构的主机上运行 Raspberry Pi OS(树莓派操作系统)。我们将从下载镜像、提取内核和设备树文件,到启动模拟环境,并进行一些常见的操作,如更改密码和交叉编译,以及如何通过 GDB 进行远程调试。
1. 下载 Raspberry Pi OS 镜像
首先,我们需要下载适用于树莓派的轻量版 Raspberry Pi OS 镜像。本文使用的是 2024-10-22-raspios-bullseye-armhf-lite.img
,这是一个基于 Debian Bullseye 的 ARM 架构镜像。
你可以从 Raspberry Pi 官方网站 或其他可信来源下载该镜像。
2. 提取内核和设备树文件
为了在 QEMU 中运行 Raspberry Pi OS,我们需要从镜像中提取内核 (kernel*.img
) 和设备树文件 (.dtb
)。以下是具体步骤:
2.1 创建挂载点并挂载镜像
# 1. 创建挂载点
sudo mkdir /mnt/rpi# 2. 挂载镜像文件
sudo losetup -f --show -P 2024-10-22-raspios-bullseye-armhf-lite.img
# 假设输出为 /dev/loop0# 3. 挂载第一个分区
sudo mount /dev/loop0p1 /mnt/rpi
2.2 复制内核和设备树文件
# 4. 复制内核和设备树文件
cp /mnt/rpi/kernel* .
cp /mnt/rpi/*.dtb .# 5. 卸载分区
sudo umount /mnt/rpi# 6. 删除 loop 设备
sudo losetup -d /dev/loop0
至此,我们已经成功提取了内核和设备树文件,这些文件将在后续步骤中用于 QEMU 启动。
3. 使用 QEMU 启动 Raspberry Pi OS
3.1 启动树莓派 3B 模拟环境
以下命令将使用 QEMU 模拟树莓派 3B 环境,并加载我们提取的内核和设备树文件:
sudo qemu-system-aarch64 -M raspi3b \
-append "rw earlyprintk loglevel=8 console=ttyAMA0,115200 dwc_otg.lpm_enable=0 root=/dev/mmcblk0p2 rootdelay=1" \
-dtb ./bcm2710-rpi-3-b-plus.dtb \
-drive format=raw,file=2024-10-22-raspios-bullseye-armhf-lite.img \
-kernel kernel8.img \
-m 1G \
-smp 4 -serial stdio \
-net nic -net user,hostfwd=tcp::5022-:22 \
-usb -device usb-kbd -device usb-mouse \
-k en-us \
-display sdl
参数说明:
-M raspi3b
:指定模拟的硬件平台为树莓派 3B。-append
:传递给内核的启动参数,包括根文件系统位置、日志级别等。-dtb
:指定设备树文件。-drive
:指定镜像文件及其格式。-kernel
:指定内核文件。-m
:分配内存大小(1GB)。-smp
:指定 CPU 核心数(4 核)。-net
:配置网络,允许通过 SSH 访问(主机端口 5022 映射到虚拟机端口 22)。-usb
:启用 USB 支持,添加键盘和鼠标设备。-display sdl
:使用 SDL 图形显示。
运行上述命令后,QEMU 将启动树莓派模拟环境,并进入 Raspberry Pi OS 的登录界面。
4. 使用预编译的 versatilepb 内核进行仿真
https://github.com/dhruvvyas90/qemu-rpi-kernel
如果你希望使用更通用的 ARM 平台(如 VersatilePB),可以使用以下命令:
qemu-system-arm -M versatilepb -cpu arm1176 -m 256 \
-drive format=raw,file=2024-10-22-raspios-bullseye-armhf-lite.img \
-dtb versatile-pb-bullseye-5.10.63.dtb \
-kernel kernel-qemu-5.10.63-bullseye \
-net nic -net user,hostfwd=tcp::5022-:22 \
-net user,hostfwd=tcp::2333-:2333 \
-nographic \
-append "root=/dev/sda2 panic=1 rootfstype=ext4 rw"
参数说明:
-M versatilepb
:指定模拟的硬件平台为 VersatilePB。-cpu arm1176
:指定 CPU 类型。-nographic
:禁用图形界面,仅使用命令行模式。
4. 更改默认密码
Raspberry Pi OS 新版本需要通过在镜像文件中写入文件进行配置账号密码,否则无法实现登录。
这里我们直接挂载镜像来修改密码
以下是具体步骤:
# 1. 创建挂载点
sudo mkdir /mnt/rpi# 2. 挂载镜像文件
sudo losetup -f --show -P 2024-10-22-raspios-bullseye-armhf-lite.img# 3. 挂载第二个分区
sudo mount /dev/loop0p2 /mnt/rpi# 4. 更改密码
sudo chroot /mnt/rpi passwd pi# 5. 卸载分区
sudo umount /mnt/rpi# 6. 删除 loop 设备
sudo losetup -d /dev/loop0
运行上述命令后,输入新密码即可完成更改。
5. 交叉编译与远程调试
5.1 交叉编译工具链配置
为了在 x86 主机上为 ARM 架构编译程序,我们需要设置交叉编译工具链。以下是配置示例:
./configure --host=arm-linux-gnueabihf --target=arm-linux-gnueabihf CC=/home/kali/rpi-tools/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc --prefix=/opt/arm-linux-gnueabihf-gdb-8.2make CXX=/home/kali/rpi-tools/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-g++ CC=/home/kali/rpi-tools/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc
5.2 使用 GDB 进行远程调试
在目标系统中启动 gdbserver
:
$ ./gdbserver :2333 /bin/sh
在主机端使用 GDB 连接到目标系统:
gef➤ gef-remote 127.0.0.1 2333
6. 使用qemu直接进行调试
qemu-aarch64 配合gdb可以实现调试arm架构的程序
# 1. 安装 QEMU User 模式工具
sudo apt install qemu-user gdb-multiarch# 2. 用 QEMU 运行 ARM 可执行程序
qemu-aarch64 <你的ARM程序># 3. 运行 gdbserver 进行远程调试(在主机上执行)
qemu-aarch64 -g 2333 <你的ARM程序># 4. 在另一个终端启动 gdb-multiarch 并连接 gdbserver
gdb-multiarch
gef> set architecture aarch64
gef> gef-remote 127.0.0.1:2333
参考链接
https://zhuanlan.zhihu.com/p/613032457
https://www.gandalf.site/2018/12/iotqemuiot.html