Showing posts with label embedded linux. Show all posts
Showing posts with label embedded linux. Show all posts

Monday, November 3, 2008

On-Target source Level Debugging Using NFS

Many a times we would like to have to have a luxury of source level debugging but do not have fancy tools like a JTAG/ICE. But thanks to NFS, we do have a solution. Using NFS one can mount the entire source directory ( or any other directory for that matter) on to the target and run a debuggger on the target.

Besides aiding source level debugging NFS can help save crucial development time by circumventing the need to flash the board for every little change. If only a small portion of the code changes, selectively compile that particular program and replace the existing program on the board with the newly built program. Copy-And-Paste instead of Flash-And-Burn!!!


1. Build the Kernel Image for the target with NFS support.

2. Install NFS server package on the host. On debian machines it is as simple as

sudo apt-get install nfs-kernel-server

3. A file called /etc/exports is created. Open this file for editing.

add the following line :-

/home/kernelexploit 192.168.1.1(rw,all_squash,anonuid=kernelexploit,anongid=1000,insecure,no_subtree_check)

where /home/kernelexploit is the path on the host. This will be mounted on the target. [192.168.1.1] is the IP address of the target in my system. Replace it with your board specific parameters.

4. On the target type the following command

mkdir -p /home/kernelexploit-target [ This is where the remote directory would be mapped]

mount -t nfs -o async,noatime,exec,rw,nfsvers=2,nolock 192.168.1.11:/home/kernelexploit /home/kernelexploit-target


Where, 192.168.1.11 is the IP address of the host machine and /home/kernelexploit is the path on the host. The trailing /home/kernelexploit-target is a directory we created on the target where the remote directory is mounted.





Sunday, September 28, 2008

First Steps with Linux Kernel Programming

Like any programming endeavour, this one begins by saying hello to the world and remembering MAHAKALI : The supreme consciousness and the creatrix of the universe.

So without much ado, here are the steps :-

1. create a file called hello.c.Use an editor of your choice. Some people like vi/emacs whereas others use kate or gedit. Suit yourselves guys.

2. your first kernel program looks like this :-

#include <> /* for __init and __exit */
#include <> /* for MODULE related macros */
#include <>

/* this is the function which is invoked on issuing the "insmod" command */
/* unlike userland programs, there is no main function. Init module is the entry point */

static int __init hello_init(void)
{
printk(KERN_ALERT "Jai Mahakali: Jai Bhawani: Welcome !\n");
return 0;
}

/* ths is the function which is invoked on issuing the "rmmod" command */
/* it is an indication to the kernel that this module is no longer needed and can be unloaded */
static void __exit hello_exit(void)
{
printk(KERN_ALERT "Jai Kaal Bhairav : Adieus \n");
}

/* module_init : adds a special section to module's object code indicating the module initialization func */
/* module exit : ditto */

module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("Dual BSD\GPL"); /* add this if you dont want to get kernel taint warnings */
MODULE_AUTHOR("Nemesis KERNELEXPLOIT@GMAIL.COM");
MODULE_DESCRIPTION("Hello World");

3. Write the make file (courtesy Linux Device Drivers 3rd Edition). I don't exactly enjoy writing makefiles. Infact I am yet to meet a person who does.

-------------------------------------------x-------------------------------------------------x------------------------------------x------------------------

# To build modules outside of the kernel tree, we run "make"
# in the kernel source tree; the Makefile these then includes this
# Makefile once again.
# This conditional selects whether we are being included from the
# kernel Makefile or not.
ifeq ($(KERNELRELEASE),)

# Assume the source tree is where the running kernel was built
# You should set KERNELDIR in the environment if it's elsewhere
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
# The current directory is passed to sub-makes as argument
PWD := $(shell pwd)

modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules

modules_install:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install

clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions

.PHONY: modules modules_install clean

else
# called from kernel build system: just declare what our modules are
obj-m := hello.o

endif

-------------------------------------------x-------------------------------------------------x------------------------------------x-----------------------

4. issue the following command

nemesis@tantra:~/device-drivers$ make
make -C /lib/modules/2.6.18-6-686/build M=/home/nemesis/device-drivers modules
make[1]: Entering directory `/usr/src/linux-headers-2.6.18-6-686'
CC [M] /home/nemesis/device-drivers/hello.o
/home/nemesis/device-drivers/hello.c:19:1: warning: unknown escape sequence '\G'
/home/nemesis/device-drivers/hello.c:21:35: warning: no newline at end of file
Building modules, stage 2.
MODPOST
CC /home/nemesis/device-drivers/hello.mod.o
LD [M] /home/nemesis/device-drivers/hello.ko
make[1]: Leaving directory `/usr/src/linux-headers-2.6.18-6-686'
nemesis@tantra:~/device-drivers$

5. Wonderful!!! we have our shiny new module ready!!! Execute the insmod command. Well you need to be root to be able to insert a module into the kernel. If you are not a part of the sudoer's group you will not be able to proceed further. But we are not going to be daunted by a little glitch are we now ?

