|
|
@@ -0,0 +1,173 @@ |
|
|
# Running Ubuntu 16.04.1 armhf on Qemu |
|
|
|
|
|
This is a writeup about how to install [Ubuntu 16.04.1 Xenial Xerus](https://wiki.ubuntu.com/XenialXerus/ReleaseNotes) for the 32-bit hard-float ARMv7 (armhf) architecture on a Qemu VM via [Ubuntu netboot](http://cdimage.ubuntu.com/netboot/16.04.1/). |
|
|
|
|
|
The setup will create a Ubuntu VM with [LPAE](https://www.arm.com/products/processors/technologies/virtualization-extensions.php) extensions (generic-lpae) enabled. However, this writeup should also work for non-LPAE (generic) kernels. |
|
|
|
|
|
The performance of the resulting VM is quite good, and it allows VMs with >1G ram (compared to 256M on `versatilepb` and 1G on `versatile-a9`/`versatile-a15`). It also supports `virtio` disks whereas `versatile-a9`/`versatile-a15` only support SD cards via the `-sd` argument. |
|
|
|
|
|
## Get netboot files |
|
|
|
|
|
The netboot files are available on the official [Ubuntu mirror](http://ports.ubuntu.com/ubuntu-ports/dists/xenial/main/installer-armhf/current/images/generic-lpae/netboot/). The following commands will download the kernel (vmlinuz) and initrd (initrd.gz) in a new directory called `netboot`: |
|
|
|
|
|
```bash |
|
|
mkdir netboot |
|
|
cd netboot |
|
|
wget -r -nH -nd -np -R "index.html*" --quiet http://ports.ubuntu.com/ubuntu-ports/dists/xenial/main/installer-armhf/current/images/generic-lpae/netboot/ |
|
|
``` |
|
|
|
|
|
## Create a image file |
|
|
|
|
|
The following command creates a image file that will be used as a disk for the Ubuntu system: |
|
|
|
|
|
```bash |
|
|
qemu-img create -f qcow2 ubuntu.img 16G |
|
|
``` |
|
|
|
|
|
## Setup networking |
|
|
|
|
|
Installing Ubuntu via netboot requires an Internet connection. Therefore the Ubuntu VM requires a network intefaces that can use the Internet connection of the host system. The host systems needs to create a tuntap device for the VM and a bridge that will connect the tuntap interface with the Internet-facing interface. The bridge is called `br0` and the tuntap device for the Ubuntu VM will be `tap0`. |
|
|
|
|
|
```bash |
|
|
sudo ip tuntap add dev tap0 mode tap |
|
|
sudo ip link set up dev tap0 |
|
|
sudo ip link set tap0 master br0 |
|
|
``` |
|
|
|
|
|
Creating a bridge and adding the Internet-facing interface (e.g. `eth0`): |
|
|
|
|
|
```bash |
|
|
sudo ip link add br0 type bridge |
|
|
sudo ip link set eth0 master br0 |
|
|
``` |
|
|
|
|
|
Allow IP packet forwarding: |
|
|
|
|
|
```bash |
|
|
sudo sysctl -w net.ipv4.ip_forward=1 |
|
|
``` |
|
|
|
|
|
Start a DHCP server in the bridge so that the Ubuntu VM receives an IP address: |
|
|
|
|
|
```bash |
|
|
echo "subnet 192.168.0.0 netmask 255.255.255.0 { |
|
|
range 192.168.0.10 192.168.0.100; |
|
|
option routers 192.168.0.1; |
|
|
option domain-name-servers 208.67.222.222, 208.67.220.220; |
|
|
}" > qemu-dhcpd.conf |
|
|
sudo dhcpd -cf qemu-dhcpd.conf br0 |
|
|
``` |
|
|
|
|
|
## Start the netboot installation |
|
|
|
|
|
From the netboot directory (containing the netboot files `vmlinuz` and `initrd.gz`), run the following command: |
|
|
|
|
|
```bash |
|
|
qemu-system-arm \ |
|
|
-kernel vmlinuz \ |
|
|
-initrd initrd.gz \ |
|
|
-append "root=/dev/ram" \ |
|
|
-no-reboot \ |
|
|
-nographic \ |
|
|
-m 1024 \ |
|
|
-M virt \ |
|
|
-serial stdio \ |
|
|
-net nic \ |
|
|
-net tap,ifname=tap0,script=no,downscript=no \ |
|
|
-hda ubuntu.img |
|
|
``` |
|
|
|
|
|
The kernel should now boot into the Ubuntu installer within the terminal window where the command has been executed. |
|
|
|
|
|
## Extract the new kernel |
|
|
|
|
|
After the installation process has been finished, extract the kernel and initrd files from the new installed Ubuntu system. Mount the Ubuntu image: |
|
|
|
|
|
```bash |
|
|
qemu-img convert -f qcow2 -O raw ubuntu.img ubuntu-raw.img |
|
|
sudo losetup /dev/loop0 ubuntu-raw.img |
|
|
OFFSET=$(($(sudo fdisk -l /dev/loop0 |grep /dev/loop0p1 |awk '{print $3}')*512)) |
|
|
sudo mount -o loop,offset=$OFFSET /dev/loop0 /mnt |
|
|
``` |
|
|
|
|
|
Create a new directory `boot` for the new kernel and initrd files and copy them into it: |
|
|
|
|
|
```bash |
|
|
mkdir boot |
|
|
cp /mnt/initrd.img-4.4.0-38-generic-lpae |
|
|
cp /mnt/vmlinuz-4.4.0-38-generic-lpae boot |
|
|
``` |
|
|
|
|
|
Cleanup: |
|
|
|
|
|
```bash |
|
|
sudo umount /mnt |
|
|
sudo losetup -d /dev/loop0 |
|
|
rm ubuntu-raw.img |
|
|
``` |
|
|
|
|
|
*TODO*: Add working solution that does not require to convert the image file. |
|
|
|
|
|
## Start the Ubuntu VM |
|
|
|
|
|
The Ubuntu VM directory should now have the following structure: |
|
|
|
|
|
```bash |
|
|
├── boot |
|
|
│ ├── initrd.img-4.4.0-38-generic-lpae |
|
|
│ └── vmlinuz-4.4.0-38-generic-lpae |
|
|
├── netboot |
|
|
│ ├── initrd.gz |
|
|
│ └── vmlinuz |
|
|
└── ubuntu.img |
|
|
``` |
|
|
|
|
|
Start Qemu: |
|
|
|
|
|
```bash |
|
|
qemu-system-arm \ |
|
|
-kernel boot/vmlinuz-4.4.0-38-generic-lpae \ |
|
|
-initrd boot/initrd.img-4.4.0-38-generic-lpae \ |
|
|
-append "root=/dev/vda2 rootfstype=ext4" \ |
|
|
-no-reboot \ |
|
|
-nographic \ |
|
|
-m 1024 \ |
|
|
-M virt \ |
|
|
-serial stdio \ |
|
|
-monitor telnet:127.0.0.1:9000,server,nowait \ |
|
|
-net nic \ |
|
|
-net tap,ifname=tap0,script=no,downscript=no \ |
|
|
-drive file=ubuntu.img,if=virtio |
|
|
``` |
|
|
|
|
|
The following script can be used for starting the VM: |
|
|
|
|
|
```bash |
|
|
#!/bin/sh |
|
|
NET_IF=tap0 |
|
|
BRIDGE=br0 |
|
|
if ! grep --quiet $NET_IF /proc/net/dev;then |
|
|
echo "Creating ${NET_IF} device" |
|
|
sudo ip tuntap add dev $NET_IF mode tap |
|
|
sudo ip l s up dev $NET_IF |
|
|
fi |
|
|
if grep --quiet $BRIDGE /proc/net/dev;then |
|
|
sudo ip l s $NET_IF master $BRIDGE |
|
|
else |
|
|
echo "${BRIDGE} does not exist!" |
|
|
exit |
|
|
fi |
|
|
qemu-system-arm \ |
|
|
-kernel boot/vmlinuz-4.4.0-38-generic-lpae \ |
|
|
-initrd boot/initrd.img-4.4.0-38-generic-lpae \ |
|
|
-append "root=/dev/vda2 rootfstype=ext4" \ |
|
|
-no-reboot \ |
|
|
-nographic \ |
|
|
-m 1024 \ |
|
|
-M virt \ |
|
|
-serial stdio \ |
|
|
-monitor telnet:127.0.0.1:9000,server,nowait \ |
|
|
-net nic \ |
|
|
-net tap,ifname=tap0,script=no,downscript=no \ |
|
|
-drive file=ubuntu.img,if=virtio |
|
|
``` |