HOWTO build additional kernel modules for Android

伯和蔼
2023-12-01
https://github.com/marco-pratesi/android/blob/master/HOWTOs/Android-Build-Kernel-Modules-HOWTO.txt


点击(此处)折叠或打开

  1. *************************************************
  2. HOWTO build additional kernel modules for Android
  3. *************************************************

  4. ----------
  5. Disclaimer
  6. ----------

  7. This HOWTO assumes usage of root privileges, i.e. that your device is rooted.
  8. It is also assumed that you are able to use a root shell on a Terminal Emulator
  9. on Android: its usage is implicitly assumed (and is never explicitly cited).
  10. Rooting your Android device might void your warranty, damage it,
  11. kill your cat, burn your house, and cause many other dreadful things.
  12. I do not take any responsibility, you are completely on your own.
  13. If you don't know what "rooting Android" means, this HOWTO is not suited
  14. for you.

  15. -------------------
  16. Scope of this HOWTO
  17. -------------------

  18. So many documents dealing with the Linux kernel compilation for GNU/Linux
  19. are already available.
  20. This document is not intended to write yet another one of them: here, I suppose
  21. that you are already familiar with this topic; if you are not, train yourself
  22. building kernel on GNU/Linux before (it is a good idea anyway :-) ).
  23. There are some documents about cross-compilation of the Linux kernel
  24. for Android, too; I prepared this HOWTO to collect and organize informations
  25. relevant to my needs and to support other HOWTOs I want to write.
  26. This HOWTO also discusses *native* build of kernel modules for Android;
  27. to the best of my knowledge, at the time of this writing, this is the only
  28. document facing this topic.

  29. --------------
  30. Test platforms
  31. --------------

  32. Tested, not exhaustively, using the following build platforms:
  33. - GNU/Linux Ubuntu 12.04 x86 (32 bit)
  34. - GNU/Linux Ubuntu 14.04 x86_64 (64 bit).

  35. Tested on a Google Nexus 7 3G 2012 tablet, with
  36. - Cyanogenmod 10.1.3
  37. - Cyanogenmod 10.2.1
  38. I made only few tests on 10.2.1, as I experienced some problems
  39. with CTRL and cursor arrows on the Android Terminal Emulator
  40. (both with the virtual keyboard and with an external USB keyboard),
  41. and I was not comfortable with some behaviors of the default shell.
  42. Do not blame me as a newbie: I performed wipings and factory reset more than
  43. once, but such annoying behaviors persisted, and I can not tolerate being
  44. uncomfortable with the only true user interface, i.e. the shell terminal. :-)
  45. Then I went back to 10.1.3 and carried out all the work on it.

  46. ------------------------
  47. Get Linux kernel sources
  48. ------------------------

  49. Download the kernel source tree that has been used to build the kernel
  50. running on your mobile device.
  51. Some relevant repositories may be:
  52. https://android.googlesource.com/
  53. https://github.com/cyanogenmod/
  54. If such sources are either not available or packed without documentation
  55. (and you do not have a crystal ball to guess how to compile them),
  56. search for the kernel source tree that most closely matches your case.

  57. As an example, kernel sources of Cyanogenmod for the Google Nexus 7 2012,
  58. both for the Wi-Fi version (codename: grouper) and the 3G version
  59. (codename: tilapia), can be found [1] at
  60. https://github.com/cyanogenmod/android_kernel_asus_grouper/ =>
  61. https://github.com/cyanogenmod/android_kernel_asus_grouper/tree/cm-10.1
  62. https://github.com/cyanogenmod/android_kernel_asus_grouper/tree/cm-10.2
  63. [...]

  64. Hint: download a zip/tar.gz archive through the web page of the repository,
  65. to save a lot of time and bandwidth; cloning through the git client,
  66. you would download the .git directory, too, that takes a lot of disk space
  67. and bandwidth, and is only needed for more advanced usage of the repository.
  68. The same suggestion may be useful for suubsequent sections of this document.

  69. ------------------------------------------------------
  70. Choose a toolchain to cross-compile the kernel sources
  71. (or use a native compiler, if you are brave enough)
  72. ------------------------------------------------------

  73. The best option for compatibility: if it is possible (if it is available),
  74. choose the same toolchain that has been used to build the kernel
  75. of your Android distribution.
  76. As you can experience on GNU/Linux, this option is not a must, but minimizes
  77. the risk of binary incompatibilities.

  78. Some available toolchains:

  79. - the prebuilt gcc on android.googlesource.com [2]
  80.   (for 64 bit build platforms only)
  81.   https://android.googlesource.com/platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6 =>
  82.   https://android.googlesource.com/platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/+/master =>
  83.   https://android.googlesource.com/platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/+archive/master.tar.gz

  84. - the Cyanogenmod prebuilt toolchain [1] (for 32 bit build platforms;
  85.   installation of some 32 bit libraries is needed on 64 bit build platforms)
  86.   https://github.com/CyanogenMod/android_prebuilt.git =>
  87.   https://github.com/CyanogenMod/android_prebuilt =>
  88.   https://github.com/CyanogenMod/android_prebuilt/tree/cm-10.1 =>
  89.   https://github.com/CyanogenMod/android_prebuilt/archive/cm-10.1.zip
  90.   https://github.com/CyanogenMod/android_prebuilt/tree/cm-10.2 =>
  91.   https://github.com/CyanogenMod/android_prebuilt/archive/cm-10.2.zip
  92.   [...]

  93. - the Android Native Development Kit (NDK) [3]

  94. Install (i.e. unpack) the toolchain(s) in the directory you prefer.

  95. Alternatively, you can build your modules just on your mobile device,
  96. using a native compiler [8] instead of a cross-compiler.
  97. This option is discussed at the end of this document.

  98. ----------------------------------------------------
  99. Set environment variables according to the toolchain
  100. ----------------------------------------------------

  101. For all toolchains:
  102. export ARCH=arm
  103. export SUBARCH=arm

  104. For the android.googlesource.com prebuilt gcc:
  105. export PATH=[your_installation_path]/bin:$PATH
  106. (as an example:
  107.  export PATH=/opt/android.googlesource.com/platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin:$PATH
  108. )
  109. export CROSS_COMPILE=arm-eabi-

  110. For the Cyanogenmod prebuilt toolchain:
  111. export PATH=[your_installation_path]/linux-x86/toolchain/arm-eabi-4.4.3/bin:$PATH
  112. (as an example:
  113.  export PATH=/opt/android_prebuilt-cm-10.1/linux-x86/toolchain/arm-eabi-4.4.3/bin:$PATH
  114. )
  115. export CROSS_COMPILE=arm-eabi-

  116. For Android NDK:
  117. set the PATH environment variable according to
  118. - usage of either a 32 bit or a 64 bit build platform
  119. - your installation path of the Android NDK
  120. - the cross-compiler version you want to use
  121. as an example:
  122. export PATH=/opt/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin:$PATH
  123. export CROSS_COMPILE=arm-linux-androideabi-

  124. For another toolchain:
  125. search for the documentation of that toolchain :-)
  126. Very likely, the directory to prepend to the PATH environment variable
  127. is the [...]/bin directory where you find many gcc executables named
  128. [NAME_PREFIX]addr2line
  129. [NAME_PREFIX]ar
  130. [NAME_PREFIX]as
  131. [NAME_PREFIX]c++
  132. [NAME_PREFIX]c++filt
  133. [NAME_PREFIX]cpp
  134. [NAME_PREFIX]g++
  135. [NAME_PREFIX]gcc
  136. [NAME_PREFIX]gcov
  137. [NAME_PREFIX]gdb
  138. [NAME_PREFIX]gprof
  139. [NAME_PREFIX]ld
  140. [NAME_PREFIX]nm
  141. [NAME_PREFIX]objcopy
  142. [NAME_PREFIX]objdump
  143. [NAME_PREFIX]ranlib
  144. [NAME_PREFIX]readelf
  145. [NAME_PREFIX]size
  146. [NAME_PREFIX]strings
  147. [NAME_PREFIX]strip
  148. [NAME_PREFIX]...
  149. ([NAME_PREFIX] is very likely something as "arm-eabi-",
  150. "arm-linux-androideabi-", and so on)
  151. then, after the PATH environment variable, set
  152. export CROSS_COMPILE=[NAME_PREFIX]
  153. and then hope for the best and try :-)

  154. ---------------------------------
  155. Build the needed kernel module(s)
  156. ---------------------------------

  157. Unpack the kernel sources and cd to their tree.
  158. Example:
  159. unzip android_kernel_asus_grouper-cm-10.1.zip
  160. cd android_kernel_asus_grouper-cm-10.1

  161. The kernel may refuse loading modules if the vermagic does not match,
  162. thus edit the Makefile to set KERNELRELEASE just according to it [1].
  163. To find the exact target kernel version string, you may either run
  164. "uname -a" / "cat /proc/version" on a shell terminal (Android Terminal
  165. Emulator / ADB shell / ...), or look for informations about the system
  166. (Kernel version) in the Setting GUI/Application.
  167. Examples about Google Nexus 7 2012 GSM (tilapia):
  168. Settings => About tablet => Kernel version:
  169. CM-10.1.3: 3.1.10-gd08812a build03@cyanogenmod #1 Mod Sep 23 20:47:32 PDT 2013
  170. CM-10.2.1: 3.1.10-g30c5396 build02@cyanogenmod #1 Mon Feb 3 16:09:59 PST 2014
  171. $ uname -a
  172. CM-10.1.3: Linux localhost 3.1.10-gd08812a #1 SMP PREEMPT Mon Sep 23 20:47:32 PDT 2013 armv7l GNU/Linux
  173. CM-10.2.1: Linux localhost 3.1.10-g30c5396 #1 SMP PREEMPT Mon Feb 3 16:09:59 PST 2014 armv7l GNU/Linux
  174. diff Makefile.old Makefile # for CM-10.1.3:
  175. 380c380
  176. < KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
  177. ---
  178. > KERNELRELEASE = "3.1.10-gd08812a"
  179. Alternatively, you may edit include/config/kernel.release accordingly
  180. (if it exists).
  181. NOTE: in more complex cases, you may have to also edit include/linux/vermagic.h
  182. and some other similar stuff, eventually after some subsequent steps.

  183. Choose a config to start with - if possible, just the one matching the kernel
  184. you are currently running on your mobile device - and copy it as .config
  185. in the kernel sources tree.
  186. Example:
  187. cp arch/arm/configs/cyanogenmod_grouper_defconfig .config

  188. NOTE: check if loadable module support is enabled ("CONFIG_MODULES=y").
  189. If it is not, to add hardware support, rebuilding and reinstalling
  190. (i.e. reflashing) the whole kernel is needed anyway:
  191. - if you want to use modules, you have to build a kernel with loadable module
  192.   support enabled
  193. - if you decide to choose the static option, without loadable module support,
  194.   to change the set of supported hardware you need to rebuild and reinstall
  195.   the whole kernel each time anyway.
  196. As an example, loadable module support is disabled on Cyanogenmod
  197. for the Google Nexus 7 2013 tablet and for the Google Nexus 4 smartphone:
  198. "# CONFIG_MODULES is not set" in
  199. https://github.com/CyanogenMod/android_kernel_google_msm/blob/cm-10.2/arch/arm/configs/cyanogen_flo_defconfig
  200. https://github.com/CyanogenMod/android_kernel_google_msm/blob/cm-10.2/arch/arm/configs/cyanogen_mako_defconfig
  201. https://github.com/CyanogenMod/android_kernel_google_msm/blob/cm-11.0/arch/arm/configs/cyanogen_flo_defconfig
  202. https://github.com/CyanogenMod/android_kernel_google_msm/blob/cm-11.0/arch/arm/configs/cyanogen_mako_defconfig

  203. Manipulate .config as it is usually done on GNU/Linux: after all, you are
  204. dealing with the Linux kernel anyway, even though
  205. - you are *cross*-compiling it
  206. - your target platform is Android/Linux instead of GNU/Linux

  207. Even though you are cross-compiling, you can also use "make menuconfig":
  208. as an example, to build the ftdi_sio.ko and mcs7830.ko modules:

  209. Device Drivers ---> USB support --->
  210.                     ^^^^^^^^^^^^^^^^ check that host-side and OTG support are enabled...
  211.                     ^^^^^^^^^^^^^^^^ very interesting: USB Gadget Support (http://www.linux-usb.org/gadget)
  212. *** USB port drivers ***
  213. USB Serial Converter support --->
  214. <M> USB FTDI Single Port Serial Driver (CONFIG_USB_SERIAL_FTDI_SIO)

  215. Device Drivers ---> Network device support ---> USB Network Adapters --->
  216. <M> MosChip MCS7830 based Ethernet adapters

  217. However, a quicker (if appropriate) solution consists of editing .config
  218. with bare hands:
  219. cp .config .config.old
  220. edit .config with a text editor, according to the following diff:
  221. diff .config.old .config
  222. 1267c1267
  223. < # CONFIG_USB_NET_MCS7830 is not set
  224. ---
  225. > CONFIG_USB_NET_MCS7830=m
  226. 2457c2457
  227. < # CONFIG_USB_SERIAL_FTDI_SIO is not set
  228. ---
  229. > CONFIG_USB_SERIAL_FTDI_SIO=m

  230. Prepare for build using the provided .config [4], [5]:
  231. make oldconfig
  232. make prepare
  233. make modules_prepare
  234. (For further options, run "make help".)

  235. Build the needed modules; you do not have to build everything, you can avoid
  236. building the static part of the kernel and unneeded (already installed)
  237. modules [5], [6]:
  238. make M=[directory of the module to build]
  239. Examples:
  240. make M=drivers/usb/serial/ # to build drivers/usb/serial/ftdi_sio.ko
  241. make M=drivers/net/usb/ # to build drivers/net/usb/mcs7830.ko
  242. (You may want to run "make" with the -j option to set the number of CPU
  243. cores to be used on the build platform [1], e.g. "make -j2 ..." on a dual-core
  244. netbook; anyway, if you only have to build a few modules, this option
  245. is almost insignificant.)

  246. NOTE: Cyanogenmod 10.1.3 and 10.2.1 did not load modules I built
  247. with Android NDK; the following error messages were provided:
  248. ------------------------------
  249. # insmod ftdi_sio.ko
  250. insmod: can't insert 'ftdi_sio.ko': invalid module format
  251. # dmesg | tail
  252. [...]
  253. [...] ftdi_sio: unknown relocation: 27
  254. ------------------------------
  255. The CFLAGS_MODULE=-fno-pic option solved the problem [7]:
  256. make CFLAGS_MODULE=-fno-pic M=drivers/usb/serial/
  257. make CFLAGS_MODULE=-fno-pic M=drivers/net/usb/

  258. Strip modules to remove unneded symbols and save memory on the target device
  259. that will run them:
  260. ${CROSS_COMPILE}strip --strip-debug [path]/[just_built_module].ko
  261. Example:
  262. ls -l drivers/usb/serial/ftdi_sio.ko # about 300 kbytes before stripping it
  263. ${CROSS_COMPILE}strip --strip-debug drivers/usb/serial/ftdi_sio.ko
  264. ls -l drivers/usb/serial/ftdi_sio.ko # about 100 kbytes after stripping it
  265. ls -l drivers/net/usb/mcs7830.ko # about 200 kbytes before stripping it
  266. ${CROSS_COMPILE}strip --strip-debug drivers/net/usb/mcs7830.ko
  267. ls -l drivers/net/usb/mcs7830.ko # about 10 kbytes after stripping it

  268. Through a program capable of viewing/editing binary files (e.g. VIM),
  269. open a .ko module in the target system (very likely, in /system/lib/modules)
  270. and the built module(s), to check whether "vermagic=..." is the same;
  271. if it is not and the built modules do not load, go back and try again,
  272. changing something accordingly in your build process.

  273. --------------------
  274. Test built module(s)
  275. --------------------

  276. After building a kernel module, you can put it the /data/local directory
  277. (or in /sdcard, or somewhere else) of the target Android device.
  278. The system directory for kernel modules is very likely /system/lib/modules;
  279. I do not suggest using it: apart from the fact that you have to remount
  280. /system as read-write to add/remove files to /system/lib/modules,
  281. custom built modules are more easily identified if you put them elsewhere.
  282. One uploaded a module to the target system, try to load it into
  283. the running kernel: as an example,
  284. insmod /data/local/ftdi_sio.ko
  285. If no errors are reported, check if the module has been loaded:
  286. lsmod | grep ftdi_sio

  287. If something went wrong, try the following commands to investigate:
  288. insmod /data/local/ftdi_sio.ko ; dmesg
  289. insmod /data/local/ftdi_sio.ko ; dmesg | grep ftdi
  290. and then search the web for the problem you are experiencing; an exhaustive
  291. discussion of all possible cases is not possible, you mileage may vary,
  292. I can only wish you good luck :-)

  293. --------------------------------------------------
  294. HOWTO build your modules through a native compiler
  295. --------------------------------------------------

  296. You can build your modules just on your mobile device using a native
  297. compiler, whose installation is discussed in [8], i.e. you can natively
  298. build your modules just on your (target) mobile device, instead of
  299. cross compiling them.

  300. First step: build and install a native compiler as discussed in [8].
  301. Yes, you need a cross-compiler - namely Android NDK - to build your
  302. native compiler :-D but you need it only once: subsequently, you can use
  303. the native compiler to build your stuff :-)

  304. Then follow the steps discussed in this document, skipping what is
  305. related to cross-build.
  306. Briefly: unpack your kernel sources, edit the Makefile, prepare your .config,
  307. make your modules, strip them.
  308. Some simple tricks are needed to solve some minor problems, as discusses
  309. in the following.

  310. *** 1 ***

  311. "make modules_prepare" fails, because the "elf.h" available in Android NDK
  312. (i.e. the one used by the native compiler [8]) is not enough.
  313. To overcome this problem, copy in the scripts/mod/ directory of the kernel
  314. sources tree the "elf.h" available in Glibc.
  315. You can easily find it: you can just copy /usr/include/elf.h from a GNU/Linux
  316. installation (I used the one available in GNU/Linux Ubuntu 14.04 x86_64).
  317. Edit scripts/mod/elf.h to remove inclusion of <bits/auxv.h>, as it is
  318. not available in Android NDK and is not needed:
  319. diff -up scripts/mod/elf.h.orig scripts/mod/elf.h
  320. ------------------------------
  321. --- scripts/mod/elf.h.orig
  322. +++ scripts/mod/elf.h
  323. @@ -972,7 +972,7 @@
  324.      } a_un;
  325.  } Elf64_auxv_t;

  326. -#include <bits/auxv.h>
  327. +//#include <bits/auxv.h>
  328.  /* Note section contents. Each entry in the note section begins with
  329.     a header of a fixed form. */

  330. ------------------------------

  331. Then edit scripts/mod/modpost.h to include just scripts/mod/elf.h:
  332. diff -up scripts/mod/modpost.h.orig scripts/mod/modpost.h
  333. ------------------------------
  334. --- scripts/mod/modpost.h.orig
  335. +++ scripts/mod/modpost.h
  336. @@ -7,7 +7,7 @@
  337.  #include <sys/mman.h>
  338.  #include <fcntl.h>
  339.  #include <unistd.h>
  340. -#include <elf.h>
  341. +#include "elf.h"

  342.  #include "elfconfig.h"

  343. ------------------------------

  344. *** 2 ***

  345. Just as for cross-compilation of modules through Android NDK,
  346. the CFLAGS_MODULE=-fno-pic may be needed to avoid relocation errors
  347. when loading the modules [7]: as an example,
  348. make CFLAGS_MODULE=-fno-pic M=drivers/usb/serial/
  349. make CFLAGS_MODULE=-fno-pic M=drivers/net/usb/

  350. *** 3 ***

  351. "make menuconfig" and "make nconfig" fail if ncurses headers are not found,
  352. i.e. if they are either not available or installed in a "non-standard"
  353. directory; to solve this problem, edit scripts/kconfig/Makefile to add
  354. an include path: as an example,
  355. diff -up scripts/kconfig/Makefile.orig scripts/kconfig/Makefile
  356. ------------------------------
  357. --- scripts/kconfig/Makefile.orig
  358. +++ scripts/kconfig/Makefile
  359. @@ -147,7 +147,7 @@
  360.  # Use recursively expanded variables so we do not call gcc unless
  361.  # we really need to do so. (Do not call gcc as part of make mrproper)
  362.  HOST_EXTRACFLAGS += $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags) \
  363. - -DLOCALE
  364. + -DLOCALE -I/data/local/include/ncurses

  365.  # ===========================================================================
  366.  # Shared Makefile for the various kconfig executables:
  367. ------------------------------
  368. where /data/local/include/ncurses is the directory containing curses.h

  369. I successfully used "make menuconfig" and "make nconfig" both via the ADB shell
  370. and on the Android Terminal Emulator, but please note that your terminal
  371. must provide at least
  372. - 19 lines by 80 columns to run "make menuconfig"
  373. - 20 lines and 75 columns to run "make nconfig"
  374. hence you may have to set small fonts on the Android Terminal Emulator,
  375. especially if the screen must provide room for the virtual keyboard, too.
  376. Via ADB, I experienced some "refresh" problems with "make menuconfig",
  377. however they can be almost completely solved through a suited setting
  378. of the TERM environment variable and they do not prevent usage of the tool.

  379. ----------
  380. References
  381. ----------

  382. [1] http://mehrvarz.github.io/building-nexus-7-kernel/
  383. [2] http://source.android.com/source/building-kernels.html
  384. [3] https://developer.android.com/tools/sdk/ndk/index.html
  385. [4] http://www.pixelbeat.org/docs/rebuild_kernel_module.html
  386. [5] http://askubuntu.com/questions/168279/how-do-i-build-a-single-in-tree-kernel-module
  387. [6] http://www.linuxquestions.org/questions/linux-kernel-70/rebuilding-a-single-kernel-module-595116/#post3648679
  388. [7] http://stackoverflow.com/questions/11614441/hello-world-kernel-module-for-android-unknown-relocation-27-when-insmod
  389. [8] https://github.com/marco-pratesi/android/tree/master/gcc_and_friends


<script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script>
阅读(131) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~
评论热议
 类似资料:

相关阅读

相关文章

相关问答