Thursday, November 25, 2010

Building Embedded linux and emulating it using Qemu

Qemu Overview:


QEMU is a generic and open source machine emulator and virtualizer.

When used as a machine emulator, QEMU can run OSes and programs made for one machine (e.g. an ARM board) on a different machine (e.g. your own PC). By using dynamic translation, it achieves very good performa\nce.

When used as a virtualizer, QEMU achieves near native performances by executing the guest code directly on the host CPU. QEMU supports virtualization when executing under the Xen hypervisor or using the KVM kernel module in Linux. When using KVM, QEMU can virtualize x86, server and embedded PowerPC, and S390 guests.

Software to be Installed:

  •  Install qemu using "sudo apt-get install qemu".
  •  Install arm toolchain from here and untar the downloaded file with tar xvf then set the path by adding a line .bashrc in your home directory "export PATH=/<toolchain folder>/bin:${PATH}".
  •  Install Ncurses library with "sudo apt-get install libncurses5-dev" which is required for menu\ based configuration in kernel and  busybox.

U-Boot for ARM on Qemu:

Download the latest U-Boot source from here  and untar the source with the following command,


     $ tar xvf u-boot-1.3.4.tar.bz2
Then enter into the U-Boot main folder.

Basically Qemu supports the following board,

Supported machines are:

          integratorcp ARM Integrator/CP (ARM926EJ-S) (default)
          versatilepb ARM Versatile/PB (ARM926EJ-S)
          versatileab ARM Versatile/AB (ARM926EJ-S)
          realview   ARM RealView Emulation Baseboard (ARM926EJ-S)
          akita      Akita PDA (PXA270)
          spitz      Spitz PDA (PXA270)
          borzoi     Borzoi PDA (PXA270)
          terrier    Terrier PDA (PXA270)
          cheetah    Palm Tungsten|E aka. Cheetah PDA (OMAP310)
          lm3s811evb Stellaris LM3S811EVB
          lm3s6965evb Stellaris LM3S6965EVB
          connex     Gumstix Connex (PXA255)
          verdex     Gumstix Verdex (PXA270)
          mainstone  Mainstone II (PXA27x)

So, we can experiment the u-boot with versatile platform board,
To configure the u-boot for versatile platform board, run the following command 
      $ make versatilepb_config ARCH=arm CROSS_COMPILE=arm-none-eabi-
To build and create the u-boot binary run the following command,

      $ make all ARCH=arm CROSS_COMPILE=arm-none-eabi-

This will create u-boot.bin the binary format for u-boot for versatile platform board.

In order to simulate the u-boot in Qemu emulator the following command would be used,
       $ qemu-system-arm -M versatilepb -m 128M -nographic -kernel u-boot.bin

this will give you the u-boot prompt as,
     U-Boot 2010.09 (Oct 14 2010 - 14:44:36)
     DRAM:  0 Bytes
     ## Unknown FLASH on Bank 1 - Size = 0x00000000 = 0 MB
     Flash: 0 Bytes
     *** Warning - bad CRC, using default environment
     In:    serial
     Out:   serial
     Err:   serial
     Net:   SMC91111-0
     VersatilePB #

with this, we can try all the u-boot command here except  flash memory related commands, example: bootm,cp.b etc., since qemu does not support the emulation of flash memory on versatile platform board.

Compiling Kernel for Qemu:

First, download the latest kernel source from the server
and extract the tar file using following command,

      $ tar xvf linux-2.6.27.tar.gz


Then enter in the main directory, In order to set the predefined configuration for the versatile platform board run the following command,

       $ make ARCH=arm versatile_defconfig

we can do the detailed configuration by running the following command,

       $ make ARCH=arm menuconfig


this will through you a configuration window, in that we can do all the necessary configuration and save that configuration.

Now to build the kernel with compressed image called zImage, run the following command,

       $ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- all

This will take sometime to produce the zImage which is located in arch/arm/boot path.

zImage can be run in qemu using the following command,

       $ qemu-system-arm -M versatilepb -m 128M -kernel zImage


above command will run the kernal image and display the message that it didn't found the root filesystem.

Building rootfilesystem with busybox for qemu:

Download the latest busybox source which is available server and extract the tar file with the following command,

        $ tar xvf busybox-1.13.4.tar.bz2


Enter into the busybix folder. To make configuration for our convinient way, run the following command,
        $ make  menuconfig


this will give you a ncurses based configuration menu, in that enter into the following option

       $ Busybox settings --> Build option
then select the option "Build busybox as a static binary" and enter the cross compiler prefix "arm-none-linux-gnueabi-"
To build the Busybox, run the following command,

       $ make
      $ make install  

this will create a folder called _install in the main directory, this folder contain the rootfilesystem tree.

In order to create the rootfilesystem image with ext2 filesystem we can use the tool called "genext2fs".
        $ genext2fs -b 8192 -I 2048 -d /path/to/root_folder -D device_table.txt rootfs.img

here the text file contain the specification of nodes to be created, for creating console following specification should be there in device table file.

<name><type><mode><uid><gid><major><minor><start><inc><count>
/dev/console  c      600         0         0           5            1            0          0           -
this will generate the rootfilesystem image, we can compact that image even more with "gzip". Run the following command from the busybox main directory,


       $ gzip -c rootfs.img > rootfs.img.gz
Now we have both the kernel image and rootfilesystem for emulate in the qemu environment.

First copy the zImage which we have created in the previous topic and put it in the busybox main directory and run the following command,

      $ qemu-system-arm -M versatilepb -m 128M -kernel zImage -initrd rootfs.img.gz -append "root=/dev/ram"

this will run the linux kernel and execute the shell, finally display the '#' prompt. with this prompt we can execute normall shell command like ls, cd etc., but when we try to execute command like ps,mount etc., then we will get the error message that /proc directory is missing.

Now we can create the missing directory inside the _install folder where the rootfilesystem tree is present, for that run the following command,

      $ mkdir proc sys dev etc etc/init.d
When the kernel is executed the first user space application run by the kernel is /sbin/init , and its default behavior is to run the following initialization file /etc/inittab, so create the inittab file and write the following script in that file,
::sysinit:/etc/init.d/rcS
::respawn:/bin/sh

then we need to create the rcS file and add the  following line into that in order to mount the psuedo filesystem,
#! /bin/sh
mount -t proc none /proc
mount -t sysfs none /sys

Now the rootfilesystem directory is fully populated, we can recreate the rootfilesystem image using the previous method.
we can emulate this fully populated rootfilesystem and kernel by running the following command,
    $ qemu-system-arm -M versatilepb -m 128M -kernel zImage -initrd rootfs.img.gz -append "root=/dev/ram"

This will be executed and prompt will appear.


1 comment:

  1. This is really interesting blog on arm board, You are a very skilled blogger. I've joined your rss feed and look forward to seeking more of your excellent post. Also, I've shared your web site in my social networks! Thank You!!!

    ReplyDelete