Saturday, December 5, 2009

ARM on QEMU

Goal : Run linux on a verstaline board (simulated by QEMU)

why : Because it is not always possible to have the real board available for development.

Prerequisites:
==============

1. QEMU : ofcourse
on debian systems : sudo apt-get install qemu
on RH systems : sudo yum install qemu

2. This one depends on what kind of communication mechanism is used between the host (your development) system and the guest sytem on QEMU. I prefer to use networking.

---- Have DHCP running so that guest system on qemu can use it to get an IP address.
---- host TAP devices used to connect to QEMU. The kernel config of the host should have TAP/TUN networking enabled. The switch for this is CONFIG_TUN.

grep CONFIG_TUN= /boot/config-`uname -r`

This should return you the state of the switch.

nemesis@nemesis-laptop:~$ grep CONFIG_TUN= /boot/config-`uname -r`
CONFIG_TUN=m


nemesis@nemesis-laptop:~$ ls -al /dev/net/tun
crw-rw-rw- 1 root root 10, 200 2009-11-03 11:46 /dev/net/tun


This verifies that the device exists indeed. If not, create it manually.

mknod /dev/net/tun c 10 200


Configure bridge-control
==================
Add the following to a script file

#!/bin/sh
/usr/sbin/brctl addbr br0 ### Add a bridge
/sbin/ifconfig eth0 0.0.0.0 promisc up ### set up eth0
/usr/sbin/brctl addif br0 eth0 ### add an intf(eth0) to the bridge (br0)
/sbin/dhclient br0 ### enable dhcp
/sbin/iptables -F FORWARD

Build kernel
=========

The quickest way is to use the default config file for the versatile platform.
Simply copy the config file from configs directory for ARM arch and rename it as .config

cp /arch/arm/configs/versatile_defconfig /.config

Config the Linux kernel (xconfig, menuconfig or simply using vim to edit..have it your way)

1. Enable ARM EABI support : switch CONFIG_AEABI (part of kernel features)
2. Enable DHCP : Switch CONFIG_IP_PNP_DHCP
3. Enable Universal TUN/TAP driver : switch CONFIG_TUN
4. Enable tmpfs : Switch CONFIG_TMPFS

Now we are ready to make (my day)
Ofcourse ARCH = arm
and CROSS_COMPILE = your_cross_compiler (I use codesourcery and for me it is
arm-none-linux-gnueabi-)

What about the Root File System ?
=======================

We will NFS mount the root filesystem. Build your rootfs.

1. edit /etc/exports ===> Add the following line

/mnt/arm-linux-rootfs / *(rw,sync,no_root_squash)

Here the untarred rootfs is at /mnt/arm-linux-rootfs and it is accessible as rw filesystem from any systems (indicated by *). If static ip-addresses are assigned, use the ip-address of the peer here.

2. restart the nfs service so that our changes come into effect.

/etc/init.d/nfs restart


Boot into Linux on QEMU
======================

qemu-system-arm -M versatilepb -kernel zImage-versatile -append root="/dev/nfs nfsroot=:/mnt/arm-linux-rootfs rw ip=dhcp" \
-net nic,vlan=0 -net tap,vlan=0,ifname=tap0,script=./qemu-ifup


qemu-ifup
=============================

#!/bin/sh

echo "Executing /etc/qemu-ifup"
echo "Bringing up $1 for bridged mode..."
sudo /sbin/ifconfig $1 0.0.0.0 promisc up
echo "Adding $1 to br0..."
sudo /usr/sbin/brctl addif br0 $1
sleep 2



Source : http://fedoraproject.org/wiki/Architectures/ARM/HowToQemu
http://www.aurel32.net/info/debian_arm_qemu.php

Sunday, November 29, 2009

Cross Toolchains : PART2 (Kernel Headers)

1. Download the kernel sources from kernel.org

2. cd to the sources root directory

3. run the following command to extract the headers for ARM

make headers_install ARCH=arm INSTALL_HDR_PATH=/usr/include/arm-linux-headers
Where ARCH specifies the architecture for which the headers are to be generated. INSTALL_HDR_PATH is the path on the local system where the header files will be placed. The default is /usr/include

To see a list of all supported architectures

ls -d include/asm-* | sed 's/.*-//'

make headers_install_all exports headers for all architectures simultaneously. Not very useful for the average embedded programmer.

#Decribe the API for the user space programs wishing to use kernel services
#Used by system's C library (glibc or uClibc) to define available system calls as well as constants and structures to be used with these system calls.
#Kernel headers are backward compatible.


