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

From odroid US
Revision as of 18:23, 28 February 2013 by Osterluk (Talk | contribs) (Networking Setup)

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

Introduction

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.

Prerequisites

  • 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

    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 
    

    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
    wget http://odroid.us/odroid/users/osterluk/qemu-example.tgz
    
    

    Here are the files we now have:

  • ./zImage A kernel built for vexpress-a9 machine
  • ./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

    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
    

    cortex-a9

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

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


    Did not find a match, we need a newer build of qemu -- and we need to build it from source. First, we need to install some dependant packages

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

    Building Qemu

    Go to http://wiki.qemu.org/Download and download qemu-1.4.0.tar.bz2

    Download the source and expand it:

    cd $HOME
    mkdir qemu-build
    cd qemu-build
    # copy the source from the directory you downloaded it to
    cp /tmp/qemu-1.4.0.tar.bz2 .
    bunzip2 qemu-1.4.0.tar.bz2
    tar -xvf qemu-1.4.0.tar
    

    Now configure qemu and build it

    cd $HOME/qemu-build/qemu-1.4.0
    ./configure
    make
    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.

    qemu-img create rootfs-buildroot.ext2 200M
    

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

    mkfs.ext3 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
    ls
    cd ../
    sudo umount ./mnt
    

    launch-no-bridge

    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:

    ./launch-no-bridge
    

    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...

    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: http://www.microhowto.info/howto/persistently_bridge_traffic_between_two_or_more_ethernet_interfaces_on_debian.html

    I used this on my Mint Maya host:

    cat /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 (after each host boot)

    sudo modprobe bridge
    sudo modprobe 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.
    
    lp
    rtc
    bridge
    tun
    


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

    sudo tunctl -u $UID -t tap0
    


    Add the bridge, and set it up:

    sudo brctl addbr br0
    sudo ifconfig eth0 0.0.0.0 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
                                                    tap0
    

    launch

    #! /bin/sh
    # filename: launch
    # Set environment variables to make it easier to change
    ROOTFS=rootfs-buildroot.ext2
    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.