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-sizereturns the maximum amount of data that can be written to the device using thedownloadcommand, if there is a limit.productreturns the product name, e.g. “krillin” on the bq Aquaris E4.5 Ubuntu Edition.kernelreturns “lk” on the bq Aquaris E4.5 Ubuntu Edition.versionreturns “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 thegetvarwire command with the given variable.format: Formats the given partition. The client will first request thepartition-typeof 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-sizeis requested and an empty filesystem image generated on/tmpon 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 thesignaturecommand.reboot: Issues therebootwire command.reboot-bootloader: Issues thereboot-bootloaderwire command.continue: issues thecontinuewire 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 thebootwire command.flash []: Checks themax-download-sizethe 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.imgetc.) 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.txtand requests every key using thegetvarcommand. 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.imgand 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:
$ fastboot getvar kernel getvar version
kernel: lk
version: 0.5
The following command line options are supported:
-w: Erase and format theuserdataandcachepartitions before executing any other commands.-u: Erase partitions before flashing them.-b: Set an alternative base address for thebootandflash:rawcommands.-n: Set an alternative page size for thebootandflash:rawcommands (default: 2048).-s: Set a target device serial number in case multiple devices are connected. Can also be set through theANDROID_SERIALenvironment variable.-S: Overrides the themax-download-sizelimit reported by the device.-l: List device paths when executing thedevicescommand.-p: Set the product name, can also be set through theANDROID_PRODUCT_OUTenvironment 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!
