Raspbian "stretch" for Raspberry Pi 3 on QEMU

Wim Vanderbauwhede edited this page Feb 10, 2019 · 6 revisions

Raspbian "stretch" for Raspberry Pi 3 on QEMU

Raspbian "buster" stretch on QEMU, login prompt.

Date: 2018-10-12

This tutorial explains how to run the Raspbian Linux distribution for the Raspberry Pi 3 on QEMU, a generic and open source machine emulator and virtualizer.

QEMU supports many physical hardware platforms, and has recently added support for the Raspberry Pi 3 with the raspi3 model. However, there is currently no emulation of the BCM2835 USB controller, so there is no USB support and also, more critically, no networking support. Furthermore, the raspi3 model only works for 64-bit linux kernels, and the Raspbian kernel is 32-bit.

Therefore, in this tutorial we will use a different board model, the Arm Versatile board, versatilepb, to run Raspbian on QEMU.

QEMU version

  • Get QEMU 2.11.0 or later (I did not test a later version) from qemu.org

Raspbian image

QEMU Raspberry Pi Linux kernel and DTB

You need a separate Linux kernel (kernel-qemu-4.14.50-stretch) for the versatilepb board on QEMU, and the corresponding device tree blob (versatile-pb.dtb). This is a Raspberry Pi kernel that has been patched to run on the Arm Versatile board.

Running QEMU

With these preparations done, we can boot the Raspbian image on QEMU. We use the versatilepb board model (-M) and the arm1176 CPU model (-cpu). This board model supports at most 256MB of RAM (-m).

The -kernel and -dtb options take the relative paths to the kernel and dtb files.

The -serial stdio option redirects the boot output messages and the console to your terminal. You can control the log level using loglevel= in the -append string, which contains all options to be passed on to the kernel at boot time. On the physical Raspberry Pi, these options can be provided in the cmdline.txt file. Note also console=ttyAMA0, the Arm equivalent of console=ttyS0 on Intel machines.

In our case, the key option is root=/dev/sda2 which tells the kernel the location of the root partition to be mounted.

You can also use PARTUUID=... instead of /dev/sda2. PARTUUID means Partition Universally Unique Identifier. This is not needed for our use with QEMU but it is if you want to boot from a USB drive, because you can't rely on the name and need the unique partition identifier. If you use exactly the same image as I did then the PARTUUID is ee25660b-02. To get the actual PARTUUID for the Raspbian instance you downloaded, the easiest way is to look in the file cmdline.txt in the boot partition on the image file. In Linux, you can mount the partition following the approach as explained in my Debian tutorial. On MacOS you can just double-click on the image file. On Windows you can use 7Zip.

The memory card is modeled using

-drive file=2018-10-09-raspbian-stretch-lite.img,format=raw

Finally, the network is integrated in the board model, but we use the option

-redir tcp:5022::22      

This is a convenience option which lets you ssh into the guest using

$ ssh -p 5022 localhost

The complete invocation is:

$ qemu-system-arm \
   -kernel raspbian_bootpart/kernel-qemu-4.14.50-stretch \
   -dtb raspbian_bootpart/versatile-pb.dtb \
   -m 256 -M versatilepb -cpu arm1176 \
   -serial stdio \
   -append "rw console=ttyAMA0 root=/dev/sda2 rootfstype=ext4  loglevel=8 rootwait fsck.repair=yes memtest=1" \
   -drive file=2018-10-09-raspbian-stretch-lite.img,format=raw \
   -redir tcp:5022::22  \
   -no-reboot

When booting is finished, you will see a prompt

raspberrypi login:

You can now login with username pi and password raspberry. Start the ssh server:

$ sudo systemctl ssh start

You can now log in via ssh as well:

$ ssh -p 5022 pi@localhost
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.