Emulating a Raspberry Pi on a Linux Computer

Hello there,

Wish you all a very Happy New Year 2017!

In this post, I’ll show how you can emulate a Raspberry Pi on your Linux (Debian-based) system (I don’t know whether this will work on Windows, haven’t  used it any ages).

The short backstory, I enrolled in the 1-month long “A developer’s Guide to the Internet of Things (IoT)” offered by IBM on Coursera. There was a need to use a Raspberry Pi to complete a few assignments. Since I was uninterested to get a new one nor invest a Raspberry Pi, here’s what I found after a few Google searches. This method is same as virtualizing any other operating system, but the steps involved is different.

This post will guide you through setting up the virtualization of Raspbian (the Debian flavor for Raspberry Pi) and also connect the emulation to the internet.

There are three steps to get things done: download raspbian, setup the QEMU emulator and compile a QEMU ready kernel to compile.

Step 1 – Getting Raspbian

You can get a distribution of Raspbian from here. Please note that the distribution needs to Wheezy or Jessie based. This post works well with Raspbian Jessie.

Step 2 – Installing QEMU

QEMU is an OpenSource emulation software that includes processors ranging from the Raspberry Pi’s ARM processor to the modern architectures of amd64 and i386. Installing is very simple on Linux and it can be done using the package manager. For Ubuntu and other Debian-based distributions, the command is

sudo apt-get update
sudo apt-get install qemu-system-x86

To check the correct installation, do as follow:

qemu-system-arm --version
QEMU emulator version 2.0.0 (Debian 2.0.0+dfsg-2ubuntu1.19), Copyright (c)
 2003-2008 Fabrice Bellard

To emulate Jessie image with 4.x.xx kernel in this repo, steps differ slightly compared to a lot of (and standard) wheezy emulating guides on the internet.

In order to prepare your image for the first time, you will need a Linux box (or any other OS that can mount an ext4 file from a .img file). Copy your newly downloaded Raspberry Pi image to a current directory and unzip it. Then rename it to rpi.img (if you want to have an easy life copy/pasting the rest of tutorial). You might keep the original zip file intact, in case you screw up the image, you would not be forced to re-download that 1GB file.

Step 3 – QEMU-Ready Raspberry Pi Kernel

You can download the QEMU-Ready R-Pi’s kernel from here.  Or you can simply clone the git repository in the directory that you just created using the command below:

  1. fdisk -l <image-file>. It should show output like this one:
Disk 2015-11-21-raspbian-jessie.img: 3.7 GiB, 3934257152 bytes, 7684096 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: 0xea0e7380

Device                          Boot  Start     End Sectors  Size Id Type
2015-11-21-raspbian-jessie.img1        8192  131071  122880   60M  c W95 FAT32 (LBA)
2015-11-21-raspbian-jessie.img2      131072 7684095 7553024  3.6G 83 Linux

The filesystem (.img2) starts at sector 131072, which equals 512 * 131072 = 67108864 bytes. Use this as the offset, ie. mount -v -o offset=67108864 -t ext4 your-image-file.img /path/to/mnt/

  1. cd /path/to/mnt
  2. sudo nano ./etc/ld.so.preload
  3. Comment out every entry in it, Ctrl-x » Y to save and exit
  4. sudo nano ./etc/fstab
  5. Comment out entries containing,/dev/mmcblk Ctrl-x » Y to save and exit
  6. cd ~
  7. sudo umount /path/to/mnt

Once done with these changes, you can emulate it on Qemu by:

Step 5 – Emulating

Once QEMU is installed and you have necessary files for emulation as mentioned above, follow the following steps to emulate RPi.

Run:

qemu-system-arm -kernel kernel-qemu \
                -cpu arm1176 \
                -m 256 \
                -M versatilepb \
                -no-reboot \
                -serial stdio \
                -append "root=/dev/sda2 panic=1 rootfstype=ext4 rw init=/bin/bash" \
                -hda rpi.img
    You should get prompt ‘#’ (bash) at the end of processing.
  1. Edit /etc/ld.so.preload by commenting (with the symbol) the 1st line, e.g.:
    # /usr/lib/arm-linux-gnueabihf/libcofi_rpi.so
    #
    # ... rest of the file
    
  2. Edit /etc/udev/rules.d/90-qemu.rules by adding the following lines:
    KERNEL=="sda", SYMLINK+="mmcblk0"
    KERNEL=="sda?", SYMLINK+="mmcblk0p%n"
    KERNEL=="sda2", SYMLINK+="root"
    
  3. Run:
    sudo poweroff
  4. Re-emulate by running:
    qemu-system-arm -kernel kernel-qemu \
                    -cpu arm1176 \
                    -m 256 \
                    -M versatilepb \
                    -serial stdio \
                    -append "root=/dev/sda2 panic=1 rootfstype=ext4 rw"
                    -drive "file=rpi.img,index=0,media=disk,format=raw

     

