Elastic Sheep

Because elasticdog was already taken

Elastic Sheep header image 2

Building and emulating a basic ARM Linux system

January 17th, 2011 · 11 Comments · Uncategorized

Here are my notes about the process I used to build a basic ARM linux system testable with QEMU. This knowledged has been gathered from the balau82.wordpress.com blog and from a Pierre Ficheux’s article introducing BuildRoot and published in Linux Magazine special issue n°47.

Here is a summary of the environment I will use:

  • Ubuntu 10.04 development host
  • ELDK 4.2 ARM cross compilation toolchain
  • Linux kernel 2.6.37
  • BuildRoot 2010.11
  • QEMU 0.13
  • Emulated hardware target: Versatile/PB development platform

Installing a cross compilation toolchain

The Embedded Linux Development Toolkit (ELDK) contains a GCC cross-compilation toolchain and a number of pre-built target tools and libraries. It is available for ARM, PPC and PPC64 targets (Documentation and ELDK 4.2 ARM ISO).

The ELDK 4.2 toolchain is EABI (the ELDK 4.1 was OABI).

A full install of the ELDK 4.2 development tools and target components for the ARM target require about 2GB of disk space. Only installing the development tools will require just 71MB. To avoid installing the target components you need to empty the etc/rpm_arm.list file provided in the ISO distribution.

# Mount the ISO and copy its content in the current directory
$> sudo mkdir /mnt/tmp
$> sudo mount –o loop –t iso9660 arm-2008-11-24.iso /mnt/eldk42
$> cp –r /mnt/eldk42 .
$> unmount /mnt/eldk42

# Patch the rpm_arm.list file
$> cd eldk42/etc
$> mv rpm_arm.list rpm_arm.list.original
$> touch rpm_arm.list
$> cd ..

# Install the toolchain
$> sudo mkdir –p /opt/ELDK42/arm
$> ./install –d /opt/ELDK42/arm arm

The toolchain is installed in /opt/ELDK42/arm.

Cross compilation environment variables

I use a shell script to set default environment variables required to cross compile the kernel.



Execute this script before any call to the kernel makefile.

Kernel configuration and build

To use the default kernel configuration for the Versatile/PB platform and then access the configuration menu:

$> curl –O http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.37.tar.bz2
$> tar xjvf linux-2.6.37.tar.bz2
$> cd linux-2.6.37
$> ../set_env_arm.sh
$> make versatile_defconfig
$> make menuconfig

In the configuration menu, I modify the following settings:

  • Disable the module support
  • Kernel Features / Use the ARM EABI

The ARM EABI option is required because of the ELDK 4.2 toolchain configuration.

Then to build the kernel:

$> make

The resulting kernel image is in the file arch/arm/boot/zImage.

Building QEMU from the sources

Compiling QEMU from source requires the following packages to be installed in Ubuntu: zliblg-dev libsdl-dev.

$> curl –O http://wiki.qemu.org/download/qemu-0.13.0.tar.gz
$> tar xzvf qemu-0.13.0.tar.gz
$> cd qemu-0.13.0
$> ./configure --target-list=arm-softmmu --enable-sdl
$> make

The generated executable is arm-softmmu/qemu-system-arm.

To get a list of the supported machines:

$> arm-softmmu/qemu-system-arm –M ?
realview-pb-a8 ARM RealView Platform Baseboard for Cortex-A8
realview-pbx-a9 ARM RealView Platform Baseboard Explore for Cortex-A9
versatilepb ARM Versatile/PB (ARM926EJ-S)

Executing the linux kernel in QEMU

The QEMU emulator is started by specifiying a machine to emulate and a Linux compressed image.

$> cd arm-softmmu
$> ./qemu-system-arm -M versatilepb –m 128M 
-kernel ../../linux-2.6.37/arch/arm/boot/zImage

The-m option specifies the RAM size available for the versatilepb machine. It defaults to 16MB if not specified.

The following capture shows the kernel boot in QEMU. The kernel boot ends with a kernel panic because we don’t have provided an init filesystem.

Building a root filesystem with BuildRoot

Buildroot is a set of makefile that helps to build complete embedded Linux system. It can compiles a GCC cross-compilation toolchain, a kernel and a root filesystem with selectable applications and packages.

I already have a compiled kernel thus I will use BuildRoot to only build a basic root filesystem containing the Busybox shell. This root filesystem will be a simple compressed CPIO archive.

$> curl –O http://buildroot.uclibc.org/downloads/buildroot-2010.11.tar.bz2
$> tar xjvf buildroot-2010.11.tar.bz2
$> cd buildroot-2010.11.tar.bz2
$> make menuconfig

