[Milestone XT720 Android Development] Mioze7Ae:
This works damn it!!!!

Confirmed. "fastboot boot boot.img" works with a modified kernel.

THE PLAN

I don't know how to build a kernel so instead I decided to modify a working Motorola XT720 kernel. For the basis of this experiment I used the boot.img (derived from on UK STR_U2_01.1E.0 md5sum=9e51b3352389865457363bdf93401419) that Dexter's been using in his ROMs. To verify that I'm actually running modified fastbooted kernel, I change the kernel's output for "uname -a". Using the unmodified kernel the output is:

# busybox uname -a
Linux localhost 2.6.29-omap1 #1 PREEMPT Tue Jul 13 17:19:35 IST 2010 armv7l GNU/Linux

My goal was to change the "#1" to "#9" so that after fastbooting the modified kernel I would see:

# busybox uname -a
Linux localhost 2.6.29-omap1 #9 PREEMPT Tue Jul 13 17:19:35 IST 2010 armv7l GNU/Linux

ANATOMY OF DEXTER'S BOOT.IMG

The kernel is gzipped, so in order to modify the strings used by uname, we have to extract the kernel image, gunzip it, modify it, gzip the modified kernel, replace the gzipped kernel in boot.img. Following http://xdaforums.com/showthread.php?t=777380 to discover the start of the kernel.gz, I identified this layout in boot.img

# 0x000000 boot.img : first byte
# 0x000800 boot.img-kernel : first byte
# 0x003B75 kernel.gz : first byte
# 0x279213 kernel.gz : last byte
# 0x279287 boot.img-kernel : last byte
# 0x279800 boot.img-ramdisk.gz : first byte
# 0x2AF7A6 boot.img-ramdisk.gz : last byte
# 0x37ffff boot.img : last byte

I found the end of the kernel.gz using a binary search by extracting different sizes until gzip stopped complaining about trailing garbage or missing data.

MODIFYING BOOT.IMG

I then split boot.img into three parts as follows:

#!/bin/bash

extract () {
# extract outfile first last
dd if=boot.img of=$1 bs=1 skip=$(( 16#$2 )) count=$(( 16#$3 - 16#$2 + 1 ))
}

extract boot-front 000000 003B74
extract boot-kernel.gz 003B75 279213
extract boot-back 279214 37FFFF

I then modified the kernel

$ gunzip -c boot-kernel.gz > boot-kernel
$ sed "s/#1 PREEMPT/#9 PREEMPT/g" boot-kernel > new-kernel
$ diff <(hexdump -C boot-kernel) <(hexdump -C new-kernel)
248302c248302
< 003cd190 43 43 29 20 29 20 23 31 20 50 52 45 45 4d 50 54 |CC) ) #1 PREEMPT|
---
> 003cd190 43 43 29 20 29 20 23 39 20 50 52 45 45 4d 50 54 |CC) ) #9 PREEMPT|
315155c315155
< 004d9b00 00 00 00 00 00 00 00 00 00 00 00 23 31 20 50 52 |...........#1 PR|
---
> 004d9b00 00 00 00 00 00 00 00 00 00 00 00 23 39 20 50 52 |...........#9 PR|

The next step is to compress the modified kernel. To get a new kernel that was smaller than the original one, I used:

$ gzip -cn -8 new-kernel > new-kernel.gz
$ ls -l boot-kernel.gz new-kernel.gz
-rw-r--r-- 1 Mioze7Ae Mioze7Ae 2577695 2011-03-09 16:06 boot-kernel.gz
-rw-r--r-- 1 Mioze7Ae Mioze7Ae 2577683 2011-03-09 16:04 new-kernel.gz

To overlay the new kernel on top of the old kernel:

$ dd if=new-kernel.gz of=boot-kernel.gz conv=notrunc
$ zcat boot-kernel.gz | md5sum - new-kernel

and then assemble the modified boot.img

$ cat boot-front boot-kernel.gz boot-back > modified.img

TESTING

Boot into the fastboot bootloader using

$ adb reboot bootloader

This is not the same as the bootloader used for flashing. It actually says "Fastboot" on top. Then boot the modified kernel (I had to use sudo to get fastboot to work).

$ sudo ./fastboot devices
XXXXXXXXXXXXXXX	fastboot
$ sudo ./fastboot boot modified.img
downloading 'boot.img'... OKAY [ 0.346s]
booting... OKAY [ 3.657s]
finished. total time: 4.003s

Wait for the phone to boot and then:

[B]
$ adb shell busybox uname -a
Linux localhost 2.6.29-omap1 [COLOR="Red"]#9[/COLOR] PREEMPT Tue Jul 13 17:19:35 IST 2010 armv7l GNU/Linux
[/B]

DON'T BOTHER TRYING TO NANDROID THE MODIFIED BOOT.IMG, I'VE CONFIRMED THAT THE BOOTLOADER WILL REJECT IT AND FALLBACK TO A PREVIOUS BOOT.IMG. I'm not yet sure if it fallsback to the last bootloader-verified boot.img or to the sbf-flashed boot.img. If you try nandroid anyway (perhaps because you think I'm not technically competent to test nandroid) I recommend immediately reflashing a known good kernel in OpenRecovery and rebooting between each attempt. The phone has two boot.img. I'm not sure if the backup one comes from the sbf or if somehow the active one is alternated by the bootloader after each successful validation. My superstition is to let the bootloader see two known good kernels between each attempt. BE VERY CAREFUL. fastboot boot boot.img doesn't flash anything--that should be safe.

UPDATE 06/26/2012 FOR THE SAKE OF POSTERITY: It turns out that there was a bug in our custom recovery that prevented nandroid from writing to boot.img (details: the recovery kernel creates the boot raw device as read-write, but normal boot creates the device as read-only. Since we use a bootstrapped recovery that hijacks normal boot we had a read-only boot), so in reality it doesn't "fallback" to a previous version... nandroid never installed it. In fixed open recovery writing a modified boot.img causes a soft-brick that can be rescued from sbf.