FastbootTransportUsb.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. /** @file
  2. Copyright (c) 2014, ARM Ltd. All rights reserved.<BR>
  3. SPDX-License-Identifier: BSD-2-Clause-Patent
  4. **/
  5. /*
  6. * Implementation of the FASTBOOT_TRANSPORT_PROTOCOL using the USB_DEVICE_PROTOCOL
  7. */
  8. #include <Protocol/UsbDevice.h>
  9. #include <Protocol/AndroidFastbootTransport.h>
  10. #include <Protocol/SimpleTextOut.h>
  11. #include <Library/BaseLib.h>
  12. #include <Library/BaseMemoryLib.h>
  13. #include <Library/DebugLib.h>
  14. #include <Library/MemoryAllocationLib.h>
  15. #include <Library/UefiBootServicesTableLib.h>
  16. #include <Library/UefiDriverEntryPoint.h>
  17. STATIC USB_DEVICE_PROTOCOL *mUsbDevice;
  18. // Configuration attributes:
  19. // bit 7 reserved and must be 1, bit 6 means self-powered.
  20. #define CONFIG_DESC_ATTRIBUTES (BIT7 | BIT6)
  21. #define MAX_PACKET_SIZE_BULK 512
  22. STATIC USB_DEVICE_PROTOCOL *mUsbDevice;
  23. STATIC EFI_EVENT mReceiveEvent = NULL;
  24. STATIC LIST_ENTRY mPacketList;
  25. // List type for queued received packets
  26. typedef struct _FASTBOOT_USB_PACKET_LIST {
  27. LIST_ENTRY Link;
  28. VOID *Buffer;
  29. UINTN BufferSize;
  30. } FASTBOOT_USB_PACKET_LIST;
  31. /*
  32. No string descriptors - all string descriptor members are set to 0
  33. */
  34. STATIC USB_DEVICE_DESCRIPTOR mDeviceDescriptor = {
  35. sizeof (USB_DEVICE_DESCRIPTOR), // Length
  36. USB_DESC_TYPE_DEVICE, // DescriptorType
  37. 0x0200, // BcdUSB
  38. 0xFF, // DeviceClass
  39. 0, // DeviceSubClass
  40. 0, // DeviceProtocol
  41. 64, // MaxPacketSize0
  42. FixedPcdGet32 (PcdAndroidFastbootUsbVendorId), // IdVendor
  43. FixedPcdGet32 (PcdAndroidFastbootUsbProductId), // IdProduct
  44. 0, // BcdDevice
  45. 0, // StrManufacturer
  46. 0, // StrProduct
  47. 0, // StrSerialNumber
  48. 1 // NumConfigurations
  49. };
  50. /*
  51. We have one configuration, one interface, and two endpoints (one IN, one OUT)
  52. */
  53. // Lazy (compile-time) way to concatenate descriptors to pass to the USB device
  54. // protocol
  55. #pragma pack(1)
  56. typedef struct {
  57. USB_CONFIG_DESCRIPTOR ConfigDescriptor;
  58. USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
  59. USB_ENDPOINT_DESCRIPTOR EndpointDescriptor1;
  60. USB_ENDPOINT_DESCRIPTOR EndpointDescriptor2;
  61. } GET_CONFIG_DESCRIPTOR_RESPONSE;
  62. #pragma pack()
  63. STATIC GET_CONFIG_DESCRIPTOR_RESPONSE mGetConfigDescriptorResponse = {
  64. { // USB_CONFIG_DESCRIPTOR
  65. sizeof (USB_CONFIG_DESCRIPTOR), // Length;
  66. USB_DESC_TYPE_CONFIG, // DescriptorType;
  67. sizeof (GET_CONFIG_DESCRIPTOR_RESPONSE), // TotalLength;
  68. 1, // NumInterfaces;
  69. 1, // ConfigurationValue;
  70. 0, // Configuration;
  71. CONFIG_DESC_ATTRIBUTES, // Attributes;
  72. 0 // MaxPower;
  73. },
  74. { // USB_INTERFACE_DESCRIPTOR
  75. sizeof (USB_INTERFACE_DESCRIPTOR), // Length;
  76. USB_DESC_TYPE_INTERFACE, // DescriptorType;
  77. 0, // InterfaceNumber;
  78. 0, // AlternateSetting;
  79. 2, // NumEndpoints;
  80. 0xFF, // InterfaceClass;
  81. // Vendor specific interface subclass and protocol codes.
  82. // I found these values in the Fastboot code
  83. // (in match_fastboot_with_serial in fastboot.c).
  84. 0x42, // InterfaceSubClass;
  85. 0x03, // InterfaceProtocol;
  86. 0 // Interface;
  87. },
  88. { // USB_ENDPOINT_DESCRIPTOR (In Endpoint)
  89. sizeof (USB_ENDPOINT_DESCRIPTOR), // Length;
  90. USB_DESC_TYPE_ENDPOINT, // DescriptorType;
  91. 1 | BIT7, // EndpointAddress;
  92. 0x2, // Attributes;
  93. MAX_PACKET_SIZE_BULK, // MaxPacketSize;
  94. 16 // Interval;
  95. },
  96. { // STATIC USB_ENDPOINT_DESCRIPTOR (Out Endpoint)
  97. sizeof (USB_ENDPOINT_DESCRIPTOR), // Length;
  98. USB_DESC_TYPE_ENDPOINT, // DescriptorType;
  99. 1, // EndpointAddress;
  100. 0x2, // Attributes;
  101. MAX_PACKET_SIZE_BULK, // MaxPacketSize;
  102. 16 // Interval;
  103. }
  104. };
  105. STATIC
  106. VOID
  107. DataReceived (
  108. IN UINTN Size,
  109. IN VOID *Buffer
  110. )
  111. {
  112. FASTBOOT_USB_PACKET_LIST *NewEntry;
  113. NewEntry = AllocatePool (sizeof (*NewEntry));
  114. ASSERT (NewEntry != NULL);
  115. NewEntry->Buffer = Buffer;
  116. NewEntry->BufferSize = Size;
  117. InsertTailList (&mPacketList, &NewEntry->Link);
  118. if (mReceiveEvent) {
  119. gBS->SignalEvent (mReceiveEvent);
  120. }
  121. }
  122. STATIC
  123. VOID
  124. DataSent (
  125. IN UINT8 EndpointIndex
  126. )
  127. {
  128. // Don't care.
  129. }
  130. /*
  131. Set up the transport system for use by Fastboot.
  132. e.g. For USB this probably means making the device enumerable.
  133. */
  134. EFI_STATUS
  135. FastbootTransportUsbStart (
  136. EFI_EVENT ReceiveEvent
  137. )
  138. {
  139. GET_CONFIG_DESCRIPTOR_RESPONSE *Responses;
  140. mReceiveEvent = ReceiveEvent;
  141. mGetConfigDescriptorResponse.ConfigDescriptor.TotalLength = sizeof (GET_CONFIG_DESCRIPTOR_RESPONSE);
  142. Responses = &mGetConfigDescriptorResponse;
  143. InitializeListHead (&mPacketList);
  144. return mUsbDevice->Start (&mDeviceDescriptor, (VOID **)&Responses, DataReceived, DataSent);
  145. }
  146. /*
  147. Function to be called when all Fastboot transactions are finished, to
  148. de-initialise the transport system.
  149. e.g. A USB OTG system might want to get out of peripheral mode so it can be
  150. a USB host.
  151. */
  152. EFI_STATUS
  153. FastbootTransportUsbStop (
  154. VOID
  155. )
  156. {
  157. // not yet implemented in USB
  158. return EFI_SUCCESS;
  159. }
  160. /*
  161. Send data. This function can be used both for command responses like "OKAY"
  162. and for the data phase (the protocol doesn't describe any situation when the
  163. latter might be necessary, but does allow it)
  164. */
  165. EFI_STATUS
  166. FastbootTransportUsbSend (
  167. IN UINTN BufferSize,
  168. IN CONST VOID *Buffer,
  169. IN EFI_EVENT *FatalErrorEvent
  170. )
  171. {
  172. // Current USB protocol is blocking, so ignore FatalErrorEvent
  173. return mUsbDevice->Send (1, BufferSize, Buffer);
  174. }
  175. /*
  176. When the event has been Signalled to say data is available from the host,
  177. this function is used to get data. In order to handle the case where several
  178. packets are received before ReceiveEvent's notify function is called, packets
  179. received are queued, and each call to this function returns the next packet in
  180. the queue. It should therefore be called in a loop, the exit condition being a
  181. return of EFI_NOT_READY.
  182. Parameters:
  183. Buffer - The buffer in which to place data
  184. BufferSize - The size of Buffer in bytes
  185. Return EFI_NOT_READY if there is no data available
  186. */
  187. EFI_STATUS
  188. FastbootTransportUsbReceive (
  189. OUT UINTN *BufferSize,
  190. OUT VOID **Buffer
  191. )
  192. {
  193. FASTBOOT_USB_PACKET_LIST *Entry;
  194. if (IsListEmpty (&mPacketList)) {
  195. return EFI_NOT_READY;
  196. }
  197. Entry = (FASTBOOT_USB_PACKET_LIST *)GetFirstNode (&mPacketList);
  198. *BufferSize = Entry->BufferSize;
  199. *Buffer = Entry->Buffer;
  200. RemoveEntryList (&Entry->Link);
  201. FreePool (Entry);
  202. return EFI_SUCCESS;
  203. }
  204. STATIC FASTBOOT_TRANSPORT_PROTOCOL mTransportProtocol = {
  205. FastbootTransportUsbStart,
  206. FastbootTransportUsbStop,
  207. FastbootTransportUsbSend,
  208. FastbootTransportUsbReceive
  209. };
  210. EFI_STATUS
  211. FastbootTransportUsbEntryPoint (
  212. IN EFI_HANDLE ImageHandle,
  213. IN EFI_SYSTEM_TABLE *SystemTable
  214. )
  215. {
  216. EFI_STATUS Status;
  217. // Assume there's only one USB peripheral controller.
  218. Status = gBS->LocateProtocol (&gUsbDeviceProtocolGuid, NULL, (VOID **)&mUsbDevice);
  219. if (EFI_ERROR (Status)) {
  220. return Status;
  221. }
  222. Status = gBS->InstallProtocolInterface (
  223. &ImageHandle,
  224. &gAndroidFastbootTransportProtocolGuid,
  225. EFI_NATIVE_INTERFACE,
  226. &mTransportProtocol
  227. );
  228. return Status;
  229. }