Hacking Ubuntu Touch, Part 8: Fastboot
NOTE: This is a continuation of the series.
NOTE: The information in this article was obtained by analzying the reference implementation client and disecting the protocol traffic with Wireshark. The signature
feature of the reference client seems to be undocumented, most likely for a good reason. Don’t take this as a reference!
Sometimes you need direct access to the lower levels of your device, and we have already looked at how ADB enables developers and power users to do many useful things. But what do you do when you can’t rely on the operating system, which runs the ADB daemon? Maybe you want to push and boot a modified kernel just once? Or your OS is broken and no longer exposes an ADB interface, so you have to re-flash everything?
This is where Fastboot comes in.
Fastboot basics
Fastboot is a simple interface to the Android bootloader. It is much more generic than vendor-specific protocols (look at all the crazy solutions in the MediaTek articles), but allows vendor-specific extensions. Most Android device bootloaders can be switched to Fastboot mode, but not every device might interpret every possible command. A “locked” bootloader e.g. will typically refuse to flash partitions or only let signed images through. Sometimes it may be possible to unlock the bootloader.
Unlike ADB, which also runs over TCP/IP, Fastboot only supports USB. The design is much simpler, there are only the bootloader and a client on the USB Host. The reference client implementation is part of the Android SDK.
The Fastboot wire protocol
The protocol is very simple: It consists of ASCII text commands up to 64 bytes in size, in the form
. All data is transported in USB Bulk mode frames. The bootloader will answer every command with an ASCII text response of up to 64 bytes in length. The following responses are legal:
INFO
, potentially followed by an informational message that the reference client prints tostderr
.OKAY
, potentially followed by a response that may or may not be checked.FAIL
, potentially followed by a failure reason.DATA
, followed by the amount of data the bootloader is willing to accept. This is always compared against the amount of data the client announced as a parameter with the command, and the command is aborted if it wants to send more data than the bootloader can take.
If the command has a payload, it is sent in a second transfer after a positive response.
The following commands are used in the reference implementation:
getvar:
queries a bootloader variable. Every bootloader may expose different variables, the following ones are actively used by the reference client and exposed by the MediaTek Little Kernel:
partition-type:
returns the type of the partition with the given name, e.g. “raw data” or “ext4”.partition-size:
returns the size of the partition with the given name in hexadecimal.max-download-size
returns the maximum amount of data that can be written to the device using thedownload
command, if there is a limit.product
returns the product name, e.g. “krillin” on the bq Aquaris E4.5 Ubuntu Edition.kernel
returns “lk” on the bq Aquaris E4.5 Ubuntu Edition.version
returns “0.5” on the bq Aquaris E4.5 Ubuntu Edition.
erase:
erases the partition with the given name.
download:
sends size
(in hexadecimal, max. 32 bits) bytes of data to the bootloader memory for later processing.
flash:
writes the data the bootloader has previously received using the download
command to the partition with the given name. Note that if multiple pairs of the download
and flash
commands are issued to the same partition, every flash
command will append its data at the end of the previous writes. This means that large partitions have to be written in blocks of max-download-size
bytes.
signature
activates a 256 bytes long signature that was previously sent to the device using the download
command. I am not sure what the bootloader does with this signature, probably it is uses for a cryptographic verification process.
continue
aborts Fastboot mode and the bootloader continues to boot normally.
boot
boots into an Android boot image that was previously sent to the device using the download
command.
reboot-bootloader
reboots into the bootloader.
OEM commands
The bootloader may implement additional, manufacturer-specific commands. These do not follow the usual protocol command format, and they cannot have a payload. Some manufacturers implement a lot of OEM commands, as can be seen here. MediaTek just implements two: fastboot oem p2u on
and fastboot oem p2u off
, these enable or disable the redirection of Linux kernel messages to the UART.
Note that the most well-known OEM command, fastboot oem unlock
, is not available on the most devices. This command was invented by Google for their Nexus devices.
Reference client commands
The reference fastboot client supports the following commands:
devices
: Detects and lists attached devices.getvar
: Issues thegetvar
wire command with the given variable.format
: Formats the given partition. The client will first request thepartition-type
of the partition and compare it against a list of known “generators” (mkfs tools), of which there currently is just one: ext4. If there is a generator for the returned partition type, thepartition-size
is requested and an empty filesystem image generated on/tmp
on the host. This image is then downloaded to device memory and flashed to the given partition.signature
: The given signature file is downloaded to the device and activated using thesignature
command.reboot
: Issues thereboot
wire command.reboot-bootloader
: Issues thereboot-bootloader
wire command.continue
: issues thecontinue
wire command.boot []
: Loads the given kernel image file (and optionally the ramdisk), builds an Android boot image on the fly, downloads the generated image to device memory and issues theboot
wire command.flash []
: Checks themax-download-size
the device supports, then downloads the given image file to the partition with the given name in chunks (“sparse mode”, if necessary). If no filename is given, the client tries to guess the filename from a list of default filenames (boot.img
,recovery.img
etc.) and the product name.flash:raw []
: Loads the given kernel image file (and optionally the ramdisk), builds an Android boot image on the fly, downloads the generated image to device memory and flashes it to the given partition.flashall
: This is probably intended for automated flashing on production lines. The client reads key-value pairs from a configuration file calledandroid-info.txt
and requests every key using thegetvar
command. The responses are compared to the values from the configuration file, making sure that the device is in the expected state. Thenboot.img
,recovery.img
,system.img
and their associated signature files are downloaded, activated and written to the corresponding partitions.update
: Applies a device update from a ZIP archive. This is exactly the same step asflashall
, except that the image and signature files are extracted from the archive.oem
: Sends an OEM command.
The reference client supports the concatenation of commands, e.g. the following works:
The following command line options are supported:
-w
: Erase and format theuserdata
andcache
partitions before executing any other commands.-u
: Erase partitions before flashing them.-b
: Set an alternative base address for theboot
andflash:raw
commands.-n
: Set an alternative page size for theboot
andflash:raw
commands (default: 2048).-s
: Set a target device serial number in case multiple devices are connected. Can also be set through theANDROID_SERIAL
environment variable.-S
: Overrides the themax-download-size
limit reported by the device.-l
: List device paths when executing thedevices
command.-p
: Set the product name, can also be set through theANDROID_PRODUCT_OUT
environment variable.-c
: override the kernel command line used when generating Android boot images on the fly.-i
: Specify a vendor ID in case the client does not detect the USB device.
That’s it for today. If you know better and/or something has changed, please do find me on the Freenode IRC or on Launchpad.net and get in contact!