Wednesday, August 18, 2010

Nexus One (HTC Passion): compile and flash a kernel

Update 2: my camera doesn't work with the custom kernel. no idea why. Also, I figured out how to extract the boot.img from the phone directly.

Update: mention how to update the bcm4329.ko wifi driver so that wifi will work again.

This page will tell you how to download and compile the android kernel, and try it out on your phone temporarily (without writing it to flash) using "fastboot boot zImage".

Assuming that worked, here's how to actually write the kernel to the phone's flash.

By this point you should already have fastboot. You'll also need a phone with an unlocked bootloader and probably rooted as well.

You'll also need the boot.img from your phone. It seems to be possible to pull it off a working phone, but I didn't try that. I'm running cyanogen 6, and the boot.img was in the update-cm-6.0.0-N1-RC3-signed.zip.

Next you need to unpack it using the split_bootimg perl script which I found in this tutorial.

That produced output like this:
$ ./split_bootimg.pl boot.img
Page size: 2048 (0x00000800)
Kernel size: 2206592 (0x0021ab80)
Ramdisk size: 167182 (0x00028d0e)
Second size: 0 (0x00000000)
Board name: 
Command line: no_console_suspend=1 msmsdcc_sdioirq=1 wire.search_count=5
Writing boot.img-kernel ... complete.
Writing boot.img-ramdisk.gz ... complete.

Next, you need mkbootimg. Supposedly you can use "fastboot flash:raw" to avoid this, but it didn't work for me. mkbootimg comes with the (multi-gigabyte) android sources, so I ended up downloading a pre-compiled mkbootimg binary, which made me feel dirty, but saved me many hours of downloading and compiling.

Constructing the right command line for mkbootimg was a pain, but eventually I was able to build a my-boot.img identical to the original:

./mkbootimg --kernel boot.img-kernel --ramdisk boot.img-ramdisk.gz -o my-boot.img --cmdline 'no_console_suspend=1 msmsdcc_sdioirq=1 wire.search_count=5' --base 0x20000000

The boot.img-kernel and boot.img-ramdisk.gz came from split_bootimg, as did the --cmdline string. The "--base 0x20000000" is specific to the N1 (aka nexus one aka HTC passion).

Once you get the boot.img constructed properly, reboot into the bootloader by holding down the trackball while you boot (or use "adb reboot-bootloader"). Then:
$ sudo ./fastboot flash boot my-boot.img
$ sudo ./fastboot reboot

If you get it wrong, your phone will hang at the screen with the unlocked padlock forever. Pull the battery to cold boot and reboot into the bootloader again.

(Nexus One / HTC Passion): If that worked, you may find that "wifi" under Settings... on the phone just says "error". That's because the bcm4329.ko kernel module doesn't match the kernel version.

Here's the bcm4329.ko that matches this 2.6.32 kernel (which has the serial port enabled).

The kernel module lives in /system/lib/modules/. The /system filesystem was mounted read-only on my phone, so from the root shell on my phone (adb shell) I remounted it read-write and then backed up the original kernel module, so that I can switch back to the old kernel if I need to:
# mount -oremount,rw /system
# cp /system/lib/modules/bcm4329.ko /sdcard/bcm4329.ko-orig

Then I copied over the file with "adb push bcm4329.ko /system/lib/modules/", then remounted /system back to read-only:
# mount -oremount,ro /system

It started working immediately.

2 comments:

Possamai said...

Does not work, I have the same kernel :(
Always shows me "error"...

Danny Lawrence said...

Greaat read thankyou