razaina.fr

Build Kernel Module for: Samsung Galaxy SIII (GT I9305)

Here are the infos regarding the phone:

  • Model Number: GT-I9305
  • CyanogenMod version: 11-20150125-NIGHTLY-i9305
  • Android Version: 4.4.4
  • Baseband Version: I9305XXUENG1
  • Kernel Version: 3.0.64-CM-gc426a2f build02@cyanogenmod #1 Sun Jan 25 13:36:34 PST 2015
  • CPU: ARMv7 Processor rev0 (v7)
  • Build Number: cm_i9305-userdebug 4.4.4 KTU84Q 00e9a874q7 test-keys

Step 1: Get the sources of the kernel

Sources code can be found on Cyanogendmod’s website

Step 2: Prepare the kernel

Configure the kernel

If the running kernel has been configured to have /proc/config.gz then pull it in order to extract the configuration file. Otherwise check in the following directory the one that will fit your kernel: ../android_kernel_samsung_smdk4412/arch/arm/configs.

I picked the following default configuration file “cyanogenmod_i9305_defconfig”.

Then run the make command as follows:

export
PATH=$PATH:$NDK_HOME/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86/bin
make ARCH=arm CROSS_COMPILE=arm-linux-androideabi- cyanogenmod_i9300_defconfig

Compile the kernel

First of all, I had to modify the Makefile:

  • At the beginning of the file set the correct version so all modules will be compiled with the right version number.
VERSION = 3
PATCHLEVEL = 0
SUBLEVEL = 64
EXTRAVERSION = -CM-gc426a2f
NAME = Sneaky Weasel
  • Based on this blog post I also added the proper parameter while the “setlocalversion” script is called so the EXTRAVERSION is not ovewritten by a default version:
# Store (new) KERNELRELASE string in include/config/kernel.release
include/config/kernel.release: include/config/auto.conf FORCE
	$(Q)rm -f $@
	$(Q)echo "$(KERNELVERSION)$$($(CONFIG_SHELL) $(srctree)/scripts/setlocalversion --save-scmversion $(srctree))" > $@
  • Based on this diff I modified accordingly my Makefile. Otherwise I had the following error:
arm-linux-androideabi-ld: error: arch/arm/boot/compressed/piggy.gzip.o: unknown CPU architecture
arm-linux-androideabi-ld: error: arch/arm/boot/compressed/lib1funcs.o: unknown CPU architecture
make[4]: *** [arch/arm/boot/compressed/vmlinux] Error 1
make[3]: *** [arch/arm/boot/compressed/vmlinux] Error 2
  • Finally we can compile the kernel;
make ARCH=arm CROSS_COMPILE=arm-linux-androideabi-

Step 3: Compile the module

The source code of my module is as follows:

#include <linux/module.h>
#include <linux/kernel.h>

int init_module(void)
{
    printk(KERN_INFO "+++++++++++++++++++++++++  Hello Kernel !!! +++++++++++++++++++++\n");
    return 0;
}


void cleanup_module(void)
{
    printk(KERN_INFO "++++++++++++++++++++++++++++ Goodbye Kernel !!!+++++++++++++++++++++\n");

}

MODULE_AUTHOR("razaina");
MODULE_LICENSE("GPL");
MODULE_VERSION("1");
MODULE_DESCRIPTION("Prints hello world!");

My Makefile looks like:

obj-m := hello.o
KDIR := /home/razaina/Android-kernel-sources/android_kernel_samsung_smdk4412/
PWD := $(shell pwd)
CCPATH := /home/razaina/android-ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86/bin/
default:
	$(MAKE) CFLAGS_MODULE=-fno-pic ARCH=arm CROSS_COMPILE=$(CCPATH)/arm-linux-androideabi- -C $(KDIR) M=$(PWD) modules

Do not forget the “-fno-pic” flag otherwise your module won’t work and you’ll get the following error message in dmesg:

c0 your_module_name: unknown relocation: 3

You can also get the following:

Unknown symbol _GLOBAL_OFFSET_TABLE_ (err 0)

This is because if you do not explicitely tell the compiler to build the module with “NO Position-Independent Code”, then your module will try to look for the “GLOBAL_OFFSET_TABLE” while trying to call some shared functions.

Then compile external modules in order to create the file “Module.symvers” in the kernel’s root directory.

make ARCH=arm CROSS_COMPILE=arm-linux-androideabi- modules_prepare
make ARCH=arm CROSS_COMPILE=arm-linux-androideabi- modules

Finally…compile your module using the make command.