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