Hacking Ubuntu Touch, Part 3: How images are flashed
NOTE: This is a continuation of the previous article in the series. Thanks to Barry Warsaw, Oliver Grawert, Jani Monoses and Ondrej Kubik from Canonical for their assistance.
UPDATE 07.05.2015: Thanks to Barry Warsaw for pointing out why the
version archive has to be unpacked to the phone.
We now know what an image is and what it looks like on the inside, but at this point you may wonder: How do all these binary blobs, the ext4 filesystem image and the custom tarball get flashed into device memory? What does ubuntu-device-flash do with them and what happens during the process?
Let’s look at what happens after I use
ubuntu-device-flash to completely reset my bq Aquaris E4.5 Ubuntu Edition to its pristine state using the following command (here I explain the necessity of the
--recovery-image parameter for this device):
Some of the actions, e.g the upload of the signing keys and tarballs, actually run in parallel, but I list everything in the order in which the processes are spawned, and I assume that the action described in the current step has been successfully completed before the next step begins.
Preparing the environment
fastboot getvar productcommand to detect the attached device. This process blocks until the device is in fastboot mode. Once it shows up,
ubuntu-device-flashstarts downloading the image for the detected device (if necessary).
When the device is ready and the image has been successfully downloaded,
fastboot flash recovery /tmp/recovery.imgis spawned to upload the specified temporary recovery image to the internal recovery partition of the phone. This takes about two seconds on my device.
fastboot format cacheis spawned to format the internal cache partition of the device. This takes about two seconds.
fastboot boot /tmp/recovery.imgis spawned to upload the specified temporary recovery image to the device and boot it once.
The device boots into the temporarily uploaded recovery image.
Uploading the image files
The device has restarted, rebooted into Recovery Mode and runs an ADB server.
adb shell lsuntil this is successfull and returns the right directory entries, indicating that the device has booted into recovery.
adb shell rm -rf /cache/recovery/*.xz /cache/recovery/*.xz.ascis spawned to delete any old image files from the cache partition.
adb push /home/sturmflut/.cache/ubuntuimages/ubuntu-touch/stable/krillin/version-21.tar.xzis spawned to push the image metadata file to the phone.
adb push /home/sturmflut/.cache/ubuntuimages/gpg/image-signing.tar.xzis spawned to push the image signing keys to the device. This archive contains the following two keys:
adb push /home/sturmflut/.cache/ubuntuimages/pool/device-0142302186687e3e48e6987283f6caf5d471a4160f98aa6a3cb7658f96471297.tar.xzis spawned to push the device tarball to the device.
adb push /home/sturmflut/.cache/ubuntuimages/gpg/image-master.tar.xzis spawned to push the image master keys to the device.
adb push /home/sturmflut/.cache/ubuntuimages/pool/custom-80897f6b2dbcbc12a01735e0fc965a6cc2cdb346f1da05b919406a7790565523.tar.xzis spawned to push the custom tarball to the device.
adb push /home/sturmflut/.cache/ubuntuimages/pool/ubuntu-d2dfa371c65640e688fd9272b3ede7dbddbfed27f548a0d988c083b1d1c78158.tar.xzis spawned to push the ubuntu tarball to the device.
A temporary commands file is generated and uploaded to the phone as
adb reboot recoveryis spawned to reboot the phone into the temporarily uploaded recovery system.
The Recovery Mode environment
At this point the phone reboots a second time into Recovery Mode and the recovery init system starts
/sbin/recovery as always, but this time there’s a difference: it detects the
/cache/recovery/ubuntu_command commands file uploaded earlier and spawns
/sbin/system-image-upgrader instead of showing the usual user menu. The Ubuntu circle will start spinning on the display and flashing begins.
Maybe we should have a look a the environment before we progress, especially the flash partitions and filesystems information that has been dumped to
The first hexadecimal value after the partition name indicates the size of the partition and the second value is the start offset in bytes. The last partition ends at 0x1D02FFFFF, which is 7427 megabytes in, so not all of the 8 gigabytes of flash memory in the device are accessible.
Notice that the first seven partitions point to the same block device,
mmcblk0. Why? Because they are not part of the partition table, but are special partitions which have a fixed location and a fixed size, depending on how the manufacturer designed the hardware. The kernel creates a character device for each so you don’t have to fiddle with offsets:
Of all these partitions, only three (the first entry is a ramdisk and the “emmc” ones are fake devices) are used as actual filesystems, namely
The “system-image-upgrader does the work” part
system-image-upgrader interprets the commands from the
/cache/recovery/ubuntu_command commands file. I’ve written about this file a couple of times already, and now is the moment to look at it.
This is pretty much what one would expect, but I’ll explain the steps:
systempartitions are formated as ext4 filesystems.
The GPG keyrings are loaded and validated against their signature files, which are signed by GPG key IDs 3F272F5B and D265EACD (the Ubuntu master signing keys).
systempartition is mounted.
ubuntuarchive is unpacked to
/and validated against its signature. If you’ve wondered why all the contents of the archive is in a
system/sub-directory, this is why: It has to end up in
/systeminside the Recovery Environment.
devicearchive is unpacked to
/and validated against its signature. We’ve looked at this archive in the previous article, and we know that it contains binary blob images (
boot.img) besides an Android bit container. It will probably be surprising for many that those binary blobs are written to their respective partitions in this step as well! So the
unpackcommand also includes flashing raw images to partitions!
customarchive is unpacked to
/and validated against its signature.
versionarchive is unpacked to
/and validated against its signature. This is necessary because the system-image client on the device, which will later care about OTA updates, needs the metadata to know wich image server to download from, which channel to use etc.
systempartition is unmounted.
At this time the phone is fully flashed and the system reboots normally.
If you know better and/or something has changed, please find me on Launchpad.net and do get in contact!