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

Terminalbash
qemu-system-arm --version
qemu-system-arm -machine help | grep -E 'raspi|virt'

This tiny check prevents version-shaped confusion

  • --version matters because Raspberry Pi models and implemented devices vary across QEMU releases and distribution packages.

  • -machine help is authoritative for the binary installed on this Ubuntu host; a command copied from newer online documentation may name a board absent locally.

  • grep only 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-arm installed; no sample output is invented.

Install the system emulator, then stop and inspect

Terminalbash
sudo apt update
sudo apt install qemu-system-arm
qemu-system-arm --version

Risk level: caution. Review the command before running it.

Installation is not proof that an image will boot

  • apt update refreshes package indexes and apt install changes 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-arm alone 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: raspi2b models 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.img for 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 rootwait must match this emulated boot path.

Inventory an image without mounting or changing it

Terminalbash
file raspberry-pi-os.img
fdisk -l raspberry-pi-os.img

The partition table tells the story the filename cannot

  • file gives a first-pass identification; it does not prove that an image targets Pi 2 or contains a compatible kernel.

  • fdisk -l reads the image partition table and reports partition numbers, offsets, sizes, and types without attaching a loop device.

  • If the download is compressed as .xz or .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.img is replaced with the correct local path.

A direct Pi 2 boot is a matched-set experiment

Terminalbash
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-reboot

Risk level: caution. Review the command before running it.

Read this template as a contract, not a magic incantation

  • -machine raspi2b chooses board emulation; it is fundamentally different from -machine virt.

  • -kernel and -dtb bypass the normal physical-board firmware selection. Those artifacts must match each other and support QEMU’s implemented devices.

  • root=/dev/mmcblk0p2 is 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=sd makes the file writable by default. Work on a disposable copy or add snapshot=on while experimenting so the source image is not altered.

  • -serial stdio -display none places the serial console in the terminal. Press Ctrl+A, then X to 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

Terminalbash
cp --reflink=auto raspberry-pi-os.img raspberry-pi-os-lab.img
sha256sum raspberry-pi-os.img raspberry-pi-os-lab.img

A disposable image buys room to make honest mistakes

  • --reflink=auto uses filesystem copy-on-write when available and otherwise performs a conventional copy.

  • sha256sum should 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 virt machine is not automatically wired into raspi2b, 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: raspi3b and raspi4b are 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 virt platform—not a Raspberry Pi SD image.

  • For AArch64, invoke qemu-system-aarch64 and select a 64-bit CPU; QEMU documents that virt otherwise has a 32-bit default CPU in relevant releases.

  • Define storage and network devices explicitly because virt has 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/kvm on x86 does not make cross-architecture Pi emulation native-speed.

For one executable, leave the virtual board behind

Terminalbash
file ./hello-arm
qemu-arm -L /usr/arm-linux-gnueabihf ./hello-arm

User mode answers a deliberately smaller question

  • file should confirm the executable architecture, bitness, ABI, and whether it is dynamically linked before you select an emulator.

  • qemu-arm runs a 32-bit ARM Linux process; use the architecture-appropriate user emulator for a different binary, such as qemu-aarch64 for AArch64.

  • -L supplies 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 help before assuming the package is broken. QEMU 6.2 removed the old raspi2 and raspi3 aliases; current commands use raspi2b and raspi3b when those models are compiled in.

  • QEMU opens but prints nothing: confirm the kernel console name and baud rate, retain earlycon only 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 virt are not evidence for raspi2b.

  • 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.

Keep following the ARM boundary

Documentation used for the hardware claims