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):
$ ubuntu-device-flash touch --bootstrap --wipe --recovery-image /tmp/recovery.img
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
:
Partition Information:
preloader 0x0000000001400000 0x0000000000000000 2 /dev/misc-sd
mbr 0x0000000000080000 0x0000000000000000 2 /dev/block/mmcblk0
pro_info 0x0000000000300000 0x0000000000100000 2 /dev/block/mmcblk0
nvram 0x0000000000500000 0x0000000000400000 2 /dev/block/mmcblk0
seccfg 0x0000000000020000 0x0000000001d00000 2 /dev/block/mmcblk0
uboot 0x0000000000060000 0x0000000001d20000 2 /dev/block/mmcblk0
bootimg 0x0000000001400000 0x0000000001d80000 2 /dev/block/mmcblk0
recovery 0x0000000001400000 0x0000000003180000 2 /dev/block/mmcblk0
misc 0x0000000000080000 0x0000000004b80000 2 /dev/block/mmcblk0
logo 0x0000000000300000 0x0000000004c00000 2 /dev/block/mmcblk0
expdb 0x0000000000a00000 0x0000000004f00000 2 /dev/block/mmcblk0
bmtpool 0x0000000000000000 0x00000000febf00a8 2 /dev/block/mmcblk0
ebr1 0x0000000000080000 0x0000000000080000 2 /dev/block/mmcblk0p1
protect_f 0x0000000000a00000 0x0000000000900000 2 /dev/block/mmcblk0p2
protect_s 0x0000000000a00000 0x0000000001300000 2 /dev/block/mmcblk0p3
sec_ro 0x0000000000600000 0x0000000004580000 2 /dev/block/mmcblk0p4
cache 0x000000002bc00000 0x0000000005900000 2 /dev/block/mmcblk0p5
android 0x0000000080c00000 0x0000000031500000 2 /dev/block/mmcblk0p6
usrdata 0x000000011e200000 0x00000000b2100000 2 /dev/block/mmcblk0p7
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:
$ ls -la /dev/
crw-r----- 1 root system 237, 0 May 6 12:50 preloader
crw------- 1 root root 237, 1 May 6 12:50 mbr
crw------- 1 root root 237, 2 May 6 12:50 ebr1
crw-rw---- 1 root system 237, 3 May 6 12:50 pro_info
crw-rw---- 1 root system 237, 4 May 6 12:50 nvram
crw------- 1 root root 237, 5 May 6 12:50 protect_f
crw------- 1 root root 237, 6 May 6 12:50 protect_s
crw-rw---- 1 root system 237, 7 May 6 12:50 seccfg
crw------- 1 root root 237, 8 May 6 12:50 uboot
crw-r----- 1 root system 237, 9 May 6 12:50 bootimg
crw-r----- 1 root system 237, 10 May 6 12:50 recovery
crw-r----- 1 root system 237, 11 May 6 12:50 sec_ro
crw-rw---- 1 root system 237, 12 May 6 12:50 misc
crw------- 1 root root 237, 13 May 6 12:50 logo
crw------- 1 root root 237, 14 May 6 12:50 expdb
crw------- 1 root root 237, 15 May 6 12:50 cache
crw------- 1 root root 237, 16 May 6 12:50 android
crw------- 1 root root 237, 17 May 6 12:50 usrdata
crw------- 1 root root 237, 18 May 6 12:50 bmtpool
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
:
recovery filesystem table
=========================
0 /tmp ramdisk (null) (null) 0
1 /uboot emmc /dev/uboot (null) 0
2 /boot emmc /dev/bootimg (null) 0
3 /cache ext4 /dev/block/mmcblk0p5 (null) 0
4 /data ext4 /dev/block/mmcblk0p7 (null) 0
5 /misc emmc misc (null) 0
6 /recovery emmc /dev/recovery (null) 0
7 /system ext4 /dev/block/mmcblk0p6 (null) 0
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.
~ # cat /cache/recovery/ubuntu_command.applying
format data
format system
load_keyring image-master.tar.xz image-master.tar.xz.asc
load_keyring image-signing.tar.xz image-signing.tar.xz.asc
mount system
update ubuntu-d2dfa371c65640e688fd9272b3ede7dbddbfed27f548a0d988c083b1d1c78158.tar.xz ubuntu-d2dfa371c65640e688fd9272b3ede7dbddbfed27f548a0d988c083b1d1c78158.tar.xz.asc
update device-0142302186687e3e48e6987283f6caf5d471a4160f98aa6a3cb7658f96471297.tar.xz device-0142302186687e3e48e6987283f6caf5d471a4160f98aa6a3cb7658f96471297.tar.xz.asc
update custom-80897f6b2dbcbc12a01735e0fc965a6cc2cdb346f1da05b919406a7790565523.tar.xz custom-80897f6b2dbcbc12a01735e0fc965a6cc2cdb346f1da05b919406a7790565523.tar.xz.asc
update version-21.tar.xz version-21.tar.xz.asc
unmount system
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!