Qemu Raspberry Pi Emulator

Ubuntu 12.04

$ sudo add-apt-repository ppa:linaro-maintainers/tools

$ sudo apt-get update

$ sudo apt-get install qemu-system qemu-user

$ qemu-arm -cpu ? | grep arm1136
  arm1136
  arm1136-r2

$ wget -c https://web.archive.org/web/20150214035104/http://www.xecdesign.com/downloads/linux-qemu/kernel-qemu

$ wget -c http://downloads.raspberrypi.org/raspbian/images/raspbian-2014-12-25/2014-12-24-wheezy-raspbian.zip

$ unzip 2014-12-24-wheezy-raspbian.zip

$ sudo apt-get install kpartx

Remarque : Qemu a besoin d’un noyau Linux spécifique xecdesign.com/compiling-a-kernel/

Dans le cas de Raspbian, l’image système n’est pas directement utilisable par Qemu et nécessite quelques modifications. Les images système du Raspberry Pi contiennent un disque complet avec un MBR et plusieurs partitions (deux dans le cas de Raspbian). Les périphériques correspondant aux partitions peuvent ensuite être générés kpartx.

$ sudo kpartx -av 2014-12-24-wheezy-raspbian.img

On a créé les périphériques /dev/mapper/loop0p1 et /dev/mapper/loop0p2 correspondant aux deux partitions contenues dans l’image 2014-12-24-wheezy-raspbian.img. La deuxième partition contient la racine du système.

$ sudo mkdir /mnt/loop0p2
$ sudo mount /dev/mapper/loop0p2 /mnt/loop0p2

La première modification à apporter consiste à désactiver l’utilisation de la bibliothèque cofi_rpi, propre au Raspberry Pi et inutilisable dans Qemu. Pour cela, il faut éditer le fichier /mnt/loop0p2/etc/ld.so.preload et mettre en commentaire la ligne suivante :

$ sudo vim /mnt/loop0p2/etc/ld.so.preload
#/usr/lib/arm-linux-gnueabihf/libcofi_rpi.so

La seconde modification consiste à corriger une différence de nommage des périphériques de stockage entre le noyau utilisé pour Qemu et le noyau de Raspbian. Cette différence est susceptible de générer quelques erreurs. Pour corriger ce problème, il faut éditer le fichier /mnt/loop0p2/etc/udev/rules.d/90-qemu.rules avec le contenu suivant :

$ sudo vim /mnt/loop0p2/etc/udev/rules.d/90-qemu.rules
KERNEL=="sda", SYMLINK+="mmcblk0"
KERNEL=="sda?", SYMLINK+="mmcblk0p%n"
KERNEL=="sda2", SYMLINK+="root"

Le noyau utilisé par Qemu voit le disque /dev/sda, alors que le “vrai” noyau de la Raspbian voit /dev/mmcblk0. Cette modification permet de créer des liens symboliques pour être plus proche du vrai Raspberry Pi.

Une fois ces ajustements opérés, on démonte la partition loop0p2 et on supprime les périphériques précédemment générés :

$ sudo umount /mnt/loop0p2
$ sudo kpartx -d 2014-12-24-wheezy-raspbian.img

Maintenant, on va démarrer l’émulation du Raspberry Pi avec la commande suivante :

$ 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-12-24-wheezy-raspbian.img

$ 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-12-24-wheezy-raspbian.img    
...
Raspbian GNU/Linux 7 raspberrypi ttyAMA0

raspberrypi login: pi
password: raspberry

$ loadkeys fr
$ sudo raspi-config
$ uname -a
Linux raspberrypi 3.10.26+ #2 Fri Jan 17 22:13:59 EST 2014 armv6l GNU/Linux

Si on veut une connexion en ssh :

$ 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-12-24-wheezy-raspbian.img -redir tcp:5022::22

$ ssh -p 5022 pi@localhost

Connexion Internet

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

Verify whether DHCP server is runing :

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

Verify bridge interface is created, and it is configured to DHCP gateway :

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)  
  1. Bind eth0 to virbr0
$ brctl addif virbr0 eth0
  1. Create a tap interface and make it up
$ tunctl -t tap0 && ifconfig tap0 up
  1. Bind tap0 to virbr0
$ brctl addif virbr0 tap0
  1. Make sure tap0&eth0 are binded :
root@unknown:~# brctl show
bridge name bridge id  STP enabled interfaces
virbr0  8000.1a9819c54ba8 yes       eth0
                                    tap0
  1. My configuration:
root@unknown:~# ifconfig
eth0      Link encap:Ethernet  HWaddr 48:84:3c:c6:33:34 
...
lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0


tap0      Link encap:Ethernet  HWaddr 1a:98:19:c5:4b:a8 
...
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
...
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
  1. Brought qemu with NIC :
$ 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.stackexchange.com justtrythis.blogspot.fr