Monday, January 10, 2011

HOWTO: install a custom kernel on HTC Desire

=== Disclaimer ===

I take no responsibility for anything that may go wrong by you following these instructions. Proceed at your own risk!

I tested this howto with a Bravo HTC Desire, rooted with Unrevoked 3.22.

=== Requirements ===

- A rooted HTC Desire (Bravo)

- The android SDK + NDK (to get the cross-compile toolchain):

- The latest HTC Desire kernel (choose "HTC Desire - Froyo MR - 2.6.32 kernel source code")

- The koush's AnyKernel template (to generate the at the end of the build process)

=== HOWTO ===

- Prepare the cross-compiler environment (replace /opt/android with the path where you have installed the Andorid NDK):

$ export PATH=/opt/android/android-ndk-r5/toolchains/arm-eabi-4.4.0/prebuilt/linux-x86/bin:$PATH

At this point arm-eabi-gcc, as well as other binutils and compiler binaries, should be in your $PATH.

- Untar the kernel

- save the kernel config (if you want to restore the original kernel config):
$ adb pull /proc/config.gz

- [optional] Apply the following patches to the kernel:
   - 0001-sync-disable-fsync-fdatasync-sync_file_range-syscall
   - 0002-writeback-change-default-dirty-memory-settings
   - 0003-sched-replace-CFS-with-the-BFS-scheduler

- [optional] Take my kernel configuration:
$ wget -O bravo-2.6.32-gd96f2c0/.config

Or use the previously saved config.gz either.

- Build the kernel:
$ cd bravo-2.6.32-gd96f2c0/
$ make ARCH=arm CROSS_COMPILE=arm-eabi- oldconfig
$ make ARCH=arm CROSS_COMPILE=arm-eabi-

Now you should find the fresh new kernel, ready to be flashed on your HTC Desire, in arch/arm/boot/zImage.

- Apply the following patch to the koush's AnyKernel source (to fix a syntax error when trying to flash from ClockworkMod):
   - 0001-updater-script-specify-the-mount-options-for-the-sys

- Replace the zImage in the AnyKernel template with your zImage:
$ cp bravo-2.6.32-gd96f2c0/arch/arm/boot/zImage AnyKernel/kernel/zImage

- Go back to the template directory (you will see three subdirectories: META-INF, kernel & system) and generate the
$ zip -r ../ *

- Connect your phone via a USB cable (be sure to turn on USB debugging on your phone: Settings -> Applications -> Development -> USB debugging)

- Push and the wireless module to the SD card of your phone:
$ adb push /sdcard/
$ adb push bravo-2.6.32-gd96f2c0/drivers/net/wireless/bcm4329_204/bcm4329.ko /sdcard/bcm4329.ko

- Reboot your phone in ClockworkMod recovery (power-on while holding Volume down key and select RECOVERY)

- In ClockworkMod select "apply" (confirm: choose Yes)

- Reboot your phone via "reboot system now"

At this point your custom new kernel should boot.

=== Fix the bcm4329 wireless module loading without S-OFF ===

The bcm4329.ko module can't be properly overwritten in the /system partition without S-OFF the device and so give access in read-write to the /system partition. However, we can enforce the usage of our new module binding any other writable directory to /system/lib/modules (i.e., /data/local).

- the latest ARM toolchain downloadable from the CodeSourcery site

Download and install the ARM toolchain and be sure that arm-none-linux-gnueabi-gcc is in your $PATH.

- get the latest version of busybox from git (or download a recent stable version if you prefer):
$ git clone git://

- use my busybox config file:
$ cd busybox
$ wget -O .config

- cross-compile busybox:
$ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- oldconfig
$ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi-

- copy the busybox binary into the /data/local directory on your phone:
$ adb push busybox /data/local/busybox

- bind the directory /system/lib/modules with /data/local:
$ adb shell
$ su
# cat /sdcard/bcm4329.ko > /data/local/bcm4329.ko
# /data/local/busybox mount --bind /data/local /system/lib/modules

After this trick go on your phone check Settings -> Wireless & networks -> Wi-Fi. The wireless connection should start normally.

=== Results ===

Here is my score with this kernel using the Quadrant benchmark: 1370!


cony said...

Hi,arighi. I have som problem when porting my custom kernel on my HTC Desire when following your steps. I custom my kernel with Oprofile function in the configuration. However, after the whole step I followed in your articles, the oprofile doesn't exit in my system. Did you know where might be the problem? I was thinking that the problem could be at the process when I used koush's program to put my kernel into the boot.img. Do you have any idea about this? Also, without using the koush's program,I couln't find other desire's tutorial of putting the kernel into the boot.img. Did you know other way that I can try to? thanks~

Esben Sune Rasmussen said...

Excellent post :-) although i can't seem to download the updater script patch..

Best regards, Esben

Fatih said...

Hi Andrea,

Your Blog is so good and usefull. I want to ask you a question.
I don't understand correctly "how to compile a C program for HTC desire?"

For example this is hello.c file;
int main()
printf("hello android.");
return 0;

when I tried to
# arm-eabi-gcc hello.c
it gives lots of error. Where is header files in NDK?

Thx in Advance,

arighi said...

@Fatih: to compile my own C programs I used the gcc/g++ toolchain available from the CodeSourcery website; here's the latest one:

arighi said...

@Esben Sune Rasmussen: are you sure? the link doesn't seem broken:

arighi said...

@cony: did you build oprofile as a module? try to build it statically in the kernel.