Implementing Fastboot in UEFI

Terms and abbreviations

  • UEFI: Unified Extensible Firmware Interface,

  • Fastboot: protocol used by Android host tools to maniplulate the target filesystem; there is number of articles that describes it, like

  • HAL: hardware abstraction layer. In this article - board-dependent driver or library that provides generic interface to another driver
  • protocol (in terms of UEFI): set of functions, that may be called by "protocol consumer" and shall be implemented by "protocol provider".

Target hardware

Currently, the PandaBoard. It is expected that, with replaced HAL, it could be run on VExpress or Arndale


  • Bero for Juice and Android
  • Grant Likely as Linaro‚Äôs UEFI Architect

Other contacts

  • #linaro-enterprise talk to ronynandy (UEFI USB driver for Arndale)


To build the UEFI for the PandaBoard, run commands

git clone git:// uefi-fastboot
cd uefi-fastboot
git checkout fastboot-20130613
export CROSS_COMPILE=arm-linux-gnueabi-
pushd PandaBoardPkg

In case of success build, you will have the files Build/PandaBoard/DEBUG_ARMLINUXGCC/FV/MLO and Build/PandaBoard/DEBUG_ARMLINUXGCC/ARM/FastbootApp.efi generated. You should put these files to the root of 1st, FAT-formatted partition of SD card.

Also, there is a script in the root of the git repository.

Sources and comments

The Fastboot implementation consists of several major parts:

  • changes the main boot code to enable execution of fastboot
  • the fastboot application, that uses the fastboot protocol
  • the implementation of fastboot protocol, that calls the usb driver
  • the usb driver, which in turn consists of hardware-dependent and generic parts.

public interfaces

UsbGadgetProtocol, from MdePkg/Include/Protocol/UsbGadget.h

typedef struct _EFI_USB_GADGET_PROTOCOL {

        EFI_STATUS EFIAPI (*Alloc)(VOID *Context);
        EFI_STATUS EFIAPI (*Free)(VOID *Context);       // NOT IMPLEMENTED

        EFI_STATUS EFIAPI (*Init)(VOID *Context);
        EFI_STATUS EFIAPI (*Connect)(VOID *Context);
        EFI_STATUS EFIAPI (*Disconnect)(VOID *Context);
        EFI_STATUS EFIAPI (*Enable)(VOID *Context);
        EFI_STATUS EFIAPI (*Disable)(VOID *Context);
        EFI_STATUS EFIAPI (*StartupEvents)(VOID *Context);
        EFI_STATUS EFIAPI (*Interrupt)(VOID *Context);

        EFI_STATUS EFIAPI (*SetupEP)(VOID *Context, UINTN id, VOID *_Ep);
        EFI_STATUS EFIAPI (*WriteURB)(VOID *Context, VOID *_Urb);

extern EFI_GUID gEfiUSBGadgetProtocolGuid;

UsbGadgetFastboot protocol, from FastbootPkg/Include/Protocol/UsbGadgetFastboot.h

        EFI_STATUS (*Connect)(VOID **Context);
        EFI_STATUS (*Read)(VOID *Context, UINT8 *Bytes, UINTN BytesSize, UINTN *BytesRead);
        EFI_STATUS (*Write)(VOID *Context, UINT8 *Bytes, UINTN BytesSize, UINTN *BytesWritten);
        EFI_STATUS (*Print)(VOID *Context);
        EFI_STATUS (*Close)(VOID *Context);

extern EFI_GUID gEfiUsbGadgetFastbootProtocolGuid;

main boot code

This patch adds the needed functionality. This is function DefineFastBoot, which is called from the file Bds.c. The function adds new boot entry, depending on the PcdEnableFastboot compile-time variable. However, for debugging purposes, I compiled stand-alone FastbootApp.efi binary, put it to the SD card boot partition and execute it from shell by typing command

> fs0:
> FastbootApp.efi

fastboot application

This is the loop reading from driver implementing fastboot protocol (which reminds the exchange over the serial line), handling commands and sending responses. Sources are in FastbootPkg/Application. The application gets the pointer to UsbGadgetFastbootProtocol, and then calls its methods (Open, then Read/Write, and Close on exit).

fastboot protocol driver

This is the driver that implements protocol used by fastboot app -- and consumes protocol provided by usb driver. It needs to instantiate a lot of structures to register with usb driver -- USB_GADGET_INSTANCE, USB_STRING_DESCRIPTOR, USB_DEVICE_DESCRIPTOR etc. Sources are in FastbootPkg/Protocol The driver requests the pointer to the UsbGadget protocol. On init, the following methods of the gadget driver will be called (sequence matters) with the pointer to USB_GADGET_INSTANCE structure:

This allows it to enter stable state waiting for the connection (USB cable plug-in)

Then, once the application calls UsbFastbootGadget::Read, the driver enters busy loop calling UsbGadget::Interrupt. All service interrupts will be processed inside the UsbGadget driver, and once the USB device gets address assigned, configured, and receives the data on endpoint 1 (0x01, data in), this data will be reported back to caller.

When the application calls UsbFastbootGadget::Write, the driver will get next URB (USB Request Block) using USBD_Next_URB and directly call UsbGadget::WriteURB to send the response on endpoint 2 (0x82, data out).

usb driver, generic part

The generic part of the usb driver is the library, with sources in MdeModulePkg/Library/UsbGadgetLib. This library provides several functions with prefix of USBD_

usb driver, hardware dependend part

This is the "real" driver. It exposes the UsbGadget interface and implements it - with the help of UsbGadgetLib. No function in this interface can be NULL -- all of them will be called by (in our case) fastboot protocol driver. Sources are in Omap44xxPkg/UsbGadgetDxe

This is the most complex part of the code; code is splitted to several source files to ease understanding and modifications. The most interesting part is Peri.c, where all the functions that deals with hardware are located. Also, Interrupt.c (where the processing of IRQ is placed), SetupEp.c (configuring endpoints) and WriteURB.c (sending out the data) are also the places to review.

ARM/UEFI/FastBoot (last modified 2013-11-25 06:59:59)