here is what to do:
sudo /usr/sbin/visudo
add the following line at the end of this file
your-username ALL=(ALL) ALL

Now that we have this out of our way , proceed with insmod

nemesis@tantra:~/device-drivers$sudo /sbin/insmod hello.ko
nemesis@tantra:~/device-drivers$dmesg

here is what you see at the end of the output
Jai Mahakali: Jai Bhawani: Welcome !

Now its time we unload the module
nemesis@tantra:~/device-drivers$sudo /sbin/rmmod hello.ko
nemesis@tantra:~/device-drivers$dmesg

here is what you see at the end of the output
Jai Kaal Bhairav : Adieus


6 . Its time we gather some info about our module
nemesis@tantra:~/device-drivers$sudo /sbin/modinfo hello.ko
filename: hello.ko
license: Dual BSDGPL
author: Nemesis KERNELEXPLOIT@GMAIL.COM
description: Hello World
vermagic: 2.6.18-6-686 SMP mod_unload 686 REGPARM gcc-4.1
depends:

Some Kernel Modules may accept user-specified parameters.


modinfo -p ${modulename}

The command above shows a current list of all parameters of a loadable
module. Loadable modules, after being loaded into the running kernel, also
reveal their parameters in /sys/module/${modulename}/parameters/. Some of these parameters may be changed at runtime by the command

echo -n ${value} > /sys/module/${modulename}/parameters/${parm}

7. at a final look at the elf-object code of hello.ko to see the __init section. Just to let you guys know that I wasnt bluffing !

nemesis@tantra:~/device-drivers$readelf -a hello.ko
Symbol table '.symtab' contains 32 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 SECTION LOCAL DEFAULT 1
2: 00000000 0 SECTION LOCAL DEFAULT 2
3: 00000000 0 SECTION LOCAL DEFAULT 3
4: 00000000 0 SECTION LOCAL DEFAULT 4
5: 00000000 0 SECTION LOCAL DEFAULT 5
6: 00000000 0 SECTION LOCAL DEFAULT 6
7: 00000000 0 SECTION LOCAL DEFAULT 7
8: 00000000 0 SECTION LOCAL DEFAULT 8
9: 00000000 0 SECTION LOCAL DEFAULT 9
10: 00000000 0 SECTION LOCAL DEFAULT 10
11: 00000000 0 SECTION LOCAL DEFAULT 11
12: 00000000 0 SECTION LOCAL DEFAULT 12
13: 00000000 0 SECTION LOCAL DEFAULT 13
14: 00000000 0 SECTION LOCAL DEFAULT 14
15: 00000000 0 SECTION LOCAL DEFAULT 15
16: 00000000 0 SECTION LOCAL DEFAULT 16
17: 00000000 0 SECTION LOCAL DEFAULT 17
18: 00000000 0 FILE LOCAL DEFAULT ABS hello.c
19: 00000000 12 FUNC LOCAL DEFAULT 2 hello_exit
20: 00000000 14 FUNC LOCAL DEFAULT 4 hello_init
21: 00000000 20 OBJECT LOCAL DEFAULT 7 __mod_license19
22: 00000020 36 OBJECT LOCAL DEFAULT 7 __mod_author20
23: 00000044 24 OBJECT LOCAL DEFAULT 7 __mod_description21
24: 00000000 0 FILE LOCAL DEFAULT ABS hello.mod.c
25: 00000060 57 OBJECT LOCAL DEFAULT 7 __mod_vermagic5
26: 00000000 128 OBJECT LOCAL DEFAULT 8 ____versions
27: 00000099 9 OBJECT LOCAL DEFAULT 7 __module_depends
28: 00000000 608 OBJECT GLOBAL DEFAULT 10 __this_module
29: 00000000 12 FUNC GLOBAL DEFAULT 2 cleanup_module
30: 00000000 14 FUNC GLOBAL DEFAULT 4 init_module
31: 00000000 0 NOTYPE GLOBAL DEFAULT UND printk

Well Adieus for now! Next up is a dummy char driver.

Saturday, September 27, 2008

Linux Device Drivers: Device Types

Classes of Linux Devices

1. Character [CHAR] Devices
- Can be accessed as a stream of bytes 
- Normally MUST implement open, close, read and write functionalities
- Can be accessed ONLY Sequentially unlike a regular file where it is posssible to move back & forth. However there can be a workaround for this using mmap() and lseek operations
- Mapped to a node in the filesystem e.g. /dev/ttyS0
- examples : serial ports, text consoles

2. Block Devices
- normally capable of hosting a filesystem
- Mapped to a node in the filesystem 
- In most of UNIX systems, block devices can ONLY handle I/O operations that transfer one or more blocks.
- Linux allows block devices to be read and written to like char devices

3. Network Interfaces
- Normally a hardware interface but software interface can also exist e.g. the loopback
- Unlike char device it is NOT stream oriented
- not mapped to a node in filesystem
- instead of read and write , they support receieve and transmit operations