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
-
ubuntu-device-flash
uses thefastboot getvar product
command to detect the attached device. This process blocks until the device is in fastboot mode. Once it shows up,ubuntu-device-flash
starts 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.img
is 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 cache
is spawned to format the internal cache partition of the device. This takes about two seconds. -
fastboot boot /tmp/recovery.img
is 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.
-
ubuntu-device-flash
repeatedly callsadb shell ls
until 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.asc
is spawned to delete any old image files from the cache partition. -
adb push /home/sturmflut/.cache/ubuntuimages/ubuntu-touch/stable/krillin/version-21.tar.xz
is spawned to push the image metadata file to the phone. -
adb push /home/sturmflut/.cache/ubuntuimages/gpg/image-signing.tar.xz
is 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.xz
is spawned to push the device tarball to the device. -
adb push /home/sturmflut/.cache/ubuntuimages/gpg/image-master.tar.xz
is spawned to push the image master keys to the device. -
adb push /home/sturmflut/.cache/ubuntuimages/pool/custom-80897f6b2dbcbc12a01735e0fc965a6cc2cdb346f1da05b919406a7790565523.tar.xz
is spawned to push the custom tarball to the device. -
adb push /home/sturmflut/.cache/ubuntuimages/pool/ubuntu-d2dfa371c65640e688fd9272b3ede7dbddbfed27f548a0d988c083b1d1c78158.tar.xz
is spawned to push the ubuntu tarball to the device. -
A temporary commands file is generated and uploaded to the phone as
/cache/recovery/ubuntu_command
viaadb push
. -
adb reboot recovery
is 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 /tmp/recovery.log
:
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 mmcblk0p5
, mmcblk0p6
and mmcblk0p7
:
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:
-
The
data
andsystem
partitions 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).
-
the
system
partition is mounted. -
The
ubuntu
archive is unpacked to/
and validated against its signature. If you’ve wondered why all the contents of the archive is in asystem/
sub-directory, this is why: It has to end up in/system
inside the Recovery Environment. -
The
device
archive 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 (uboot.img
,recovery.img
andboot.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 theunpack
command also includes flashing raw images to partitions! -
The
custom
archive is unpacked to/
and validated against its signature. -
The
version
archive 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. -
The
system
partition 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!