A lot of people are interested in a Raspberry Pi and want to get some idea about the operating system running on Pi without the need to buy a Pi first. I actually searched for a convenient way to test a backup script called raspiBackup I wrote for the Raspberry Pi. A nice way to evaluate Raspbian or to run any tests is to use QEMU to emulate the Raspberry Pi. Note that special Pi hardware like GPIO et al cannot be simulated. It's just the processor which is simulated. You need a Raspbian Image and a system with Linux or Windows.  Today I configured my system to run a Pi in QEMU and the following article will explain step by step how I installed and configure QVM on my Debian based Linux. The image has a networking connection right after startup and will use the existing host network connection  with NAT. Finally a script is provided which executes the steps described and simplifies the image creation process.


1. Quickstart


1.1 Installation of QEMU

Prerequisite:  Host CPU supports hardware virtualisation. Test it with 
egrep '^flags.*(vmx|svm)' /proc/cpuinfo
If you don't get an output you most probably cannot run the ARM emulation.
a) sudo apt-get install kvm qemu qemu-kvm-extras

1.2 Download of the Raspbianimage and the Linux kernel for qemu 

a) wget http://downloads.raspberrypi.org/raspbian/images/2012-12-16-wheezy-raspbian/2012-12-16-wheezy-raspbian.zip
b) unzip  2012-12-16-wheezy-raspbian.zip
c) wget http://xecdesign.com/downloads/linux-qemu/kernel-qemu

1.3 Modify image so it can start with qemu

a) file  2012-12-16-wheezy-raspbian.zip
Multiply the startsector of partition 2 with 512 and use this as the offset in the following command
b) sudo mount 2012-12-16-wheezy-raspbian.zip -o offset=62914560 /mnt
c) sudo nano /mnt/etc/ld.so.preload
Comment out the first line and insert # in front of the line
d) sudo umount /mnt

1.4 Start Image

sudo qemu-system-arm -kernel kernel-qemu -cpu arm1176 -m 256 -M versatilepb -no-reboot -append "root=/dev/sda2 panic=1" -hda 2012-12-16-wheezy-raspbian.img -net nic -net tap,ifname=tap0,vlan=0 

1.5 Logon and configure

a) Logon with userid pi and password raspberry
Change the keyboard layout and time zone accordingly. Disk resizse doesn't work with raspi-config. See below for instructions.
d) startx


Now you can tes the simulated Pi. Note there is not much free space on the disk.
If you want do use the whole host screen for your Pi use <CTRL><ALT>f. The same keys will revert the setting. <CTRL> <ALT>2 opens a QEMU monitor which may be interesting for people who whant to understand the internals of QEMU. <CTRL><ALT>1 opens the normal console window again.

2. Resize the virtual disk


The virtual disk of the distributed Raspbian image is about 2GB and ist mostly used. If you want to increase the disk size follow the follwoing steps:

2.1  Create a virtual qcow disk

qcow disks use real disk space only if the virtual disk needs this space. As an alternative the current img disk can be expanded but will use the virtual disk space also on the host disk even it's not fully used.
a) sudo shutdown -h now (on Raspberry guest)
b) qemu-img convert -f raw -O qcow2 2012-12-16-wheezy-raspbian.img raspbian.qcow (on host)

2.2 Increase the size of the virtual disk

a) qemu-img resize raspbian.qcow +6G (on host)
b) sudo qemu-system-arm -kernel kernel-qemu -cpu arm1176 -m 256 -M versatilepb -no-reboot -append "root=/dev/sda2 panic=1" -hda
raspian.qcow -net nic -net tap,ifname=tap0,vlan=0  (on host)
c) No use raspi-config to resize the virtual sd card or execute steps d-f
d) PART_START=$(parted /dev/sda -ms unit s p |grep “^2″ | cut -f 2 -d:); echo -e " p\nd\n2\nn\np\n2\n$PART_START\np\n\nw\n" | sudo fdisk /dev/sda (on Raspberry guest)
e) sudo shutdown -r now (on Raspberry guest)
f) sudo resize2fs /dev/sda2 (on Raspberry guest)

