Cross compile linux kernel module for specific kernel
This post will revolve around the Netgear DGND3300v2 router and compiling the dm9601 drivers. I am not an expert and so this post might be missing certain key points relevant to your target platform. In short: There are two distinct issues. One is cross compiling for a specific architecture, for this you need a toolchain. This is fine for compiling executables. But, if you want to compile a LKM (loadable kernel module) you need to use the kbuild system with the kernel source of the specific platform you are compiling for. This is the tricky part.
Compiling an executable
As mentioned compiling for another platform requires a cross-compiling toolchain, for the router it was MIPS III Big Endian. Fortunately, there are prebuilt binaries for this here. Now at this point you can compile code to be compiled!
Notice the uClibc flag, this was needed as my router uses it instead of glibc.
Compiling a kernel module
To use the kbuild system (link) you need to use a Makefile. A simple example from tldp.org (which you need the source file from):
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
then run:
This builds an external module file hello-1.ko from hello-1.c. In the first few lines "-C /lib/modules/$(shell uname -r)/build " points make towards your kernel headers. Header files and module.symvers are required (has to be built).
Compiling a kernel module for another platform
Using the same Makefile (hopefully), you can cross-compile the module using the ARCH and CROSS_COMPILE paramters of Make. ARCH needs to be the platform name and CROSS_COMPILE the path of your toolchain. For example:
Notice the ending hyphen, the files under that location are the toolchain: e.g
mips-linux-uclibc-cpp
mips-linux-uclibc-gcc-4.2.3
mips-linux-uclibc-gdb
mips-linux-uclibc-ldconfig
Cross compile for another platform.
Now the only difference with the previous example is changing the path to the kernel source in the Makefile like so:
all:
make -C /home/chris/linux-headers M=$(PWD) modules
clean:
make -C /home/chris/linux-headers M=$(PWD) clean
running it with the same command as before will give the kernel module:
Conclusion:
Disclaimer: I am extremely inexperienced and I only learnt what I had to to get the drivers to work.
But in this scenario there were two distinct parts. 1. The first was getting the correct toolchain for your platform, this turned out to be rather tricky as the target was compiled using glibc so my first few downloaded toolchains didn't work. 2. The second having the correct kernel headers, this again turned out to be rather tricky as my router kernel version seems to be specifically patched for MIPS.
Luckily through different places Netgear has GPL released both the toolchain and kernel source.
Add new comment