Techies who work in the embedded domain must be familiar with the ARM (Advanced RISC Machine) architecture. In the modern era, our lives have been taken over by mobile devices like phones, PDAs, MP3 players and GPS devices that use this architecture. ARM has cemented its place in the embedded devices market because of its low cost, lower power requirements, less heat dissipation and good performance.
Purchasing ARM development hardware can be an expensive proposition. Thankfully, the QEMU developers have added the functionality of emulating the ARM processor to QEMU. You can use QEMU for two purposes in this arena — to run an ARM program, and to boot and run the ARM kernel.
In the first case, you can run and test ARM programs without installing ARM OS or its kernel. This feature is very helpful and time-saving. In the second case, you can try to boot the Linux kernel for ARM, and test it.
Compiling QEMU for ARM
In the last article, we compiled QEMU for x86. This time let’s compile it for ARM. Download the QEMU source, if you don’t have it already. Extract the tarball, change to the extracted directory, configure and build it as follows:
$ tar -zxvf qemu-0.14.0.tar.gz $ cd qemu-0.14.0 $ ./configure –target-list=arm-softmmu $ make $ su # make install
You will find two output binaries, qemu-arm
and qemu-system-arm
, in the source code directory. The first is used to execute ARM binary files, and the second to boot the ARM OS.
Obtaining an ARM tool-chain
Let’s develop a small test program. Just as you need the x86 tool-chain to develop programs for Intel, you need the ARM tool-chain for ARM program development. You can download it from here.
Extract the archive’s contents, and view a list of the available binaries:
$ tar -jxvf arm-2010.09-50-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2 $ cd arm-2010.09/bin/ $ ls -rwxr-xr-x 1 root root 569820 Nov 7 22:23 arm-none-linux-gnueabi-addr2line -rwxr-xr-x 2 root root 593236 Nov 7 22:23 arm-none-linux-gnueabi-ar -rwxr-xr-x 2 root root 1046336 Nov 7 22:23 arm-none-linux-gnueabi-as -rwxr-xr-x 2 root root 225860 Nov 7 22:23 arm-none-linux-gnueabi-c++ -rwxr-xr-x 1 root root 572028 Nov 7 22:23 arm-none-linux-gnueabi-c++filt -rwxr-xr-x 1 root root 224196 Nov 7 22:23 arm-none-linux-gnueabi-cpp -rwxr-xr-x 1 root root 18612 Nov 7 22:23 arm-none-linux-gnueabi-elfedit -rwxr-xr-x 2 root root 225860 Nov 7 22:23 arm-none-linux-gnueabi-g++ -rwxr-xr-x 2 root root 222948 Nov 7 22:23 arm-none-linux-gnueabi-gcc
Cross-compiling and running the test program for ARM
Now use the arm-none-linux-gnueabi-gcc
tool to compile a test C program. Before proceeding, you should add the ARM tool-chain to your PATH:
# PATH=/(Your-path)/arm-2010.09/bin:$PATH
Create a small test program, test.c
, with the basic “Hello world”:
#include<stdio.h> int main(){ printf("Welcome to Open World\n"); }
Use the ARM compiler to compile this program:
# arm-none-linux-gnueabi-gcc test.c -o test
Once the file is compiled successfully, check the properties of the output file, showing that the output executable is built for ARM:
# file test test: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.16, not stripped
Run the test program:
#qemu-arm -L /your-path/arm-2010.09/arm-none-linux-gnueabi/libc ./test Welcome to Open World
While executing the program, you must link it to the ARM library. The option -L
is used for this purpose.
Building the Linux kernel for ARM
So, you are now done with the ARM tool-chain and qemu-arm
. The next step is to build the Linux kernel for ARM. The mainstream Linux kernel already contains supporting files and code for ARM; you need not patch it, as you used to do some years ago.
Download latest version of Linux from kernel.org (v2.6.37 as of this writing), and extract the tarball, enter the extracted directory, and configure the kernel for ARM:
# tar -jxvf linux-2.6.37.tar.bz2 # cd linux-2.6.37 # make menuconfig ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi-
Here, specify the architecture as ARM, and invoke the ARM tool-chain to build the kernel. In the configuration window, navigate to “Kernel Features”, and enable “Use the ARM EABI to compile the kernel”. (EABI is Embedded Application Binary Interface.) Without this option, the kernel won’t be able to load your test program.
Modified kernel for u-boot
In subsequent articles, we will be doing lots of testing on u-boot — and for that, we need a modified kernel. The kernel zImage
files are not compatible with u-boot, so let’s use uImage
instead, which is a kernel image with the header modified to support u-boot. Compile the kernel, while electing to build a uImage
for u-boot. Once again, specify the architecture and use the ARM tool-chain:
# make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- uImage -s Generating include/generated/mach-types.h arch/arm/mm/alignment.c: In function 'do_alignment': arch/arm/mm/alignment.c:720:21: warning: 'offset.un' may be used uninitialized in this function . . . Kernel: arch/arm/boot/Image is ready Kernel: arch/arm/boot/zImage is ready Image Name: Linux-2.6.37 Created: Thu May 5 16:59:28 2011 Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 1575492 Bytes = 1538.57 kB = 1.50 MB Load Address: 00008000 Entry Point: 00008000 Image arch/arm/boot/uImage is ready
After the compilation step, the uImage
is ready. Check the file’s properties:
# file arch/arm/boot /uImage uImage: u-boot legacy uImage, Linux-2.6.37, Linux/ARM, OS Kernel Image (Not compressed), 1575492 bytes, Thu May 5 17:11:30 2011, Load Address: 0x00008000, Entry Point: 0x00008000, Header CRC: 0xFC6898D9, Data CRC: 0x5D0E1B70
Now test this image on QEMU; the result is shown in Figure 1:
# qemu-system-arm -M versatilepb -m 128M -kernel /home/manoj/Downloads/linux-2.6.37/arch/arm/boot/uImage
The kernel will crash at the point where it searches for a root filesystem, which you didn’t specify in the above command.
The next task is to develop a dummy filesystem for your testing. It’s very simple — develop a small test C program hello.c
, and use it to build a small dummy filesystem:
#include<stdio.h> int main(){ while(1){ printf("Hello Open World\n"); getchar(); }
The endless loop (while(1)) will print a message when the user presses a key. Compile this program for ARM, but compile it statically; as you are trying to create a small dummy filesystem, you will not use any library in it. In GCC, the -static
option does this for you:
# arm-none-linux-gnueabi-gcc hello.c -static -o hello
Use the output file to create a root filesystem. The command cpio
is used for this purpose. Execute the following command:
# echo hello | cpio -o --format=newc > rootfs 1269 blocks
Check the output file:
# file rootfs rootfs: ASCII cpio archive (SVR4 with no CRC)
You now have a dummy filesystem ready for testing with this command:
# qemu-system-arm -M versatilepb -m 128M -kernel /home/manoj/Downloads/ linux-2.6.37/arch/arm/boot/uImage -initrd rootfs -append "root=/dev/ram rdinit=/hello"
When the kernel boots, it mounts rootfs as its filesystem, and starts the hello program as init. So now you are able to run ARM programs, and boot the ARM kernel inside QEMU.
The next step would be to use u-boot on QEMU. An array of testing is ahead of us, which we will cover in a forthcoming article.
i follow the same steps but qemu-arm not generated to execute binary files
check the post above! ;)
i used this command for testing> qemu-system-arm -M versatilepb -m 128M -kernel my_path/arch/arm/boot/uImage.
i get a blank screen with no prints…plz suggest how to overcome this?
I used the command line below and I got output.
qemu-system-arm -M versatilepb -kernel /home/jharris/linux-2.6.39/arch/arm/boot/uImage -initrd rootfs -append “root=/dev/ram rdinit=/hello console=ttyAMA0” -nographic
hi…i’m new to embedded linux field. i am trying to emulate arm develpmnt board using Qemu and boot linux on to it. i compiled the kernel and got the uImage.but when i test this image on qemu it shows–
qemu: fatal: Trying to execute code outside RAM or ROM at 0x50008000 R00=00000000 R01=00000183 R02=00000100 R03=00000000 R04=00000000 R05=00000000 R06=00000000 R07=00000000 R08=00000000 R09=00000000 R10=00000000 R11=00000000 R12=00000000 R13=00000000 R14=00000000 R15=50008000 PSR=400001d3 -Z– A svc32 Aborted.
i used this command for testing> qemu-system-arm -M versatilepb -m 128M -kernel /root/ls6410/kernel/s3c-linux-2.6.28.6-Real6410/arch/arm/boot/uImage.
can you suggest an method to fix this?
thanks,
can any one help me adding the PATH.
i get this error arm-none-linux-gnueabi-gcc: command not found
qemu-arm not installed can any one help me
When I try to run the executable it gives me command not found error:
qemu-arm -L /home/netuser/el/el_test/arm-2010q1/arm-none-linux-gnueabi/libc/ ./ltest
If ‘qemu-arm’ is not a typo you can use command-not-found to lookup the package that contains it, like this:
cnf qemu-arm
How to resolve this issue?
check above post
If you are miss to get qemu-arm installed. Just add arm-linux-user in qemu configuration and compile,
$./configure –target-list=arm-linux-user
$make
$ make install
/configure –target-list=arm-linux-user when i execute this command it is showing
Error: zlib check failed
Make sure to have the zlib libs and headers installed.
how i can solve this issue please give me sugg
#apt-get install zlib1g-dev
will resolve your error.
./configure –target-list=arm-softmmu
when executing make command i got the following error.
Makefile:24: no file name for `-include’
make[1]: *** No rule to make target `vl.o’, needed by `all’. Stop.
make: *** [subdir-libhw32] Error 2
How i can resolve this issue?Please help me.
Hi, I’m wonder what is “-M versatilepb” stand for? I don’t find it on qemu’s help message. Thanks!
Hi Abhishek,
Followed the above steps as mentioned in this article.
When I try to test uImage on Qemu using this command and resonse as follows,
qemu-system-arm -M versatilepb -m 128M -kernel /home/kiran/linux-3.8.2/arch/arm/boot/uImage
VNC server running on `127.0.0.1:5900′
qemu: hardware error: pl011_read: Bad offset d60
CPU #0:
R00=00000000 R01=00000000 R02=00000000 R03=00000000
R04=00000000 R05=00000000 R06=101f3d60 R07=00000000
R08=00000000 R09=00000000 R10=00000000 R11=00000000
R12=00000000 R13=00000000 R14=00000000 R15=00000004
PSR=400001db -Z– A und32
Aborted (core dumped)
Gone through many blogs but could not able to succeed.
Thanks in advance,
Solution for vnc server running on 127.0.0.1:15900 and got hangs…
open vncviewer from command and type the address that is shown on the screen (ex-127.0.0.1:15900)
when building qemu source i did not get qemu-arm binary..
please can anyone help
Did you check it in arm-softmmu Directory?
hi all i tried the below command in ubuntu (which is installed in my virtualbox).
its hanging there can anyone help me.
root@:~# qemu-system-arm -M versatilepb -m 128M -kernel /home/udayk/Downloads/linux-3.17.2/arch/arm/boot/uImage
oss: Could not initialize DAC
oss: Failed to open `/dev/dsp’
oss: Reason: No such file or directory
oss: Could not initialize DAC
oss: Failed to open `/dev/dsp’
oss: Reason: No such file or directory
audio: Failed to create voice `lm4549.out’
VNC server running on `127.0.0.1:5900′
Great post.
And I use “arm-linux-gnueabi-” instead of “arm-none-linux-gnueabi-“.
I launch kernel with `-nographic -append “… console=ttyAMA0″` instead of `-append “…”`.