{"id":1008,"date":"2011-08-27T00:50:03","date_gmt":"2011-08-26T22:50:03","guid":{"rendered":"http:\/\/hex.ro\/wp\/?p=1008"},"modified":"2015-05-04T00:07:22","modified_gmt":"2015-05-03T22:07:22","slug":"compile-an-android-kernel-module-outside-the-kernel-source-tree","status":"publish","type":"post","link":"https:\/\/hex.ro\/wp\/blog\/compile-an-android-kernel-module-outside-the-kernel-source-tree\/","title":{"rendered":"Compile an Android kernel module outside the kernel source tree."},"content":{"rendered":"<p>I&#8217;ve decided to make a short tutorial and present the way I compile kernel modules (outside the kernel sources).<\/p>\n<p>I&#8217;ve built few kernel modules (mainly governors &#8211; ineractive and smartass, but also cifs \/ nls-utf8, etc) and I started receiving private messages asking how I did it.<\/p>\n<p>For kernel modules that come with the kernel itself &#8211; cifs \/ tun for example &#8211; they just work if you compile the kernel and activate correct config parameters.<br \/>\nSome other modules (such as the smartass governor that doesn&#8217;t come with the kernel) you compile outside the kernel source. However they require changes since kernel does not export the symbols the module needs to use &#8211; so you have to know what k_all_syms are needed, grab them from the phone and update the kernel module.<\/p>\n<p>So there will be changes there. However, the main steps are:<\/p>\n<p>a) follow tutorials to get the kernel \/ android ndk to compile. People seem able to do this.<br \/>\nb) then take the module you want (For example <code>cpufreq_smartass.c<\/code> from here: <a href=\"http:\/\/pastebin.com\/rR4QUCrk\">http:\/\/pastebin.com\/rR4QUCrk<\/a> ) and copy it in a new folder on the disk.<br \/>\nc) create a Makefile like the one below, but with your paths of course:<\/p>\n<pre class=\"lang: bash\">\r\nKERNEL_DIR=\/home\/viulian\/android_platform\/kernel-2.1.A.0.435\/kernel\r\n\r\nobj-m := cpufreq_smartass.o\r\nPWD := $(shell pwd)\r\ndefault:\r\n        $(MAKE) ARCH=arm CROSS_COMPILE=\/home\/viulian\/android_platform\/prebuilt\/linux-x86\/toolchain\/arm-eabi-4.4.3\/bin\/arm-eabi- -C $(KERNEL_DIR) SUBDIRS=$(PWD) modules\r\nclean:\r\n        $(MAKE) -C $(KERNEL_DIR) SUBDIRS=$(PWD) clean\r\n<\/pre>\n<p>d) execute make<\/p>\n<p>Of course, the module source code needs to be adjusted as you need to put in the CPU frequencies, and also update the k_all_syms pointers .. But you can retrieve them from <code>\/proc\/kallsyms<\/code> on the device itself &#8211; just look for the method name, and use the address you see in the log.<\/p>\n<p>If you still can&#8217;t get it to compile, try to compile a very basic hello_world kernel module. I used the code below when testing:<\/p>\n<pre class=\"lang: cpp\">\r\n#include <linux\/module.h>  \/* Needed by all modules *\/\r\n#include <linux\/kernel.h>  \/* Needed for KERN_ALERT *\/\r\n \r\nMODULE_LICENSE(\"GPL\");\r\nMODULE_AUTHOR(\"viulian, 2011\");\r\nMODULE_DESCRIPTION(\"Demo module for X10i\");\r\n \r\nint init_module(void)\r\n{\r\n   printk(\"<1>Hello world\\n\");\r\n\r\n   \/\/ A non 0 return means init_module failed; module can't be loaded.\r\n   return 0;\r\n}\r\n\r\nvoid cleanup_module(void)\r\n{\r\n  printk(KERN_ALERT \"Goodbye world 1.\\n\");\r\n}\r\n<\/pre>\n<p>It is not perfect, but if you manage to insmod and then check dmesg, you will see &#8220;Hello world&#8221; written there.<\/p>\n<p>One more thing, Linux kernel is fussy about the module versions. Even if nothing is changed between two kernel versions related to what a module needs, is enough a small difference in module&#8217;s modinfo value to make the kernel to refuse the module.<\/p>\n<p>For this, you need to trick your local kernel and adjust EXTRAVERSION value in kernel&#8217;s main Makefile to have the exact version of the one on the device:<\/p>\n<p>In X10 stock kernel (GB 2.3.3 release), the kernel version is 2.6.29-00054-g5f01537 visible in phone settings.<\/p>\n<p>This means that the kernel on the phone will only accept modules that are compiled for that exact version. But the kernel version is just a string in the module .ko, so is a string comparison &#8211; the module might work perfectly, but is not loaded.<br \/>\nThere is luck though, the string value comes from a define in kernel&#8217;s Makefile, which you can change before you compile!<\/p>\n<p>The Makefile in the kernel you are going to use to build the module will have to include these lines at the top:<\/p>\n<pre class=\"lang: bash\">VERSION = 2\r\nPATCHLEVEL = 6\r\nSUBLEVEL = 29\r\nEXTRAVERSION = -00054-g5f01537\r\n<\/pre>\n<p>Other than that, it should work ..<\/p>\n<p>Expect phone reboots and difficulty to debug if stuff goes wrong. Android kernel doesn&#8217;t come with <strong>syslog<\/strong> functionality, kernel printk output is found in <code>\/proc\/kmsg<\/code>. Dmesg works, but you can&#8217;t execute if if phone reboots.<br \/>\nI usually had to keep another adb shell opening with &#8216;cat \/proc\/kmsg&#8217; which showed as much as possible from the module&#8217;s outputs.<\/p>\n<p>Happy compiling on your risk!<\/p>\n<p>PS: I&#8217;ve posted the same tutorial on XDA&#8217;s website here: http:\/\/forum.xda-developers.com\/showthread.php?p=17020258#post17020258<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;ve decided to make a short tutorial and present the way I compile kernel modules (outside the kernel sources). I&#8217;ve built few kernel modules (mainly governors &#8211; ineractive and smartass, but also cifs \/ nls-utf8, etc) and I started receiving private messages asking how I did it. For kernel modules that come with the kernel [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[33,24],"tags":[],"class_list":["post-1008","post","type-post","status-publish","format-standard","hentry","category-android","category-it"],"_links":{"self":[{"href":"https:\/\/hex.ro\/wp\/wp-json\/wp\/v2\/posts\/1008","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/hex.ro\/wp\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/hex.ro\/wp\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/hex.ro\/wp\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/hex.ro\/wp\/wp-json\/wp\/v2\/comments?post=1008"}],"version-history":[{"count":6,"href":"https:\/\/hex.ro\/wp\/wp-json\/wp\/v2\/posts\/1008\/revisions"}],"predecessor-version":[{"id":1647,"href":"https:\/\/hex.ro\/wp\/wp-json\/wp\/v2\/posts\/1008\/revisions\/1647"}],"wp:attachment":[{"href":"https:\/\/hex.ro\/wp\/wp-json\/wp\/v2\/media?parent=1008"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/hex.ro\/wp\/wp-json\/wp\/v2\/categories?post=1008"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/hex.ro\/wp\/wp-json\/wp\/v2\/tags?post=1008"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}