[LG Optimus Black] aprold:
I was teaching myself CM7 kernel build process yesterday (more here) and stumbled across AnyKernel. Big thanks to Koush! However whatever I tried I was not able to get rid of segmentation fault error in unpackbootimg. But I liked the AnyKernel idea so much that I cooked up my own version of it. Lets call it Kernel Injector. Whenever you want to deploy your kernel image you don't have to mess around with read-split-merge-write-boot-image procedure any more. This is all done by the update script now:

ui_print("");
ui_print("Kernel Injector by Aprold");
mount("ext4", "EMMC", "/dev/block/mmcblk0p8", "/system");
ui_print("Extracting files...");
package_extract_file("zImage", "/tmp/zImage");
package_extract_dir("modules", "/system/lib/modules");
package_extract_file("kinjector", "/tmp/kinjector");
set_perm(0, 0, 0777, "/tmp/kinjector");
ui_print("Injecting kernel...");
assert(run_program("/system/bin/dd", "if=/dev/block/mmcblk0p3", "of=/tmp/boot.img")=="0");
assert(run_program("/tmp/kinjector", "/tmp/boot.img", "/tmp/zImage", "/tmp/boot.new")=="0");
assert(run_program("/system/bin/dd", "if=/tmp/boot.new", "of=/dev/block/mmcblk0p3")=="0");
unmount("/system");
ui_print("Done!");

Boot image is read and written using system's own dd. Combining kernel image with existing ramdisk is the job for kinjector:

/* Kernel Injector by Aprold */

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>

int main(int argc, char **argv) {
FILE *in, *out;
unsigned char *header_buf, *kernel_buf, *ramdisk_buf;
unsigned page_size, *kernel_size, kernel_buf_size, ramdisk_size, ramdisk_buf_size;

if (argc < 3) {
printf("Usage: %s <existing boot image> <new kernel image> [new boot image]\n", argv[0]);
return 1;
}
// open existing boot image for reading header and ramdisk from there
if (in = fopen(argv[1], "rb")) {
// get page size from input file
fseek(in, 36, SEEK_SET);
fread(&page_size, sizeof(page_size), 1, in);
fseek(in, 0, SEEK_SET);
// read header
header_buf = (unsigned char*)malloc(page_size);
fread(header_buf, page_size, 1, in);
// get kernel and ramdisk sizes from header
kernel_size = (unsigned*)header_buf + 2;
ramdisk_size = *((unsigned*)header_buf + 4);
// read ramdisk
ramdisk_buf_size = (ramdisk_size / page_size + 1) * page_size;
ramdisk_buf = (unsigned char*)malloc(ramdisk_buf_size);
fseek(in, (*kernel_size / page_size + 2) * page_size, SEEK_SET);
fread(ramdisk_buf, ramdisk_buf_size, 1, in);
fclose(in);
// open new kernel image
if (in = fopen(argv[2], "rb")) {
// get kernel size
fseek(in, 0, SEEK_END);
*kernel_size = ftell(in);
fseek(in, 0, SEEK_SET);
// read kernel
kernel_buf_size = (*kernel_size / page_size + 1) * page_size;
kernel_buf = (unsigned char*)malloc(kernel_buf_size);
fread(kernel_buf, *kernel_size, 1, in);
memset(kernel_buf + *kernel_size, 0, kernel_buf_size - *kernel_size);
// frite new boot image
out = fopen(argv[argc > 3 ? 3 : 1], "wb");
fwrite(header_buf, page_size, 1, out);
fwrite(kernel_buf, kernel_buf_size, 1, out);
fwrite(ramdisk_buf, ramdisk_buf_size, 1, out);
fclose(out);
free(kernel_buf);
}
else {
printf("Failed to open kernel image %s\n", argv[2]);
return 2;
}
free(header_buf);
free(ramdisk_buf);
}
else {
printf("Failed to open boot image %s\n", argv[1]);
return 1;
}

return 0;
}

Compile it like that:

/usr/bin/arm-linux-gnueabi-gcc -static -o kinjector kinjector.c

Included is an update.zip which you can use as a reference for your own script. Tested with my phone and I even managed to not brick it.

All comments and suggestions are most welcome!

- Aprold