2.3 Definition on /dev/mmcblk0px

Some programs need /dev/mmcblk0p1 and /dev/mmcblk0p2. Create following definitions in /etc/udev/rules.d/90-qemu.rules to get them created at boot time:
KERNEL=="sda", SYMLINK+="mmcblk0"
KERNEL=="sda?", SYMLINK+="mmcblk0p%n"
KERNEL=="sda2", SYMLINK+="root"

3. Script to prepare an image for qemu emulator

If you have to convert multiple images the following script written by me will speed up the preparation process and execute the preparation steps mentioned above.


4. Network connection setup for the KVM Images

In order to allow qemu to connect via the hostsystem to the external network there has to exist a bridge and you have to connect your existing network interface eth0 to a bridge. I used following definitions in /etc/network/interfaces

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet manual

auto br0
iface br0 inet dhcp
bridge_ports eth0
   bridge_stp off
   bridge_fd 0
   bridge_maxwait 0

5. Start a KVM image

I want to get my KVM image to get the same IP address all the time. So it's important to use the same MAC all the time. I use the following script to get this done:

DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
if [ -e $F ]; then
    if grep -q "^$1 " $F; then
        mac=$(grep "^$1 " $F | cut -d ' ' -f 2)
        echo "Reusing mac $mac for $1"
if (( ! found )); then
    # generate a random mac address for the qemu nic
    mac=$(printf 'DE:AD:BE:EF:%02X:%02X\n' $((RANDOM%256)) $((RANDOM%256)))
    echo "$1 $mac" >> $F
    echo "Generated mac $mac for $1"
sudo qemu-system-arm -kernel $DIR/kernel-qemu -cpu arm1176 -m 256 -M versatilepb -no-reboot -append "root=/dev/sda2 panic=1" -hda $DIR/$1 -net nic,macaddr=$mac  -net tap



HOWTO: Virtual Raspbian on Qemu in Ubuntu Linux 12.10

QEMU – Emulating Raspberry Pi the easy way (Linux or Windows!)

Emulate a Raspberry Pi with Qemu+ KVM

Howto setup Raspberry Pi emulation with QEMU on LInux or Windows

KVM/ARM: The Design and Implementation of the Linux ARM Hypervisor


Gotchas with QEMU emulation and Raspberry

I use the emulation primaily to test raspiBackup.sh. The tst of the restore of a backuped image requires direct access from the host to an empty image. This is possible when following commands are executed

sudo losetup -d /dev/loop0
sudo losetup /dev/loop0 raspiBackupRestore.img
kpartx -av /dev/loop0

Now it's possible to access /dev/loop0 from the host and to restore the backup. But unfortunately the restore of the tar and rsync backup worked fine but the started VM reported filesystem errors. In contrast the dd backup didn't create any issues. It took me some time to find out the root cause: I use a quite old raspbian image to backup which was created somewhere in 2014. That's why the image uses the contents of the fake-hwclock to get it's actual time and that's in 2014 (It's now 2015 already). tar and rsync restore change the filesystem of the image and write the actual date the restore was executed in the filesystem so the booting image detects that the filesystem was changed in the future and asks to execute fsck. The dd restore doesn't change the filesystem so there is no issue during boot. The fix of this was to execute the following commands at the end of the restore

mount /dev/loop0p2 /mnt
echo $(date +"%Y-%m-%d %T") > /mnt/etc/fake-hwclock.data
umount /mnt

That way the fake-hwclock of the old raspbian images was set to the actual time and the image starts not any more in 2014.

Add comment

Spam Kommentare sind sinnlos denn sie werden nicht publiziert. Sie werden vor der Publizierung auf Spam geprüft. Deshalb kann es aber etwas dauern bis ein Kommentar sichtbar wird.
Die eMail ist optional und nicht öffentlich sichtbar Sie wird u.U. genutzt um offline zu kommunizieren

Spam comments are useless because they will not be published. Before they are published they are checked for spam. Therefore it may take some time until the comment is published.
eMail is optional and hidden and may be used to contact you offline