Step-by-step Using qemu to Boot an Emulated Odroid

From odroid US
Revision as of 13:42, 8 February 2016 by Osterluk (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

NOTE: This has not been third-party tested yet. You can be the first!

This tutorial is for Linux Developers using Linux hosts. It is really not for Windows hosts -- although you can certainly work through this tutorial on a virtual machine guest.

It was tested on a "clean" Debian 6 machine, a VMWare virtual machine. You can find your own copy here: Debian6t VM VMWare Player is free as well: VMWare Player


If you don't know what qemu is for, look around on Wikipedia.

Is it good for everything? No. Is a hammer good for sawing? Not so much. Consider qemu as another tool for your toolchest.

If you need to develop code for a platform that is not yet available, qemu might help. Also, if you are doing certain kernel work, it can be handy.

Generally, your root file system doesn't care which kernel you use. This tutorial uses a kernel configured for a vexpress-a9 platform (TBD. check that exact name). You can boot root file systems meant for odroid without changes.

It is possible to allocate a large amount of RAM to the emulated machine, and it is possible, but not necessarily faster to emulate multiple cores.


  • You need a Linux host (or virtual machine) running a Debian-based distribution: Debian, Ubuntu, Mint, Knoppix, etc.
  • The example file set will let you boot an emulated machine, without any odroid hardware
  • Overview

    We are going to:

  • Do some setup on the host
  • Download the example files and extract them
  • Build qemu if required
  • Create a root file system partition image from a root file system tarball
  • Boot the system in a simple way
  • Configure a network bridge
  • Boot the system with full network support

    Interesting Links

    These are some of the good references I used:

    tinkering-is-fun tinkering-is-fun

    Host Setup

    Make sure you have the neccessary programs installed

    # update the list of available packages
    # as root:
    apt-get update
    sudo apt-get install libpixman-1-dev zlib1g-dev libglib2.0-dev shtool build-essential

    Download Example Files

    You can use your browser, or use web get to get the example files tarball.

    #Create a working folder, and move into it.
    mkdir odroidu2
    cd odroidu2/
    # Get the example files
    tar -xvf qemu-example.tgz

    Here are the files we now have:

  • zImage A kernel built for vexpress-a9 machine, from linux-3.2 source. That machine will not build on HK sources at this point.
  • rootfs.tar.gz A root file system tarball, from the buildroot/busybox tutorial
  • rootfs-buildroot.ext2 A root file system partition image, converted from rootfs.tar.gz
  • launch-no-bridge A simple script to launch with the root file system isolated on its own virtual LAN
  • launch A more involved launch script that uses a network bridge for full networking support by sharing the host network interface
  • launch-ubuntu Launches on rootfs-ubuntu.ext4 that you can extract from your favorite SD-Card image
  • vexpress_defconfig default kernel config for linux-3.2.0
  • vexpress_odroid_qemu_defconfig kernel config I used for this tutorial, created zImage with it.

    Check for any Existing Qemu

    See if you already have qemu installed:

    qemu-system-arm --version

    QEMU PC emulator version 0.12.5 (Debian 0.12.5+dfsg-3squeeze1), Copyright (c) 2003-2008 Fabrice Bellard

    See if the cortex-a9 is supported:

    qemu-system-arm -cpu ? | grep cortex-a9


    OK, we at least have the required CPU. Now check the machine type:

    qemu-system-arm -M ? | grep vexpress-a9

    On newer releases, there may be a new-enough qemu. I see v2.1.2 is current on Debian Jessie

    sudo apt-get install qemu

    Did not find a match, we need a newer build of qemu -- and we need to build it from source. See the next section.

    Building Qemu

    First, we need to install some dependant packages

    sudo apt-get install libpixman-1-dev zlib1g-dev libglib2.0-dev shtool build-essential

    Get the qemu source

    Download the source and expand it:

    cd $HOME
    mkdir qemu-build
    cd qemu-build
    # note: qemu-2.5.0 is available, but not yet tested for this example
    tar -xvf qemu-1.4.0.tar

    Configure and Build

    Now configure qemu and build it. If you use the Debian6t VMWare Virtual Machine, you need to allocate 2GB or so of memory. The build will fail otherwise. The default of 384MB and 1GB failed each for me.

    Note: If you just want to have qemu-arm-static, so you can run individual ARM binaries or to bootstrap Debian, then you can build a subset of the whole package.

    Build statically-linked qemu-arm package like this:

    cd $HOME/qemu-build/qemu-1.4.0
    ./configure --prefix=/usr/local --static --disable-kvm --target-list=arm-linux-user
    sudo make install

    See where the qemu-arm binary was installed to: (I see it in /usr/local/bin)

    which qemu-arm

    Rename the file to denote that it is statically linked:

    # adjust the path depending on where your system installed the qemu-arm binary
    sudo mv /usr/local/bin/qemu-arm /usr/local/bin/qemu-arm-static

    If you are working through this tutorial just to get qemu-arm-static, you can stop now as the remaining sections have to do with emulating a whole ARM system.

    Build again to get a dynamically linked qemu-system-arm, the full-system ARM emulator.

    cd $HOME/qemu-build/qemu-1.4.0
    ./configure --enable-system --prefix=/usr/local --disable-kvm --target-list=arm-linux-user 
    sudo make install

    Check the version to see if we are properly installed:

    qemu-1.4.0$ qemu-system-arm --version

    QEMU emulator version 1.4.0, Copyright (c) 2003-2008 Fabrice Bellard

    OK. Make sure our machine is included:

    qemu-system-arm -M ? | grep vexpress

    vexpress-a9 ARM Versatile Express for Cortex-A9 vexpress-a15 ARM Versatile Express for Cortex-A15

    Nice. There <could> be a machine built for odroid, but so far I haven't heard of one. There is a project going on to build a machine for Rasperry Pi that can run unmodified kernels.

    We are done with the build files. They can be deleted.

    Create Root File System Partition Image

    Yes, there is a distinction between a partition image and a tarball of the partition contents. The kernel will want to mount a filesystem. It doesn't know how to mount just a tarball.

    All we need is a small amount of space to hold the buildroot/busybox root file system. 200M is OK. You can change this as needed, of course.

    cd $HOME/odroidu2
    qemu-img create rootfs-buildroot.ext2 200M

    Formating 'rootfs-buildroot.ext2', fmt=raw, size=204800 kB

    sudo mkfs.ext2 rootfs-buildroot.ext2
    mke2fs 1.41.12 (17-May-2010)
    rootfs-buildroot.ext2 is not a block special device.
    Proceed anyway? (y,n) y
    Filesystem label=
    OS type: Linux
    Block size=1024 (log=0)
    Fragment size=1024 (log=0)
    Stride=0 blocks, Stripe width=0 blocks
    51200 inodes, 204800 blocks
    10240 blocks (5.00%) reserved for the super user
    First data block=1
    Maximum filesystem blocks=67371008
    25 block groups
    8192 blocks per group, 8192 fragments per group
    2048 inodes per group
    Superblock backups stored on blocks: 
    	8193, 24577, 40961, 57345, 73729
    Writing inode tables: done                            
    Writing superblocks and filesystem accounting information: done

    Now loop mount the partition image file

    mkdir mnt
    sudo mount -o loop rootfs-buildroot.ext2 mnt

    And expand the root file system image tarball into it

    cd mnt
    sudo tar -xvzf ../rootfs.tar.gz
    # take a look around, if you like
    cd ../
    sudo umount ./mnt


    Now try the simplest thing. Launch without setting up a network bridge. Here is a simple script to make things easier:

    #! /bin/sh
    # filename: launch-no-bridge
    # Set environment variables to make it easier to change
    export ROOTFS=rootfs-buildroot.ext2
    export NETWORK="-net nic -net user"
    export KERNEL="-kernel zImage "
    qemu-system-arm -append "root=/dev/mmcblk0 rw physmap.enabled=0 console=ttyAMA0" -M vexpress-a9 $KERNEL -sd $ROOTFS  $NETWORK -nographic

    Launch it like this:


    It looks just like a normal boot. The username is root, no password.

    Networking Setup

    Sorry, but the tutorial is rough from here on. I have other things I should be working on...

    If you play with your network settings, be prepared to loose internet connectivity -- you may have to restart networking to get back on the net. A better approach may be to bridge a second network interface to the tap for qemu target. At least you would keep your primary network connection.

    The qemu-1.4 "bridge-helper" <should> work, but I'm just stuck finding the right incantations... I used a manual networking setup method.

    The command line options will work if you get your host network set up properly. It takes some fiddling. Sorry. (I could use some help here)

    This link might help you with the general concepts:

    I used this on my Mint Maya host:

    # This is a here-file, copy and paste into terminal window to create the file
    cat << EOF >/etc/network/interfacesbridge
    auto lo
    iface lo inet loopback
    auto br0 
    iface br0 inet dhcp
    	bridge_ports eth0 tap0
    	bridge_stp off

    We need the tunctl and brctl utilities to set up a network bridge to the emulated target

    sudo apt-get install uml-utilities bridge-utils 

    We need some modules loaded

    sudo modprobe bridge tun

    Or if you like, you can add bridge and tun to /etc/modules

    # /etc/modules: kernel modules to load at boot time.
    # This file contains the names of kernel modules that should be loaded
    # at boot time, one per line. Lines beginning with "#" are ignored.

    Create a persistent tunnel, with permissions so you qemu can access it as you start the session

    sudo tunctl -u $UID -t tap0

    This step will cause the network connection to be dropped. Something to note if you are not on the serial console Add the bridge, and set it up:

    sudo brctl addbr br0
    sudo ifconfig eth0 promisc up
    sudo brctl addif br0 eth0
    sudo brctl addif br0 tap0
    sudo dhclient br0
    #iptables -F FORWARD

    Networking cannot possibly work until the host is set up correctly. Show the bridge configuration. You should see eth0 and tap0 in the bridge. Your indices may be different. I hope this is reasonably clear.

    sudo brctl show

    bridge name    bridge id        STP enabled    interfaces
    br0        8000.90e6ba5ccfbf    no              eth0


    #! /bin/sh
    # filename: launch
    # Set environment variables to make it easier to change
    NETWORK="-net nic,vlan=0 -net tap,vlan=0,ifname=tap0,script=no"
    KERNEL="-kernel zImage "
    qemu-system-arm -append "root=/dev/mmcblk0 rw physmap.enabled=0 console=ttyAMA0" -M vexpress-a9 $KERNEL -sd $ROOTFS  $NETWORK -nographic

    Now you can use udhcpc to bring up the network.

    Launching on Ubuntu

    You can run the Hardkernel Ubuntu images with this qemu -- Graphics is not going to work, without additional effort. First you need a partition image. If you have one already, good. I'm not talking about an SD Card image -- that would be a disk image with two partitions and other stuff.

    You can pull out the rootfs data from the SD-Card image by following these steps: How_to_Mount_SD-Card_Image_to_Extract_Root_File_System

    Once you have it rename it to rootfs-ubuntu.ext4 and put it in the same directory as the example files.

    Here is the launch-ubuntu script:

    #! /bin/sh
    # filename launch-ubuntu
    # Set environment variables to make it easier to change
    NETWORK="-net nic,vlan=0 -net tap,vlan=0,ifname=tap0,script=no"
    #NETWORK="-net nic -net user"
    KERNEL="-kernel zImage "
    qemu-system-arm -append "root=/dev/mmcblk0 rw physmap.enabled=0 console=ttyAMA0" -M vexpress-a9 $KERNEL -sd $ROOTFS  $NETWORK -serial stdio

    Do ./launch-ubuntu to bring it up. It will boot with some complaints, but you can fix them by editing /etc/fstab from

    UUID=e139ce78-9841-40fe-8823-96a304a09859 / ext4  errors=remount-ro,noatime 0 1
    /dev/mmcblk0p1 /media/boot vfat defaults 0 1


    /dev/mmcblk0 / ext4  errors=remount-ro,noatime 0 1

    Further Experiments

    Someone who knows the graphics subsystem, could actually get the graphics mode working. Rasberry Pi can do it.

    The kernel source I used was linux-3.2.0, right from I included the configuration I used as vexpress_odroid_qemu_defconfig. There is probably some graphics stuff that needs to be included.

    There is probably a qemu-system-arm command line option to be figured out as well.

    I actually see some characters come up in the graphics window, but the fonts are odd and the text disappears