mathr / blog / #

Raspbian in QEMU

Even the latest QEMU warns that it can't boot Raspbian Jessie due to missing device drivers, but it seems (almost) all that is needed is to use a different kernel. Here follows a somewhat raw dump of what I did to get an emulated Raspbian Jessie up and running on my amd64 host machine. It's based mostly on these pages:

host $ sudo aptitude install -t jessie-backports qemu-system-arm
host $ git clone https://github.com/dhruvvyas90/qemu-rpi-kernel.git
host $ cp qemu-rpi-kernel/kernel-qemu-4.4.12-jessie kernel-qemu
host $ wget http://director.downloads.raspberrypi.org/raspbian_lite/images/raspbian_lite-2016-05-31/2016-05-27-raspbian-jessie-lite.zip
host $ unzip 2016-05-27-raspbian-jessie-lite.zip
host $ cp 2016-05-27-raspbian-jessie-lite.img raspbian.img
host $ head -c $((8 * 1024 * 1024 * 1024)) /dev/zero >> raspbian.img
host $ /sbin/fdisk raspbian.img
# resize the second partition, using the same start sector

Welcome to fdisk (util-linux 2.25.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.


Command (m for help): p
Disk raspbian.img: 9.3 GiB, 9977200640 bytes, 19486720 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x6fcf21f3

Device        Boot  Start     End Sectors  Size Id Type
raspbian.img1        8192  137215  129024   63M  c W95 FAT32 (LBA)
raspbian.img2      137216 2709503 2572288  1.2G 83 Linux


Command (m for help): d
Partition number (1,2, default 2): 2

Partition 2 has been deleted.

Command (m for help): n
Partition type
   p   primary (1 primary, 0 extended, 3 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (2-4, default 2): 2
First sector (2048-19486719, default 2048): 137216
Last sector, +sectors or +size{K,M,G,T,P} (137216-19486719, default 19486719): 

Created a new partition 2 of type 'Linux' and of size 9.2 GiB.

Command (m for help): w
The partition table has been altered.
Syncing disks.

host $ mkdir mnt
host $ sudo mount -o offset=$((512 * 137216)) -t ext4 raspbian.img mnt
# note that the above uses the numbers output by fdisk, which may differ
host $ sudo nano mnt/etc/ld.so.preload
# comment out all lines
host $ sudo nano mnt/etc/fstab
# comment out /dev/mm* lines
host $ sudo umount mnt
host $ cat >> start.sh <<EOF
#!/bin/sh
qemu-system-arm -kernel kernel-qemu -cpu arm1176 -m 256 -M versatilepb \
  -serial stdio -append "root=/dev/sda2 rootfstype=ext4 rw" -hda raspbian.img
EOF
host $ chmod +x start.sh
host $ ./start.sh
qemu login pi:raspberry
qemu $ sudo resize2fs /dev/sda2
qemu $ sudo nano /etc/dphys-swapfile
CONF_SWAPSIZE=2048
qemu $ sudo reboot
# wait for dd to finish creating swap on next boot
qemu $ df -h .
Filesystem      Size  Used Avail Use% Mounted on
/dev/root       9.1G  2.8G  6.0G  32% /
qemu $ free -m
             total       used       free     shared    buffers     cached
Mem:           248        236         12          4          5        212
-/+ buffers/cache:         18        230
Swap:         2047          0       2047

So this gives a raspi emulation with some free space to play with and enough virtual memory to compile demanding things. A few flaws though: (a QEMU bug) can't allocate more than 256MB RAM to the emulation and swap will be slow, and the emulated CPU is an ARMv6 while pi3 has ARMv7. Not sure whether QEMU supports ARMv7, and if it does I don't know which -cpu flag to use. Work in progress!

I haven't done any benchmarks yet, but it feels a lot slower than a real Pi 3, so I'll probably not use this for anything after all.