]> git.proxmox.com Git - mirror_edk2.git/commitdiff
EmbeddedPkg/AndroidFastbootTransportUsbDxe: Implemented Android FastBoot over USB
authorOlivier Martin <olivier.martin@arm.com>
Wed, 5 Mar 2014 04:51:31 +0000 (04:51 +0000)
committeroliviermartin <oliviermartin@6f19259b-4bc3-4df7-8a09-765794883524>
Wed, 5 Mar 2014 04:51:31 +0000 (04:51 +0000)
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Olivier Martin <olivier.martin@arm.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15316 6f19259b-4bc3-4df7-8a09-765794883524

EmbeddedPkg/Drivers/AndroidFastbootTransportUsbDxe/FastbootTransportUsb.c [new file with mode: 0644]
EmbeddedPkg/Drivers/AndroidFastbootTransportUsbDxe/FastbootTransportUsbDxe.inf [new file with mode: 0644]
EmbeddedPkg/EmbeddedPkg.dec
EmbeddedPkg/EmbeddedPkg.dsc

diff --git a/EmbeddedPkg/Drivers/AndroidFastbootTransportUsbDxe/FastbootTransportUsb.c b/EmbeddedPkg/Drivers/AndroidFastbootTransportUsbDxe/FastbootTransportUsb.c
new file mode 100644 (file)
index 0000000..e7da1fa
--- /dev/null
@@ -0,0 +1,278 @@
+/** @file\r
+\r
+  Copyright (c) 2014, ARM Ltd. All rights reserved.<BR>\r
+\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+/*\r
+ * Implementation of the FASTBOOT_TRANSPORT_PROTOCOL using the USB_DEVICE_PROTOCOL\r
+ */\r
+\r
+#include <Protocol/UsbDevice.h>\r
+#include <Protocol/AndroidFastbootTransport.h>\r
+#include <Protocol/SimpleTextOut.h>\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+\r
+STATIC USB_DEVICE_PROTOCOL *mUsbDevice;\r
+\r
+// Configuration attributes:\r
+// bit 7 reserved and must be 1, bit 6 means self-powered.\r
+#define CONFIG_DESC_ATTRIBUTES      (BIT7 | BIT6)\r
+\r
+#define MAX_PACKET_SIZE_BULK        512\r
+\r
+STATIC USB_DEVICE_PROTOCOL  *mUsbDevice;\r
+STATIC EFI_EVENT             mReceiveEvent = NULL;\r
+STATIC LIST_ENTRY            mPacketList;\r
+\r
+// List type for queued received packets\r
+typedef struct _FASTBOOT_USB_PACKET_LIST {\r
+  LIST_ENTRY  Link;\r
+  VOID       *Buffer;\r
+  UINTN       BufferSize;\r
+} FASTBOOT_USB_PACKET_LIST;\r
+\r
+\r
+/*\r
+  No string descriptors - all string descriptor members are set to 0\r
+*/\r
+\r
+STATIC USB_DEVICE_DESCRIPTOR mDeviceDescriptor = {\r
+  sizeof (USB_DEVICE_DESCRIPTOR),                  //Length\r
+  USB_DESC_TYPE_DEVICE,                            //DescriptorType\r
+  0x0200,                                          //BcdUSB\r
+  0xFF,                                            //DeviceClass\r
+  0,                                               //DeviceSubClass\r
+  0,                                               //DeviceProtocol\r
+  64,                                              //MaxPacketSize0\r
+  FixedPcdGet32 (PcdAndroidFastbootUsbVendorId),   //IdVendor\r
+  FixedPcdGet32 (PcdAndroidFastbootUsbProductId),  //IdProduct\r
+  0,                                               //BcdDevice\r
+  0,                                               //StrManufacturer\r
+  0,                                               //StrProduct\r
+  0,                                               //StrSerialNumber\r
+  1                                                //NumConfigurations\r
+};\r
+\r
+/*\r
+  We have one configuration, one interface, and two endpoints (one IN, one OUT)\r
+*/\r
+\r
+// Lazy (compile-time) way to concatenate descriptors to pass to the USB device\r
+// protocol\r
+\r
+#pragma pack(1)\r
+typedef struct {\r
+  USB_CONFIG_DESCRIPTOR     ConfigDescriptor;\r
+  USB_INTERFACE_DESCRIPTOR  InterfaceDescriptor;\r
+  USB_ENDPOINT_DESCRIPTOR   EndpointDescriptor1;\r
+  USB_ENDPOINT_DESCRIPTOR   EndpointDescriptor2;\r
+} GET_CONFIG_DESCRIPTOR_RESPONSE;\r
+#pragma pack()\r
+\r
+STATIC GET_CONFIG_DESCRIPTOR_RESPONSE mGetConfigDescriptorResponse = {\r
+  { // USB_CONFIG_DESCRIPTOR\r
+    sizeof (USB_CONFIG_DESCRIPTOR),                   //Length;\r
+    USB_DESC_TYPE_CONFIG,                             //DescriptorType;\r
+    sizeof (GET_CONFIG_DESCRIPTOR_RESPONSE),          //TotalLength;\r
+    1,                                                //NumInterfaces;\r
+    1,                                                //ConfigurationValue;\r
+    0,                                                //Configuration;\r
+    CONFIG_DESC_ATTRIBUTES,                           //Attributes;\r
+    0                                                 //MaxPower;\r
+  },\r
+  { // USB_INTERFACE_DESCRIPTOR\r
+    sizeof (USB_INTERFACE_DESCRIPTOR), //Length;\r
+    USB_DESC_TYPE_INTERFACE, //DescriptorType;\r
+    0,                                                //InterfaceNumber;\r
+    0,                                                //AlternateSetting;\r
+    2,                                                //NumEndpoints;\r
+    0xFF,                                             //InterfaceClass;\r
+    // Vendor specific interface subclass and protocol codes.\r
+    // I found these values in the Fastboot code\r
+    // (in match_fastboot_with_serial in fastboot.c).\r
+    0x42,                                             //InterfaceSubClass;\r
+    0x03,                                             //InterfaceProtocol;\r
+    0                                                 //Interface;\r
+  },\r
+  { // USB_ENDPOINT_DESCRIPTOR (In Endpoint)\r
+    sizeof (USB_ENDPOINT_DESCRIPTOR),                 //Length;\r
+    USB_DESC_TYPE_ENDPOINT,                           //DescriptorType;\r
+    1 | BIT7,                                         //EndpointAddress;\r
+    0x2,                                              //Attributes;\r
+    MAX_PACKET_SIZE_BULK,                             //MaxPacketSize;\r
+    16                                                //Interval;\r
+  },\r
+  { // STATIC USB_ENDPOINT_DESCRIPTOR (Out Endpoint)\r
+    sizeof (USB_ENDPOINT_DESCRIPTOR),                 //Length;\r
+    USB_DESC_TYPE_ENDPOINT,                           //DescriptorType;\r
+    1,                                                //EndpointAddress;\r
+    0x2,                                              //Attributes;\r
+    MAX_PACKET_SIZE_BULK,                             //MaxPacketSize;\r
+    16                                                //Interval;\r
+  }\r
+};\r
+\r
+STATIC\r
+VOID\r
+DataReceived (\r
+  IN UINTN    Size,\r
+  IN VOID    *Buffer\r
+  )\r
+{\r
+  FASTBOOT_USB_PACKET_LIST *NewEntry;\r
+\r
+  NewEntry = AllocatePool (sizeof (*NewEntry));\r
+  ASSERT (NewEntry != NULL);\r
+\r
+  NewEntry->Buffer = Buffer;\r
+  NewEntry->BufferSize = Size;\r
+\r
+  InsertTailList (&mPacketList, &NewEntry->Link);\r
+\r
+  if (mReceiveEvent) {\r
+    gBS->SignalEvent (mReceiveEvent);\r
+  }\r
+}\r
+\r
+STATIC\r
+VOID\r
+DataSent (\r
+  IN UINT8 EndpointIndex\r
+  )\r
+{\r
+  // Don't care.\r
+}\r
+\r
+/*\r
+  Set up the transport system for use by Fastboot.\r
+  e.g. For USB this probably means making the device enumerable.\r
+*/\r
+EFI_STATUS\r
+FastbootTransportUsbStart (\r
+  EFI_EVENT ReceiveEvent\r
+  )\r
+{\r
+  GET_CONFIG_DESCRIPTOR_RESPONSE  *Responses;\r
+\r
+  mReceiveEvent = ReceiveEvent;\r
+\r
+  mGetConfigDescriptorResponse.ConfigDescriptor.TotalLength = sizeof (GET_CONFIG_DESCRIPTOR_RESPONSE);\r
+  Responses = &mGetConfigDescriptorResponse;\r
+\r
+  InitializeListHead (&mPacketList);\r
+\r
+  return mUsbDevice->Start (&mDeviceDescriptor, (VOID **) &Responses, DataReceived, DataSent);\r
+}\r
+\r
+/*\r
+  Function to be called when all Fastboot transactions are finished, to\r
+  de-initialise the transport system.\r
+  e.g. A USB OTG system might want to get out of peripheral mode so it can be\r
+       a USB host.\r
+*/\r
+EFI_STATUS\r
+FastbootTransportUsbStop (\r
+  VOID\r
+  )\r
+{\r
+  // not yet implemented in USB\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/*\r
+  Send data. This function can be used both for command responses like "OKAY"\r
+  and for the data phase (the protocol doesn't describe any situation when the\r
+   latter might be necessary, but does allow it)\r
+ */\r
+EFI_STATUS\r
+FastbootTransportUsbSend (\r
+  IN        UINTN      BufferSize,\r
+  IN  CONST VOID      *Buffer,\r
+  IN        EFI_EVENT *FatalErrorEvent\r
+  )\r
+{\r
+  // Current USB protocol is blocking, so ignore FatalErrorEvent\r
+  return mUsbDevice->Send(1, BufferSize, Buffer);\r
+}\r
+\r
+/*\r
+  When the event has been Signalled to say data is available from the host,\r
+  this function is used to get data. In order to handle the case where several\r
+  packets are received before ReceiveEvent's notify function is called, packets\r
+  received are queued, and each call to this function returns the next packet in\r
+  the queue. It should therefore be called in a loop, the exit condition being a\r
+  return of EFI_NOT_READY.\r
+\r
+  Parameters:\r
+    Buffer      - The buffer in which to place data\r
+    BufferSize  - The size of Buffer in bytes\r
+\r
+  Return EFI_NOT_READY if there is no data available\r
+*/\r
+EFI_STATUS\r
+FastbootTransportUsbReceive (\r
+  OUT UINTN  *BufferSize,\r
+  OUT VOID  **Buffer\r
+  )\r
+{\r
+  FASTBOOT_USB_PACKET_LIST *Entry;\r
+\r
+  if (IsListEmpty (&mPacketList)) {\r
+    return EFI_NOT_READY;\r
+  }\r
+\r
+  Entry = (FASTBOOT_USB_PACKET_LIST *) GetFirstNode (&mPacketList);\r
+\r
+  *BufferSize = Entry->BufferSize;\r
+  *Buffer = Entry->Buffer;\r
+\r
+  RemoveEntryList (&Entry->Link);\r
+  FreePool (Entry);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+STATIC FASTBOOT_TRANSPORT_PROTOCOL mTransportProtocol = {\r
+  FastbootTransportUsbStart,\r
+  FastbootTransportUsbStop,\r
+  FastbootTransportUsbSend,\r
+  FastbootTransportUsbReceive\r
+};\r
+\r
+EFI_STATUS\r
+FastbootTransportUsbEntryPoint (\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_SYSTEM_TABLE *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+\r
+  // Assume there's only one USB peripheral controller.\r
+  Status = gBS->LocateProtocol (&gUsbDeviceProtocolGuid, NULL, (VOID **) &mUsbDevice);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = gBS->InstallProtocolInterface (\r
+                  &ImageHandle,\r
+                  &gAndroidFastbootTransportProtocolGuid,\r
+                  EFI_NATIVE_INTERFACE,\r
+                  &mTransportProtocol\r
+                  );\r
+  return Status;\r
+}\r
diff --git a/EmbeddedPkg/Drivers/AndroidFastbootTransportUsbDxe/FastbootTransportUsbDxe.inf b/EmbeddedPkg/Drivers/AndroidFastbootTransportUsbDxe/FastbootTransportUsbDxe.inf
new file mode 100644 (file)
index 0000000..c5ada1a
--- /dev/null
@@ -0,0 +1,46 @@
+#/** @file\r
+#\r
+#  Copyright (c) 2013-2014, ARM Ltd. All rights reserved.<BR>\r
+#\r
+#  This program and the accompanying materials\r
+#  are licensed and made available under the terms and conditions of the BSD License\r
+#  which accompanies this distribution. The full text of the license may be found at\r
+#  http://opensource.org/licenses/bsd-license.php\r
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#\r
+#**/\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = FastbootTransportUsbDxe\r
+  FILE_GUID                      = f6bec3fe-88fb-11e3-ae84-e73b77561c35\r
+  MODULE_TYPE                    = UEFI_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  ENTRY_POINT                    = FastbootTransportUsbEntryPoint\r
+\r
+[Sources.common]\r
+  FastbootTransportUsb.c\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  BaseMemoryLib\r
+  MemoryAllocationLib\r
+  UefiBootServicesTableLib\r
+  UefiDriverEntryPoint\r
+\r
+[Protocols]\r
+  gEfiDriverBindingProtocolGuid\r
+  gUsbDeviceProtocolGuid\r
+  gAndroidFastbootTransportProtocolGuid\r
+  gEfiSimpleTextOutProtocolGuid\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  EmbeddedPkg/EmbeddedPkg.dec\r
+\r
+[FixedPcd]\r
+  gEmbeddedTokenSpaceGuid.PcdAndroidFastbootUsbVendorId\r
+  gEmbeddedTokenSpaceGuid.PcdAndroidFastbootUsbProductId\r
index 95fb60e880198fa8a35202ef998c8ccc13f4400b..c219befc30f5f9b893e8388ae514b6f2058e9570 100644 (file)
   gEmbeddedTokenSpaceGuid.PcdGdbMaxPacketRetryCount|10000000|UINT32|0x0000004c\r
   gEmbeddedTokenSpaceGuid.PcdGdbTimerPeriodMilliseconds|250|UINT32|0x0000004d\r
 \r
+  #\r
+  # Android FastBoot\r
+  #\r
+\r
+  # The Android FastBoot utility has hard-coded USB Vendor IDs that it recognises\r
+  # (and 0xf00d isn't one of them!).\r
+  # You'll need to pass it "-i 0xf00d" to get it to recognise this device.\r
+  gEmbeddedTokenSpaceGuid.PcdAndroidFastbootUsbVendorId|0xf00d|UINT32|0x00000022\r
+  gEmbeddedTokenSpaceGuid.PcdAndroidFastbootUsbProductId|0xbeef|UINT32|0x00000023\r
+\r
 [PcdsFixedAtBuild.ARM]\r
   gEmbeddedTokenSpaceGuid.PcdPrePiCpuMemorySize|32|UINT8|0x00000010\r
   gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize|0|UINT8|0x00000011\r
index a9db4ed6aff7b83a50cfa4cb87d76a3e8e9ecddb..7c3021aa5252cead2366f6305cf9abc88fc4c22f 100644 (file)
   EmbeddedPkg/Universal/MmcDxe/MmcDxe.inf\r
 \r
   EmbeddedPkg/Application/AndroidFastboot/AndroidFastbootApp.inf\r
+  EmbeddedPkg/Drivers/AndroidFastbootTransportUsbDxe/FastbootTransportUsbDxe.inf\r
 \r
 [Components.IA32, Components.X64, Components.IPF, Components.ARM]\r
   EmbeddedPkg/GdbStub/GdbStub.inf\r