2 The module to produce Usb Bus PPI.
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
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
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.
19 #include "PeiUsbLib.h"
22 // UsbIo PPI interface function
24 PEI_USB_IO_PPI mUsbIoPpi
= {
25 PeiUsbControlTransfer
,
27 PeiUsbGetInterfaceDescriptor
,
28 PeiUsbGetEndpointDescriptor
,
32 EFI_PEI_PPI_DESCRIPTOR mUsbIoPpiList
= {
33 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
39 The enumeration routine to detect device change.
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.
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.
52 IN EFI_PEI_SERVICES
**PeiServices
,
53 IN PEI_USB_HOST_CONTROLLER_PPI
*UsbHcPpi
,
54 IN PEI_USB2_HOST_CONTROLLER_PPI
*Usb2HcPpi
58 Configure new detected usb device.
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.
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.
71 PeiConfigureUsbDevice (
72 IN EFI_PEI_SERVICES
**PeiServices
,
73 IN PEI_USB_DEVICE
*PeiUsbDevice
,
75 IN OUT UINT8
*DeviceAddress
79 Get all configurations from a detected usb device.
81 @param PeiServices Describes the list of possible PEI Services.
82 @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.
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.
90 PeiUsbGetAllConfiguration (
91 IN EFI_PEI_SERVICES
**PeiServices
,
92 IN PEI_USB_DEVICE
*PeiUsbDevice
96 Get the start position of next wanted descriptor.
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.
104 @retval EFI_SUCCESS Get wanted descriptor successfully.
105 @retval EFI_DEVICE_ERROR Error occurred.
109 GetExpectedDescriptor (
114 OUT UINTN
*ParsedBytes
118 The entrypoint of the module, it will enumerate all HCs.
120 @param FileHandle Handle of the file being invoked.
121 @param PeiServices Describes the list of possible PEI Services.
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.
131 IN EFI_PEI_FILE_HANDLE FileHandle
,
132 IN CONST EFI_PEI_SERVICES
**PeiServices
137 PEI_USB_HOST_CONTROLLER_PPI
*UsbHcPpi
;
138 PEI_USB2_HOST_CONTROLLER_PPI
*Usb2HcPpi
;
140 if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle
))) {
145 // gPeiUsbHostControllerPpiGuid and gPeiUsb2HostControllerPpiGuid should not
146 // be produced at the same time
151 // Get UsbHcPpi at first.
153 Status
= PeiServicesLocatePpi (
154 &gPeiUsbHostControllerPpiGuid
,
159 if (EFI_ERROR (Status
)) {
161 // No more host controller, break out
165 PeiUsbEnumeration ((EFI_PEI_SERVICES
**) PeiServices
, UsbHcPpi
, NULL
);
171 // Then try to get Usb2HcPpi.
174 Status
= PeiServicesLocatePpi (
175 &gPeiUsb2HostControllerPpiGuid
,
180 if (EFI_ERROR (Status
)) {
182 // No more host controller, break out
186 PeiUsbEnumeration ((EFI_PEI_SERVICES
**) PeiServices
, NULL
, Usb2HcPpi
);
192 return EFI_UNSUPPORTED
;
199 The Hub Enumeration just scans the hub ports one time. It also
200 doesn't support hot-plug.
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.
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.
213 IN EFI_PEI_SERVICES
**PeiServices
,
214 IN PEI_USB_DEVICE
*PeiUsbDevice
,
215 IN UINT8
*CurrentAddress
220 PEI_USB_IO_PPI
*UsbIoPpi
;
221 EFI_USB_PORT_STATUS PortStatus
;
223 EFI_PHYSICAL_ADDRESS AllocateAddress
;
224 PEI_USB_DEVICE
*NewPeiUsbDevice
;
225 UINTN InterfaceIndex
;
229 UsbIoPpi
= &PeiUsbDevice
->UsbIoPpi
;
231 DEBUG ((EFI_D_INFO
, "PeiHubEnumeration: DownStreamPortNo: %x\n", PeiUsbDevice
->DownStreamPortNo
));
233 for (Index
= 0; Index
< PeiUsbDevice
->DownStreamPortNo
; Index
++) {
235 Status
= PeiHubGetPortStatus (
239 (UINT32
*) &PortStatus
242 if (EFI_ERROR (Status
)) {
246 DEBUG ((EFI_D_INFO
, "USB Status --- Port: %x ConnectChange[%04x] Status[%04x]\n", Index
, PortStatus
.PortChangeStatus
, PortStatus
.PortStatus
));
248 // Only handle connection/enable/overcurrent/reset change.
250 if ((PortStatus
.PortChangeStatus
& (USB_PORT_STAT_C_CONNECTION
| USB_PORT_STAT_C_ENABLE
| USB_PORT_STAT_C_OVERCURRENT
| USB_PORT_STAT_C_RESET
)) == 0) {
253 if (IsPortConnect (PortStatus
.PortStatus
)) {
255 // Begin to deal with the new device
257 MemPages
= sizeof (PEI_USB_DEVICE
) / EFI_PAGE_SIZE
+ 1;
258 Status
= PeiServicesAllocatePages (
263 if (EFI_ERROR (Status
)) {
264 return EFI_OUT_OF_RESOURCES
;
267 NewPeiUsbDevice
= (PEI_USB_DEVICE
*) ((UINTN
) AllocateAddress
);
268 ZeroMem (NewPeiUsbDevice
, sizeof (PEI_USB_DEVICE
));
270 NewPeiUsbDevice
->Signature
= PEI_USB_DEVICE_SIGNATURE
;
271 NewPeiUsbDevice
->DeviceAddress
= 0;
272 NewPeiUsbDevice
->MaxPacketSize0
= 8;
273 NewPeiUsbDevice
->DataToggle
= 0;
275 &(NewPeiUsbDevice
->UsbIoPpi
),
277 sizeof (PEI_USB_IO_PPI
)
280 &(NewPeiUsbDevice
->UsbIoPpiList
),
282 sizeof (EFI_PEI_PPI_DESCRIPTOR
)
284 NewPeiUsbDevice
->UsbIoPpiList
.Ppi
= &NewPeiUsbDevice
->UsbIoPpi
;
285 NewPeiUsbDevice
->AllocateAddress
= (UINTN
) AllocateAddress
;
286 NewPeiUsbDevice
->UsbHcPpi
= PeiUsbDevice
->UsbHcPpi
;
287 NewPeiUsbDevice
->Usb2HcPpi
= PeiUsbDevice
->Usb2HcPpi
;
288 NewPeiUsbDevice
->Tier
= (UINT8
) (PeiUsbDevice
->Tier
+ 1);
289 NewPeiUsbDevice
->IsHub
= 0x0;
290 NewPeiUsbDevice
->DownStreamPortNo
= 0x0;
292 if (((PortStatus
.PortChangeStatus
& USB_PORT_STAT_C_RESET
) == 0) ||
293 ((PortStatus
.PortStatus
& (USB_PORT_STAT_CONNECTION
| USB_PORT_STAT_ENABLE
)) == 0)) {
295 // If the port already has reset change flag and is connected and enabled, skip the port reset logic.
297 PeiResetHubPort (PeiServices
, UsbIoPpi
, (UINT8
)(Index
+ 1));
299 PeiHubGetPortStatus (
303 (UINT32
*) &PortStatus
306 PeiHubClearPortFeature (
310 EfiUsbPortResetChange
314 NewPeiUsbDevice
->DeviceSpeed
= (UINT8
) PeiUsbGetDeviceSpeed (PortStatus
.PortStatus
);
315 DEBUG ((EFI_D_INFO
, "Device Speed =%d\n", PeiUsbDevice
->DeviceSpeed
));
317 if (USB_BIT_IS_SET (PortStatus
.PortStatus
, USB_PORT_STAT_SUPER_SPEED
)){
318 NewPeiUsbDevice
->MaxPacketSize0
= 512;
319 } else if (USB_BIT_IS_SET (PortStatus
.PortStatus
, USB_PORT_STAT_HIGH_SPEED
)) {
320 NewPeiUsbDevice
->MaxPacketSize0
= 64;
321 } else if (USB_BIT_IS_SET (PortStatus
.PortStatus
, USB_PORT_STAT_LOW_SPEED
)) {
322 NewPeiUsbDevice
->MaxPacketSize0
= 8;
324 NewPeiUsbDevice
->MaxPacketSize0
= 8;
327 if(NewPeiUsbDevice
->DeviceSpeed
!= EFI_USB_SPEED_HIGH
) {
328 if (PeiUsbDevice
->DeviceSpeed
== EFI_USB_SPEED_HIGH
) {
329 NewPeiUsbDevice
->Translator
.TranslatorPortNumber
= (UINT8
)Index
;
330 NewPeiUsbDevice
->Translator
.TranslatorHubAddress
= *CurrentAddress
;
332 CopyMem(&(NewPeiUsbDevice
->Translator
), &(PeiUsbDevice
->Translator
), sizeof(EFI_USB2_HC_TRANSACTION_TRANSLATOR
));
337 // Configure that Usb Device
339 Status
= PeiConfigureUsbDevice (
346 if (EFI_ERROR (Status
)) {
349 DEBUG ((EFI_D_INFO
, "PeiHubEnumeration: PeiConfigureUsbDevice Success\n"));
351 Status
= PeiServicesInstallPpi (&NewPeiUsbDevice
->UsbIoPpiList
);
353 if (NewPeiUsbDevice
->InterfaceDesc
->InterfaceClass
== 0x09) {
354 NewPeiUsbDevice
->IsHub
= 0x1;
356 Status
= PeiDoHubConfig (PeiServices
, NewPeiUsbDevice
);
357 if (EFI_ERROR (Status
)) {
361 PeiHubEnumeration (PeiServices
, NewPeiUsbDevice
, CurrentAddress
);
364 for (InterfaceIndex
= 1; InterfaceIndex
< NewPeiUsbDevice
->ConfigDesc
->NumInterfaces
; InterfaceIndex
++) {
366 // Begin to deal with the new device
368 MemPages
= sizeof (PEI_USB_DEVICE
) / EFI_PAGE_SIZE
+ 1;
369 Status
= PeiServicesAllocatePages (
374 if (EFI_ERROR (Status
)) {
375 return EFI_OUT_OF_RESOURCES
;
377 CopyMem ((VOID
*)(UINTN
)AllocateAddress
, NewPeiUsbDevice
, sizeof (PEI_USB_DEVICE
));
378 NewPeiUsbDevice
= (PEI_USB_DEVICE
*) ((UINTN
) AllocateAddress
);
379 NewPeiUsbDevice
->AllocateAddress
= (UINTN
) AllocateAddress
;
380 NewPeiUsbDevice
->UsbIoPpiList
.Ppi
= &NewPeiUsbDevice
->UsbIoPpi
;
381 NewPeiUsbDevice
->InterfaceDesc
= NewPeiUsbDevice
->InterfaceDescList
[InterfaceIndex
];
382 for (EndpointIndex
= 0; EndpointIndex
< NewPeiUsbDevice
->InterfaceDesc
->NumEndpoints
; EndpointIndex
++) {
383 NewPeiUsbDevice
->EndpointDesc
[EndpointIndex
] = NewPeiUsbDevice
->EndpointDescList
[InterfaceIndex
][EndpointIndex
];
386 Status
= PeiServicesInstallPpi (&NewPeiUsbDevice
->UsbIoPpiList
);
388 if (NewPeiUsbDevice
->InterfaceDesc
->InterfaceClass
== 0x09) {
389 NewPeiUsbDevice
->IsHub
= 0x1;
391 Status
= PeiDoHubConfig (PeiServices
, NewPeiUsbDevice
);
392 if (EFI_ERROR (Status
)) {
396 PeiHubEnumeration (PeiServices
, NewPeiUsbDevice
, CurrentAddress
);
408 The enumeration routine to detect device change.
410 @param PeiServices Describes the list of possible PEI Services.
411 @param UsbHcPpi The pointer of PEI_USB_HOST_CONTROLLER_PPI instance.
412 @param Usb2HcPpi The pointer of PEI_USB2_HOST_CONTROLLER_PPI instance.
414 @retval EFI_SUCCESS The usb is enumerated successfully.
415 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.
416 @retval Others Other failure occurs.
421 IN EFI_PEI_SERVICES
**PeiServices
,
422 IN PEI_USB_HOST_CONTROLLER_PPI
*UsbHcPpi
,
423 IN PEI_USB2_HOST_CONTROLLER_PPI
*Usb2HcPpi
429 EFI_USB_PORT_STATUS PortStatus
;
430 PEI_USB_DEVICE
*PeiUsbDevice
;
432 EFI_PHYSICAL_ADDRESS AllocateAddress
;
433 UINT8 CurrentAddress
;
434 UINTN InterfaceIndex
;
438 if (Usb2HcPpi
!= NULL
) {
439 Usb2HcPpi
->GetRootHubPortNumber (
442 (UINT8
*) &NumOfRootPort
444 } else if (UsbHcPpi
!= NULL
) {
445 UsbHcPpi
->GetRootHubPortNumber (
448 (UINT8
*) &NumOfRootPort
452 return EFI_INVALID_PARAMETER
;
455 DEBUG ((EFI_D_INFO
, "PeiUsbEnumeration: NumOfRootPort: %x\n", NumOfRootPort
));
457 for (Index
= 0; Index
< NumOfRootPort
; Index
++) {
459 // First get root port status to detect changes happen
461 if (Usb2HcPpi
!= NULL
) {
462 Usb2HcPpi
->GetRootHubPortStatus (
469 UsbHcPpi
->GetRootHubPortStatus (
476 DEBUG ((EFI_D_INFO
, "USB Status --- Port: %x ConnectChange[%04x] Status[%04x]\n", Index
, PortStatus
.PortChangeStatus
, PortStatus
.PortStatus
));
478 // Only handle connection/enable/overcurrent/reset change.
480 if ((PortStatus
.PortChangeStatus
& (USB_PORT_STAT_C_CONNECTION
| USB_PORT_STAT_C_ENABLE
| USB_PORT_STAT_C_OVERCURRENT
| USB_PORT_STAT_C_RESET
)) == 0) {
483 if (IsPortConnect (PortStatus
.PortStatus
)) {
484 MemPages
= sizeof (PEI_USB_DEVICE
) / EFI_PAGE_SIZE
+ 1;
485 Status
= PeiServicesAllocatePages (
490 if (EFI_ERROR (Status
)) {
491 return EFI_OUT_OF_RESOURCES
;
494 PeiUsbDevice
= (PEI_USB_DEVICE
*) ((UINTN
) AllocateAddress
);
495 ZeroMem (PeiUsbDevice
, sizeof (PEI_USB_DEVICE
));
497 PeiUsbDevice
->Signature
= PEI_USB_DEVICE_SIGNATURE
;
498 PeiUsbDevice
->DeviceAddress
= 0;
499 PeiUsbDevice
->MaxPacketSize0
= 8;
500 PeiUsbDevice
->DataToggle
= 0;
502 &(PeiUsbDevice
->UsbIoPpi
),
504 sizeof (PEI_USB_IO_PPI
)
507 &(PeiUsbDevice
->UsbIoPpiList
),
509 sizeof (EFI_PEI_PPI_DESCRIPTOR
)
511 PeiUsbDevice
->UsbIoPpiList
.Ppi
= &PeiUsbDevice
->UsbIoPpi
;
512 PeiUsbDevice
->AllocateAddress
= (UINTN
) AllocateAddress
;
513 PeiUsbDevice
->UsbHcPpi
= UsbHcPpi
;
514 PeiUsbDevice
->Usb2HcPpi
= Usb2HcPpi
;
515 PeiUsbDevice
->IsHub
= 0x0;
516 PeiUsbDevice
->DownStreamPortNo
= 0x0;
518 if (((PortStatus
.PortChangeStatus
& USB_PORT_STAT_C_RESET
) == 0) ||
519 ((PortStatus
.PortStatus
& (USB_PORT_STAT_CONNECTION
| USB_PORT_STAT_ENABLE
)) == 0)) {
521 // If the port already has reset change flag and is connected and enabled, skip the port reset logic.
525 PeiUsbDevice
->UsbHcPpi
,
526 PeiUsbDevice
->Usb2HcPpi
,
531 if (Usb2HcPpi
!= NULL
) {
532 Usb2HcPpi
->GetRootHubPortStatus (
539 UsbHcPpi
->GetRootHubPortStatus (
547 if (Usb2HcPpi
!= NULL
) {
548 Usb2HcPpi
->ClearRootHubPortFeature (
552 EfiUsbPortResetChange
555 UsbHcPpi
->ClearRootHubPortFeature (
559 EfiUsbPortResetChange
564 PeiUsbDevice
->DeviceSpeed
= (UINT8
) PeiUsbGetDeviceSpeed (PortStatus
.PortStatus
);
565 DEBUG ((EFI_D_INFO
, "Device Speed =%d\n", PeiUsbDevice
->DeviceSpeed
));
567 if (USB_BIT_IS_SET (PortStatus
.PortStatus
, USB_PORT_STAT_SUPER_SPEED
)){
568 PeiUsbDevice
->MaxPacketSize0
= 512;
569 } else if (USB_BIT_IS_SET (PortStatus
.PortStatus
, USB_PORT_STAT_HIGH_SPEED
)) {
570 PeiUsbDevice
->MaxPacketSize0
= 64;
571 } else if (USB_BIT_IS_SET (PortStatus
.PortStatus
, USB_PORT_STAT_LOW_SPEED
)) {
572 PeiUsbDevice
->MaxPacketSize0
= 8;
574 PeiUsbDevice
->MaxPacketSize0
= 8;
578 // Configure that Usb Device
580 Status
= PeiConfigureUsbDevice (
587 if (EFI_ERROR (Status
)) {
590 DEBUG ((EFI_D_INFO
, "PeiUsbEnumeration: PeiConfigureUsbDevice Success\n"));
592 Status
= PeiServicesInstallPpi (&PeiUsbDevice
->UsbIoPpiList
);
594 if (PeiUsbDevice
->InterfaceDesc
->InterfaceClass
== 0x09) {
595 PeiUsbDevice
->IsHub
= 0x1;
597 Status
= PeiDoHubConfig (PeiServices
, PeiUsbDevice
);
598 if (EFI_ERROR (Status
)) {
602 PeiHubEnumeration (PeiServices
, PeiUsbDevice
, &CurrentAddress
);
605 for (InterfaceIndex
= 1; InterfaceIndex
< PeiUsbDevice
->ConfigDesc
->NumInterfaces
; InterfaceIndex
++) {
607 // Begin to deal with the new device
609 MemPages
= sizeof (PEI_USB_DEVICE
) / EFI_PAGE_SIZE
+ 1;
610 Status
= PeiServicesAllocatePages (
615 if (EFI_ERROR (Status
)) {
616 return EFI_OUT_OF_RESOURCES
;
618 CopyMem ((VOID
*)(UINTN
)AllocateAddress
, PeiUsbDevice
, sizeof (PEI_USB_DEVICE
));
619 PeiUsbDevice
= (PEI_USB_DEVICE
*) ((UINTN
) AllocateAddress
);
620 PeiUsbDevice
->AllocateAddress
= (UINTN
) AllocateAddress
;
621 PeiUsbDevice
->UsbIoPpiList
.Ppi
= &PeiUsbDevice
->UsbIoPpi
;
622 PeiUsbDevice
->InterfaceDesc
= PeiUsbDevice
->InterfaceDescList
[InterfaceIndex
];
623 for (EndpointIndex
= 0; EndpointIndex
< PeiUsbDevice
->InterfaceDesc
->NumEndpoints
; EndpointIndex
++) {
624 PeiUsbDevice
->EndpointDesc
[EndpointIndex
] = PeiUsbDevice
->EndpointDescList
[InterfaceIndex
][EndpointIndex
];
627 Status
= PeiServicesInstallPpi (&PeiUsbDevice
->UsbIoPpiList
);
629 if (PeiUsbDevice
->InterfaceDesc
->InterfaceClass
== 0x09) {
630 PeiUsbDevice
->IsHub
= 0x1;
632 Status
= PeiDoHubConfig (PeiServices
, PeiUsbDevice
);
633 if (EFI_ERROR (Status
)) {
637 PeiHubEnumeration (PeiServices
, PeiUsbDevice
, &CurrentAddress
);
642 // Disconnect change happen, currently we don't support
652 Configure new detected usb device.
654 @param PeiServices Describes the list of possible PEI Services.
655 @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.
656 @param Port The port to be configured.
657 @param DeviceAddress The device address to be configured.
659 @retval EFI_SUCCESS The new detected usb device is configured successfully.
660 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.
661 @retval Others Other failure occurs.
665 PeiConfigureUsbDevice (
666 IN EFI_PEI_SERVICES
**PeiServices
,
667 IN PEI_USB_DEVICE
*PeiUsbDevice
,
669 IN OUT UINT8
*DeviceAddress
672 EFI_USB_DEVICE_DESCRIPTOR DeviceDescriptor
;
674 PEI_USB_IO_PPI
*UsbIoPpi
;
677 UsbIoPpi
= &PeiUsbDevice
->UsbIoPpi
;
678 Status
= EFI_SUCCESS
;
679 ZeroMem (&DeviceDescriptor
, sizeof (EFI_USB_DEVICE_DESCRIPTOR
));
681 // Get USB device descriptor
684 for (Retry
= 0; Retry
< 3; Retry
++) {
685 Status
= PeiUsbGetDescriptor (
688 (USB_DT_DEVICE
<< 8),
694 if (!EFI_ERROR (Status
)) {
695 DEBUG ((EFI_D_INFO
, "PeiUsbGet Device Descriptor the %d time Success\n", Retry
));
701 DEBUG ((EFI_D_ERROR
, "PeiUsbGet Device Descriptor fail: %x %r\n", Retry
, Status
));
705 if ((DeviceDescriptor
.BcdUSB
>= 0x0300) && (DeviceDescriptor
.MaxPacketSize0
== 9)) {
706 PeiUsbDevice
->MaxPacketSize0
= 1 << 9;
708 PeiUsbDevice
->MaxPacketSize0
= DeviceDescriptor
.MaxPacketSize0
;
713 Status
= PeiUsbSetDeviceAddress (
719 if (EFI_ERROR (Status
)) {
720 DEBUG ((EFI_D_ERROR
, "PeiUsbSetDeviceAddress Failed: %r\n", Status
));
723 MicroSecondDelay (USB_SET_DEVICE_ADDRESS_STALL
);
725 PeiUsbDevice
->DeviceAddress
= *DeviceAddress
;
728 // Get whole USB device descriptor
730 Status
= PeiUsbGetDescriptor (
733 (USB_DT_DEVICE
<< 8),
735 (UINT16
) sizeof (EFI_USB_DEVICE_DESCRIPTOR
),
739 if (EFI_ERROR (Status
)) {
740 DEBUG ((EFI_D_ERROR
, "PeiUsbGetDescriptor First Failed\n"));
745 // Get its default configuration and its first interface
747 Status
= PeiUsbGetAllConfiguration (
751 if (EFI_ERROR (Status
)) {
754 MicroSecondDelay (USB_GET_CONFIG_DESCRIPTOR_STALL
);
756 Status
= PeiUsbSetConfiguration (
761 if (EFI_ERROR (Status
)) {
769 Get all configurations from a detected usb device.
771 @param PeiServices Describes the list of possible PEI Services.
772 @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.
774 @retval EFI_SUCCESS The new detected usb device is configured successfully.
775 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.
776 @retval Others Other failure occurs.
780 PeiUsbGetAllConfiguration (
781 IN EFI_PEI_SERVICES
**PeiServices
,
782 IN PEI_USB_DEVICE
*PeiUsbDevice
786 EFI_USB_CONFIG_DESCRIPTOR
*ConfigDesc
;
787 PEI_USB_IO_PPI
*UsbIoPpi
;
788 UINT16 ConfigDescLength
;
792 UINTN InterfaceIndex
;
796 UsbIoPpi
= &PeiUsbDevice
->UsbIoPpi
;
799 // First get its 4-byte configuration descriptor
801 Status
= PeiUsbGetDescriptor (
804 (USB_DT_CONFIG
<< 8), // Value
807 PeiUsbDevice
->ConfigurationData
810 if (EFI_ERROR (Status
)) {
811 DEBUG ((EFI_D_ERROR
, "PeiUsbGet Config Descriptor First Failed\n"));
814 MicroSecondDelay (USB_GET_CONFIG_DESCRIPTOR_STALL
);
816 ConfigDesc
= (EFI_USB_CONFIG_DESCRIPTOR
*) PeiUsbDevice
->ConfigurationData
;
817 ConfigDescLength
= ConfigDesc
->TotalLength
;
820 // Then we get the total descriptors for this configuration
822 Status
= PeiUsbGetDescriptor (
825 (USB_DT_CONFIG
<< 8),
828 PeiUsbDevice
->ConfigurationData
831 if (EFI_ERROR (Status
)) {
832 DEBUG ((EFI_D_ERROR
, "PeiUsbGet Config Descriptor all Failed\n"));
836 // Parse this configuration descriptor
837 // First get the current config descriptor;
839 Status
= GetExpectedDescriptor (
840 PeiUsbDevice
->ConfigurationData
,
843 (UINT8
) sizeof (EFI_USB_CONFIG_DESCRIPTOR
),
847 if (EFI_ERROR (Status
)) {
851 Ptr
= PeiUsbDevice
->ConfigurationData
+ SkipBytes
;
852 PeiUsbDevice
->ConfigDesc
= (EFI_USB_CONFIG_DESCRIPTOR
*) Ptr
;
854 Ptr
+= sizeof (EFI_USB_CONFIG_DESCRIPTOR
);
855 LengthLeft
= ConfigDescLength
- SkipBytes
- sizeof (EFI_USB_CONFIG_DESCRIPTOR
);
857 for (InterfaceIndex
= 0; InterfaceIndex
< PeiUsbDevice
->ConfigDesc
->NumInterfaces
; InterfaceIndex
++) {
860 // Get the interface descriptor
862 Status
= GetExpectedDescriptor (
866 (UINT8
) sizeof (EFI_USB_INTERFACE_DESCRIPTOR
),
870 if (EFI_ERROR (Status
)) {
875 if (InterfaceIndex
== 0) {
876 PeiUsbDevice
->InterfaceDesc
= (EFI_USB_INTERFACE_DESCRIPTOR
*) Ptr
;
878 PeiUsbDevice
->InterfaceDescList
[InterfaceIndex
] = (EFI_USB_INTERFACE_DESCRIPTOR
*) Ptr
;
880 Ptr
+= sizeof (EFI_USB_INTERFACE_DESCRIPTOR
);
881 LengthLeft
-= SkipBytes
;
882 LengthLeft
-= sizeof (EFI_USB_INTERFACE_DESCRIPTOR
);
885 // Parse all the endpoint descriptor within this interface
887 NumOfEndpoint
= PeiUsbDevice
->InterfaceDescList
[InterfaceIndex
]->NumEndpoints
;
888 ASSERT (NumOfEndpoint
<= MAX_ENDPOINT
);
890 for (Index
= 0; Index
< NumOfEndpoint
; Index
++) {
892 // Get the endpoint descriptor
894 Status
= GetExpectedDescriptor (
898 (UINT8
) sizeof (EFI_USB_ENDPOINT_DESCRIPTOR
),
902 if (EFI_ERROR (Status
)) {
907 if (InterfaceIndex
== 0) {
908 PeiUsbDevice
->EndpointDesc
[Index
] = (EFI_USB_ENDPOINT_DESCRIPTOR
*) Ptr
;
910 PeiUsbDevice
->EndpointDescList
[InterfaceIndex
][Index
] = (EFI_USB_ENDPOINT_DESCRIPTOR
*) Ptr
;
912 Ptr
+= sizeof (EFI_USB_ENDPOINT_DESCRIPTOR
);
913 LengthLeft
-= SkipBytes
;
914 LengthLeft
-= sizeof (EFI_USB_ENDPOINT_DESCRIPTOR
);
922 Get the start position of next wanted descriptor.
924 @param Buffer Buffer containing data to parse.
925 @param Length Buffer length.
926 @param DescType Descriptor type.
927 @param DescLength Descriptor length.
928 @param ParsedBytes Bytes has been parsed.
930 @retval EFI_SUCCESS Get wanted descriptor successfully.
931 @retval EFI_DEVICE_ERROR Error occurred.
935 GetExpectedDescriptor (
940 OUT UINTN
*ParsedBytes
943 UINT16 DescriptorHeader
;
953 // Buffer length should not less than Desc length
955 if (Length
< DescLength
) {
956 return EFI_DEVICE_ERROR
;
959 DescriptorHeader
= (UINT16
) (*Ptr
+ ((*(Ptr
+ 1)) << 8));
964 // Check to see if it is a start of expected descriptor
966 if (DescriptorHeader
== ((DescType
<< 8) | DescLength
)) {
970 if ((UINT8
) (DescriptorHeader
>> 8) == DescType
) {
971 if (Len
> DescLength
) {
972 return EFI_DEVICE_ERROR
;
976 // Descriptor length should be at least 2
977 // and should not exceed the buffer length
980 return EFI_DEVICE_ERROR
;
984 return EFI_DEVICE_ERROR
;
987 // Skip this mismatch descriptor
994 *ParsedBytes
= Parsed
;
1000 Send reset signal over the given root hub port.
1002 @param PeiServices Describes the list of possible PEI Services.
1003 @param UsbHcPpi The pointer of PEI_USB_HOST_CONTROLLER_PPI instance.
1004 @param Usb2HcPpi The pointer of PEI_USB2_HOST_CONTROLLER_PPI instance.
1005 @param PortNum The port to be reset.
1006 @param RetryIndex The retry times.
1011 IN EFI_PEI_SERVICES
**PeiServices
,
1012 IN PEI_USB_HOST_CONTROLLER_PPI
*UsbHcPpi
,
1013 IN PEI_USB2_HOST_CONTROLLER_PPI
*Usb2HcPpi
,
1020 EFI_USB_PORT_STATUS PortStatus
;
1023 if (Usb2HcPpi
!= NULL
) {
1024 MicroSecondDelay (200 * 1000);
1029 Status
= Usb2HcPpi
->SetRootHubPortFeature (
1036 if (EFI_ERROR (Status
)) {
1037 DEBUG ((EFI_D_ERROR
, "SetRootHubPortFeature EfiUsbPortReset Failed\n"));
1042 // Drive the reset signal for at least 50ms. Check USB 2.0 Spec
1043 // section 7.1.7.5 for timing requirements.
1045 MicroSecondDelay (USB_SET_ROOT_PORT_RESET_STALL
);
1048 // clear reset root port
1050 Status
= Usb2HcPpi
->ClearRootHubPortFeature (
1057 if (EFI_ERROR (Status
)) {
1058 DEBUG ((EFI_D_ERROR
, "ClearRootHubPortFeature EfiUsbPortReset Failed\n"));
1062 MicroSecondDelay (USB_CLR_ROOT_PORT_RESET_STALL
);
1065 // USB host controller won't clear the RESET bit until
1066 // reset is actually finished.
1068 ZeroMem (&PortStatus
, sizeof (EFI_USB_PORT_STATUS
));
1070 for (Index
= 0; Index
< USB_WAIT_PORT_STS_CHANGE_LOOP
; Index
++) {
1071 Status
= Usb2HcPpi
->GetRootHubPortStatus (
1077 if (EFI_ERROR (Status
)) {
1081 if (!USB_BIT_IS_SET (PortStatus
.PortStatus
, USB_PORT_STAT_RESET
)) {
1085 MicroSecondDelay (USB_WAIT_PORT_STS_CHANGE_STALL
);
1088 if (Index
== USB_WAIT_PORT_STS_CHANGE_LOOP
) {
1089 DEBUG ((EFI_D_ERROR
, "ResetRootPort: reset not finished in time on port %d\n", PortNum
));
1093 Usb2HcPpi
->ClearRootHubPortFeature (
1097 EfiUsbPortResetChange
1100 Usb2HcPpi
->ClearRootHubPortFeature (
1104 EfiUsbPortConnectChange
1110 Usb2HcPpi
->SetRootHubPortFeature(
1117 Usb2HcPpi
->ClearRootHubPortFeature (
1121 EfiUsbPortEnableChange
1124 MicroSecondDelay ((RetryIndex
+ 1) * 50 * 1000);
1126 MicroSecondDelay (200 * 1000);
1131 Status
= UsbHcPpi
->SetRootHubPortFeature (
1138 if (EFI_ERROR (Status
)) {
1139 DEBUG ((EFI_D_ERROR
, "SetRootHubPortFeature EfiUsbPortReset Failed\n"));
1144 // Drive the reset signal for at least 50ms. Check USB 2.0 Spec
1145 // section 7.1.7.5 for timing requirements.
1147 MicroSecondDelay (USB_SET_ROOT_PORT_RESET_STALL
);
1150 // clear reset root port
1152 Status
= UsbHcPpi
->ClearRootHubPortFeature (
1159 if (EFI_ERROR (Status
)) {
1160 DEBUG ((EFI_D_ERROR
, "ClearRootHubPortFeature EfiUsbPortReset Failed\n"));
1164 MicroSecondDelay (USB_CLR_ROOT_PORT_RESET_STALL
);
1167 // USB host controller won't clear the RESET bit until
1168 // reset is actually finished.
1170 ZeroMem (&PortStatus
, sizeof (EFI_USB_PORT_STATUS
));
1172 for (Index
= 0; Index
< USB_WAIT_PORT_STS_CHANGE_LOOP
; Index
++) {
1173 Status
= UsbHcPpi
->GetRootHubPortStatus (
1179 if (EFI_ERROR (Status
)) {
1183 if (!USB_BIT_IS_SET (PortStatus
.PortStatus
, USB_PORT_STAT_RESET
)) {
1187 MicroSecondDelay (USB_WAIT_PORT_STS_CHANGE_STALL
);
1190 if (Index
== USB_WAIT_PORT_STS_CHANGE_LOOP
) {
1191 DEBUG ((EFI_D_ERROR
, "ResetRootPort: reset not finished in time on port %d\n", PortNum
));
1195 UsbHcPpi
->ClearRootHubPortFeature (
1199 EfiUsbPortResetChange
1202 UsbHcPpi
->ClearRootHubPortFeature (
1206 EfiUsbPortConnectChange
1212 UsbHcPpi
->SetRootHubPortFeature(
1219 UsbHcPpi
->ClearRootHubPortFeature (
1223 EfiUsbPortEnableChange
1226 MicroSecondDelay ((RetryIndex
+ 1) * 50 * 1000);