]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.c
MdeModulePkg: Apply uncrustify changes
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbBusPei / UsbPeim.c
CommitLineData
4b1bf81c 1/** @file\r
2The module to produce Usb Bus PPI.\r
3\r
d1102dba
LG
4Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
5\r
9d510e61 6SPDX-License-Identifier: BSD-2-Clause-Patent\r
4b1bf81c 7\r
8**/\r
9\r
10#include "UsbPeim.h"\r
11#include "HubPeim.h"\r
12#include "PeiUsbLib.h"\r
13\r
14//\r
15// UsbIo PPI interface function\r
16//\r
1436aea4 17PEI_USB_IO_PPI mUsbIoPpi = {\r
4b1bf81c 18 PeiUsbControlTransfer,\r
19 PeiUsbBulkTransfer,\r
20 PeiUsbGetInterfaceDescriptor,\r
21 PeiUsbGetEndpointDescriptor,\r
22 PeiUsbPortReset\r
23};\r
24\r
1436aea4 25EFI_PEI_PPI_DESCRIPTOR mUsbIoPpiList = {\r
4b1bf81c 26 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
27 &gPeiUsbIoPpiGuid,\r
28 NULL\r
29};\r
30\r
31/**\r
32 The enumeration routine to detect device change.\r
d1102dba 33\r
4b1bf81c 34 @param PeiServices Describes the list of possible PEI Services.\r
35 @param UsbHcPpi The pointer of PEI_USB_HOST_CONTROLLER_PPI instance.\r
36 @param Usb2HcPpi The pointer of PEI_USB2_HOST_CONTROLLER_PPI instance.\r
37\r
38 @retval EFI_SUCCESS The usb is enumerated successfully.\r
39 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.\r
40 @retval Others Other failure occurs.\r
41\r
42**/\r
43EFI_STATUS\r
44PeiUsbEnumeration (\r
1436aea4
MK
45 IN EFI_PEI_SERVICES **PeiServices,\r
46 IN PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi,\r
47 IN PEI_USB2_HOST_CONTROLLER_PPI *Usb2HcPpi\r
4b1bf81c 48 );\r
49\r
50/**\r
51 Configure new detected usb device.\r
d1102dba 52\r
4b1bf81c 53 @param PeiServices Describes the list of possible PEI Services.\r
54 @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.\r
55 @param Port The port to be configured.\r
56 @param DeviceAddress The device address to be configured.\r
57\r
58 @retval EFI_SUCCESS The new detected usb device is configured successfully.\r
59 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.\r
60 @retval Others Other failure occurs.\r
61\r
62**/\r
63EFI_STATUS\r
64PeiConfigureUsbDevice (\r
1436aea4
MK
65 IN EFI_PEI_SERVICES **PeiServices,\r
66 IN PEI_USB_DEVICE *PeiUsbDevice,\r
67 IN UINT8 Port,\r
68 IN OUT UINT8 *DeviceAddress\r
4b1bf81c 69 );\r
70\r
71/**\r
72 Get all configurations from a detected usb device.\r
d1102dba 73\r
4b1bf81c 74 @param PeiServices Describes the list of possible PEI Services.\r
75 @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.\r
76\r
77 @retval EFI_SUCCESS The new detected usb device is configured successfully.\r
78 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.\r
79 @retval Others Other failure occurs.\r
80\r
81**/\r
82EFI_STATUS\r
83PeiUsbGetAllConfiguration (\r
1436aea4
MK
84 IN EFI_PEI_SERVICES **PeiServices,\r
85 IN PEI_USB_DEVICE *PeiUsbDevice\r
4b1bf81c 86 );\r
87\r
88/**\r
89 Get the start position of next wanted descriptor.\r
d1102dba 90\r
4b1bf81c 91 @param Buffer Buffer containing data to parse.\r
92 @param Length Buffer length.\r
93 @param DescType Descriptor type.\r
94 @param DescLength Descriptor length.\r
95 @param ParsedBytes Bytes has been parsed.\r
96\r
97 @retval EFI_SUCCESS Get wanted descriptor successfully.\r
98 @retval EFI_DEVICE_ERROR Error occurred.\r
99\r
100**/\r
101EFI_STATUS\r
102GetExpectedDescriptor (\r
1436aea4
MK
103 IN UINT8 *Buffer,\r
104 IN UINTN Length,\r
105 IN UINT8 DescType,\r
106 IN UINT8 DescLength,\r
107 OUT UINTN *ParsedBytes\r
4b1bf81c 108 );\r
109\r
110/**\r
111 The entrypoint of the module, it will enumerate all HCs.\r
d1102dba 112\r
4b1bf81c 113 @param FileHandle Handle of the file being invoked.\r
114 @param PeiServices Describes the list of possible PEI Services.\r
115\r
116 @retval EFI_SUCCESS Usb initialization is done successfully.\r
117 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.\r
118 @retval EFI_UNSUPPORTED Can't find required PPI.\r
119\r
120**/\r
121EFI_STATUS\r
122EFIAPI\r
123PeimInitializeUsb (\r
1436aea4
MK
124 IN EFI_PEI_FILE_HANDLE FileHandle,\r
125 IN CONST EFI_PEI_SERVICES **PeiServices\r
4b1bf81c 126 )\r
127{\r
1436aea4
MK
128 EFI_STATUS Status;\r
129 UINTN Index;\r
130 PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi;\r
131 PEI_USB2_HOST_CONTROLLER_PPI *Usb2HcPpi;\r
4b1bf81c 132\r
133 if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle))) {\r
134 return EFI_SUCCESS;\r
135 }\r
136\r
137 //\r
d1102dba 138 // gPeiUsbHostControllerPpiGuid and gPeiUsb2HostControllerPpiGuid should not\r
4b1bf81c 139 // be produced at the same time\r
140 //\r
141 Index = 0;\r
142 while (TRUE) {\r
143 //\r
144 // Get UsbHcPpi at first.\r
145 //\r
146 Status = PeiServicesLocatePpi (\r
147 &gPeiUsbHostControllerPpiGuid,\r
148 Index,\r
149 NULL,\r
1436aea4 150 (VOID **)&UsbHcPpi\r
4b1bf81c 151 );\r
152 if (EFI_ERROR (Status)) {\r
153 //\r
154 // No more host controller, break out\r
155 //\r
156 break;\r
157 }\r
1436aea4
MK
158\r
159 PeiUsbEnumeration ((EFI_PEI_SERVICES **)PeiServices, UsbHcPpi, NULL);\r
4b1bf81c 160 Index++;\r
161 }\r
162\r
163 if (Index == 0) {\r
164 //\r
165 // Then try to get Usb2HcPpi.\r
166 //\r
167 while (TRUE) {\r
168 Status = PeiServicesLocatePpi (\r
169 &gPeiUsb2HostControllerPpiGuid,\r
170 Index,\r
171 NULL,\r
1436aea4 172 (VOID **)&Usb2HcPpi\r
d1102dba 173 );\r
4b1bf81c 174 if (EFI_ERROR (Status)) {\r
175 //\r
176 // No more host controller, break out\r
177 //\r
178 break;\r
d1102dba 179 }\r
1436aea4
MK
180\r
181 PeiUsbEnumeration ((EFI_PEI_SERVICES **)PeiServices, NULL, Usb2HcPpi);\r
4b1bf81c 182 Index++;\r
183 }\r
184 }\r
d1102dba 185\r
4b1bf81c 186 if (Index == 0) {\r
187 return EFI_UNSUPPORTED;\r
188 }\r
189\r
190 return EFI_SUCCESS;\r
191}\r
192\r
193/**\r
194 The Hub Enumeration just scans the hub ports one time. It also\r
195 doesn't support hot-plug.\r
d1102dba 196\r
4b1bf81c 197 @param PeiServices Describes the list of possible PEI Services.\r
198 @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.\r
199 @param CurrentAddress The DeviceAddress of usb device.\r
200\r
201 @retval EFI_SUCCESS The usb hub is enumerated successfully.\r
202 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.\r
203 @retval Others Other failure occurs.\r
204\r
205**/\r
206EFI_STATUS\r
207PeiHubEnumeration (\r
1436aea4
MK
208 IN EFI_PEI_SERVICES **PeiServices,\r
209 IN PEI_USB_DEVICE *PeiUsbDevice,\r
210 IN UINT8 *CurrentAddress\r
4b1bf81c 211 )\r
212{\r
213 UINTN Index;\r
214 EFI_STATUS Status;\r
215 PEI_USB_IO_PPI *UsbIoPpi;\r
216 EFI_USB_PORT_STATUS PortStatus;\r
217 UINTN MemPages;\r
218 EFI_PHYSICAL_ADDRESS AllocateAddress;\r
219 PEI_USB_DEVICE *NewPeiUsbDevice;\r
8a718ba9
SZ
220 UINTN InterfaceIndex;\r
221 UINTN EndpointIndex;\r
4b1bf81c 222\r
1436aea4 223 UsbIoPpi = &PeiUsbDevice->UsbIoPpi;\r
4b1bf81c 224\r
87000d77 225 DEBUG ((DEBUG_INFO, "PeiHubEnumeration: DownStreamPortNo: %x\n", PeiUsbDevice->DownStreamPortNo));\r
d987459f 226\r
4b1bf81c 227 for (Index = 0; Index < PeiUsbDevice->DownStreamPortNo; Index++) {\r
4b1bf81c 228 Status = PeiHubGetPortStatus (\r
1436aea4
MK
229 PeiServices,\r
230 UsbIoPpi,\r
231 (UINT8)(Index + 1),\r
232 (UINT32 *)&PortStatus\r
233 );\r
4b1bf81c 234\r
235 if (EFI_ERROR (Status)) {\r
236 continue;\r
237 }\r
238\r
87000d77 239 DEBUG ((DEBUG_INFO, "USB Status --- Port: %x ConnectChange[%04x] Status[%04x]\n", Index, PortStatus.PortChangeStatus, PortStatus.PortStatus));\r
d987459f
SZ
240 //\r
241 // Only handle connection/enable/overcurrent/reset change.\r
242 //\r
243 if ((PortStatus.PortChangeStatus & (USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE | USB_PORT_STAT_C_OVERCURRENT | USB_PORT_STAT_C_RESET)) == 0) {\r
244 continue;\r
245 } else {\r
4b1bf81c 246 if (IsPortConnect (PortStatus.PortStatus)) {\r
4b1bf81c 247 //\r
248 // Begin to deal with the new device\r
249 //\r
250 MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;\r
1436aea4
MK
251 Status = PeiServicesAllocatePages (\r
252 EfiBootServicesCode,\r
253 MemPages,\r
254 &AllocateAddress\r
255 );\r
4b1bf81c 256 if (EFI_ERROR (Status)) {\r
257 return EFI_OUT_OF_RESOURCES;\r
258 }\r
259\r
1436aea4 260 NewPeiUsbDevice = (PEI_USB_DEVICE *)((UINTN)AllocateAddress);\r
4b1bf81c 261 ZeroMem (NewPeiUsbDevice, sizeof (PEI_USB_DEVICE));\r
262\r
1436aea4
MK
263 NewPeiUsbDevice->Signature = PEI_USB_DEVICE_SIGNATURE;\r
264 NewPeiUsbDevice->DeviceAddress = 0;\r
265 NewPeiUsbDevice->MaxPacketSize0 = 8;\r
266 NewPeiUsbDevice->DataToggle = 0;\r
4b1bf81c 267 CopyMem (\r
268 &(NewPeiUsbDevice->UsbIoPpi),\r
269 &mUsbIoPpi,\r
270 sizeof (PEI_USB_IO_PPI)\r
271 );\r
272 CopyMem (\r
273 &(NewPeiUsbDevice->UsbIoPpiList),\r
274 &mUsbIoPpiList,\r
275 sizeof (EFI_PEI_PPI_DESCRIPTOR)\r
276 );\r
277 NewPeiUsbDevice->UsbIoPpiList.Ppi = &NewPeiUsbDevice->UsbIoPpi;\r
1436aea4 278 NewPeiUsbDevice->AllocateAddress = (UINTN)AllocateAddress;\r
4b1bf81c 279 NewPeiUsbDevice->UsbHcPpi = PeiUsbDevice->UsbHcPpi;\r
280 NewPeiUsbDevice->Usb2HcPpi = PeiUsbDevice->Usb2HcPpi;\r
1436aea4 281 NewPeiUsbDevice->Tier = (UINT8)(PeiUsbDevice->Tier + 1);\r
4b1bf81c 282 NewPeiUsbDevice->IsHub = 0x0;\r
283 NewPeiUsbDevice->DownStreamPortNo = 0x0;\r
284\r
d1102dba 285 if (((PortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) == 0) ||\r
1436aea4
MK
286 ((PortStatus.PortStatus & (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE)) == 0))\r
287 {\r
d987459f 288 //\r
d1102dba 289 // If the port already has reset change flag and is connected and enabled, skip the port reset logic.\r
d987459f
SZ
290 //\r
291 PeiResetHubPort (PeiServices, UsbIoPpi, (UINT8)(Index + 1));\r
d1102dba 292\r
d987459f 293 PeiHubGetPortStatus (\r
1436aea4
MK
294 PeiServices,\r
295 UsbIoPpi,\r
296 (UINT8)(Index + 1),\r
297 (UINT32 *)&PortStatus\r
298 );\r
d987459f
SZ
299 } else {\r
300 PeiHubClearPortFeature (\r
301 PeiServices,\r
302 UsbIoPpi,\r
1436aea4 303 (UINT8)(Index + 1),\r
d987459f
SZ
304 EfiUsbPortResetChange\r
305 );\r
306 }\r
4b1bf81c 307\r
1436aea4 308 NewPeiUsbDevice->DeviceSpeed = (UINT8)PeiUsbGetDeviceSpeed (PortStatus.PortStatus);\r
87000d77 309 DEBUG ((DEBUG_INFO, "Device Speed =%d\n", PeiUsbDevice->DeviceSpeed));\r
4b1bf81c 310\r
1436aea4 311 if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_SUPER_SPEED)) {\r
d987459f
SZ
312 NewPeiUsbDevice->MaxPacketSize0 = 512;\r
313 } else if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_HIGH_SPEED)) {\r
314 NewPeiUsbDevice->MaxPacketSize0 = 64;\r
315 } else if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_LOW_SPEED)) {\r
316 NewPeiUsbDevice->MaxPacketSize0 = 8;\r
317 } else {\r
318 NewPeiUsbDevice->MaxPacketSize0 = 8;\r
319 }\r
4b1bf81c 320\r
1436aea4 321 if (NewPeiUsbDevice->DeviceSpeed != EFI_USB_SPEED_HIGH) {\r
d12c6a78 322 if (PeiUsbDevice->DeviceSpeed == EFI_USB_SPEED_HIGH) {\r
323 NewPeiUsbDevice->Translator.TranslatorPortNumber = (UINT8)Index;\r
324 NewPeiUsbDevice->Translator.TranslatorHubAddress = *CurrentAddress;\r
325 } else {\r
1436aea4 326 CopyMem (&(NewPeiUsbDevice->Translator), &(PeiUsbDevice->Translator), sizeof (EFI_USB2_HC_TRANSACTION_TRANSLATOR));\r
4b1bf81c 327 }\r
d12c6a78 328 }\r
4b1bf81c 329\r
330 //\r
331 // Configure that Usb Device\r
332 //\r
333 Status = PeiConfigureUsbDevice (\r
1436aea4
MK
334 PeiServices,\r
335 NewPeiUsbDevice,\r
336 (UINT8)(Index + 1),\r
337 CurrentAddress\r
338 );\r
4b1bf81c 339\r
340 if (EFI_ERROR (Status)) {\r
341 continue;\r
342 }\r
1436aea4 343\r
87000d77 344 DEBUG ((DEBUG_INFO, "PeiHubEnumeration: PeiConfigureUsbDevice Success\n"));\r
4b1bf81c 345\r
346 Status = PeiServicesInstallPpi (&NewPeiUsbDevice->UsbIoPpiList);\r
347\r
348 if (NewPeiUsbDevice->InterfaceDesc->InterfaceClass == 0x09) {\r
1436aea4 349 NewPeiUsbDevice->IsHub = 0x1;\r
4b1bf81c 350\r
351 Status = PeiDoHubConfig (PeiServices, NewPeiUsbDevice);\r
352 if (EFI_ERROR (Status)) {\r
353 return Status;\r
354 }\r
355\r
356 PeiHubEnumeration (PeiServices, NewPeiUsbDevice, CurrentAddress);\r
357 }\r
4b1bf81c 358\r
8a718ba9
SZ
359 for (InterfaceIndex = 1; InterfaceIndex < NewPeiUsbDevice->ConfigDesc->NumInterfaces; InterfaceIndex++) {\r
360 //\r
361 // Begin to deal with the new device\r
362 //\r
363 MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;\r
1436aea4
MK
364 Status = PeiServicesAllocatePages (\r
365 EfiBootServicesCode,\r
366 MemPages,\r
367 &AllocateAddress\r
368 );\r
8a718ba9
SZ
369 if (EFI_ERROR (Status)) {\r
370 return EFI_OUT_OF_RESOURCES;\r
371 }\r
1436aea4 372\r
8a718ba9 373 CopyMem ((VOID *)(UINTN)AllocateAddress, NewPeiUsbDevice, sizeof (PEI_USB_DEVICE));\r
1436aea4
MK
374 NewPeiUsbDevice = (PEI_USB_DEVICE *)((UINTN)AllocateAddress);\r
375 NewPeiUsbDevice->AllocateAddress = (UINTN)AllocateAddress;\r
8a718ba9 376 NewPeiUsbDevice->UsbIoPpiList.Ppi = &NewPeiUsbDevice->UsbIoPpi;\r
1436aea4 377 NewPeiUsbDevice->InterfaceDesc = NewPeiUsbDevice->InterfaceDescList[InterfaceIndex];\r
8a718ba9
SZ
378 for (EndpointIndex = 0; EndpointIndex < NewPeiUsbDevice->InterfaceDesc->NumEndpoints; EndpointIndex++) {\r
379 NewPeiUsbDevice->EndpointDesc[EndpointIndex] = NewPeiUsbDevice->EndpointDescList[InterfaceIndex][EndpointIndex];\r
380 }\r
381\r
382 Status = PeiServicesInstallPpi (&NewPeiUsbDevice->UsbIoPpiList);\r
383\r
384 if (NewPeiUsbDevice->InterfaceDesc->InterfaceClass == 0x09) {\r
1436aea4 385 NewPeiUsbDevice->IsHub = 0x1;\r
8a718ba9
SZ
386\r
387 Status = PeiDoHubConfig (PeiServices, NewPeiUsbDevice);\r
388 if (EFI_ERROR (Status)) {\r
389 return Status;\r
390 }\r
391\r
392 PeiHubEnumeration (PeiServices, NewPeiUsbDevice, CurrentAddress);\r
393 }\r
394 }\r
395 }\r
4b1bf81c 396 }\r
397 }\r
398\r
4b1bf81c 399 return EFI_SUCCESS;\r
400}\r
401\r
402/**\r
403 The enumeration routine to detect device change.\r
d1102dba 404\r
4b1bf81c 405 @param PeiServices Describes the list of possible PEI Services.\r
406 @param UsbHcPpi The pointer of PEI_USB_HOST_CONTROLLER_PPI instance.\r
407 @param Usb2HcPpi The pointer of PEI_USB2_HOST_CONTROLLER_PPI instance.\r
408\r
409 @retval EFI_SUCCESS The usb is enumerated successfully.\r
410 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.\r
411 @retval Others Other failure occurs.\r
412\r
413**/\r
414EFI_STATUS\r
415PeiUsbEnumeration (\r
1436aea4
MK
416 IN EFI_PEI_SERVICES **PeiServices,\r
417 IN PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi,\r
418 IN PEI_USB2_HOST_CONTROLLER_PPI *Usb2HcPpi\r
4b1bf81c 419 )\r
420{\r
421 UINT8 NumOfRootPort;\r
422 EFI_STATUS Status;\r
423 UINT8 Index;\r
424 EFI_USB_PORT_STATUS PortStatus;\r
425 PEI_USB_DEVICE *PeiUsbDevice;\r
426 UINTN MemPages;\r
427 EFI_PHYSICAL_ADDRESS AllocateAddress;\r
428 UINT8 CurrentAddress;\r
8a718ba9
SZ
429 UINTN InterfaceIndex;\r
430 UINTN EndpointIndex;\r
4b1bf81c 431\r
432 CurrentAddress = 0;\r
d12c6a78 433 if (Usb2HcPpi != NULL) {\r
4b1bf81c 434 Usb2HcPpi->GetRootHubPortNumber (\r
1436aea4
MK
435 PeiServices,\r
436 Usb2HcPpi,\r
437 (UINT8 *)&NumOfRootPort\r
438 );\r
d12c6a78 439 } else if (UsbHcPpi != NULL) {\r
4b1bf81c 440 UsbHcPpi->GetRootHubPortNumber (\r
441 PeiServices,\r
442 UsbHcPpi,\r
1436aea4 443 (UINT8 *)&NumOfRootPort\r
4b1bf81c 444 );\r
d12c6a78 445 } else {\r
446 ASSERT (FALSE);\r
447 return EFI_INVALID_PARAMETER;\r
4b1bf81c 448 }\r
449\r
87000d77 450 DEBUG ((DEBUG_INFO, "PeiUsbEnumeration: NumOfRootPort: %x\n", NumOfRootPort));\r
d987459f 451\r
4b1bf81c 452 for (Index = 0; Index < NumOfRootPort; Index++) {\r
453 //\r
454 // First get root port status to detect changes happen\r
455 //\r
456 if (Usb2HcPpi != NULL) {\r
457 Usb2HcPpi->GetRootHubPortStatus (\r
1436aea4
MK
458 PeiServices,\r
459 Usb2HcPpi,\r
460 (UINT8)Index,\r
461 &PortStatus\r
462 );\r
4b1bf81c 463 } else {\r
464 UsbHcPpi->GetRootHubPortStatus (\r
465 PeiServices,\r
466 UsbHcPpi,\r
1436aea4 467 (UINT8)Index,\r
4b1bf81c 468 &PortStatus\r
469 );\r
470 }\r
1436aea4 471\r
87000d77 472 DEBUG ((DEBUG_INFO, "USB Status --- Port: %x ConnectChange[%04x] Status[%04x]\n", Index, PortStatus.PortChangeStatus, PortStatus.PortStatus));\r
d987459f
SZ
473 //\r
474 // Only handle connection/enable/overcurrent/reset change.\r
475 //\r
476 if ((PortStatus.PortChangeStatus & (USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE | USB_PORT_STAT_C_OVERCURRENT | USB_PORT_STAT_C_RESET)) == 0) {\r
477 continue;\r
478 } else {\r
4b1bf81c 479 if (IsPortConnect (PortStatus.PortStatus)) {\r
4b1bf81c 480 MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;\r
1436aea4
MK
481 Status = PeiServicesAllocatePages (\r
482 EfiBootServicesCode,\r
483 MemPages,\r
484 &AllocateAddress\r
485 );\r
4b1bf81c 486 if (EFI_ERROR (Status)) {\r
487 return EFI_OUT_OF_RESOURCES;\r
488 }\r
489\r
1436aea4 490 PeiUsbDevice = (PEI_USB_DEVICE *)((UINTN)AllocateAddress);\r
4b1bf81c 491 ZeroMem (PeiUsbDevice, sizeof (PEI_USB_DEVICE));\r
492\r
1436aea4
MK
493 PeiUsbDevice->Signature = PEI_USB_DEVICE_SIGNATURE;\r
494 PeiUsbDevice->DeviceAddress = 0;\r
495 PeiUsbDevice->MaxPacketSize0 = 8;\r
496 PeiUsbDevice->DataToggle = 0;\r
4b1bf81c 497 CopyMem (\r
498 &(PeiUsbDevice->UsbIoPpi),\r
499 &mUsbIoPpi,\r
500 sizeof (PEI_USB_IO_PPI)\r
501 );\r
502 CopyMem (\r
503 &(PeiUsbDevice->UsbIoPpiList),\r
504 &mUsbIoPpiList,\r
505 sizeof (EFI_PEI_PPI_DESCRIPTOR)\r
506 );\r
1436aea4
MK
507 PeiUsbDevice->UsbIoPpiList.Ppi = &PeiUsbDevice->UsbIoPpi;\r
508 PeiUsbDevice->AllocateAddress = (UINTN)AllocateAddress;\r
509 PeiUsbDevice->UsbHcPpi = UsbHcPpi;\r
510 PeiUsbDevice->Usb2HcPpi = Usb2HcPpi;\r
511 PeiUsbDevice->IsHub = 0x0;\r
512 PeiUsbDevice->DownStreamPortNo = 0x0;\r
4b1bf81c 513\r
d1102dba 514 if (((PortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) == 0) ||\r
1436aea4
MK
515 ((PortStatus.PortStatus & (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE)) == 0))\r
516 {\r
d987459f 517 //\r
d1102dba 518 // If the port already has reset change flag and is connected and enabled, skip the port reset logic.\r
d987459f
SZ
519 //\r
520 ResetRootPort (\r
521 PeiServices,\r
522 PeiUsbDevice->UsbHcPpi,\r
523 PeiUsbDevice->Usb2HcPpi,\r
524 Index,\r
525 0\r
526 );\r
4b1bf81c 527\r
d987459f
SZ
528 if (Usb2HcPpi != NULL) {\r
529 Usb2HcPpi->GetRootHubPortStatus (\r
530 PeiServices,\r
531 Usb2HcPpi,\r
1436aea4 532 (UINT8)Index,\r
d987459f
SZ
533 &PortStatus\r
534 );\r
535 } else {\r
536 UsbHcPpi->GetRootHubPortStatus (\r
537 PeiServices,\r
538 UsbHcPpi,\r
1436aea4 539 (UINT8)Index,\r
d987459f
SZ
540 &PortStatus\r
541 );\r
542 }\r
4b1bf81c 543 } else {\r
d987459f
SZ
544 if (Usb2HcPpi != NULL) {\r
545 Usb2HcPpi->ClearRootHubPortFeature (\r
1436aea4
MK
546 PeiServices,\r
547 Usb2HcPpi,\r
548 (UINT8)Index,\r
549 EfiUsbPortResetChange\r
550 );\r
d987459f
SZ
551 } else {\r
552 UsbHcPpi->ClearRootHubPortFeature (\r
553 PeiServices,\r
554 UsbHcPpi,\r
1436aea4 555 (UINT8)Index,\r
d987459f
SZ
556 EfiUsbPortResetChange\r
557 );\r
558 }\r
4b1bf81c 559 }\r
560\r
1436aea4 561 PeiUsbDevice->DeviceSpeed = (UINT8)PeiUsbGetDeviceSpeed (PortStatus.PortStatus);\r
87000d77 562 DEBUG ((DEBUG_INFO, "Device Speed =%d\n", PeiUsbDevice->DeviceSpeed));\r
4b1bf81c 563\r
1436aea4 564 if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_SUPER_SPEED)) {\r
d987459f
SZ
565 PeiUsbDevice->MaxPacketSize0 = 512;\r
566 } else if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_HIGH_SPEED)) {\r
567 PeiUsbDevice->MaxPacketSize0 = 64;\r
568 } else if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_LOW_SPEED)) {\r
569 PeiUsbDevice->MaxPacketSize0 = 8;\r
570 } else {\r
571 PeiUsbDevice->MaxPacketSize0 = 8;\r
572 }\r
573\r
4b1bf81c 574 //\r
575 // Configure that Usb Device\r
576 //\r
577 Status = PeiConfigureUsbDevice (\r
1436aea4
MK
578 PeiServices,\r
579 PeiUsbDevice,\r
580 Index,\r
581 &CurrentAddress\r
582 );\r
4b1bf81c 583\r
584 if (EFI_ERROR (Status)) {\r
585 continue;\r
586 }\r
1436aea4 587\r
87000d77 588 DEBUG ((DEBUG_INFO, "PeiUsbEnumeration: PeiConfigureUsbDevice Success\n"));\r
4b1bf81c 589\r
590 Status = PeiServicesInstallPpi (&PeiUsbDevice->UsbIoPpiList);\r
591\r
592 if (PeiUsbDevice->InterfaceDesc->InterfaceClass == 0x09) {\r
593 PeiUsbDevice->IsHub = 0x1;\r
594\r
595 Status = PeiDoHubConfig (PeiServices, PeiUsbDevice);\r
596 if (EFI_ERROR (Status)) {\r
597 return Status;\r
598 }\r
599\r
600 PeiHubEnumeration (PeiServices, PeiUsbDevice, &CurrentAddress);\r
601 }\r
8a718ba9
SZ
602\r
603 for (InterfaceIndex = 1; InterfaceIndex < PeiUsbDevice->ConfigDesc->NumInterfaces; InterfaceIndex++) {\r
604 //\r
605 // Begin to deal with the new device\r
606 //\r
607 MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;\r
1436aea4
MK
608 Status = PeiServicesAllocatePages (\r
609 EfiBootServicesCode,\r
610 MemPages,\r
611 &AllocateAddress\r
612 );\r
8a718ba9
SZ
613 if (EFI_ERROR (Status)) {\r
614 return EFI_OUT_OF_RESOURCES;\r
615 }\r
1436aea4 616\r
8a718ba9 617 CopyMem ((VOID *)(UINTN)AllocateAddress, PeiUsbDevice, sizeof (PEI_USB_DEVICE));\r
1436aea4
MK
618 PeiUsbDevice = (PEI_USB_DEVICE *)((UINTN)AllocateAddress);\r
619 PeiUsbDevice->AllocateAddress = (UINTN)AllocateAddress;\r
8a718ba9 620 PeiUsbDevice->UsbIoPpiList.Ppi = &PeiUsbDevice->UsbIoPpi;\r
1436aea4 621 PeiUsbDevice->InterfaceDesc = PeiUsbDevice->InterfaceDescList[InterfaceIndex];\r
8a718ba9
SZ
622 for (EndpointIndex = 0; EndpointIndex < PeiUsbDevice->InterfaceDesc->NumEndpoints; EndpointIndex++) {\r
623 PeiUsbDevice->EndpointDesc[EndpointIndex] = PeiUsbDevice->EndpointDescList[InterfaceIndex][EndpointIndex];\r
624 }\r
625\r
626 Status = PeiServicesInstallPpi (&PeiUsbDevice->UsbIoPpiList);\r
627\r
628 if (PeiUsbDevice->InterfaceDesc->InterfaceClass == 0x09) {\r
629 PeiUsbDevice->IsHub = 0x1;\r
630\r
631 Status = PeiDoHubConfig (PeiServices, PeiUsbDevice);\r
632 if (EFI_ERROR (Status)) {\r
633 return Status;\r
634 }\r
635\r
636 PeiHubEnumeration (PeiServices, PeiUsbDevice, &CurrentAddress);\r
637 }\r
638 }\r
4b1bf81c 639 } else {\r
640 //\r
641 // Disconnect change happen, currently we don't support\r
642 //\r
643 }\r
644 }\r
645 }\r
646\r
647 return EFI_SUCCESS;\r
648}\r
649\r
650/**\r
651 Configure new detected usb device.\r
d1102dba 652\r
4b1bf81c 653 @param PeiServices Describes the list of possible PEI Services.\r
654 @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.\r
655 @param Port The port to be configured.\r
656 @param DeviceAddress The device address to be configured.\r
657\r
658 @retval EFI_SUCCESS The new detected usb device is configured successfully.\r
659 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.\r
660 @retval Others Other failure occurs.\r
661\r
662**/\r
663EFI_STATUS\r
664PeiConfigureUsbDevice (\r
1436aea4
MK
665 IN EFI_PEI_SERVICES **PeiServices,\r
666 IN PEI_USB_DEVICE *PeiUsbDevice,\r
667 IN UINT8 Port,\r
668 IN OUT UINT8 *DeviceAddress\r
4b1bf81c 669 )\r
670{\r
1436aea4
MK
671 EFI_USB_DEVICE_DESCRIPTOR DeviceDescriptor;\r
672 EFI_STATUS Status;\r
673 PEI_USB_IO_PPI *UsbIoPpi;\r
674 UINT8 Retry;\r
4b1bf81c 675\r
676 UsbIoPpi = &PeiUsbDevice->UsbIoPpi;\r
677 Status = EFI_SUCCESS;\r
678 ZeroMem (&DeviceDescriptor, sizeof (EFI_USB_DEVICE_DESCRIPTOR));\r
679 //\r
680 // Get USB device descriptor\r
681 //\r
682\r
1436aea4 683 for (Retry = 0; Retry < 3; Retry++) {\r
4b1bf81c 684 Status = PeiUsbGetDescriptor (\r
685 PeiServices,\r
686 UsbIoPpi,\r
687 (USB_DT_DEVICE << 8),\r
688 0,\r
689 8,\r
690 &DeviceDescriptor\r
691 );\r
692\r
693 if (!EFI_ERROR (Status)) {\r
87000d77 694 DEBUG ((DEBUG_INFO, "PeiUsbGet Device Descriptor the %d time Success\n", Retry));\r
4b1bf81c 695 break;\r
696 }\r
697 }\r
698\r
699 if (Retry == 3) {\r
87000d77 700 DEBUG ((DEBUG_ERROR, "PeiUsbGet Device Descriptor fail: %x %r\n", Retry, Status));\r
4b1bf81c 701 return Status;\r
702 }\r
703\r
b9953b65 704 if ((DeviceDescriptor.BcdUSB >= 0x0300) && (DeviceDescriptor.MaxPacketSize0 == 9)) {\r
d987459f
SZ
705 PeiUsbDevice->MaxPacketSize0 = 1 << 9;\r
706 } else {\r
707 PeiUsbDevice->MaxPacketSize0 = DeviceDescriptor.MaxPacketSize0;\r
708 }\r
4b1bf81c 709\r
1436aea4 710 (*DeviceAddress)++;\r
4b1bf81c 711\r
712 Status = PeiUsbSetDeviceAddress (\r
1436aea4
MK
713 PeiServices,\r
714 UsbIoPpi,\r
715 *DeviceAddress\r
716 );\r
4b1bf81c 717\r
718 if (EFI_ERROR (Status)) {\r
87000d77 719 DEBUG ((DEBUG_ERROR, "PeiUsbSetDeviceAddress Failed: %r\n", Status));\r
4b1bf81c 720 return Status;\r
721 }\r
1436aea4 722\r
04910ceb 723 MicroSecondDelay (USB_SET_DEVICE_ADDRESS_STALL);\r
4b1bf81c 724\r
725 PeiUsbDevice->DeviceAddress = *DeviceAddress;\r
726\r
727 //\r
728 // Get whole USB device descriptor\r
729 //\r
730 Status = PeiUsbGetDescriptor (\r
1436aea4
MK
731 PeiServices,\r
732 UsbIoPpi,\r
733 (USB_DT_DEVICE << 8),\r
734 0,\r
735 (UINT16)sizeof (EFI_USB_DEVICE_DESCRIPTOR),\r
736 &DeviceDescriptor\r
737 );\r
4b1bf81c 738\r
739 if (EFI_ERROR (Status)) {\r
87000d77 740 DEBUG ((DEBUG_ERROR, "PeiUsbGetDescriptor First Failed\n"));\r
4b1bf81c 741 return Status;\r
742 }\r
8a718ba9 743\r
4b1bf81c 744 //\r
745 // Get its default configuration and its first interface\r
746 //\r
747 Status = PeiUsbGetAllConfiguration (\r
1436aea4
MK
748 PeiServices,\r
749 PeiUsbDevice\r
750 );\r
4b1bf81c 751 if (EFI_ERROR (Status)) {\r
752 return Status;\r
753 }\r
1436aea4 754\r
04910ceb 755 MicroSecondDelay (USB_GET_CONFIG_DESCRIPTOR_STALL);\r
4b1bf81c 756\r
757 Status = PeiUsbSetConfiguration (\r
1436aea4
MK
758 PeiServices,\r
759 UsbIoPpi\r
760 );\r
4b1bf81c 761\r
762 if (EFI_ERROR (Status)) {\r
763 return Status;\r
764 }\r
765\r
766 return EFI_SUCCESS;\r
767}\r
768\r
769/**\r
770 Get all configurations from a detected usb device.\r
d1102dba 771\r
4b1bf81c 772 @param PeiServices Describes the list of possible PEI Services.\r
773 @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.\r
774\r
775 @retval EFI_SUCCESS The new detected usb device is configured successfully.\r
776 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.\r
777 @retval Others Other failure occurs.\r
778\r
779**/\r
780EFI_STATUS\r
781PeiUsbGetAllConfiguration (\r
1436aea4
MK
782 IN EFI_PEI_SERVICES **PeiServices,\r
783 IN PEI_USB_DEVICE *PeiUsbDevice\r
4b1bf81c 784 )\r
785{\r
1436aea4
MK
786 EFI_STATUS Status;\r
787 EFI_USB_CONFIG_DESCRIPTOR *ConfigDesc;\r
788 PEI_USB_IO_PPI *UsbIoPpi;\r
789 UINT16 ConfigDescLength;\r
790 UINT8 *Ptr;\r
791 UINTN SkipBytes;\r
792 UINTN LengthLeft;\r
793 UINTN InterfaceIndex;\r
794 UINTN Index;\r
795 UINTN NumOfEndpoint;\r
4b1bf81c 796\r
797 UsbIoPpi = &PeiUsbDevice->UsbIoPpi;\r
798\r
799 //\r
800 // First get its 4-byte configuration descriptor\r
801 //\r
802 Status = PeiUsbGetDescriptor (\r
1436aea4
MK
803 PeiServices,\r
804 UsbIoPpi,\r
805 (USB_DT_CONFIG << 8), // Value\r
806 0, // Index\r
807 4, // Length\r
808 PeiUsbDevice->ConfigurationData\r
809 );\r
4b1bf81c 810\r
811 if (EFI_ERROR (Status)) {\r
87000d77 812 DEBUG ((DEBUG_ERROR, "PeiUsbGet Config Descriptor First Failed\n"));\r
4b1bf81c 813 return Status;\r
814 }\r
1436aea4 815\r
04910ceb 816 MicroSecondDelay (USB_GET_CONFIG_DESCRIPTOR_STALL);\r
4b1bf81c 817\r
1436aea4
MK
818 ConfigDesc = (EFI_USB_CONFIG_DESCRIPTOR *)PeiUsbDevice->ConfigurationData;\r
819 ConfigDescLength = ConfigDesc->TotalLength;\r
4b1bf81c 820\r
70425456
RN
821 //\r
822 // Reject if TotalLength even cannot cover itself.\r
823 //\r
824 if (ConfigDescLength < OFFSET_OF (EFI_USB_CONFIG_DESCRIPTOR, TotalLength) + sizeof (ConfigDesc->TotalLength)) {\r
825 return EFI_DEVICE_ERROR;\r
826 }\r
827\r
828 //\r
829 // Reject if TotalLength exceeds the PeiUsbDevice->ConfigurationData.\r
830 //\r
831 if (ConfigDescLength > sizeof (PeiUsbDevice->ConfigurationData)) {\r
832 return EFI_DEVICE_ERROR;\r
833 }\r
834\r
4b1bf81c 835 //\r
836 // Then we get the total descriptors for this configuration\r
837 //\r
838 Status = PeiUsbGetDescriptor (\r
1436aea4
MK
839 PeiServices,\r
840 UsbIoPpi,\r
841 (USB_DT_CONFIG << 8),\r
842 0,\r
843 ConfigDescLength,\r
844 PeiUsbDevice->ConfigurationData\r
845 );\r
4b1bf81c 846\r
847 if (EFI_ERROR (Status)) {\r
87000d77 848 DEBUG ((DEBUG_ERROR, "PeiUsbGet Config Descriptor all Failed\n"));\r
4b1bf81c 849 return Status;\r
850 }\r
1436aea4 851\r
4b1bf81c 852 //\r
853 // Parse this configuration descriptor\r
854 // First get the current config descriptor;\r
855 //\r
856 Status = GetExpectedDescriptor (\r
1436aea4
MK
857 PeiUsbDevice->ConfigurationData,\r
858 ConfigDescLength,\r
859 USB_DT_CONFIG,\r
860 (UINT8)sizeof (EFI_USB_CONFIG_DESCRIPTOR),\r
861 &SkipBytes\r
862 );\r
4b1bf81c 863\r
864 if (EFI_ERROR (Status)) {\r
865 return Status;\r
866 }\r
867\r
1436aea4
MK
868 Ptr = PeiUsbDevice->ConfigurationData + SkipBytes;\r
869 PeiUsbDevice->ConfigDesc = (EFI_USB_CONFIG_DESCRIPTOR *)Ptr;\r
4b1bf81c 870\r
1436aea4 871 Ptr += sizeof (EFI_USB_CONFIG_DESCRIPTOR);\r
4b1bf81c 872 LengthLeft = ConfigDescLength - SkipBytes - sizeof (EFI_USB_CONFIG_DESCRIPTOR);\r
873\r
8a718ba9 874 for (InterfaceIndex = 0; InterfaceIndex < PeiUsbDevice->ConfigDesc->NumInterfaces; InterfaceIndex++) {\r
4b1bf81c 875 //\r
8a718ba9 876 // Get the interface descriptor\r
4b1bf81c 877 //\r
878 Status = GetExpectedDescriptor (\r
1436aea4
MK
879 Ptr,\r
880 LengthLeft,\r
881 USB_DT_INTERFACE,\r
882 (UINT8)sizeof (EFI_USB_INTERFACE_DESCRIPTOR),\r
883 &SkipBytes\r
884 );\r
4b1bf81c 885\r
886 if (EFI_ERROR (Status)) {\r
887 return Status;\r
888 }\r
889\r
890 Ptr += SkipBytes;\r
8a718ba9 891 if (InterfaceIndex == 0) {\r
1436aea4 892 PeiUsbDevice->InterfaceDesc = (EFI_USB_INTERFACE_DESCRIPTOR *)Ptr;\r
8a718ba9 893 }\r
4b1bf81c 894\r
1436aea4
MK
895 PeiUsbDevice->InterfaceDescList[InterfaceIndex] = (EFI_USB_INTERFACE_DESCRIPTOR *)Ptr;\r
896\r
897 Ptr += sizeof (EFI_USB_INTERFACE_DESCRIPTOR);\r
4b1bf81c 898 LengthLeft -= SkipBytes;\r
8a718ba9
SZ
899 LengthLeft -= sizeof (EFI_USB_INTERFACE_DESCRIPTOR);\r
900\r
901 //\r
902 // Parse all the endpoint descriptor within this interface\r
903 //\r
904 NumOfEndpoint = PeiUsbDevice->InterfaceDescList[InterfaceIndex]->NumEndpoints;\r
905 ASSERT (NumOfEndpoint <= MAX_ENDPOINT);\r
906\r
907 for (Index = 0; Index < NumOfEndpoint; Index++) {\r
908 //\r
909 // Get the endpoint descriptor\r
910 //\r
911 Status = GetExpectedDescriptor (\r
1436aea4
MK
912 Ptr,\r
913 LengthLeft,\r
914 USB_DT_ENDPOINT,\r
915 (UINT8)sizeof (EFI_USB_ENDPOINT_DESCRIPTOR),\r
916 &SkipBytes\r
917 );\r
8a718ba9
SZ
918\r
919 if (EFI_ERROR (Status)) {\r
920 return Status;\r
921 }\r
922\r
923 Ptr += SkipBytes;\r
924 if (InterfaceIndex == 0) {\r
1436aea4 925 PeiUsbDevice->EndpointDesc[Index] = (EFI_USB_ENDPOINT_DESCRIPTOR *)Ptr;\r
8a718ba9 926 }\r
8a718ba9 927\r
1436aea4
MK
928 PeiUsbDevice->EndpointDescList[InterfaceIndex][Index] = (EFI_USB_ENDPOINT_DESCRIPTOR *)Ptr;\r
929\r
930 Ptr += sizeof (EFI_USB_ENDPOINT_DESCRIPTOR);\r
8a718ba9
SZ
931 LengthLeft -= SkipBytes;\r
932 LengthLeft -= sizeof (EFI_USB_ENDPOINT_DESCRIPTOR);\r
933 }\r
4b1bf81c 934 }\r
935\r
936 return EFI_SUCCESS;\r
937}\r
938\r
939/**\r
940 Get the start position of next wanted descriptor.\r
d1102dba 941\r
4b1bf81c 942 @param Buffer Buffer containing data to parse.\r
943 @param Length Buffer length.\r
944 @param DescType Descriptor type.\r
945 @param DescLength Descriptor length.\r
946 @param ParsedBytes Bytes has been parsed.\r
947\r
948 @retval EFI_SUCCESS Get wanted descriptor successfully.\r
949 @retval EFI_DEVICE_ERROR Error occurred.\r
950\r
951**/\r
952EFI_STATUS\r
953GetExpectedDescriptor (\r
1436aea4
MK
954 IN UINT8 *Buffer,\r
955 IN UINTN Length,\r
956 IN UINT8 DescType,\r
957 IN UINT8 DescLength,\r
958 OUT UINTN *ParsedBytes\r
4b1bf81c 959 )\r
960{\r
1436aea4
MK
961 USB_DESC_HEAD *Head;\r
962 UINTN Offset;\r
4b1bf81c 963\r
c96de1db 964 //\r
dbeaf585 965 // Total length is too small that cannot hold the single descriptor header plus data.\r
c96de1db
RN
966 //\r
967 if (Length <= sizeof (USB_DESC_HEAD)) {\r
968 DEBUG ((DEBUG_ERROR, "GetExpectedDescriptor: met mal-format descriptor, total length = %d!\n", Length));\r
969 return EFI_DEVICE_ERROR;\r
970 }\r
4b1bf81c 971\r
c96de1db
RN
972 //\r
973 // All the descriptor has a common LTV (Length, Type, Value)\r
974 // format. Skip the descriptor that isn't of this Type\r
975 //\r
976 Offset = 0;\r
977 Head = (USB_DESC_HEAD *)Buffer;\r
978 while (Offset < Length - sizeof (USB_DESC_HEAD)) {\r
4b1bf81c 979 //\r
c96de1db 980 // Above condition make sure Head->Len and Head->Type are safe to access\r
4b1bf81c 981 //\r
c96de1db 982 Head = (USB_DESC_HEAD *)&Buffer[Offset];\r
4b1bf81c 983\r
c96de1db
RN
984 if (Head->Len == 0) {\r
985 DEBUG ((DEBUG_ERROR, "GetExpectedDescriptor: met mal-format descriptor, Head->Len = 0!\n"));\r
986 return EFI_DEVICE_ERROR;\r
4b1bf81c 987 }\r
988\r
4b1bf81c 989 //\r
c96de1db 990 // Make sure no overflow when adding Head->Len to Offset.\r
4b1bf81c 991 //\r
c96de1db
RN
992 if (Head->Len > MAX_UINTN - Offset) {\r
993 DEBUG ((DEBUG_ERROR, "GetExpectedDescriptor: met mal-format descriptor, Head->Len = %d!\n", Head->Len));\r
4b1bf81c 994 return EFI_DEVICE_ERROR;\r
995 }\r
996\r
c96de1db
RN
997 if (Head->Type == DescType) {\r
998 break;\r
4b1bf81c 999 }\r
c96de1db
RN
1000\r
1001 Offset += Head->Len;\r
1002 }\r
1003\r
1004 //\r
1005 // Head->Len is invalid resulting data beyond boundary, or\r
1006 // Descriptor cannot be found: No such type.\r
1007 //\r
1008 if (Length < Offset) {\r
1009 DEBUG ((DEBUG_ERROR, "GetExpectedDescriptor: met mal-format descriptor, Offset/Len = %d/%d!\n", Offset, Length));\r
1010 return EFI_DEVICE_ERROR;\r
4b1bf81c 1011 }\r
1012\r
c96de1db
RN
1013 if ((Head->Type != DescType) || (Head->Len < DescLength)) {\r
1014 DEBUG ((DEBUG_ERROR, "GetExpectedDescriptor: descriptor cannot be found, Header(T/L) = %d/%d!\n", Head->Type, Head->Len));\r
1015 return EFI_DEVICE_ERROR;\r
1016 }\r
4b1bf81c 1017\r
c96de1db 1018 *ParsedBytes = Offset;\r
4b1bf81c 1019 return EFI_SUCCESS;\r
1020}\r
1021\r
1022/**\r
1023 Send reset signal over the given root hub port.\r
d1102dba 1024\r
4b1bf81c 1025 @param PeiServices Describes the list of possible PEI Services.\r
1026 @param UsbHcPpi The pointer of PEI_USB_HOST_CONTROLLER_PPI instance.\r
1027 @param Usb2HcPpi The pointer of PEI_USB2_HOST_CONTROLLER_PPI instance.\r
1028 @param PortNum The port to be reset.\r
1029 @param RetryIndex The retry times.\r
1030\r
1031**/\r
1032VOID\r
1033ResetRootPort (\r
1436aea4
MK
1034 IN EFI_PEI_SERVICES **PeiServices,\r
1035 IN PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi,\r
1036 IN PEI_USB2_HOST_CONTROLLER_PPI *Usb2HcPpi,\r
1037 IN UINT8 PortNum,\r
1038 IN UINT8 RetryIndex\r
4b1bf81c 1039 )\r
1040{\r
1436aea4
MK
1041 EFI_STATUS Status;\r
1042 UINTN Index;\r
1043 EFI_USB_PORT_STATUS PortStatus;\r
4b1bf81c 1044\r
1045 if (Usb2HcPpi != NULL) {\r
1046 MicroSecondDelay (200 * 1000);\r
d1102dba 1047\r
4b1bf81c 1048 //\r
1049 // reset root port\r
1050 //\r
1051 Status = Usb2HcPpi->SetRootHubPortFeature (\r
1436aea4
MK
1052 PeiServices,\r
1053 Usb2HcPpi,\r
1054 PortNum,\r
1055 EfiUsbPortReset\r
1056 );\r
d1102dba 1057\r
4b1bf81c 1058 if (EFI_ERROR (Status)) {\r
87000d77 1059 DEBUG ((DEBUG_ERROR, "SetRootHubPortFeature EfiUsbPortReset Failed\n"));\r
4b1bf81c 1060 return;\r
1061 }\r
d1102dba 1062\r
d987459f
SZ
1063 //\r
1064 // Drive the reset signal for at least 50ms. Check USB 2.0 Spec\r
1065 // section 7.1.7.5 for timing requirements.\r
1066 //\r
1067 MicroSecondDelay (USB_SET_ROOT_PORT_RESET_STALL);\r
1068\r
4b1bf81c 1069 //\r
1070 // clear reset root port\r
1071 //\r
1072 Status = Usb2HcPpi->ClearRootHubPortFeature (\r
1436aea4
MK
1073 PeiServices,\r
1074 Usb2HcPpi,\r
1075 PortNum,\r
1076 EfiUsbPortReset\r
1077 );\r
d1102dba 1078\r
4b1bf81c 1079 if (EFI_ERROR (Status)) {\r
87000d77 1080 DEBUG ((DEBUG_ERROR, "ClearRootHubPortFeature EfiUsbPortReset Failed\n"));\r
4b1bf81c 1081 return;\r
1082 }\r
d987459f
SZ
1083\r
1084 MicroSecondDelay (USB_CLR_ROOT_PORT_RESET_STALL);\r
1085\r
1086 //\r
1087 // USB host controller won't clear the RESET bit until\r
1088 // reset is actually finished.\r
1089 //\r
1090 ZeroMem (&PortStatus, sizeof (EFI_USB_PORT_STATUS));\r
1091\r
1092 for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) {\r
1093 Status = Usb2HcPpi->GetRootHubPortStatus (\r
1094 PeiServices,\r
1095 Usb2HcPpi,\r
1096 PortNum,\r
1097 &PortStatus\r
d1102dba 1098 );\r
d987459f
SZ
1099 if (EFI_ERROR (Status)) {\r
1100 return;\r
1101 }\r
1102\r
1103 if (!USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_RESET)) {\r
1104 break;\r
1105 }\r
1106\r
1107 MicroSecondDelay (USB_WAIT_PORT_STS_CHANGE_STALL);\r
1108 }\r
1109\r
1110 if (Index == USB_WAIT_PORT_STS_CHANGE_LOOP) {\r
87000d77 1111 DEBUG ((DEBUG_ERROR, "ResetRootPort: reset not finished in time on port %d\n", PortNum));\r
d987459f
SZ
1112 return;\r
1113 }\r
1114\r
1115 Usb2HcPpi->ClearRootHubPortFeature (\r
1436aea4
MK
1116 PeiServices,\r
1117 Usb2HcPpi,\r
1118 PortNum,\r
1119 EfiUsbPortResetChange\r
1120 );\r
d987459f 1121\r
4b1bf81c 1122 Usb2HcPpi->ClearRootHubPortFeature (\r
1436aea4
MK
1123 PeiServices,\r
1124 Usb2HcPpi,\r
1125 PortNum,\r
1126 EfiUsbPortConnectChange\r
1127 );\r
d1102dba 1128\r
4b1bf81c 1129 //\r
1130 // Set port enable\r
1131 //\r
1436aea4
MK
1132 Usb2HcPpi->SetRootHubPortFeature (\r
1133 PeiServices,\r
1134 Usb2HcPpi,\r
1135 PortNum,\r
1136 EfiUsbPortEnable\r
1137 );\r
d1102dba 1138\r
4b1bf81c 1139 Usb2HcPpi->ClearRootHubPortFeature (\r
1436aea4
MK
1140 PeiServices,\r
1141 Usb2HcPpi,\r
1142 PortNum,\r
1143 EfiUsbPortEnableChange\r
1144 );\r
d1102dba 1145\r
4b1bf81c 1146 MicroSecondDelay ((RetryIndex + 1) * 50 * 1000);\r
1147 } else {\r
1148 MicroSecondDelay (200 * 1000);\r
d1102dba 1149\r
4b1bf81c 1150 //\r
1151 // reset root port\r
1152 //\r
1153 Status = UsbHcPpi->SetRootHubPortFeature (\r
1154 PeiServices,\r
1155 UsbHcPpi,\r
1156 PortNum,\r
1157 EfiUsbPortReset\r
1158 );\r
d1102dba 1159\r
4b1bf81c 1160 if (EFI_ERROR (Status)) {\r
87000d77 1161 DEBUG ((DEBUG_ERROR, "SetRootHubPortFeature EfiUsbPortReset Failed\n"));\r
4b1bf81c 1162 return;\r
1163 }\r
d1102dba 1164\r
d987459f
SZ
1165 //\r
1166 // Drive the reset signal for at least 50ms. Check USB 2.0 Spec\r
1167 // section 7.1.7.5 for timing requirements.\r
1168 //\r
1169 MicroSecondDelay (USB_SET_ROOT_PORT_RESET_STALL);\r
d1102dba 1170\r
4b1bf81c 1171 //\r
1172 // clear reset root port\r
1173 //\r
1174 Status = UsbHcPpi->ClearRootHubPortFeature (\r
1175 PeiServices,\r
1176 UsbHcPpi,\r
1177 PortNum,\r
1178 EfiUsbPortReset\r
1179 );\r
d1102dba 1180\r
4b1bf81c 1181 if (EFI_ERROR (Status)) {\r
87000d77 1182 DEBUG ((DEBUG_ERROR, "ClearRootHubPortFeature EfiUsbPortReset Failed\n"));\r
4b1bf81c 1183 return;\r
1184 }\r
d1102dba 1185\r
d987459f
SZ
1186 MicroSecondDelay (USB_CLR_ROOT_PORT_RESET_STALL);\r
1187\r
1188 //\r
1189 // USB host controller won't clear the RESET bit until\r
1190 // reset is actually finished.\r
1191 //\r
1192 ZeroMem (&PortStatus, sizeof (EFI_USB_PORT_STATUS));\r
1193\r
1194 for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) {\r
1195 Status = UsbHcPpi->GetRootHubPortStatus (\r
1196 PeiServices,\r
1197 UsbHcPpi,\r
1198 PortNum,\r
1199 &PortStatus\r
d1102dba 1200 );\r
d987459f
SZ
1201 if (EFI_ERROR (Status)) {\r
1202 return;\r
1203 }\r
1204\r
1205 if (!USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_RESET)) {\r
1206 break;\r
1207 }\r
1208\r
1209 MicroSecondDelay (USB_WAIT_PORT_STS_CHANGE_STALL);\r
1210 }\r
1211\r
1212 if (Index == USB_WAIT_PORT_STS_CHANGE_LOOP) {\r
87000d77 1213 DEBUG ((DEBUG_ERROR, "ResetRootPort: reset not finished in time on port %d\n", PortNum));\r
d987459f
SZ
1214 return;\r
1215 }\r
1216\r
1217 UsbHcPpi->ClearRootHubPortFeature (\r
1218 PeiServices,\r
1219 UsbHcPpi,\r
1220 PortNum,\r
1221 EfiUsbPortResetChange\r
1222 );\r
1223\r
4b1bf81c 1224 UsbHcPpi->ClearRootHubPortFeature (\r
1225 PeiServices,\r
1226 UsbHcPpi,\r
1227 PortNum,\r
1228 EfiUsbPortConnectChange\r
1229 );\r
d1102dba 1230\r
4b1bf81c 1231 //\r
1232 // Set port enable\r
1233 //\r
1436aea4 1234 UsbHcPpi->SetRootHubPortFeature (\r
4b1bf81c 1235 PeiServices,\r
1236 UsbHcPpi,\r
1237 PortNum,\r
1238 EfiUsbPortEnable\r
1239 );\r
d1102dba 1240\r
4b1bf81c 1241 UsbHcPpi->ClearRootHubPortFeature (\r
1242 PeiServices,\r
1243 UsbHcPpi,\r
1244 PortNum,\r
1245 EfiUsbPortEnableChange\r
1246 );\r
d1102dba 1247\r
4b1bf81c 1248 MicroSecondDelay ((RetryIndex + 1) * 50 * 1000);\r
1249 }\r
1436aea4 1250\r
4b1bf81c 1251 return;\r
1252}\r