I set the following options:

  • Target Architecture: arm
  • Target Architecture Variant: arm926t
  • Target ABI: EABI
  • Toolchain/Kernel Headers: 2.6.36.x (I could specify a path to my kernel sources)
  • Package Selection for the Target/Busybox 1.17.x
  • Target Fileystem Options/cpio the root filesystem and Compression method: gzip

Some dependencies you may need to install in Ubuntu: g++ flex msgfmt(gettext) patch subversion.

To start the BuildRoot execution (with optional V=1 to enable the verbose mode):

$> make V=1

BuildRoot automatically download the required source packages from their original servers, applies patches if necessary and compile them. It then builds a filesystem with the built packages installed.

Executing the kernel with the BuildRoot root filesystem

$> cd qemu-0.13.0/arm-softmmu
$> ./qemu-system-arm -M versatilepb –m 128M 
-kernel ../../linux-2.6.37/arch/arm/boot/zImage 
–initrd ../../buildroot-2010.11/output/images/rootfs.cpio.gz

The initrd option specifies a filesystem image to load as the initial ram disk. During boot the kernel will mount this ram disk as its root filesystem and look for an init executable to start. In our case the init executable is provided by Busybox.

Here a capture of the result. I am able to loginp as root and then do a ls on the root of the filesystem.

Quitting QEMU when the mouse has been grabbed

The QEMU graphical window can grab the mouse pointer to interact with the virtual machine display. Ctrl-Alt should exit the mouse grab but in my case (QEMU executed by Ubuntu emulated by OS X/VMWare Fusion) it does not work so I am unable to get back the mouse when I want to end my session.

So I use the console accessed through Ctrl-Alt-2 and the quit command.

compat_monitor0 console
QEMU 0.13.0 monitor - type 'help' for more information
(qemu) quit

Tags: ···

11 Comments so far ↓

  • teratux

    Hi .. Can u send me by email an example config file for my kernel ?? I’m trying also to build it with a Codesourcery arm eabi toolchain but when I build and run the 2.6.37 kernel qemu just says Unpacking and booting the kernel … done, and nothing more …

    I’m trying to discard any issues with the toolchain

    Thanks in advance …

  • The Chief Sheep

    Sent by PM

  • czar x

    i am having same problem as mentioned by @Teratux please guide me.


  • Abid

    Hi, we are trying to build the Kernel for ARM 926 ej-s board to be more specific the rk2818 one.

    Can you please tell me if we need to specify
    Target Architecture Variant: arm926t
    as specified by you or follow some additional steps. Also from my understanding the versatile option should be chosen, if we are targeting qemu emulaton (is that right?). In-case I am wrong and versatile works for ej-s, can you send me the .config that @Teratux has mentioned please?


  • kaiwan

    Hi, great write-up, thanks!

    A possible minor error:
    Instead of

    it should be

    . ../set_env_arm.sh

    to have the env vars set for the current shell.

  • kaiwan

    @teratux : i had the same issue w/ a recent kernel 3.1.5.
    After downgrading the kernel (i tried, it worked. I used the -append “console=ttyAMA0 …” option as well..

  • Angel

    Hi! Great post. I’d like to cross-compile a HelloWorld but I don’t know how to do it. Could you help me, please?
    I imagine that I have to cross-compile it and later add it to rootfs.cpio.gz unpacking and repacking it. I supose that I have to use the ELDK 4.2 ARM cross compilation toolchain once dot-sourced set_env_arm.sh, but I can’t even fins a “printf” in any .h on /opt/ELDK42/.
    Any help would be really welcome. Thanks in advance!

  • Angel

    Hi again,
    following the steps of buildroot I have already compiled a HelloWorld for ARM. Then I have just copied it to buildroot-2010.11/output/target/bin/ , cd’ed to buildroot-2010.11/output/target/ and done “find . | cpio –quiet -o -H newc > my_rootfs.cpio” and compressed this way “gzip -9 -c my_rootfs.cpio > my_rootfs.cpio.gz . But when the kernel boots it stops at “input: ImExPS/2 …”
    I think it’s just a matter of doing right the fakeroot.
    It would be really appreciated to get help on this. Best regards,
    / Angel

  • chandan

    Can anybody tell what steps should be taken and what should not be taken while using codesourcery toolchain instead of ELDK while following the above guidelines.

  • burak

    Hi, i ‘ve been trying to debug linux kernel for integratorCp board and when i test it with qemu i only see a black screen :S Could you please send me your config file? i want to understand whats wrong with my configuration.

  • The Chief Sheep

    Hi Burak,
    I sent you my config file by PM.
    I have also added the config file in the post for reference.

Leave a Comment