https://bugzilla.tianocore.org/show_bug.cgi?id=1373 Replace BSD 2-Clause License with BSD+Patent License. This change is based on the following emails: https://lists.01.org/pipermail/edk2-devel/2019-February/036260.html https://lists.01.org/pipermail/edk2-devel/2018-October/030385.html RFCs with detailed process for the license change: V3: https://lists.01.org/pipermail/edk2-devel/2019-March/038116.html V2: https://lists.01.org/pipermail/edk2-devel/2019-March/037669.html V1: https://lists.01.org/pipermail/edk2-devel/2019-March/037500.html Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com> Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>
		
			
				
	
	
		
			273 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			273 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @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;
 | 
						|
}
 |