Dec 16, 2010 2
Android kernel compilation, detailed instructions
Disclaimer
I am not responsible if anything goes bad. Ever. In particular if your devices will be unusable after following this tutorial! Mine didn’t :)
Introduction
I’ve recently been involved in making some changes to the Linux kernel. Not any Linux kernel but the Android Linux Kernel. I’ll share what I believe is a pretty good workflow for everyone interested in playing with it both on a NexusOne (with the stock OS, i.e. WITHOUT CyanogenMod) and on a HTC Magic (with CyanogenMod installed). They are quite similar scenarios, and many others have been writing about it. I always had to change a few things from others descriptions and therefore here I report what I found to be a working solution for the latest patched updated versions. This is an aggregation work of others spread all around the interwebs. I like things accessible in one place :)
Throughout this “tutorial” I will be assuming that you are working on a Linux environment (i.e. Ubuntu). Furthermore I work on a 32-bit system, if you are not in this situation try it out, but further changes might be needed.
Preliminary Settings
Let’s start with having all the necessary software which we will need later installed and operative. If you are already an Android and/or a Kernel developer you most probably have this already done. Skip this section.
- adb is needed. Install the latest Android SDK – I personally install it in
~/Bin/android-sdk-linux_x86
Remember to add the tools/ directory to your $PATH variable.
- ndk is needed. Install the latest Android NDK – I personally install it in
~/Bin/android-ndk-VERSION
For example the latest is version r5 and the directory will be:
~/Bin/android-ndk-r5
. Remember then to add the toolchains/arm-eabi-4.4.0/prebuilt/linux-x86/bin directory that is present inside the ndk to your $PATH variable.
- fastboot is needed. Grab it and download it inside your sdk/tools directory or anywhere that is in your $PATH
- Software is needed. Install it.
apt-get install git-core gnupg sun-java6-jdk flex bison gperf libsdl-dev libesd0-dev libwxgtk2.6-dev build-essential zip curl libncurses5-dev zlib1g-dev
If you are on a 64-bit machine also install:
apt-get install ia32-libs lib32z1-dev lib32ncurses5-dev gcc-multilib g++-multilib
In the end your ~/.bash_profile, ~/.bash_rc, … would look along the lines of:
export PATH="~/Bin/android-sdk-linux_x86/tools:~/Bin/android-ndk-r5/toolchains/arm-eabi-4.4.0/prebuilt/linux-x86/bin:${PATH}"
Now let’s dwell into the interesting things. First of all have your directory structure well planned ahead. Or you will end up losing a lot of time just remembering what is what.
mkdir ~/android mkdir ~/android/bootimg_builder cd ~/android
Now we clone the git repositories for the Google kernel and for the CyanogenMod kernel. We will have two directories with the sources for the two kernels: cm-kernel and google-kernel
git clone git://github.com/CyanogenMod/cm-kernel.git cm-kernel git clone git://android.git.kernel.org/kernel/msm.git google-kernel
This is where I will first go into explaining the procedure for the HTC Magic with CyanogenMod installed and afterwards I will explain how to make it work for the NexusOne.
HTC Magic with CyanogenMod
Let’s start by switching to our own branch, in case we want to modify anything and keep track of the changes without polluting the master branch. The latest CyanogenMod (6.1) uses the kernel version 2.6.35, we keep on using that.
cd cm-kernel git checkout -b personal_branch origin/android-msm-2.6.35-froyo-stable
Now we need to pull the configuration file off from the device, have it plugged to the PC through the USB port.
adb pull /proc/config.gz config.gz gunzip config.gz && mv config .config
Now we update the .config that will be used while compiling the kernel.
ARCH=arm CROSS_COMPILE=arm-eabi- make oldconfig ARCH=arm CROSS_COMPILE=arm-eabi- make menuconfig
The last command will open up an interactive menu. Change what you want (i.e. nothing if you don’t require particular stuff…) and then get to Exit (and select Yes if you changed something, if you didn’t you won’t be prompted).
It is time to actually compile the kernel.
ARCH=arm CROSS_COMPILE=arm-eabi- make
The first time this will be a long procedure, the resulting file will be stored in
arch/arm/boot/zImage
and you can test it on your device directly by going into fastboot mode (hold the BACK button while powering up the device). Then issue this command:
fastboot boot arch/arm/boot/zImage
The phone should boot up normally and you can confirm that it’s running your kernel by going into Settings-About-Scroll down to the Kernel section. Note that if you reboot the phone it will go back to using the pre-installed kernel. More on flashing the kernel later on.
NexusOne with standard Android OS
First we need to unlock the NexusOne to accept new roms to be installed, have it in fastboot mode by holding the TRACKBALL down while booting up and issue this command
fastboot oem unlock
Note that this will void your warranty!
We also need the NexusOne to be rooted: rooting goes beyond the scope of this tutorial. Have your phone rooted in any way that you want (i.e. by using the SuperOneClick tool (it requires a Windows machine or luck with a Linux one).
This one is much more interesting! And while being very similar it also has some differences. First of all from our ~/android/ directory let’s move to the google-kernel directory and again create our own branch to work on.
cd ~/android/google-kernel git checkout -b personal_branch origin/android-msm-2.6.32
Note that in this case we’re using the kernel version 2.6.32 which is the one that’s installed by default on the NexusOne. The latest 2.6.35 should work but I haven’t really tested.
Next we create the usual .config file
ARCH=arm CROSS_COMPILE=arm-eabi- make mahimahi_defconfig ARCH=arm CROSS_COMPILE=arm-eabi- make menuconfig
Hit Exit and save if prompted (you shouldn’t!)
We now manually modify the .config file with your favorite text editor open the file and search for these strings
nano .config uncomment CONFIG_USB_ANDROID_ACM=y (add the =y part and remove what's there) comment CONFIG_MSM_SERIAL_DEBUGGER comment CONFIG_MSM_FIQ_SUPPORT
We’re ready to compile the kernel
ARCH=arm CROSS_COMPILE=arm-eabi- make
This will take some time, the resulting product will be stored in arch/arm/boot/zImage and you can test it on your device directly by going into fastboot mode (hold the TRACKBALL down while powering up the device). Then issue this command:
fastboot boot arch/arm/boot/zImage
The phone should boot up normally and you can confirm that it’s running your kernel by going into Settings-About-Scroll down to the Kernel section. Note that if you reboot the phone it will go back to using the pre-installed kernel. More on flashing the kernel later on.
NexusOne enable my WiFi, please
The WiFi kernel module that is on the NexusOne is not compiled to work with this kernel that we are using therefore WiFi won’t work. There’s a work around but it requires you to have root privileges on your device. Rooting goes beyond the scope of this tutorial. Have your phone rooted in any way that you want (i.e. by using the SuperOneClick tool (it requires a Windows machine or luck with a Linux one).
First you copy the compiled kernel module to the phone /sdcard
cd ~/android/google-kernel adb push drivers/net/wireless/bcm4329/bcm4329.ko /sdcard/
Then you need to make the phone /system partition writable, back up the old module and install the new one
adb shell su mount -o remount,rw -t yaffs2 /dev/block/mtdblock3 /system cd /system/lib/modules/ cat ./bcm4329.ko > ./bcm4329.ko-orig cat /sdcard/bcm4329.ko > ./bcm4329.ko mount -o remount,ro -t yaffs2 /dev/block/mtdblock3 /system
At this point your WiFi should be working again! :)
On flashing for awesome later use
Now that you tested that your compiled/(modified) kernel is actually working you may want to have it installed also after rebooting the phone. To achieve this you need to flash it to the phone internal storage. It is advisable that first you backup everything using a recovery tool (Amon RA 2.0.0 for the NexusOne works great with the nandbackup tool).
First grab two utilities that will be needed for this step and unzip them into the ~/android/bootimg_builder directory that we have created previously.
Throughout this part of the tutorial I will give commands for both the Magic and the NexusOne, please use only the ones that are useful for your case.
We first need to grab the boot.img file from the running device, have the device running and connected to the PC via USB then issue the command
cd ~/android/bootimg_builder adb shell cat /dev/mtd/mtd2 > /sdcard/mtd2.img exit adb pull /sdcard/mtd2.img ./nexus-boot.img
OR for the MAGIC
adb pull /sdcard/mtd2.img ./magic-boot.img
We now extract the boot.img-kernel and ramdisk by using the supplied perl script
./split_bootimg.pl nexus-boot.img
OR for the MAGIC
./split_bootimg.pl magic-boot.img
The output of this command will be along the lines of:
Page size: 2048 (0x00000800) Kernel size: 2226104 (0x0021f7b8) Ramdisk size: 164628 (0x00028314) Second size: 0 (0x00000000) Board name: Command line: no_console_suspend=1 msmsdcc_sdioirq=1 wire.search_count=5 Writing nexus-boot.img-kernel ... complete. Writing nexus-boot.img-ramdisk.gz ... complete.
We now need to copy the compiled kernel to our working directory discarding the one extracted previously
cd ~/android/bootimg_builder cp ../google-kernel/arch/arm/boot/zImage ./nexus-boot.img-kernel OR for the MAGIC cp ../cm-kernel/arch/arm/boot/zImage ./magic-boot.img-kernel
Now we combine everything into just one boot.img that we can then flash to the device
./mkbootimg --kernel nexus-boot.img-kernel --ramdisk nexus-boot.img-ramdisk.gz -o boot.img --cmdline 'no_console_suspend=1 msmsdcc_sdioirq=1 wire.search_count=5' --base 0x20000000
OR for the MAGIC
./mkbootimg --kernel magic-boot.img-kernel --ramdisk magic-boot.img-ramdisk.gz -o boot.img --cmdline 'no_console_suspend=1 console=null'
At this point we’re ready to flash the new image to the device, have it in fastboot mode (TRACKBALL on the NexusOne, BACK on the Magick while booting up) and issue the command
fastboot flash boot boot.img fastboot reboot
If everything has gone well enjoy your new kernel installed definitively on your device. You did make a nandbackup before in case you want to go back, right? Well, I told you to :D
Conclusion and Acknowledgments
Hope you enjoyed this full tutorial on everything needed to compile, test and install a kernel on a NexusOne or on a Magic with CyanogenMod installed. I would like to thank you all that have done the hard work of writing tutorials on how to do so before [here|here], the guys that maintain CyanogenMod [here|here] and those who wrote the perl script to extract the two images from the boot.img file [here]. Mine has been just a work of aggregation. But I wanted to have everything working and described in a single post.
Cheers.
~C
