Wednesday, September 29, 2010

Creating Loadable Kernel Modules for Android

The Loadable Kernel Module architecture in Linux allows a developer to extend the functionality of a pre-built Linux operating system.  We can use this mechanism to extend Android because Linux kernel is the base operating system for all Android devices.  The Linux Kernel Module Programming Guide is the pre-requisite reading before you embark on this journey.  We will use the "Hello World" example from that guide to explain the process of compiling and loading an external Kernel module for Android Emulator.  These basic steps are the foundation for creating custom Android functionality for real-world devices.

The latest Android 2.2 Emulator from the Android SDK does not support loadable kernel modules.  Therefore, the first order of business is to compile a new kernel for the emulator that allows dynamic kernel module loading. 

Prepare the Build Enviornment

The easiest way to compile a Linux kernel for Android is to use build scripts from Android itself.  Refer to my previous blog on how to check out a Android platform build.  From the root of the platform source tree, run:

$. build/envsetup.sh
$lunch 1

Check-out the Kernel Source For the Emulator

Change to a new directory and check out the Linux kernel source for the Emulator.  Note that we must check out the version that matches our emulator because of Linux kernel compatibility rules.  See the Guide for details.  In this example, we use the Android 2.2 emulator from the official SDK.  This emulator uses kernel version 2.6.29.  You can find this version number in Settings or from /proc/version in the adb shell.

$ git clone git://android.git.kernel.org/kernel/msm.git .
$ git checkout --track -b my-goldfish-2.6.29 remotes/origin/android-goldfish-2.6.29 

Configure the Kernel Source

The easiest method to configure the kernel source is to use the configuration from a running emulator:

$ adb pull /proc/config.gz
$ gunzip config.gz
$ mv config .config 


Now edit the .config file and enable the kernel module feature:

CONFIG_MODULES=y

Save the file and proceed to build:

$ export ARCH=arm
$ export CROSS_COMPILE=arm-eabi-
$ make 


Now we have a new kernel that we can use to load our kernel modules.

Compile External Kernel Modules

Create a new directory outside the kernel source tree.  Then create a hello-3.c file and copy-n-paste the source code from the Guide.  Next, create a Makefile to use our own kernel source tree:

KERNELSRC=/mydroid/kernel

obj-m += hello-3.o
all:
    make -C $(KERNELSRC) M=$(PWD) modules

clean:
    make -C $(KERNELSRC) M=$(PWD) clean

Then run make:

$ make


It will create a "hello-3.ko" file after completion.  This is the kernel module that we will use on our Android.  If the kernel source was not configured with "CONFIG_MODULES=y", the compiler would usually throw up an error like this:

error: variable '__this_module' has initializer but incomplete type


Store the Kernel Module onto Android

We first need to use the Android SDK to create an AVD.  In this example, we set the target of the AVD to 2.2.  We then start this AVD with the emulator pointing to our newly built kernel:

$ emulator -kernel /mydroid/kernel/arch/arm/boot/zImage -avd myavd
We can store our kernel module anywhere that is writeable on Android.  No need to "repack" the system image as some on the web has suggested.  The system image from the SDK is not writeable so we will put our file on the user data partition, which is always writeable.

$ adb push /mymodule/hello-3.ko /data/hello-3.ko

Load the Kernel Module

Run the insmod command in the adb shell mode to load our module:

# cd /data
# insmod hello-3.ko

If there is no error, you can verify the new module using the lsmod command:

# lsmod
hello_3 1004 0 - Live 0xbf000000 (P)

You can also verify the module output in kmsg:

# cat /proc/kmsg
<4>hello_3: module license 'unspecified' taints kernel.
<6>Hello, world 3

Congratulations! You are now an Android kernel programmer.  Use your power wisely.

3 comments:

  1. I have tried using this approach but when I run make, I get no .ko file. The output of make lists all the modules that were built but mine isn't one of them.

    Any thoughts?

    ReplyDelete
    Replies
    1. Yeah I ran into the same problem. Make sure you grab the source code to the kernel as well:
      https://android.googlesource.com/

      I choose /devices/generic/goldfish - for emulator

      Delete