123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271 |
- /** @file
- Copyright (c) 2014, ARM Ltd. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- /*
- * Implementation of the FASTBOOT_TRANSPORT_PROTOCOL using the USB_DEVICE_PROTOCOL
- */
- #include <Protocol/UsbDevice.h>
- #include <Protocol/AndroidFastbootTransport.h>
- #include <Protocol/SimpleTextOut.h>
- #include <Library/BaseLib.h>
- #include <Library/BaseMemoryLib.h>
- #include <Library/DebugLib.h>
- #include <Library/MemoryAllocationLib.h>
- #include <Library/UefiBootServicesTableLib.h>
- #include <Library/UefiDriverEntryPoint.h>
- STATIC USB_DEVICE_PROTOCOL *mUsbDevice;
- // Configuration attributes:
- // bit 7 reserved and must be 1, bit 6 means self-powered.
- #define CONFIG_DESC_ATTRIBUTES (BIT7 | BIT6)
- #define MAX_PACKET_SIZE_BULK 512
- STATIC USB_DEVICE_PROTOCOL *mUsbDevice;
- STATIC EFI_EVENT mReceiveEvent = NULL;
- STATIC LIST_ENTRY mPacketList;
- // List type for queued received packets
- typedef struct _FASTBOOT_USB_PACKET_LIST {
- LIST_ENTRY Link;
- VOID *Buffer;
- UINTN BufferSize;
- } FASTBOOT_USB_PACKET_LIST;
- /*
- No string descriptors - all string descriptor members are set to 0
- */
- STATIC USB_DEVICE_DESCRIPTOR mDeviceDescriptor = {
- sizeof (USB_DEVICE_DESCRIPTOR), // Length
- USB_DESC_TYPE_DEVICE, // DescriptorType
- 0x0200, // BcdUSB
- 0xFF, // DeviceClass
- 0, // DeviceSubClass
- 0, // DeviceProtocol
- 64, // MaxPacketSize0
- FixedPcdGet32 (PcdAndroidFastbootUsbVendorId), // IdVendor
- FixedPcdGet32 (PcdAndroidFastbootUsbProductId), // IdProduct
- 0, // BcdDevice
- 0, // StrManufacturer
- 0, // StrProduct
- 0, // StrSerialNumber
- 1 // NumConfigurations
- };
- /*
- We have one configuration, one interface, and two endpoints (one IN, one OUT)
- */
- // Lazy (compile-time) way to concatenate descriptors to pass to the USB device
- // protocol
- #pragma pack(1)
- typedef struct {
- USB_CONFIG_DESCRIPTOR ConfigDescriptor;
- USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
- USB_ENDPOINT_DESCRIPTOR EndpointDescriptor1;
- USB_ENDPOINT_DESCRIPTOR EndpointDescriptor2;
- } GET_CONFIG_DESCRIPTOR_RESPONSE;
- #pragma pack()
- STATIC GET_CONFIG_DESCRIPTOR_RESPONSE mGetConfigDescriptorResponse = {
- { // USB_CONFIG_DESCRIPTOR
- sizeof (USB_CONFIG_DESCRIPTOR), // Length;
- USB_DESC_TYPE_CONFIG, // DescriptorType;
- sizeof (GET_CONFIG_DESCRIPTOR_RESPONSE), // TotalLength;
- 1, // NumInterfaces;
- 1, // ConfigurationValue;
- 0, // Configuration;
- CONFIG_DESC_ATTRIBUTES, // Attributes;
- 0 // MaxPower;
- },
- { // USB_INTERFACE_DESCRIPTOR
- sizeof (USB_INTERFACE_DESCRIPTOR), // Length;
- USB_DESC_TYPE_INTERFACE, // DescriptorType;
- 0, // InterfaceNumber;
- 0, // AlternateSetting;
- 2, // NumEndpoints;
- 0xFF, // InterfaceClass;
- // Vendor specific interface subclass and protocol codes.
- // I found these values in the Fastboot code
- // (in match_fastboot_with_serial in fastboot.c).
- 0x42, // InterfaceSubClass;
- 0x03, // InterfaceProtocol;
- 0 // Interface;
- },
- { // USB_ENDPOINT_DESCRIPTOR (In Endpoint)
- sizeof (USB_ENDPOINT_DESCRIPTOR), // Length;
- USB_DESC_TYPE_ENDPOINT, // DescriptorType;
- 1 | BIT7, // EndpointAddress;
- 0x2, // Attributes;
- MAX_PACKET_SIZE_BULK, // MaxPacketSize;
- 16 // Interval;
- },
- { // STATIC USB_ENDPOINT_DESCRIPTOR (Out Endpoint)
- sizeof (USB_ENDPOINT_DESCRIPTOR), // Length;
- USB_DESC_TYPE_ENDPOINT, // DescriptorType;
- 1, // EndpointAddress;
- 0x2, // Attributes;
- MAX_PACKET_SIZE_BULK, // MaxPacketSize;
- 16 // Interval;
- }
- };
- STATIC
- VOID
- DataReceived (
- IN UINTN Size,
- IN VOID *Buffer
- )
- {
- FASTBOOT_USB_PACKET_LIST *NewEntry;
- NewEntry = AllocatePool (sizeof (*NewEntry));
- ASSERT (NewEntry != NULL);
- NewEntry->Buffer = Buffer;
- NewEntry->BufferSize = Size;
- InsertTailList (&mPacketList, &NewEntry->Link);
- if (mReceiveEvent) {
- gBS->SignalEvent (mReceiveEvent);
- }
- }
- STATIC
- VOID
- DataSent (
- IN UINT8 EndpointIndex
- )
- {
- // Don't care.
- }
- /*
- Set up the transport system for use by Fastboot.
- e.g. For USB this probably means making the device enumerable.
- */
- EFI_STATUS
- FastbootTransportUsbStart (
- EFI_EVENT ReceiveEvent
- )
- {
- GET_CONFIG_DESCRIPTOR_RESPONSE *Responses;
- mReceiveEvent = ReceiveEvent;
- mGetConfigDescriptorResponse.ConfigDescriptor.TotalLength = sizeof (GET_CONFIG_DESCRIPTOR_RESPONSE);
- Responses = &mGetConfigDescriptorResponse;
- InitializeListHead (&mPacketList);
- return mUsbDevice->Start (&mDeviceDescriptor, (VOID **)&Responses, DataReceived, DataSent);
- }
- /*
- Function to be called when all Fastboot transactions are finished, to
- de-initialise the transport system.
- e.g. A USB OTG system might want to get out of peripheral mode so it can be
- a USB host.
- */
- EFI_STATUS
- FastbootTransportUsbStop (
- VOID
- )
- {
- // not yet implemented in USB
- return EFI_SUCCESS;
- }
- /*
- Send data. This function can be used both for command responses like "OKAY"
- and for the data phase (the protocol doesn't describe any situation when the
- latter might be necessary, but does allow it)
- */
- EFI_STATUS
- FastbootTransportUsbSend (
- IN UINTN BufferSize,
- IN CONST VOID *Buffer,
- IN EFI_EVENT *FatalErrorEvent
- )
- {
- // Current USB protocol is blocking, so ignore FatalErrorEvent
- return mUsbDevice->Send (1, BufferSize, Buffer);
- }
- /*
- When the event has been Signalled to say data is available from the host,
- this function is used to get data. In order to handle the case where several
- packets are received before ReceiveEvent's notify function is called, packets
- received are queued, and each call to this function returns the next packet in
- the queue. It should therefore be called in a loop, the exit condition being a
- return of EFI_NOT_READY.
- Parameters:
- Buffer - The buffer in which to place data
- BufferSize - The size of Buffer in bytes
- Return EFI_NOT_READY if there is no data available
- */
- EFI_STATUS
- FastbootTransportUsbReceive (
- OUT UINTN *BufferSize,
- OUT VOID **Buffer
- )
- {
- FASTBOOT_USB_PACKET_LIST *Entry;
- if (IsListEmpty (&mPacketList)) {
- return EFI_NOT_READY;
- }
- Entry = (FASTBOOT_USB_PACKET_LIST *)GetFirstNode (&mPacketList);
- *BufferSize = Entry->BufferSize;
- *Buffer = Entry->Buffer;
- RemoveEntryList (&Entry->Link);
- FreePool (Entry);
- return EFI_SUCCESS;
- }
- STATIC FASTBOOT_TRANSPORT_PROTOCOL mTransportProtocol = {
- FastbootTransportUsbStart,
- FastbootTransportUsbStop,
- FastbootTransportUsbSend,
- FastbootTransportUsbReceive
- };
- EFI_STATUS
- FastbootTransportUsbEntryPoint (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
- {
- EFI_STATUS Status;
- // Assume there's only one USB peripheral controller.
- Status = gBS->LocateProtocol (&gUsbDeviceProtocolGuid, NULL, (VOID **)&mUsbDevice);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- Status = gBS->InstallProtocolInterface (
- &ImageHandle,
- &gAndroidFastbootTransportProtocolGuid,
- EFI_NATIVE_INTERFACE,
- &mTransportProtocol
- );
- return Status;
- }
|