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