There will be times when you will need to run your projects on a ‘virtual’ Raspberry Pi. Maybe you are too lazy to get up and plug power into your RasPi, maybe you are too savvy and hesitate to buy one or maybe you need some automation like we do in Isaax. With help of QEMU you can launch a virtual RasPi-like machine in minutes and though its barely possible to emulate real GPIO devices attached to the board, its still useful for prototyping and automated tests.

What is QEMU

QEMU is a machine emulator and helps running different (sometimes very exotic) boards on your PC without physically owning them. QEMU has a vast supported ARM-machines list, but you are not limited with it – you can ‘assemble’ and emulate most machines by just imitating their specs.

Installation

Unfortunately QEMU is not the kind of software, where you just

sudo apt install qemu
qemu-system-arm -M raspi2

…and watch your virtual RasPi boot. QEMU is ‘have you compiled it with those options enabled?’kind of software. Well, its still worth it and I’m going to help a bit here.

We’ll download the latest release and compile it with arm-systems support only (to speed things up):

$ wget https://download.qemu.org/qemu-2.12.0-rc0.tar.xz
$ tar xvJf qemu-2.12.0-rc0.tar.xz
$ cd qemu-2.12.0-rc0
$ ./configure --target-list=arm-softmmu,aarch64-softmmu
$ make

I’m on Ubuntu 16.04 but the steps should be similar for other platforms.

Preparing Raspbian OS image

That’s simple, just go ahead and grab the latest distribution (Stretch Lite):

$ wget https://downloads.raspberrypi.org/raspbian_lite_latest
$ mv raspbian_lite_latest raspbian_lite_latest.zip
$ unzip raspbian_lite_latest.zip
  Archive:  raspbian_lite_latest.zip
    inflating: 2018-03-13-raspbian-stretch-lite.img

2018-03-13-raspbian-stretch-lite.img – is the latest raspbian at the moment of writing.

Now its recommended to transform the raw image to QEMU’s qcow2 format:

$ qemu-img convert -f raw -O qcow2 2018-03-13-raspbian-stretch-lite.img raspbian-lite.qcow2

We can also give the image some free space:

$ qemu-img resize raspbian-lite.qcow2 +1G
Image resized.

Check if the image is OK:

$ qemu-img info raspbian-lite.qcow2 
image: raspbian-lite.qcow2
file format: qcow2
virtual size: 2.7G (2931818496 bytes)
disk size: 990M
cluster_size: 65536
Format specific information:
    compat: 1.1
    lazy refcounts: false
    refcount bits: 16
    corrupt: false

Getting the working kernel

We’ve downloaded and compiled QEMU, prepared Raspbian image and are ready to do something like qemu-system-arm -M raspi2 -hda raspbian-lite.qcow2. Oops, not yet. If you try to use raspi2 machine right away (and that is what everyone would actually expect) you’ll probably be staring at the void:

In fact, I wasn’t able to run qemu-system-arm -M raspi2 at all, I’ve tried multiple kernels, dtb’s etc – no luck.

There is one kernel out there though that proved to be working, so lets go ahead and download it:

$ curl https://github.com/dhruvvyas90/qemu-rpi-kernel/raw/master/kernel-qemu-4.4.34-jessie

Memorize the path to it for use in next section. And yes, we are going to use Jessie kernel with Stretch image.

Emulating RasPi

While its a pity we won’t be doing something as simple as qemu-system-arm -M raspi2, we are going to do something different. We are going to learn how to emulate a general RasPi-like machine instead.

Fill in the paths to the kernel and qcow image and run the following command:

    qemu-system-arm \
        -kernel /path/to/kernel-qemu-4.4.34-jessie \
        -append "root=/dev/sda2 panic=1 rootfstype=ext4 rw" \
        -hda /path/to/raspbian-lite.qcow2 \
        -cpu arm1176 \
        -m 256 \
        -machine versatilepb

This time you’ll hopefully see the boot:

Now lets breakdown the options used here.

  • -kernel – obviously we tell QEMU to use our downloaded kernel (since QEMU can’t run normal rasbian kernel)
  • -append – some options for the kernel: root partition, fs type etc
  • -hda – set the hard disk image, previously prepared with qemu-img
  • -machine – versatilepb – I couldn’t find what exactly VersatilePB is, but that’s the kind of machine that works with our kernel and disk image
  • -m – set available memory. Since we mimic RasPi with versatilepb machine, we use its maximum, which is 256M
  • -cpu – arm1176 – an ARMv6 cpu type

So, if everything went well – you now have a working RasPi-like virtual machine. You can do pretty much anything with it you would with a real RasPi but you can’t ssh to it and you won’t see it in your local network (but you can set this up). Of course it also doesn’t have GPIO and no interfaces but that will do for just launching Isaax Agent inside it.

Armed with this command and its options you can research available machines further, find freshier QEMU kernels or even compile them by yourself. Some people were able to run raspi2machine as I’ve noticed.

Guestfish and Isaax Agent

While experimenting with QEMU, I couldn’t find a way to do one simple thing: pass environment variables to the machine at start time. I needed that to be able to install Isaax Agent, and as it requires a project token it has to be somewhere inside the machine after start.

What I wanted to do was basically this:

curl -fsSL get.isaax.io | sh -s stable $ISAAX_TOKEN

But alas – no way to pass that variable from our host system.

I’ve spent many hours looking for a way to stick that token inside the machine and almost got desperate until suddenly was struck by the idea of mounting the disk image and copying the token as a file. If I could do this with a couple of commands and without any interaction – that would do.

And actually there is a way to do exactly that with a single command! Welcome guestfish – the guest filesystem shell tool, which can manipulate disk image files.

Now, on our PC, lets take raspbian-lite.qcow2 and create the token-file there:

sudo guestfish --rw -i -a raspbian-lite.qcow2 write /etc/isaax.token "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpX..."

Notice the sudo – this command works only with root privileges. Assuming the command produced no errors, we can launch our QEMU machine and log in. Now inside the machine I can type:

jwt=${cat /etc/isaax.token}; curl -fsSL get.isaax.io | sh -s stable $jwt

And that will start Isaax Agent installation.

Conclusion

QEMU is surely an important tool for the IoT industry and enthusiasts. Despite not catching the latest trends it is still the only(?) virtualizer emulating machine architecture and can be invaluable in IoT software development, prototyping and testing.

One can notice the significant rise of interest for this tool since the Raspberry era and lets hope it finally gets some fresh blood and development locomotion.


isaax

Isaax is a Continuous Delivery service for IoT devices. Update thousands of devices with 1 action. You can build IoT systems more easily.

Leave a Reply

Your email address will not be published. Required fields are marked *