[Sources : 1. Documentation/make/headers_install.txt ]
nemesis@nemesis-laptop:~/arm-linux-kernel/linux-2.6.31.6$ sudo make headers_install ARCH=arm INSTALL_HDR_PATH=/usr/include/arm-linux
CHK include/linux/version.h
make[1]: `scripts/unifdef' is up to date.
INSTALL include/asm-generic (34 files)
INSTALL include/drm (12 files)
INSTALL include/linux/byteorder (2 files)
INSTALL include/linux/can (4 files)
INSTALL include/linux/dvb (8 files)
INSTALL include/linux/hdlc (1 file)
INSTALL include/linux/isdn (1 file)
INSTALL include/linux/netfilter (58 files)
INSTALL include/linux/netfilter_arp (2 files)
INSTALL include/linux/netfilter_bridge (16 files)
INSTALL include/linux/netfilter_ipv4 (46 files)
INSTALL include/linux/netfilter_ipv6 (21 files)
INSTALL include/linux/nfsd (6 files)
INSTALL include/linux/raid (2 files)
INSTALL include/linux/spi (1 file)
INSTALL include/linux/sunrpc (1 file)
INSTALL include/linux/tc_act (6 files)
INSTALL include/linux/tc_ematch (4 files)
INSTALL include/linux/usb (8 files)
INSTALL include/linux/wimax (1 file)
INSTALL include/linux (352 files)
INSTALL include/mtd (5 files)
INSTALL include/rdma (1 file)
INSTALL include/scsi (4 files)
INSTALL include/sound (9 files)
INSTALL include/video (3 files)
INSTALL include/xen (1 file)
INSTALL include (0 file)
INSTALL include/asm (32 files)

Cross Toolchains : PART 1 (Binutils)

Components of crosstoolchain
===================

1. Binutils
2. Kernel header
3. C library
4. Compiler [e.g gcc]

optional : gdb debugger etc

Binutils
=====
The target architecture needs to have its own set of tools to generate binary files for it. Also it would be nice to have some tools to enable examining these.

ld ---> linker

strip --> to strip the object file of a particular section. e.g strip the comments to reduce the code size.
      strip [ -F BFDNAME | --target=BFDNAME ]
[ -I BFDNAME | --input-target=BFDNAME ]
[ -O BFDNAME | --output-target=BFDNAME ]
[ -s | --strip-all ] [ -S | -g | --strip-debug ]
[ -K SYMBOLNAME | --keep-symbol=SYMBOLNAME ]
[ -N SYMBOLNAME | --strip-symbol=SYMBOLNAME ]
[ -x | --discard-all ] [ -X | --discard-locals ]
[ -R SECTIONNAME | --remove-section=SECTIONNAME ]
[ -o FILE ] [ -p | --preserve-dates ]
[ -v | --verbose ] [ -V | --version ] [ --help ]
OBJFILE...

e.g strip --remove section=.comment

as --> assembler
objdump
objcopy
readelf: very useful tool. I invariably use it with -a switch to retrieve the max info.

nm
: lists all the symbols in an object file.

===========
Extract from IBM's website

objdump & nm

The commands objdump and nm both display information about object files. If a crash occurs and a corefile is produced, these commands help you analyze the file.

objdump
Use this command to disassemble shared objects and libraries. After you have discovered which library or object has caused the problem, use objdump to locate the method in which the problem originates. To invoke objdump, type: objdump
nm
This command lists symbol names from object files. These symbol names can be either functions, global variables, or static variables. For each symbol, the value, symbol type, and symbol name are displayed. Lower case symbol types mean the symbol is local, while upper case means the symbol is global or external. To use this tool, type: nm

You can see a complete list of options by typing objdump -H. The -d option disassembles contents of executable sections

Run these commands on the same machine as the one that produced the core files to get the most accurate symbolic information available. This output (together with the core file, if small enough) is used by the IBM® support team for Java™ to diagnose a problem.

=================================

addr2line : very important for debugging. E.g lets say you get a core dump with a backtrace. You can use the backtrace info to go to the code directly

void test_funk()
{
printf("#NEMESIS: testing funky func \n");
printf("#NEMESIS: address of test_funk [%p]", &test_funk);
}

Output: in the output the addess printed is 0x845c. Pass this as an input to the addr2line.]

nemesis@nemesis-laptop:~/test_code$ arm-none-linux-gnueabi-addr2line 0x845c
/home/adikumar/test_code/test_3.c:5 ===> Lo and behold.You have the line in the code.


strings: Lists all string in an object file. use it with grep to find a particular string

nemesis@nemesis-laptop:~/codesourcery/arm-2009q3/bin$ arm-none-linux-gnueabi-strings test2
/lib/ld-linux.so.3
libgcc_s.so.1
__aeabi_unwind_cpp_pr0
__gmon_start__
_Jv_RegisterClasses
__aeabi_unwind_cpp_pr1
libc.so.6
abort
printf
__libc_start_main
GCC_3.5
GLIBC_2.4
###!Nemesis: LittleEndian =========> my prints
###!Nemesis: BigEndian =========> my prints
0x%x

Wednesday, November 25, 2009

Whats your Endian-ness ?

int i= 0x1;

*((char*)&i) ? printf("###!Nemesis: LittleEndian\n"):printf("###!Nemesis: BigEndian\n");
printf("0x%x \n", *((char*)&i));


Wednesday, November 18, 2009

Forthcoming Embedded Articles

1. Building cross compiled linux kernel [With debug support]. Explain various configuration options.

2. Building a customized root filesystem

3. initial Ram disk

4. Uboot Bootloader: Internals, porting

5. Linux kernel start code walk through [ARM perspective]

6. Busybox

7. Using emulators [Qemu]

8. Linux device driver Serial : ARM Primecell UART

9. Linux Network driver

10. Linux Serial Driver

11. Gnu Tool chain [ gdb, gcc etc ]. binutils Making your own toolchain

12. ucLinux , ucLibc

13. NFS mounting

14. Remote debugging with gdbserver

15. Integrating Eclipse into your embedded development system

16. Misc tools : valgrind, profiling tools etc

17. kernel boot parameters. Explain nfs boot [ ip assigned by DHCP]

18. Various kernel image formats...zImage, uImage, vmlinux etc [ explain the linking and image components]

19. uClibC vs glibc

20. different filesystems (esp squashfs )

21. scratchbox, Buildroot