Steps 6 – Connection to the Internet

Follow this article and brought your virtual RaspberryPI,  it will have IP but you can’t access the Internet from RaspberryPI. Ok no worry, that’s what this article about. Now shutdown the RaspberryPI, and  do the following in your host OS:

Install the following packages:

  • brctl — ethernet bridge administration
sudo apt-get install bridge-utils
  • tunctl — create and manage persistent TUN/TAP interfaces
sudo apt-get install uml-utilities
  • libvirt — visualization management system. This will automatically setup a DHCP server and a bridge(virbr0).
sudo apt-get installqemu-kvm libvirt-bin

make sure, DNS server & bridge automatically configured:

root@unknown:~# ps -ef | grep dns
121       1377     1  0 Dec13 ?        00:00:00 /usr/sbin/dnsmasq -u \
libvirt-dnsmasq --strict-order --bind-interfaces\
 --pid-file=/var/run/libvirt/network/default.pid\
 --conf-file= --except-interface lo --listen-address 192.168.122.1\
 --dhcp-range 192.168.122.2,192.168.122.254\
 --dhcp-leasefile=/var/lib/libvirt/dnsmasq/default.leases\
 --dhcp-lease-max=253 --dhcp-no-override

root@unknown:~# ifconfig virbr0
virbr0    Link encap:Ethernet  HWaddr 62:80:41:0f:0b:56  
          inet addr:192.168.122.1  Bcast:192.168.122.255  
Mask:255.255.255.0
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:619 errors:0 dropped:0 overruns:0 frame:0
          TX packets:685 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:44276 (44.2 KB)  TX bytes:51576 (51.5 KB)  

root@unknown:~# brctl show
bridge name bridge id  STP enabled interfaces 
virbr0  8000.000000000000 yes  

How to:

  1. Bind eth0 to virbr0
  2. create a tap interface and make it up
  3. Bind tap0 to virbr0
  4. make sure it bound successfully
  5. Brought up the Raspberry Pi with tap0
root@unknown:~# brctl addif virbr0 eth0
root@unknown:~# tunctl -t tap0 && ifconfig tap0 up
Set 'tap0' persistent and owned by uid 0
root@unknown:~# brctl addif virbr0 tap0
root@unknown:~# ifconfig
eth0      Link encap:Ethernet  HWaddr 48:84:3c:c6:33:34  
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:20070 errors:0 dropped:0 overruns:0 frame:0
          TX packets:20070 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:1697375 (1.6 MB)  TX bytes:1697375 (1.6 MB)

tap0      Link encap:Ethernet  HWaddr 1a:98:19:c5:4b:a8  
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:500 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

virbr0    Link encap:Ethernet  HWaddr 78:84:3c:e6:38:98  
          inet addr:192.168.122.1  Bcast:192.168.122.255  Mask:255.255.255.0
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:619 errors:0 dropped:0 overruns:0 frame:0
          TX packets:685 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:44276 (44.2 KB)  TX bytes:51576 (51.5 KB)

wlan0     Link encap:Ethernet  HWaddr cd:af:76:c4:6d:99  
          inet addr:192.168.1.5  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: ff70::ceff:78dd:fdc1:6d95/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1338984 errors:0 dropped:0 overruns:0 frame:0
          TX packets:997145 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:1521507128 (1.5 GB)  TX bytes:142971835 (142.9 MB)

root@unknown:~# brctl show
bridge name bridge id  STP enabled interfaces
virbr0  8000.1a9819c54ba8 yes  eth0
       tap0
root@unknown:~# qemu-system-arm -kernel kernel-qemu -cpu arm1176 -m 256\ 
-M versatilepb -no-reboot -serial stdio -append "root=/dev/sda2 panic=1\ 
rootfstype=ext4 rw" -hda 2014-09-09-wheezy-raspbian.img -net nic,\
macaddr=00:16:3e:00:00:01 -net tap,ifname=tap0,script=no,downscript=no

RaspberryPI interface set to DHCP:

pi@vrpi:~$ cat /etc/network/interfaces 
auto lo

iface lo inet loopback
iface eth0 inet dhcp

allow-hotplug wlan0
iface wlan0 inet manual
wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf
iface default inet dhcp
pi@vrpi:~$

 

This is a compilation from various sources and the credit goes to the original writers of the content.

References:

  1. http://embedonix.com/articles/linux/emulating-raspberry-pi-on-linux/
  2. http://justtrythis.blogspot.in/2014/12/share-internet-with-virtual-raspberrypi.html?m=1
  3. https://github.com/dhruvvyas90/qemu-rpi-kernel/wiki/Emulating-Jessie-image-with-4.x.xx-kernel

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s