U-boot: ARM Versatile Express Emulation On Qemu With NFS as Rootfs


Booting a Linux System Is a Three-Act Play:

Boot loader mainly sets up the groundwork for the board to be able to load the kernel. Just like an opening, the boot loader paves the way for the kernel, going as far to load it from a remote server into memory so it can be executed. After it’s in memory, the boot loader hands execution to the kernel and exits. The kernel then has its own bootstrapping process (which duplicates what the boot loader did in some cases) that readies the hardware, loads drivers, and starts its processes to manage the system. When it’s in a running state, the kernel hands off control to an init program. The kernel and init then share the stage until you shut down the system.

This blog Aims to put everything together i.e U-boot (a bootloader) , kernel and NFS Rootfilesystem to emulate a complete boot procedure on Qemu.

Environment Introduction:

Host ubuntu :- 12.04
Linux kernel version: linux-4.8
busybox version: 1.24.0
Cross compiler tool chain: arm-2014.05-29-arm-none-linux-gnueabi-i686-pc-linux gnu.tar.bz2
qemu version: qemu-2.5
u-boot: U-Boot 2016.11-00108-gca39bd8


QEMU: https://github.com/qemu/qemu
Linux: https://github.com/torvalds/linux
U-boot: http://www.denx.de/wiki/U-Boot/SourceCode
Toolchain: http://sourcery.mentor.com/public/gnu_toolchain/arm-none-linux-gnueabi/

Download and Installation of QEMU: previous blog

ARM Cross_Compiler Tool chain installation: previous blog

Download U-boot source code :

git clone git://git.denx.de/u-boot.git

Prepare for compilation:

Load default config for target board i.e vexpress_ca9x4_defconfig using 1st command and Compile U-boot using 2nd command shown in below .

1.cd u-boot
2.make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- vexpress_ca9x4_defconfig
3.make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi-

Verify qemu and U-boot cross-compiled properly and  can run successfully(test it).

Run below command and Hit any key to stop autoboot.

~/Qemu_arm/bin/qemu-system-arm -M vexpress-a9 -m 512M -kernel u-boot -nographic 


Download Linux kernel source code : Taking latest stable code

$ git clone https://github.com/torvalds/linux
$ cd linux
$ git checkout -b stable v4.8

Prepare for compilation:

Load default config for target board i.e vexpress_defconfig. defconfig  is explained here.

$ cd linux
$ make ARCH=arm CROSS_COMPILE=path to your/Binary_images/ARM_Cross_Tools/arm-2014.05/bin/arm-none-linux-gnueabi- vexpress_defconfig
e.g CROSS_COMPILE=/Home/vinay/Workspace/Binary_images/ARM_Cross_Tools/arm-2014.05/bin/arm-none-linux-gnueabi-

Run below command to configure some settings :

$ make ARCH=arm CROSS_COMPILE=path to your/Binary_images/ARM_Cross_Tools/arm-2014.05/bin/arm-none-linux-gnueabi- menuconfig

Enable some settings as shown(*use space bar to enable).

Go to :
Boot options  —>
[*] Use appended device tree blob to zImage (EXPERIMENTAL)

With this option, the boot code will look for a device tree binary (DTB) appended to zImage
(e.g. cat zImage .dtb > zImage_w_dtb).

[*] Supplement the appended DTB with traditional ATAG information (NEW)
(console=ttyAMA0) Default kernel command string.


Some old bootloaders can’t be updated to a DTB capable one, yet they provide ATAGs with memory configuration, the ramdisk address,the kernel cmdline string, etc. Such information is dynamically provided by the bootloader and can’t always be stored in a static DTB. To allow a device tree enabled kernel to be used with such bootloaders, this option allows zImage to extract the information from the ATAG list and store it at run time into the appended DTB.


Kernel hacking  —>

[*] Kernel low-level debugging functions (read help!)

Say Y here to include definitions of printascii, printch, printhex in the kernel. This is helpful if you are debugging code that executes before the console is initialized


Kernel low-level debugging port(Autodetect UART0 onVersatile Express Cortex-A core tiles) —>
(X) Use PL011 UART0 at 0x10009000 (V2P-CA9 core tile)

This option selects UART0 at 0x10009000. Except for custom models,this applies only to the V2P-CA9 tile.


[*] Early printk

Say Y here if you want to have an early console using the kernel low-level debugging functions. Add earlyprintk to your kernel parameters to enable this console.

Compile the kernel using below command :

$ make ARCH=arm CROSS_COMPILE=path to your/Binary_images/ARM_Cross_Tools/arm-2014.05/bin/arm-none-linux-gnueabi- all


