Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save kokoye2007/e531f9cc8a2f6901d1f76d04c23f4dfd to your computer and use it in GitHub Desktop.
Save kokoye2007/e531f9cc8a2f6901d1f76d04c23f4dfd to your computer and use it in GitHub Desktop.

Revisions

  1. @takeshixx takeshixx revised this gist Sep 29, 2016. 1 changed file with 7 additions and 0 deletions.
    7 changes: 7 additions & 0 deletions ubuntu-xenial-armfh-qemu.md
    Original file line number Diff line number Diff line change
    @@ -58,6 +58,13 @@ echo "subnet 192.168.0.0 netmask 255.255.255.0 {
    sudo dhcpd -cf qemu-dhcpd.conf br0
    ```

    Set router IP on bridge interface:

    ```bash
    ip addr add 192.168.0.1/24 dev br0
    ip link set up dev br0
    ```

    ## Start the netboot installation

    From the netboot directory (containing the netboot files `vmlinuz` and `initrd.gz`), run the following command:
  2. @takeshixx takeshixx created this gist Sep 29, 2016.
    173 changes: 173 additions & 0 deletions ubuntu-xenial-armfh-qemu.md
    Original file line number Diff line number Diff line change
    @@ -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
    ```