This week I’ve been hacking some of the initrd scripts in Ubuntu Touch and I thought that I’d share some of the things I learned. All of this work is based on using Image Update images, which are flashable by doing phablet-flash ubuntu-system. First, why would you want to do this? Well, the initrd includes a script called “touch” which sets up all of the partitions and does some first boot migration. I wanted to modify how this process works for some experiments on customizing the images.
Before getting started, you need the following packages installed on your dev box: abootimg, android-tools-adb, android-tools-fastboot
Note: I was told after posting this that it won’t work on some devices, including Samsung devices, because they use a non-standard boot.img format.
Getting the initrd
The initrd is inside the boot.img file. I pulled mine from here, but you can also get it by dding it off of the phone. You can find the boot partition on your device with the following scriptlet, taken from flash-touch-initrd:
for i in $BOOT; do
path=$(find /dev -name "*$i*"|grep disk| head -1)
[ -n "$path" ] && break
Once you have the boot.img file by whatever means you used, you need to unpack it. abootimg is the tool to use here, so simply run abootimg -x [boot.img]. This will unpack the initrd, kernel and boot config file.
Unpacking and Hacking the initrd
Now that you have the initrd, you need to unpack it so you can make changes. You can do this with some cpio magic, but unless you have a UNIX-sized beard, just run abootimg-unpack-initrd . This will dump everything into a folder named ramdisk. (UNIX beard guys: mkdir ramdisk; cp initrd ramdisk; cd ramdisk; cat initrd | gzip -d | cpio -i)
To make changes, simply cd into ramdisk and hack away. For this example, I’m going to add a simple line to ramdisk/scriprts/touch. My line is
echo "mfisch: it worked!" > /dev/kmsg || true
This will log a message to /var/log/kern.log which can assist us to make sure it worked. Your change will probably be less trivial.
Repacking the initrd is simple. To repack, just run abootimg-pack-initrd [initrd.img.NEW] Once you do this you’ll notice that the initrd size is quite different, even if you didn’t make any changes. After discussing this with some people, the best I can figure is that the newly packed cpio file has owners and non-zero datestamps, which make it slightly larger. One clue, when compared to mkinitramfs, abootimg-pack does not use the -R 0:0 argument and there are other differences. If you want to do this the hard way, you can also repack by doing: cd ramdisk; find . | cpio -o -H newc | gzip -9 > ../initrd.img.NEW
Rebuilding the boot image
The size change we discussed above can be an issue that you need to fix. In the file bootimg.cfg, which you extracted with abootimg -x, there is a line called bootsize. This line needs to be >= the size of the boot.img (not initrd). If the initrd file jumped by 4k or so, like mine did, be sure to bump this as well. I bumped mine from 0×837000 to 0×839000 and it worked. If you don’t do this step, you will wind up with a non-booting image. Once you correct this, rebuild the image with abootimg:
abootimg --create saucy-new.img -f bootimg.cfg -k zImage -r initrd.img.NEW
I’ve found that if your size is off, it will sometimes complain during this step, but not always. It’s best to check the size of saucy-new.img with the line you changed in bootimg.cfg at this point.
Flashing and testing
To flash the new boot image, reboot the device and use fastboot.
adb reboot bootloader
fastboot flash boot saucy-new.img
Use the power button to boot the device now.
Once booted you can go check out the kern.log and see if your change worked.
Aug 13 16:11:04 ubuntu-phablet kernel: [ 3.798412] mfisch: it worked!
Looks good to me!
Thanks to Stephane Graber and Oliver Grawart for helping me discover this process.