Once compilation of kernel is completed next step is to Install TFTP Server in Host ubuntu machine. For installation refer this .

Once tftp server is up and starts running, copy the kernel zImage and dtb image to /tftpboot.

$ cp arch/arm/boot/zImage /tftpboot/.
$ cp arch/arm/boot/dts/vexpress-v2p-ca9.dtb /tftpboot/.</pre>
<pre>$cd /tftpboot</pre>
<pre>$ cp zImage kernel
$ cat vexpress-v2p-ca9.dtb >> kernel 


Start U-BOOT:

Run below command and Hit any key to stop autoboot.

$ sudo ~/Qemu_arm/bin/qemu-system-arm -M vexpress-a9 -m 512M -serial stdio -net nic -net tap,ifname=tap0 -kernel path to u-boot/u-boot

Once boot loader is up, U-Boot in this you can load a kernel into memory and then run that image. The image loaded into memory can be stored on a server running TFTP.

You configure IP information in U-Boot by setting environment variables to configure the board’s and TFTP server’s address. To set the board’s IP address and the address of the TFTP server use the following commands:

For serverip check you host Ubuntu using ifconfig command

setenv ipaddr <set target ip>
setenv serverip <Set host ubuntu ip>
setenv netmask

The bootargs environment variable controls what kernel command-line parameters are sent during bootup. Setting bootargs works like setting the board’s IP address:

setenv bootargs 'root=/dev/mmcblk0 console=ttyAMA0,38400n8'

The device is now configured so that it can communicate over the Ethernet adapter. To download a file from a TFTP server, use the tftpboot command:

tftp 0x62008000 kernel

This loads the kernel into memory at the specified address and starts the booting process.

bootz 0x62008000



The above images shows kernel bootup dmesg in terminal. Due to absence of root file system( rootfs) , Kernel panic – not syncing: VFS: Unable to mount root fs on unknown-block(0,0)

Let’s then create the Minimal Rootfilesystem.

Compiling Busybox for ARM on QEMU : Refer

Follow all the steps from previous blog, Except (don’t follow) this steps.

Create ext3 image file and Copy all the files in our _install folder to image:Skip this step

Copy Busybox filesystem to NFS : Why NFS as RootFileSystem ?

Copy the _install directory that is generated with Busybox build into the NFS share folder:

Populate the root filesystem:

$ cp -a busybox/_install/ /rootfs_ES/.
$ sudo chmod 777 / rootfs - R
$ sudo chown nobody:nogroup /rootfs_ES/ -R


1. sudo ~/Qemu_arm/bin/qemu-system-arm -M vexpress-a9 -m 512M -serial stdio -net nic -net tap,ifname=tap0 -kernel u-boot
2. sudo ~/Qemu_arm/bin/qemu-system-arm -M vexpress-a9 -m 512M -nographic -net nic -net tap,ifname=tap0 -kernel u-boot

command 1 will give qemu graphical view where as command 2 with No graphic view.

Set environment variables as instructed above:

setenv ipaddr
setenv serverip
setenv netmask

# Set bootargs option 1 or 2, option 1 redirects dmesg to terminal , option 2 redirects both Host terminal and qemu terminal as shown below image.

1. setenv bootargs 'root=/dev/nfs rw nfsroot= init=/linuxrc console=ttyAMA0 ip='

2. setenv bootargs 'root=/dev/nfs rw nfsroot= init=/linuxrc console=ttyAMA0 console=tty0 ip='
tftp 0x62008000 kernel

bootz 0x62008000



Let me know if you have any questions or comments.




1. Pro Embedded Linux
2. https://balau82.wordpress.com/

About VinayMahadev

I am passionate about Embedded Linux systems . I believe in "If you want to learn something, read about it. If you want to understand something, write about it. If you want to master something, teach it". Here I am just trying to connect the Dots.
This entry was posted in Uncategorized. Bookmark the permalink.

8 Responses to U-boot: ARM Versatile Express Emulation On Qemu With NFS as Rootfs

  1. Pingback: ARM Versatile Express Emulation On Qemu: From Scratch | LearningFromU

  2. Pingback: ARM Versatile Express Emulation On Qemu From Scratch :Part 2 | LearningFromU

  3. minatu says:

    Very useful.
    Thanks your post.

    Liked by 1 person

  4. George says:

    Great guide but couldn’t make networking work for the TFTP :/
    Do you use any custom script for the bridging? do you set anything on the tap0 device that is created?

    Help would be appreciated!

    Liked by 1 person

  5. iptv server says:

    Nice share.
    In my opinion the most stable iptv servers are those from Fishbone IPTV cloud
    I would like to see more posts like this


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s