There is a uniquely discouraging kind of boot failure: a black QEMU window, no serial text, and an image that works perfectly in a physical Raspberry Pi. It tempts you to keep changing random command-line flags. Usually the deeper problem is that “ARM” describes an instruction set, not a complete computer.
A Raspberry Pi OS image expects a particular boot chain, Broadcom peripherals, a matching kernel and Device Tree, and an SD-card layout. QEMU can model some Raspberry Pi boards, but it does not turn every Pi image into a drop-in virtual machine. Let us choose the test boundary first; the command becomes much easier afterward.
Three doors, only one of them looks like a Pi
Board emulation (`raspi2b`): use this when software must see QEMU’s model of a Raspberry Pi 2. It is useful for early boot, kernel, serial, SD, and selected peripheral work—but only for devices QEMU implements.
Generic ARM virtual machine (`virt`): use this when you need a complete ARM Linux guest and do not need Raspberry Pi hardware identity. QEMU explicitly recommends this machine for general Linux guests.
User-mode emulation (`qemu-arm`): use this when you only need to run or debug one ARM Linux executable. It emulates the process instruction set and translates system calls; it does not boot a kernel or emulate GPIO, firmware, or an SD controller.
Ask your installed QEMU what it can model
qemu-system-arm --version
qemu-system-arm -machine help | grep -E 'raspi|virt'This tiny check prevents version-shaped confusion
--versionmatters because Raspberry Pi models and implemented devices vary across QEMU releases and distribution packages.-machine helpis authoritative for the binary installed on this Ubuntu host; a command copied from newer online documentation may name a board absent locally.greponly filters the machine list. Remove it if you want to inspect every supported ARM board.These commands are read-only. They were not executed here because this development host does not have
qemu-system-arminstalled; no sample output is invented.
Install the system emulator, then stop and inspect
sudo apt update
sudo apt install qemu-system-arm
qemu-system-arm --versionRisk level: caution. Review the command before running it.
Installation is not proof that an image will boot
apt updaterefreshes package indexes andapt installchanges the host by adding QEMU and dependencies; review the package plan before accepting it.Ubuntu’s package version depends on the Ubuntu release and enabled repositories. Use its own machine list and matching QEMU documentation.
System emulation binaries are distinct from user-mode binaries. Installing or invoking
qemu-armalone does not provide a virtual Raspberry Pi board.This workflow was documentation-validated but not installed on the content-migration host, so the article does not claim an executed installation.
For a Pi 2 experiment, the files must agree with each other
Machine:
raspi2bmodels a Raspberry Pi 2 with four Cortex-A7 cores and 1 GiB RAM in current QEMU documentation.Kernel: use a 32-bit kernel built for Raspberry Pi 2/BCM2836 and compatible with the selected root filesystem. Raspberry Pi documents
kernel7.imgfor the Pi 2 family, but a release image may package or compress kernels differently.Device Tree: the DTB describes the hardware to Linux. The conventional Pi 2 file is
bcm2709-rpi-2-b.dtb; use the DTB produced with the kernel rather than borrowing an unrelated version.Root filesystem: identify the real Linux root partition inside the raw image. Do not assume it is always partition 2 just because older images commonly used that layout.
Kernel command line: console device, root device, filesystem type, and
rootwaitmust match this emulated boot path.
Inventory an image without mounting or changing it
file raspberry-pi-os.img
fdisk -l raspberry-pi-os.imgThe partition table tells the story the filename cannot
filegives a first-pass identification; it does not prove that an image targets Pi 2 or contains a compatible kernel.fdisk -lreads the image partition table and reports partition numbers, offsets, sizes, and types without attaching a loop device.If the download is compressed as
.xzor.zip, preserve its checksum and extract a working copy first. QEMU needs the raw image, not the archive container.Do not run these placeholders literally until
raspberry-pi-os.imgis replaced with the correct local path.
A direct Pi 2 boot is a matched-set experiment
qemu-system-arm \
-machine raspi2b \
-kernel ./kernel7.img \
-dtb ./bcm2709-rpi-2-b.dtb \
-append 'console=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait rw' \
-drive file=./raspberry-pi-os.img,format=raw,if=sd \
-serial stdio \
-display none \
-no-rebootRisk level: caution. Review the command before running it.
Read this template as a contract, not a magic incantation
-machine raspi2bchooses board emulation; it is fundamentally different from-machine virt.-kerneland-dtbbypass the normal physical-board firmware selection. Those artifacts must match each other and support QEMU’s implemented devices.root=/dev/mmcblk0p2is only an example. Replace it after inspecting the image; a wrong root partition commonly ends in a kernel panic or an initramfs shell.-drive ... format=raw,if=sdmakes the file writable by default. Work on a disposable copy or addsnapshot=onwhile experimenting so the source image is not altered.-serial stdio -display noneplaces the serial console in the terminal. PressCtrl+A, thenXto ask QEMU’s character frontend to exit.This boot template was not executed here: QEMU and a legally sourced, mutually compatible image/kernel/DTB set are not present on the migration host.
Protect the image while you are still learning its boot path
cp --reflink=auto raspberry-pi-os.img raspberry-pi-os-lab.img
sha256sum raspberry-pi-os.img raspberry-pi-os-lab.imgA disposable image buys room to make honest mistakes
--reflink=autouses filesystem copy-on-write when available and otherwise performs a conventional copy.sha256sumshould initially report identical digests; after a writable guest boot, the laboratory image may legitimately differ.Keep the downloaded checksum or signature separately and validate it according to the image publisher’s instructions.
Copying a multi-gigabyte image consumes storage and I/O. Confirm free space first when reflinks are unavailable.
What the raspi2b machine can—and cannot—stand in for
Reasonable early targets: serial boot logging, kernel command-line work, SD-root mounting, CPU-visible code, and drivers for devices QEMU documents as implemented.
Not hardware validation: electrical timing, signal integrity, real GPIO-connected equipment, camera/display firmware paths, performance, thermals, and undocumented peripherals still require physical hardware.
Networking needs proof: do not paste a generic virtio network device into a Pi-board command. A device offered by the generic
virtmachine is not automatically wired intoraspi2b, and guest drivers must match the emulated controller.Device Tree overlays need context: physical firmware normally merges overlays. Direct booting a base DTB does not automatically recreate that process.
Newer Pi does not mean better Pi 2 fidelity:
raspi3bandraspi4bare different machines. QEMU’s Raspberry Pi documentation also lists missing devices per model, including Pi 4 PCIe and GENET Ethernet in documented releases.
If your real goal is ARM Linux, choose virt gladly
There is no shame in discovering that you never needed a virtual Raspberry Pi. For service testing, package builds, CI, networking experiments, or a general ARM server, the generic virt board is usually the cleaner engineering choice. It supports modern virtual hardware, large memory, many CPUs, and both 32-bit and 64-bit guest configurations.
Use an ARM64 cloud/server image, installer, kernel, or firmware specifically prepared for QEMU’s
virtplatform—not a Raspberry Pi SD image.For AArch64, invoke
qemu-system-aarch64and select a 64-bit CPU; QEMU documents thatvirtotherwise has a 32-bit default CPU in relevant releases.Define storage and network devices explicitly because
virthas no default disks or network interfaces. Match virtio drivers to the guest image.On an x86 Ubuntu host, ARM runs through QEMU TCG translation. KVM acceleration for an AArch64 guest requires a compatible AArch64 host; the presence of
/dev/kvmon x86 does not make cross-architecture Pi emulation native-speed.
For one executable, leave the virtual board behind
file ./hello-arm
qemu-arm -L /usr/arm-linux-gnueabihf ./hello-armUser mode answers a deliberately smaller question
fileshould confirm the executable architecture, bitness, ABI, and whether it is dynamically linked before you select an emulator.qemu-armruns a 32-bit ARM Linux process; use the architecture-appropriate user emulator for a different binary, such asqemu-aarch64for AArch64.-Lsupplies the guest dynamic loader and libraries from a matching sysroot. It is not a Raspberry Pi root disk and does not boot guest Linux.The guest process ultimately uses translated host-kernel system calls, so this path cannot validate a kernel module, Device Tree, bootloader, or physical peripheral.
The placeholders were not executed because neither the ARM binary nor matching sysroot is present on this host.
When the serial console stays silent
QEMU rejects the machine name: check
-machine helpbefore assuming the package is broken. QEMU 6.2 removed the oldraspi2andraspi3aliases; current commands useraspi2bandraspi3bwhen those models are compiled in.QEMU opens but prints nothing: confirm the kernel console name and baud rate, retain
earlycononly when the kernel and UART support it, and verify that output is routed to-serial stdio.Kernel reports an invalid or missing DTB: pair the DTB with the exact kernel build and the emulated board. A Pi 3 or Pi 4 tree is not a substitute for Pi 2.
Kernel cannot mount root: inspect the image partition table, filesystem driver availability,
root=value, and whether an initramfs is required.It hangs before Linux messages: suspect the kernel format, board mismatch, or boot protocol before editing the filesystem.
Network device is missing: verify that the chosen machine actually implements the controller and that the guest kernel has its driver. Options valid for
virtare not evidence forraspi2b.It is painfully slow: cross-architecture TCG prioritizes functional emulation, not Pi-like performance. Reduce the test boundary or use native ARM hardware/CI when speed is the question.
The result you can trust
Emulation is most valuable when its boundary is written down. A successful raspi2b boot demonstrates behavior against QEMU’s Raspberry Pi 2 model. A successful virt boot demonstrates behavior on a generic ARM virtual platform. A successful qemu-arm run demonstrates that one userspace program can execute through user-mode translation.
None of those results is smaller for being precise. Precision is what lets you carry the useful part of the test to the real board without promising yourself that a simulated LED ever truly blinked.
Comments and corrections