]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.c
error handling enhancement for possible null pointer dereference
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbBusPei / UsbPeim.c
CommitLineData
4b1bf81c 1/** @file\r
2The module to produce Usb Bus PPI.\r
3\r
d12c6a78 4Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
4b1bf81c 5 \r
6This program and the accompanying materials\r
7are licensed and made available under the terms and conditions\r
8of the BSD License which accompanies this distribution. The\r
9full text of the license may be found at\r
10http://opensource.org/licenses/bsd-license.php\r
11\r
12THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14\r
15**/\r
16\r
17#include "UsbPeim.h"\r
18#include "HubPeim.h"\r
19#include "PeiUsbLib.h"\r
20\r
21//\r
22// UsbIo PPI interface function\r
23//\r
24PEI_USB_IO_PPI mUsbIoPpi = {\r
25 PeiUsbControlTransfer,\r
26 PeiUsbBulkTransfer,\r
27 PeiUsbGetInterfaceDescriptor,\r
28 PeiUsbGetEndpointDescriptor,\r
29 PeiUsbPortReset\r
30};\r
31\r
32EFI_PEI_PPI_DESCRIPTOR mUsbIoPpiList = {\r
33 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
34 &gPeiUsbIoPpiGuid,\r
35 NULL\r
36};\r
37\r
38/**\r
39 The enumeration routine to detect device change.\r
40 \r
41 @param PeiServices Describes the list of possible PEI Services.\r
42 @param UsbHcPpi The pointer of PEI_USB_HOST_CONTROLLER_PPI instance.\r
43 @param Usb2HcPpi The pointer of PEI_USB2_HOST_CONTROLLER_PPI instance.\r
44\r
45 @retval EFI_SUCCESS The usb is enumerated successfully.\r
46 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.\r
47 @retval Others Other failure occurs.\r
48\r
49**/\r
50EFI_STATUS\r
51PeiUsbEnumeration (\r
52 IN EFI_PEI_SERVICES **PeiServices,\r
53 IN PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi,\r
54 IN PEI_USB2_HOST_CONTROLLER_PPI *Usb2HcPpi\r
55 );\r
56\r
57/**\r
58 Configure new detected usb device.\r
59 \r
60 @param PeiServices Describes the list of possible PEI Services.\r
61 @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.\r
62 @param Port The port to be configured.\r
63 @param DeviceAddress The device address to be configured.\r
64\r
65 @retval EFI_SUCCESS The new detected usb device is configured successfully.\r
66 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.\r
67 @retval Others Other failure occurs.\r
68\r
69**/\r
70EFI_STATUS\r
71PeiConfigureUsbDevice (\r
72 IN EFI_PEI_SERVICES **PeiServices,\r
73 IN PEI_USB_DEVICE *PeiUsbDevice,\r
74 IN UINT8 Port,\r
75 IN OUT UINT8 *DeviceAddress\r
76 );\r
77\r
78/**\r
79 Get all configurations from a detected usb device.\r
80 \r
81 @param PeiServices Describes the list of possible PEI Services.\r
82 @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.\r
83\r
84 @retval EFI_SUCCESS The new detected usb device is configured successfully.\r
85 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.\r
86 @retval Others Other failure occurs.\r
87\r
88**/\r
89EFI_STATUS\r
90PeiUsbGetAllConfiguration (\r
91 IN EFI_PEI_SERVICES **PeiServices,\r
92 IN PEI_USB_DEVICE *PeiUsbDevice\r
93 );\r
94\r
95/**\r
96 Get the start position of next wanted descriptor.\r
97 \r
98 @param Buffer Buffer containing data to parse.\r
99 @param Length Buffer length.\r
100 @param DescType Descriptor type.\r
101 @param DescLength Descriptor length.\r
102 @param ParsedBytes Bytes has been parsed.\r
103\r
104 @retval EFI_SUCCESS Get wanted descriptor successfully.\r
105 @retval EFI_DEVICE_ERROR Error occurred.\r
106\r
107**/\r
108EFI_STATUS\r
109GetExpectedDescriptor (\r
110 IN UINT8 *Buffer,\r
111 IN UINTN Length,\r
112 IN UINT8 DescType,\r
113 IN UINT8 DescLength,\r
114 OUT UINTN *ParsedBytes\r
115 );\r
116\r
117/**\r
118 The entrypoint of the module, it will enumerate all HCs.\r
119 \r
120 @param FileHandle Handle of the file being invoked.\r
121 @param PeiServices Describes the list of possible PEI Services.\r
122\r
123 @retval EFI_SUCCESS Usb initialization is done successfully.\r
124 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.\r
125 @retval EFI_UNSUPPORTED Can't find required PPI.\r
126\r
127**/\r
128EFI_STATUS\r
129EFIAPI\r
130PeimInitializeUsb (\r
131 IN EFI_PEI_FILE_HANDLE FileHandle,\r
132 IN CONST EFI_PEI_SERVICES **PeiServices\r
133 )\r
134{\r
135 EFI_STATUS Status;\r
136 UINTN Index;\r
137 PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi;\r
138 PEI_USB2_HOST_CONTROLLER_PPI *Usb2HcPpi;\r
139\r
140 if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle))) {\r
141 return EFI_SUCCESS;\r
142 }\r
143\r
144 //\r
145 // gPeiUsbHostControllerPpiGuid and gPeiUsb2HostControllerPpiGuid should not \r
146 // be produced at the same time\r
147 //\r
148 Index = 0;\r
149 while (TRUE) {\r
150 //\r
151 // Get UsbHcPpi at first.\r
152 //\r
153 Status = PeiServicesLocatePpi (\r
154 &gPeiUsbHostControllerPpiGuid,\r
155 Index,\r
156 NULL,\r
157 (VOID **) &UsbHcPpi\r
158 );\r
159 if (EFI_ERROR (Status)) {\r
160 //\r
161 // No more host controller, break out\r
162 //\r
163 break;\r
164 }\r
165 PeiUsbEnumeration ((EFI_PEI_SERVICES **) PeiServices, UsbHcPpi, NULL);\r
166 Index++;\r
167 }\r
168\r
169 if (Index == 0) {\r
170 //\r
171 // Then try to get Usb2HcPpi.\r
172 //\r
173 while (TRUE) {\r
174 Status = PeiServicesLocatePpi (\r
175 &gPeiUsb2HostControllerPpiGuid,\r
176 Index,\r
177 NULL,\r
178 (VOID **) &Usb2HcPpi\r
179 ); \r
180 if (EFI_ERROR (Status)) {\r
181 //\r
182 // No more host controller, break out\r
183 //\r
184 break;\r
185 } \r
186 PeiUsbEnumeration ((EFI_PEI_SERVICES **) PeiServices, NULL, Usb2HcPpi); \r
187 Index++;\r
188 }\r
189 }\r
190 \r
191 if (Index == 0) {\r
192 return EFI_UNSUPPORTED;\r
193 }\r
194\r
195 return EFI_SUCCESS;\r
196}\r
197\r
198/**\r
199 The Hub Enumeration just scans the hub ports one time. It also\r
200 doesn't support hot-plug.\r
201 \r
202 @param PeiServices Describes the list of possible PEI Services.\r
203 @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.\r
204 @param CurrentAddress The DeviceAddress of usb device.\r
205\r
206 @retval EFI_SUCCESS The usb hub is enumerated successfully.\r
207 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.\r
208 @retval Others Other failure occurs.\r
209\r
210**/\r
211EFI_STATUS\r
212PeiHubEnumeration (\r
213 IN EFI_PEI_SERVICES **PeiServices,\r
214 IN PEI_USB_DEVICE *PeiUsbDevice,\r
215 IN UINT8 *CurrentAddress\r
216 )\r
217{\r
218 UINTN Index;\r
219 EFI_STATUS Status;\r
220 PEI_USB_IO_PPI *UsbIoPpi;\r
221 EFI_USB_PORT_STATUS PortStatus;\r
222 UINTN MemPages;\r
223 EFI_PHYSICAL_ADDRESS AllocateAddress;\r
224 PEI_USB_DEVICE *NewPeiUsbDevice;\r
225\r
226\r
227 UsbIoPpi = &PeiUsbDevice->UsbIoPpi;\r
228\r
229 for (Index = 0; Index < PeiUsbDevice->DownStreamPortNo; Index++) {\r
230\r
231 Status = PeiHubGetPortStatus (\r
232 PeiServices,\r
233 UsbIoPpi,\r
234 (UINT8) (Index + 1),\r
235 (UINT32 *) &PortStatus\r
236 );\r
237\r
238 if (EFI_ERROR (Status)) {\r
239 continue;\r
240 }\r
241\r
242 if (IsPortConnectChange (PortStatus.PortChangeStatus)) {\r
243 PeiHubClearPortFeature (\r
244 PeiServices,\r
245 UsbIoPpi,\r
246 (UINT8) (Index + 1),\r
247 EfiUsbPortConnectChange\r
248 );\r
249\r
250 MicroSecondDelay (100 * 1000);\r
251\r
252 if (IsPortConnect (PortStatus.PortStatus)) {\r
253\r
254 PeiHubGetPortStatus (\r
255 PeiServices,\r
256 UsbIoPpi,\r
257 (UINT8) (Index + 1),\r
258 (UINT32 *) &PortStatus\r
259 );\r
260\r
261 //\r
262 // Begin to deal with the new device\r
263 //\r
264 MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;\r
265 Status = PeiServicesAllocatePages (\r
266 EfiBootServicesCode,\r
267 MemPages,\r
268 &AllocateAddress\r
269 );\r
270 if (EFI_ERROR (Status)) {\r
271 return EFI_OUT_OF_RESOURCES;\r
272 }\r
273\r
274 NewPeiUsbDevice = (PEI_USB_DEVICE *) ((UINTN) AllocateAddress);\r
275 ZeroMem (NewPeiUsbDevice, sizeof (PEI_USB_DEVICE));\r
276\r
277 NewPeiUsbDevice->Signature = PEI_USB_DEVICE_SIGNATURE;\r
278 NewPeiUsbDevice->DeviceAddress = 0;\r
279 NewPeiUsbDevice->MaxPacketSize0 = 8;\r
280 NewPeiUsbDevice->DataToggle = 0;\r
281 CopyMem (\r
282 &(NewPeiUsbDevice->UsbIoPpi),\r
283 &mUsbIoPpi,\r
284 sizeof (PEI_USB_IO_PPI)\r
285 );\r
286 CopyMem (\r
287 &(NewPeiUsbDevice->UsbIoPpiList),\r
288 &mUsbIoPpiList,\r
289 sizeof (EFI_PEI_PPI_DESCRIPTOR)\r
290 );\r
291 NewPeiUsbDevice->UsbIoPpiList.Ppi = &NewPeiUsbDevice->UsbIoPpi;\r
292 NewPeiUsbDevice->AllocateAddress = (UINTN) AllocateAddress;\r
293 NewPeiUsbDevice->UsbHcPpi = PeiUsbDevice->UsbHcPpi;\r
294 NewPeiUsbDevice->Usb2HcPpi = PeiUsbDevice->Usb2HcPpi;\r
295 NewPeiUsbDevice->IsHub = 0x0;\r
296 NewPeiUsbDevice->DownStreamPortNo = 0x0;\r
297\r
298 PeiResetHubPort (PeiServices, UsbIoPpi, (UINT8)(Index + 1));\r
299\r
300 PeiHubGetPortStatus (\r
301 PeiServices,\r
302 UsbIoPpi,\r
303 (UINT8) (Index + 1),\r
304 (UINT32 *) &PortStatus\r
305 );\r
306\r
307 NewPeiUsbDevice->DeviceSpeed = (UINT8)IsPortLowSpeedDeviceAttached (PortStatus.PortStatus);\r
308\r
309 if(NewPeiUsbDevice->DeviceSpeed != EFI_USB_SPEED_HIGH) {\r
d12c6a78 310 if (PeiUsbDevice->DeviceSpeed == EFI_USB_SPEED_HIGH) {\r
311 NewPeiUsbDevice->Translator.TranslatorPortNumber = (UINT8)Index;\r
312 NewPeiUsbDevice->Translator.TranslatorHubAddress = *CurrentAddress;\r
313 } else {\r
314 CopyMem(&(NewPeiUsbDevice->Translator), &(PeiUsbDevice->Translator), sizeof(EFI_USB2_HC_TRANSACTION_TRANSLATOR));\r
4b1bf81c 315 }\r
d12c6a78 316 }\r
4b1bf81c 317\r
318 //\r
319 // Configure that Usb Device\r
320 //\r
321 Status = PeiConfigureUsbDevice (\r
322 PeiServices,\r
323 NewPeiUsbDevice,\r
324 (UINT8) (Index + 1),\r
325 CurrentAddress\r
326 );\r
327\r
328 if (EFI_ERROR (Status)) {\r
329 continue;\r
330 }\r
331\r
332 Status = PeiServicesInstallPpi (&NewPeiUsbDevice->UsbIoPpiList);\r
333\r
334 if (NewPeiUsbDevice->InterfaceDesc->InterfaceClass == 0x09) {\r
335 NewPeiUsbDevice->IsHub = 0x1;\r
336\r
337 Status = PeiDoHubConfig (PeiServices, NewPeiUsbDevice);\r
338 if (EFI_ERROR (Status)) {\r
339 return Status;\r
340 }\r
341\r
342 PeiHubEnumeration (PeiServices, NewPeiUsbDevice, CurrentAddress);\r
343 }\r
344 }\r
345\r
346 }\r
347 }\r
348\r
349\r
350 return EFI_SUCCESS;\r
351}\r
352\r
353/**\r
354 The enumeration routine to detect device change.\r
355 \r
356 @param PeiServices Describes the list of possible PEI Services.\r
357 @param UsbHcPpi The pointer of PEI_USB_HOST_CONTROLLER_PPI instance.\r
358 @param Usb2HcPpi The pointer of PEI_USB2_HOST_CONTROLLER_PPI instance.\r
359\r
360 @retval EFI_SUCCESS The usb is enumerated successfully.\r
361 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.\r
362 @retval Others Other failure occurs.\r
363\r
364**/\r
365EFI_STATUS\r
366PeiUsbEnumeration (\r
367 IN EFI_PEI_SERVICES **PeiServices,\r
368 IN PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi,\r
369 IN PEI_USB2_HOST_CONTROLLER_PPI *Usb2HcPpi\r
370 )\r
371{\r
372 UINT8 NumOfRootPort;\r
373 EFI_STATUS Status;\r
374 UINT8 Index;\r
375 EFI_USB_PORT_STATUS PortStatus;\r
376 PEI_USB_DEVICE *PeiUsbDevice;\r
377 UINTN MemPages;\r
378 EFI_PHYSICAL_ADDRESS AllocateAddress;\r
379 UINT8 CurrentAddress;\r
380\r
381\r
382 CurrentAddress = 0;\r
d12c6a78 383 if (Usb2HcPpi != NULL) {\r
4b1bf81c 384 Usb2HcPpi->GetRootHubPortNumber (\r
385 PeiServices,\r
386 Usb2HcPpi,\r
387 (UINT8 *) &NumOfRootPort\r
388 ); \r
d12c6a78 389 } else if (UsbHcPpi != NULL) {\r
4b1bf81c 390 UsbHcPpi->GetRootHubPortNumber (\r
391 PeiServices,\r
392 UsbHcPpi,\r
393 (UINT8 *) &NumOfRootPort\r
394 );\r
d12c6a78 395 } else {\r
396 ASSERT (FALSE);\r
397 return EFI_INVALID_PARAMETER;\r
4b1bf81c 398 }\r
399\r
400 for (Index = 0; Index < NumOfRootPort; Index++) {\r
401 //\r
402 // First get root port status to detect changes happen\r
403 //\r
404 if (Usb2HcPpi != NULL) {\r
405 Usb2HcPpi->GetRootHubPortStatus (\r
406 PeiServices,\r
407 Usb2HcPpi,\r
408 (UINT8) Index,\r
409 &PortStatus\r
410 ); \r
411 } else {\r
412 UsbHcPpi->GetRootHubPortStatus (\r
413 PeiServices,\r
414 UsbHcPpi,\r
415 (UINT8) Index,\r
416 &PortStatus\r
417 );\r
418 }\r
419 DEBUG ((EFI_D_INFO, "USB Status --- ConnectChange[%04x] Status[%04x]\n", PortStatus.PortChangeStatus, PortStatus.PortStatus));\r
420 if (IsPortConnectChange (PortStatus.PortChangeStatus)) {\r
421 //\r
422 // Changes happen, first clear this change status\r
423 //\r
424 if (Usb2HcPpi != NULL) {\r
425 Usb2HcPpi->ClearRootHubPortFeature (\r
426 PeiServices,\r
427 Usb2HcPpi,\r
428 (UINT8) Index,\r
429 EfiUsbPortConnectChange\r
430 ); \r
431 } else {\r
432 UsbHcPpi->ClearRootHubPortFeature (\r
433 PeiServices,\r
434 UsbHcPpi,\r
435 (UINT8) Index,\r
436 EfiUsbPortConnectChange\r
437 );\r
438 }\r
439 MicroSecondDelay (100 * 1000);\r
440\r
441 if (IsPortConnect (PortStatus.PortStatus)) {\r
442 if (Usb2HcPpi != NULL) {\r
443 Usb2HcPpi->GetRootHubPortStatus (\r
444 PeiServices,\r
445 Usb2HcPpi,\r
446 (UINT8) Index,\r
447 &PortStatus\r
448 );\r
449 } else {\r
450 UsbHcPpi->GetRootHubPortStatus (\r
451 PeiServices,\r
452 UsbHcPpi,\r
453 (UINT8) Index,\r
454 &PortStatus\r
455 );\r
456 }\r
457\r
458 //\r
459 // Connect change happen\r
460 //\r
461 MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;\r
462 Status = PeiServicesAllocatePages (\r
463 EfiBootServicesCode,\r
464 MemPages,\r
465 &AllocateAddress\r
466 );\r
467 if (EFI_ERROR (Status)) {\r
468 return EFI_OUT_OF_RESOURCES;\r
469 }\r
470\r
471 PeiUsbDevice = (PEI_USB_DEVICE *) ((UINTN) AllocateAddress);\r
472 ZeroMem (PeiUsbDevice, sizeof (PEI_USB_DEVICE));\r
473\r
474 PeiUsbDevice->Signature = PEI_USB_DEVICE_SIGNATURE;\r
475 PeiUsbDevice->DeviceAddress = 0;\r
476 PeiUsbDevice->MaxPacketSize0 = 8;\r
477 PeiUsbDevice->DataToggle = 0;\r
478 CopyMem (\r
479 &(PeiUsbDevice->UsbIoPpi),\r
480 &mUsbIoPpi,\r
481 sizeof (PEI_USB_IO_PPI)\r
482 );\r
483 CopyMem (\r
484 &(PeiUsbDevice->UsbIoPpiList),\r
485 &mUsbIoPpiList,\r
486 sizeof (EFI_PEI_PPI_DESCRIPTOR)\r
487 );\r
488 PeiUsbDevice->UsbIoPpiList.Ppi = &PeiUsbDevice->UsbIoPpi;\r
489 PeiUsbDevice->AllocateAddress = (UINTN) AllocateAddress;\r
490 PeiUsbDevice->UsbHcPpi = UsbHcPpi;\r
491 PeiUsbDevice->Usb2HcPpi = Usb2HcPpi;\r
492 PeiUsbDevice->IsHub = 0x0;\r
493 PeiUsbDevice->DownStreamPortNo = 0x0;\r
494\r
495 ResetRootPort (\r
496 PeiServices,\r
497 PeiUsbDevice->UsbHcPpi,\r
498 PeiUsbDevice->Usb2HcPpi,\r
499 Index,\r
500 0\r
501 );\r
502\r
503 if (Usb2HcPpi != NULL) {\r
504 Usb2HcPpi->GetRootHubPortStatus (\r
505 PeiServices,\r
506 Usb2HcPpi,\r
507 (UINT8) Index,\r
508 &PortStatus\r
509 );\r
510 } else {\r
511 UsbHcPpi->GetRootHubPortStatus (\r
512 PeiServices,\r
513 UsbHcPpi,\r
514 (UINT8) Index,\r
515 &PortStatus\r
516 );\r
517 }\r
518\r
519 PeiUsbDevice->DeviceSpeed = (UINT8)IsPortLowSpeedDeviceAttached (PortStatus.PortStatus);\r
520 DEBUG ((EFI_D_INFO, "Device Speed =%d\n", PeiUsbDevice->DeviceSpeed));\r
521\r
522 //\r
523 // Configure that Usb Device\r
524 //\r
525 Status = PeiConfigureUsbDevice (\r
526 PeiServices,\r
527 PeiUsbDevice,\r
528 Index,\r
529 &CurrentAddress\r
530 );\r
531\r
532 if (EFI_ERROR (Status)) {\r
533 continue;\r
534 }\r
535 DEBUG ((EFI_D_INFO, "PeiConfigureUsbDevice Success\n"));\r
536\r
537 Status = PeiServicesInstallPpi (&PeiUsbDevice->UsbIoPpiList);\r
538\r
539 if (PeiUsbDevice->InterfaceDesc->InterfaceClass == 0x09) {\r
540 PeiUsbDevice->IsHub = 0x1;\r
541\r
542 Status = PeiDoHubConfig (PeiServices, PeiUsbDevice);\r
543 if (EFI_ERROR (Status)) {\r
544 return Status;\r
545 }\r
546\r
547 PeiHubEnumeration (PeiServices, PeiUsbDevice, &CurrentAddress);\r
548 }\r
549 } else {\r
550 //\r
551 // Disconnect change happen, currently we don't support\r
552 //\r
553 }\r
554 }\r
555 }\r
556\r
557 return EFI_SUCCESS;\r
558}\r
559\r
560/**\r
561 Configure new detected usb device.\r
562 \r
563 @param PeiServices Describes the list of possible PEI Services.\r
564 @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.\r
565 @param Port The port to be configured.\r
566 @param DeviceAddress The device address to be configured.\r
567\r
568 @retval EFI_SUCCESS The new detected usb device is configured successfully.\r
569 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.\r
570 @retval Others Other failure occurs.\r
571\r
572**/\r
573EFI_STATUS\r
574PeiConfigureUsbDevice (\r
575 IN EFI_PEI_SERVICES **PeiServices,\r
576 IN PEI_USB_DEVICE *PeiUsbDevice,\r
577 IN UINT8 Port,\r
578 IN OUT UINT8 *DeviceAddress\r
579 )\r
580{\r
581 EFI_USB_DEVICE_DESCRIPTOR DeviceDescriptor;\r
582 EFI_STATUS Status;\r
583 PEI_USB_IO_PPI *UsbIoPpi;\r
584 UINT8 Retry;\r
585\r
586 UsbIoPpi = &PeiUsbDevice->UsbIoPpi;\r
587 Status = EFI_SUCCESS;\r
588 ZeroMem (&DeviceDescriptor, sizeof (EFI_USB_DEVICE_DESCRIPTOR));\r
589 //\r
590 // Get USB device descriptor\r
591 //\r
592\r
593 for (Retry = 0; Retry < 3; Retry ++) {\r
594\r
595 PeiUsbDevice->MaxPacketSize0 = 8;\r
596\r
597 Status = PeiUsbGetDescriptor (\r
598 PeiServices,\r
599 UsbIoPpi,\r
600 (USB_DT_DEVICE << 8),\r
601 0,\r
602 8,\r
603 &DeviceDescriptor\r
604 );\r
605\r
606 if (!EFI_ERROR (Status)) {\r
607 DEBUG ((EFI_D_INFO, "PeiUsbGet Device Descriptor the %d time Sucess\n", Retry));\r
608 break;\r
609 }\r
610 }\r
611\r
612 if (Retry == 3) {\r
613 DEBUG ((EFI_D_ERROR, "PeiUsbGet Device Descriptor fail\n", Retry));\r
614 return Status;\r
615 }\r
616\r
617 PeiUsbDevice->MaxPacketSize0 = DeviceDescriptor.MaxPacketSize0;\r
618\r
619 (*DeviceAddress) ++;\r
620\r
621 Status = PeiUsbSetDeviceAddress (\r
622 PeiServices,\r
623 UsbIoPpi,\r
624 *DeviceAddress\r
625 );\r
626\r
627 if (EFI_ERROR (Status)) {\r
628 DEBUG ((EFI_D_ERROR, "PeiUsbSetDeviceAddress Failed\n"));\r
629 return Status;\r
630 }\r
631\r
632 PeiUsbDevice->DeviceAddress = *DeviceAddress;\r
633\r
634 //\r
635 // Get whole USB device descriptor\r
636 //\r
637 Status = PeiUsbGetDescriptor (\r
638 PeiServices,\r
639 UsbIoPpi,\r
640 (USB_DT_DEVICE << 8),\r
641 0,\r
642 (UINT16) sizeof (EFI_USB_DEVICE_DESCRIPTOR),\r
643 &DeviceDescriptor\r
644 );\r
645\r
646 if (EFI_ERROR (Status)) {\r
647 DEBUG ((EFI_D_ERROR, "PeiUsbGetDescriptor First Failed\n"));\r
648 return Status;\r
649 }\r
650 //\r
651 // Get its default configuration and its first interface\r
652 //\r
653 Status = PeiUsbGetAllConfiguration (\r
654 PeiServices,\r
655 PeiUsbDevice\r
656 );\r
657\r
658 if (EFI_ERROR (Status)) {\r
659 return Status;\r
660 }\r
661\r
662 Status = PeiUsbSetConfiguration (\r
663 PeiServices,\r
664 UsbIoPpi\r
665 );\r
666\r
667 if (EFI_ERROR (Status)) {\r
668 return Status;\r
669 }\r
670\r
671 return EFI_SUCCESS;\r
672}\r
673\r
674/**\r
675 Get all configurations from a detected usb device.\r
676 \r
677 @param PeiServices Describes the list of possible PEI Services.\r
678 @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.\r
679\r
680 @retval EFI_SUCCESS The new detected usb device is configured successfully.\r
681 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.\r
682 @retval Others Other failure occurs.\r
683\r
684**/\r
685EFI_STATUS\r
686PeiUsbGetAllConfiguration (\r
687 IN EFI_PEI_SERVICES **PeiServices,\r
688 IN PEI_USB_DEVICE *PeiUsbDevice\r
689 )\r
690{\r
691 EFI_STATUS Status;\r
692 EFI_USB_CONFIG_DESCRIPTOR *ConfigDesc;\r
693 PEI_USB_IO_PPI *UsbIoPpi;\r
694 UINT16 ConfigDescLength;\r
695 UINT8 *Ptr;\r
696 UINTN SkipBytes;\r
697 UINTN LengthLeft;\r
698 UINTN Index;\r
699 UINTN NumOfEndpoint;\r
700\r
701 UsbIoPpi = &PeiUsbDevice->UsbIoPpi;\r
702\r
703 //\r
704 // First get its 4-byte configuration descriptor\r
705 //\r
706 Status = PeiUsbGetDescriptor (\r
707 PeiServices,\r
708 UsbIoPpi,\r
709 (USB_DT_CONFIG << 8), // Value\r
710 0, // Index\r
711 4, // Length\r
712 PeiUsbDevice->ConfigurationData\r
713 );\r
714\r
715 if (EFI_ERROR (Status)) {\r
716 DEBUG ((EFI_D_ERROR, "PeiUsbGet Config Descriptor First Failed\n"));\r
717 return Status;\r
718 }\r
719\r
720 ConfigDesc = (EFI_USB_CONFIG_DESCRIPTOR *) PeiUsbDevice->ConfigurationData;\r
721 ConfigDescLength = ConfigDesc->TotalLength;\r
722\r
723 //\r
724 // Then we get the total descriptors for this configuration\r
725 //\r
726 Status = PeiUsbGetDescriptor (\r
727 PeiServices,\r
728 UsbIoPpi,\r
729 (USB_DT_CONFIG << 8),\r
730 0,\r
731 ConfigDescLength,\r
732 PeiUsbDevice->ConfigurationData\r
733 );\r
734\r
735 if (EFI_ERROR (Status)) {\r
736 DEBUG ((EFI_D_ERROR, "PeiUsbGet Config Descriptor all Failed\n"));\r
737 return Status;\r
738 }\r
739 //\r
740 // Parse this configuration descriptor\r
741 // First get the current config descriptor;\r
742 //\r
743 Status = GetExpectedDescriptor (\r
744 PeiUsbDevice->ConfigurationData,\r
745 ConfigDescLength,\r
746 USB_DT_CONFIG,\r
747 (UINT8) sizeof (EFI_USB_CONFIG_DESCRIPTOR),\r
748 &SkipBytes\r
749 );\r
750\r
751 if (EFI_ERROR (Status)) {\r
752 return Status;\r
753 }\r
754\r
755 Ptr = PeiUsbDevice->ConfigurationData + SkipBytes;\r
756 PeiUsbDevice->ConfigDesc = (EFI_USB_CONFIG_DESCRIPTOR *) Ptr;\r
757\r
758 Ptr += sizeof (EFI_USB_CONFIG_DESCRIPTOR);\r
759 LengthLeft = ConfigDescLength - SkipBytes - sizeof (EFI_USB_CONFIG_DESCRIPTOR);\r
760\r
761 //\r
762 // Get the first interface descriptor\r
763 //\r
764 Status = GetExpectedDescriptor (\r
765 Ptr,\r
766 LengthLeft,\r
767 USB_DT_INTERFACE,\r
768 (UINT8) sizeof (EFI_USB_INTERFACE_DESCRIPTOR),\r
769 &SkipBytes\r
770 );\r
771\r
772 if (EFI_ERROR (Status)) {\r
773 return Status;\r
774 }\r
775\r
776 Ptr += SkipBytes;\r
777 PeiUsbDevice->InterfaceDesc = (EFI_USB_INTERFACE_DESCRIPTOR *) Ptr;\r
778\r
779 Ptr += sizeof (EFI_USB_INTERFACE_DESCRIPTOR);\r
780 LengthLeft -= SkipBytes;\r
781 LengthLeft -= sizeof (EFI_USB_INTERFACE_DESCRIPTOR);\r
782\r
783 //\r
784 // Parse all the endpoint descriptor within this interface\r
785 //\r
786 NumOfEndpoint = PeiUsbDevice->InterfaceDesc->NumEndpoints;\r
787 ASSERT (NumOfEndpoint <= MAX_ENDPOINT);\r
788\r
789 for (Index = 0; Index < NumOfEndpoint; Index++) {\r
790 //\r
791 // Get the endpoint descriptor\r
792 //\r
793 Status = GetExpectedDescriptor (\r
794 Ptr,\r
795 LengthLeft,\r
796 USB_DT_ENDPOINT,\r
797 (UINT8) sizeof (EFI_USB_ENDPOINT_DESCRIPTOR),\r
798 &SkipBytes\r
799 );\r
800\r
801 if (EFI_ERROR (Status)) {\r
802 return Status;\r
803 }\r
804\r
805 Ptr += SkipBytes;\r
806 PeiUsbDevice->EndpointDesc[Index] = (EFI_USB_ENDPOINT_DESCRIPTOR *) Ptr;\r
807\r
808 Ptr += sizeof (EFI_USB_ENDPOINT_DESCRIPTOR);\r
809 LengthLeft -= SkipBytes;\r
810 LengthLeft -= sizeof (EFI_USB_ENDPOINT_DESCRIPTOR);\r
811 }\r
812\r
813 return EFI_SUCCESS;\r
814}\r
815\r
816/**\r
817 Get the start position of next wanted descriptor.\r
818 \r
819 @param Buffer Buffer containing data to parse.\r
820 @param Length Buffer length.\r
821 @param DescType Descriptor type.\r
822 @param DescLength Descriptor length.\r
823 @param ParsedBytes Bytes has been parsed.\r
824\r
825 @retval EFI_SUCCESS Get wanted descriptor successfully.\r
826 @retval EFI_DEVICE_ERROR Error occurred.\r
827\r
828**/\r
829EFI_STATUS\r
830GetExpectedDescriptor (\r
831 IN UINT8 *Buffer,\r
832 IN UINTN Length,\r
833 IN UINT8 DescType,\r
834 IN UINT8 DescLength,\r
835 OUT UINTN *ParsedBytes\r
836 )\r
837{\r
838 UINT16 DescriptorHeader;\r
839 UINT8 Len;\r
840 UINT8 *Ptr;\r
841 UINTN Parsed;\r
842\r
843 Parsed = 0;\r
844 Ptr = Buffer;\r
845\r
846 while (TRUE) {\r
847 //\r
848 // Buffer length should not less than Desc length\r
849 //\r
850 if (Length < DescLength) {\r
851 return EFI_DEVICE_ERROR;\r
852 }\r
853\r
854 DescriptorHeader = (UINT16) (*Ptr + ((*(Ptr + 1)) << 8));\r
855\r
856 Len = Buffer[0];\r
857\r
858 //\r
859 // Check to see if it is a start of expected descriptor\r
860 //\r
861 if (DescriptorHeader == ((DescType << 8) | DescLength)) {\r
862 break;\r
863 }\r
864\r
865 if ((UINT8) (DescriptorHeader >> 8) == DescType) {\r
866 if (Len > DescLength) {\r
867 return EFI_DEVICE_ERROR;\r
868 }\r
869 }\r
870 //\r
871 // Descriptor length should be at least 2\r
872 // and should not exceed the buffer length\r
873 //\r
874 if (Len < 2) {\r
875 return EFI_DEVICE_ERROR;\r
876 }\r
877\r
878 if (Len > Length) {\r
879 return EFI_DEVICE_ERROR;\r
880 }\r
881 //\r
882 // Skip this mismatch descriptor\r
883 //\r
884 Length -= Len;\r
885 Ptr += Len;\r
886 Parsed += Len;\r
887 }\r
888\r
889 *ParsedBytes = Parsed;\r
890\r
891 return EFI_SUCCESS;\r
892}\r
893\r
894/**\r
895 Send reset signal over the given root hub port.\r
896 \r
897 @param PeiServices Describes the list of possible PEI Services.\r
898 @param UsbHcPpi The pointer of PEI_USB_HOST_CONTROLLER_PPI instance.\r
899 @param Usb2HcPpi The pointer of PEI_USB2_HOST_CONTROLLER_PPI instance.\r
900 @param PortNum The port to be reset.\r
901 @param RetryIndex The retry times.\r
902\r
903**/\r
904VOID\r
905ResetRootPort (\r
906 IN EFI_PEI_SERVICES **PeiServices,\r
907 IN PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi,\r
908 IN PEI_USB2_HOST_CONTROLLER_PPI *Usb2HcPpi,\r
909 IN UINT8 PortNum,\r
910 IN UINT8 RetryIndex\r
911 )\r
912{\r
913 EFI_STATUS Status;\r
914\r
915\r
916 if (Usb2HcPpi != NULL) {\r
917 MicroSecondDelay (200 * 1000);\r
918 \r
919 //\r
920 // reset root port\r
921 //\r
922 Status = Usb2HcPpi->SetRootHubPortFeature (\r
923 PeiServices,\r
924 Usb2HcPpi,\r
925 PortNum,\r
926 EfiUsbPortReset\r
927 );\r
928 \r
929 if (EFI_ERROR (Status)) {\r
930 DEBUG ((EFI_D_ERROR, "SetRootHubPortFeature EfiUsbPortReset Failed\n"));\r
931 return;\r
932 }\r
933 \r
934 MicroSecondDelay (200 * 1000);\r
935 \r
936 //\r
937 // clear reset root port\r
938 //\r
939 Status = Usb2HcPpi->ClearRootHubPortFeature (\r
940 PeiServices,\r
941 Usb2HcPpi,\r
942 PortNum,\r
943 EfiUsbPortReset\r
944 );\r
945 \r
946 if (EFI_ERROR (Status)) {\r
947 DEBUG ((EFI_D_ERROR, "ClearRootHubPortFeature EfiUsbPortReset Failed\n"));\r
948 return;\r
949 }\r
950 \r
951 MicroSecondDelay (1 * 1000);\r
952 \r
953 Usb2HcPpi->ClearRootHubPortFeature (\r
954 PeiServices,\r
955 Usb2HcPpi,\r
956 PortNum,\r
957 EfiUsbPortConnectChange\r
958 );\r
959 \r
960 //\r
961 // Set port enable\r
962 //\r
963 Usb2HcPpi->SetRootHubPortFeature(\r
964 PeiServices,\r
965 Usb2HcPpi,\r
966 PortNum,\r
967 EfiUsbPortEnable\r
968 );\r
969 \r
970 Usb2HcPpi->ClearRootHubPortFeature (\r
971 PeiServices,\r
972 Usb2HcPpi,\r
973 PortNum,\r
974 EfiUsbPortEnableChange\r
975 );\r
976 \r
977 MicroSecondDelay ((RetryIndex + 1) * 50 * 1000);\r
978 } else {\r
979 MicroSecondDelay (200 * 1000);\r
980 \r
981 //\r
982 // reset root port\r
983 //\r
984 Status = UsbHcPpi->SetRootHubPortFeature (\r
985 PeiServices,\r
986 UsbHcPpi,\r
987 PortNum,\r
988 EfiUsbPortReset\r
989 );\r
990 \r
991 if (EFI_ERROR (Status)) {\r
992 DEBUG ((EFI_D_ERROR, "SetRootHubPortFeature EfiUsbPortReset Failed\n"));\r
993 return;\r
994 }\r
995 \r
996 MicroSecondDelay (200 * 1000);\r
997 \r
998 //\r
999 // clear reset root port\r
1000 //\r
1001 Status = UsbHcPpi->ClearRootHubPortFeature (\r
1002 PeiServices,\r
1003 UsbHcPpi,\r
1004 PortNum,\r
1005 EfiUsbPortReset\r
1006 );\r
1007 \r
1008 if (EFI_ERROR (Status)) {\r
1009 DEBUG ((EFI_D_ERROR, "ClearRootHubPortFeature EfiUsbPortReset Failed\n"));\r
1010 return;\r
1011 }\r
1012 \r
1013 MicroSecondDelay (1 * 1000);\r
1014 \r
1015 UsbHcPpi->ClearRootHubPortFeature (\r
1016 PeiServices,\r
1017 UsbHcPpi,\r
1018 PortNum,\r
1019 EfiUsbPortConnectChange\r
1020 );\r
1021 \r
1022 //\r
1023 // Set port enable\r
1024 //\r
1025 UsbHcPpi->SetRootHubPortFeature(\r
1026 PeiServices,\r
1027 UsbHcPpi,\r
1028 PortNum,\r
1029 EfiUsbPortEnable\r
1030 );\r
1031 \r
1032 UsbHcPpi->ClearRootHubPortFeature (\r
1033 PeiServices,\r
1034 UsbHcPpi,\r
1035 PortNum,\r
1036 EfiUsbPortEnableChange\r
1037 );\r
1038 \r
1039 MicroSecondDelay ((RetryIndex + 1) * 50 * 1000);\r
1040 }\r
1041 return;\r
1042}\r
1043\r
1044\r