2 The module to produce Usb Bus PPI.
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
12 #include "PeiUsbLib.h"
15 // UsbIo PPI interface function
17 PEI_USB_IO_PPI mUsbIoPpi
= {
18 PeiUsbControlTransfer
,
20 PeiUsbGetInterfaceDescriptor
,
21 PeiUsbGetEndpointDescriptor
,
25 EFI_PEI_PPI_DESCRIPTOR mUsbIoPpiList
= {
26 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
32 The enumeration routine to detect device change.
34 @param PeiServices Describes the list of possible PEI Services.
35 @param UsbHcPpi The pointer of PEI_USB_HOST_CONTROLLER_PPI instance.
36 @param Usb2HcPpi The pointer of PEI_USB2_HOST_CONTROLLER_PPI instance.
38 @retval EFI_SUCCESS The usb is enumerated successfully.
39 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.
40 @retval Others Other failure occurs.
45 IN EFI_PEI_SERVICES
**PeiServices
,
46 IN PEI_USB_HOST_CONTROLLER_PPI
*UsbHcPpi
,
47 IN PEI_USB2_HOST_CONTROLLER_PPI
*Usb2HcPpi
51 Configure new detected usb device.
53 @param PeiServices Describes the list of possible PEI Services.
54 @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.
55 @param Port The port to be configured.
56 @param DeviceAddress The device address to be configured.
58 @retval EFI_SUCCESS The new detected usb device is configured successfully.
59 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.
60 @retval Others Other failure occurs.
64 PeiConfigureUsbDevice (
65 IN EFI_PEI_SERVICES
**PeiServices
,
66 IN PEI_USB_DEVICE
*PeiUsbDevice
,
68 IN OUT UINT8
*DeviceAddress
72 Get all configurations from a detected usb device.
74 @param PeiServices Describes the list of possible PEI Services.
75 @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.
77 @retval EFI_SUCCESS The new detected usb device is configured successfully.
78 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.
79 @retval Others Other failure occurs.
83 PeiUsbGetAllConfiguration (
84 IN EFI_PEI_SERVICES
**PeiServices
,
85 IN PEI_USB_DEVICE
*PeiUsbDevice
89 Get the start position of next wanted descriptor.
91 @param Buffer Buffer containing data to parse.
92 @param Length Buffer length.
93 @param DescType Descriptor type.
94 @param DescLength Descriptor length.
95 @param ParsedBytes Bytes has been parsed.
97 @retval EFI_SUCCESS Get wanted descriptor successfully.
98 @retval EFI_DEVICE_ERROR Error occurred.
102 GetExpectedDescriptor (
107 OUT UINTN
*ParsedBytes
111 The entrypoint of the module, it will enumerate all HCs.
113 @param FileHandle Handle of the file being invoked.
114 @param PeiServices Describes the list of possible PEI Services.
116 @retval EFI_SUCCESS Usb initialization is done successfully.
117 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.
118 @retval EFI_UNSUPPORTED Can't find required PPI.
124 IN EFI_PEI_FILE_HANDLE FileHandle
,
125 IN CONST EFI_PEI_SERVICES
**PeiServices
130 PEI_USB_HOST_CONTROLLER_PPI
*UsbHcPpi
;
131 PEI_USB2_HOST_CONTROLLER_PPI
*Usb2HcPpi
;
133 if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle
))) {
138 // gPeiUsbHostControllerPpiGuid and gPeiUsb2HostControllerPpiGuid should not
139 // be produced at the same time
144 // Get UsbHcPpi at first.
146 Status
= PeiServicesLocatePpi (
147 &gPeiUsbHostControllerPpiGuid
,
152 if (EFI_ERROR (Status
)) {
154 // No more host controller, break out
159 PeiUsbEnumeration ((EFI_PEI_SERVICES
**)PeiServices
, UsbHcPpi
, NULL
);
165 // Then try to get Usb2HcPpi.
168 Status
= PeiServicesLocatePpi (
169 &gPeiUsb2HostControllerPpiGuid
,
174 if (EFI_ERROR (Status
)) {
176 // No more host controller, break out
181 PeiUsbEnumeration ((EFI_PEI_SERVICES
**)PeiServices
, NULL
, Usb2HcPpi
);
187 return EFI_UNSUPPORTED
;
194 The Hub Enumeration just scans the hub ports one time. It also
195 doesn't support hot-plug.
197 @param PeiServices Describes the list of possible PEI Services.
198 @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.
199 @param CurrentAddress The DeviceAddress of usb device.
201 @retval EFI_SUCCESS The usb hub is enumerated successfully.
202 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.
203 @retval Others Other failure occurs.
208 IN EFI_PEI_SERVICES
**PeiServices
,
209 IN PEI_USB_DEVICE
*PeiUsbDevice
,
210 IN UINT8
*CurrentAddress
215 PEI_USB_IO_PPI
*UsbIoPpi
;
216 EFI_USB_PORT_STATUS PortStatus
;
218 EFI_PHYSICAL_ADDRESS AllocateAddress
;
219 PEI_USB_DEVICE
*NewPeiUsbDevice
;
220 UINTN InterfaceIndex
;
223 UsbIoPpi
= &PeiUsbDevice
->UsbIoPpi
;
225 DEBUG ((DEBUG_INFO
, "PeiHubEnumeration: DownStreamPortNo: %x\n", PeiUsbDevice
->DownStreamPortNo
));
227 for (Index
= 0; Index
< PeiUsbDevice
->DownStreamPortNo
; Index
++) {
228 Status
= PeiHubGetPortStatus (
232 (UINT32
*)&PortStatus
235 if (EFI_ERROR (Status
)) {
239 DEBUG ((DEBUG_INFO
, "USB Status --- Port: %x ConnectChange[%04x] Status[%04x]\n", Index
, PortStatus
.PortChangeStatus
, PortStatus
.PortStatus
));
241 // Only handle connection/enable/overcurrent/reset change.
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) {
246 if (IsPortConnect (PortStatus
.PortStatus
)) {
248 // Begin to deal with the new device
250 MemPages
= sizeof (PEI_USB_DEVICE
) / EFI_PAGE_SIZE
+ 1;
251 Status
= PeiServicesAllocatePages (
256 if (EFI_ERROR (Status
)) {
257 return EFI_OUT_OF_RESOURCES
;
260 NewPeiUsbDevice
= (PEI_USB_DEVICE
*)((UINTN
)AllocateAddress
);
261 ZeroMem (NewPeiUsbDevice
, sizeof (PEI_USB_DEVICE
));
263 NewPeiUsbDevice
->Signature
= PEI_USB_DEVICE_SIGNATURE
;
264 NewPeiUsbDevice
->DeviceAddress
= 0;
265 NewPeiUsbDevice
->MaxPacketSize0
= 8;
266 NewPeiUsbDevice
->DataToggle
= 0;
268 &(NewPeiUsbDevice
->UsbIoPpi
),
270 sizeof (PEI_USB_IO_PPI
)
273 &(NewPeiUsbDevice
->UsbIoPpiList
),
275 sizeof (EFI_PEI_PPI_DESCRIPTOR
)
277 NewPeiUsbDevice
->UsbIoPpiList
.Ppi
= &NewPeiUsbDevice
->UsbIoPpi
;
278 NewPeiUsbDevice
->AllocateAddress
= (UINTN
)AllocateAddress
;
279 NewPeiUsbDevice
->UsbHcPpi
= PeiUsbDevice
->UsbHcPpi
;
280 NewPeiUsbDevice
->Usb2HcPpi
= PeiUsbDevice
->Usb2HcPpi
;
281 NewPeiUsbDevice
->Tier
= (UINT8
)(PeiUsbDevice
->Tier
+ 1);
282 NewPeiUsbDevice
->IsHub
= 0x0;
283 NewPeiUsbDevice
->DownStreamPortNo
= 0x0;
285 if (((PortStatus
.PortChangeStatus
& USB_PORT_STAT_C_RESET
) == 0) ||
286 ((PortStatus
.PortStatus
& (USB_PORT_STAT_CONNECTION
| USB_PORT_STAT_ENABLE
)) == 0))
289 // If the port already has reset change flag and is connected and enabled, skip the port reset logic.
291 PeiResetHubPort (PeiServices
, UsbIoPpi
, (UINT8
)(Index
+ 1));
293 PeiHubGetPortStatus (
297 (UINT32
*)&PortStatus
300 PeiHubClearPortFeature (
304 EfiUsbPortResetChange
308 NewPeiUsbDevice
->DeviceSpeed
= (UINT8
)PeiUsbGetDeviceSpeed (PortStatus
.PortStatus
);
309 DEBUG ((DEBUG_INFO
, "Device Speed =%d\n", PeiUsbDevice
->DeviceSpeed
));
311 if (USB_BIT_IS_SET (PortStatus
.PortStatus
, USB_PORT_STAT_SUPER_SPEED
)) {
312 NewPeiUsbDevice
->MaxPacketSize0
= 512;
313 } else if (USB_BIT_IS_SET (PortStatus
.PortStatus
, USB_PORT_STAT_HIGH_SPEED
)) {
314 NewPeiUsbDevice
->MaxPacketSize0
= 64;
315 } else if (USB_BIT_IS_SET (PortStatus
.PortStatus
, USB_PORT_STAT_LOW_SPEED
)) {
316 NewPeiUsbDevice
->MaxPacketSize0
= 8;
318 NewPeiUsbDevice
->MaxPacketSize0
= 8;
321 if (NewPeiUsbDevice
->DeviceSpeed
!= EFI_USB_SPEED_HIGH
) {
322 if (PeiUsbDevice
->DeviceSpeed
== EFI_USB_SPEED_HIGH
) {
323 NewPeiUsbDevice
->Translator
.TranslatorPortNumber
= (UINT8
)Index
;
324 NewPeiUsbDevice
->Translator
.TranslatorHubAddress
= *CurrentAddress
;
326 CopyMem (&(NewPeiUsbDevice
->Translator
), &(PeiUsbDevice
->Translator
), sizeof (EFI_USB2_HC_TRANSACTION_TRANSLATOR
));
331 // Configure that Usb Device
333 Status
= PeiConfigureUsbDevice (
340 if (EFI_ERROR (Status
)) {
344 DEBUG ((DEBUG_INFO
, "PeiHubEnumeration: PeiConfigureUsbDevice Success\n"));
346 Status
= PeiServicesInstallPpi (&NewPeiUsbDevice
->UsbIoPpiList
);
348 if (NewPeiUsbDevice
->InterfaceDesc
->InterfaceClass
== 0x09) {
349 NewPeiUsbDevice
->IsHub
= 0x1;
351 Status
= PeiDoHubConfig (PeiServices
, NewPeiUsbDevice
);
352 if (EFI_ERROR (Status
)) {
356 PeiHubEnumeration (PeiServices
, NewPeiUsbDevice
, CurrentAddress
);
359 for (InterfaceIndex
= 1; InterfaceIndex
< NewPeiUsbDevice
->ConfigDesc
->NumInterfaces
; InterfaceIndex
++) {
361 // Begin to deal with the new device
363 MemPages
= sizeof (PEI_USB_DEVICE
) / EFI_PAGE_SIZE
+ 1;
364 Status
= PeiServicesAllocatePages (
369 if (EFI_ERROR (Status
)) {
370 return EFI_OUT_OF_RESOURCES
;
373 CopyMem ((VOID
*)(UINTN
)AllocateAddress
, NewPeiUsbDevice
, sizeof (PEI_USB_DEVICE
));
374 NewPeiUsbDevice
= (PEI_USB_DEVICE
*)((UINTN
)AllocateAddress
);
375 NewPeiUsbDevice
->AllocateAddress
= (UINTN
)AllocateAddress
;
376 NewPeiUsbDevice
->UsbIoPpiList
.Ppi
= &NewPeiUsbDevice
->UsbIoPpi
;
377 NewPeiUsbDevice
->InterfaceDesc
= NewPeiUsbDevice
->InterfaceDescList
[InterfaceIndex
];
378 for (EndpointIndex
= 0; EndpointIndex
< NewPeiUsbDevice
->InterfaceDesc
->NumEndpoints
; EndpointIndex
++) {
379 NewPeiUsbDevice
->EndpointDesc
[EndpointIndex
] = NewPeiUsbDevice
->EndpointDescList
[InterfaceIndex
][EndpointIndex
];
382 Status
= PeiServicesInstallPpi (&NewPeiUsbDevice
->UsbIoPpiList
);
384 if (NewPeiUsbDevice
->InterfaceDesc
->InterfaceClass
== 0x09) {
385 NewPeiUsbDevice
->IsHub
= 0x1;
387 Status
= PeiDoHubConfig (PeiServices
, NewPeiUsbDevice
);
388 if (EFI_ERROR (Status
)) {
392 PeiHubEnumeration (PeiServices
, NewPeiUsbDevice
, CurrentAddress
);
403 The enumeration routine to detect device change.
405 @param PeiServices Describes the list of possible PEI Services.
406 @param UsbHcPpi The pointer of PEI_USB_HOST_CONTROLLER_PPI instance.
407 @param Usb2HcPpi The pointer of PEI_USB2_HOST_CONTROLLER_PPI instance.
409 @retval EFI_SUCCESS The usb is enumerated successfully.
410 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.
411 @retval Others Other failure occurs.
416 IN EFI_PEI_SERVICES
**PeiServices
,
417 IN PEI_USB_HOST_CONTROLLER_PPI
*UsbHcPpi
,
418 IN PEI_USB2_HOST_CONTROLLER_PPI
*Usb2HcPpi
424 EFI_USB_PORT_STATUS PortStatus
;
425 PEI_USB_DEVICE
*PeiUsbDevice
;
427 EFI_PHYSICAL_ADDRESS AllocateAddress
;
428 UINT8 CurrentAddress
;
429 UINTN InterfaceIndex
;
433 if (Usb2HcPpi
!= NULL
) {
434 Usb2HcPpi
->GetRootHubPortNumber (
437 (UINT8
*)&NumOfRootPort
439 } else if (UsbHcPpi
!= NULL
) {
440 UsbHcPpi
->GetRootHubPortNumber (
443 (UINT8
*)&NumOfRootPort
447 return EFI_INVALID_PARAMETER
;
450 DEBUG ((DEBUG_INFO
, "PeiUsbEnumeration: NumOfRootPort: %x\n", NumOfRootPort
));
452 for (Index
= 0; Index
< NumOfRootPort
; Index
++) {
454 // First get root port status to detect changes happen
456 if (Usb2HcPpi
!= NULL
) {
457 Usb2HcPpi
->GetRootHubPortStatus (
464 UsbHcPpi
->GetRootHubPortStatus (
472 DEBUG ((DEBUG_INFO
, "USB Status --- Port: %x ConnectChange[%04x] Status[%04x]\n", Index
, PortStatus
.PortChangeStatus
, PortStatus
.PortStatus
));
474 // Only handle connection/enable/overcurrent/reset change.
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) {
479 if (IsPortConnect (PortStatus
.PortStatus
)) {
480 MemPages
= sizeof (PEI_USB_DEVICE
) / EFI_PAGE_SIZE
+ 1;
481 Status
= PeiServicesAllocatePages (
486 if (EFI_ERROR (Status
)) {
487 return EFI_OUT_OF_RESOURCES
;
490 PeiUsbDevice
= (PEI_USB_DEVICE
*)((UINTN
)AllocateAddress
);
491 ZeroMem (PeiUsbDevice
, sizeof (PEI_USB_DEVICE
));
493 PeiUsbDevice
->Signature
= PEI_USB_DEVICE_SIGNATURE
;
494 PeiUsbDevice
->DeviceAddress
= 0;
495 PeiUsbDevice
->MaxPacketSize0
= 8;
496 PeiUsbDevice
->DataToggle
= 0;
498 &(PeiUsbDevice
->UsbIoPpi
),
500 sizeof (PEI_USB_IO_PPI
)
503 &(PeiUsbDevice
->UsbIoPpiList
),
505 sizeof (EFI_PEI_PPI_DESCRIPTOR
)
507 PeiUsbDevice
->UsbIoPpiList
.Ppi
= &PeiUsbDevice
->UsbIoPpi
;
508 PeiUsbDevice
->AllocateAddress
= (UINTN
)AllocateAddress
;
509 PeiUsbDevice
->UsbHcPpi
= UsbHcPpi
;
510 PeiUsbDevice
->Usb2HcPpi
= Usb2HcPpi
;
511 PeiUsbDevice
->IsHub
= 0x0;
512 PeiUsbDevice
->DownStreamPortNo
= 0x0;
514 if (((PortStatus
.PortChangeStatus
& USB_PORT_STAT_C_RESET
) == 0) ||
515 ((PortStatus
.PortStatus
& (USB_PORT_STAT_CONNECTION
| USB_PORT_STAT_ENABLE
)) == 0))
518 // If the port already has reset change flag and is connected and enabled, skip the port reset logic.
522 PeiUsbDevice
->UsbHcPpi
,
523 PeiUsbDevice
->Usb2HcPpi
,
528 if (Usb2HcPpi
!= NULL
) {
529 Usb2HcPpi
->GetRootHubPortStatus (
536 UsbHcPpi
->GetRootHubPortStatus (
544 if (Usb2HcPpi
!= NULL
) {
545 Usb2HcPpi
->ClearRootHubPortFeature (
549 EfiUsbPortResetChange
552 UsbHcPpi
->ClearRootHubPortFeature (
556 EfiUsbPortResetChange
561 PeiUsbDevice
->DeviceSpeed
= (UINT8
)PeiUsbGetDeviceSpeed (PortStatus
.PortStatus
);
562 DEBUG ((DEBUG_INFO
, "Device Speed =%d\n", PeiUsbDevice
->DeviceSpeed
));
564 if (USB_BIT_IS_SET (PortStatus
.PortStatus
, USB_PORT_STAT_SUPER_SPEED
)) {
565 PeiUsbDevice
->MaxPacketSize0
= 512;
566 } else if (USB_BIT_IS_SET (PortStatus
.PortStatus
, USB_PORT_STAT_HIGH_SPEED
)) {
567 PeiUsbDevice
->MaxPacketSize0
= 64;
568 } else if (USB_BIT_IS_SET (PortStatus
.PortStatus
, USB_PORT_STAT_LOW_SPEED
)) {
569 PeiUsbDevice
->MaxPacketSize0
= 8;
571 PeiUsbDevice
->MaxPacketSize0
= 8;
575 // Configure that Usb Device
577 Status
= PeiConfigureUsbDevice (
584 if (EFI_ERROR (Status
)) {
588 DEBUG ((DEBUG_INFO
, "PeiUsbEnumeration: PeiConfigureUsbDevice Success\n"));
590 Status
= PeiServicesInstallPpi (&PeiUsbDevice
->UsbIoPpiList
);
592 if (PeiUsbDevice
->InterfaceDesc
->InterfaceClass
== 0x09) {
593 PeiUsbDevice
->IsHub
= 0x1;
595 Status
= PeiDoHubConfig (PeiServices
, PeiUsbDevice
);
596 if (EFI_ERROR (Status
)) {
600 PeiHubEnumeration (PeiServices
, PeiUsbDevice
, &CurrentAddress
);
603 for (InterfaceIndex
= 1; InterfaceIndex
< PeiUsbDevice
->ConfigDesc
->NumInterfaces
; InterfaceIndex
++) {
605 // Begin to deal with the new device
607 MemPages
= sizeof (PEI_USB_DEVICE
) / EFI_PAGE_SIZE
+ 1;
608 Status
= PeiServicesAllocatePages (
613 if (EFI_ERROR (Status
)) {
614 return EFI_OUT_OF_RESOURCES
;
617 CopyMem ((VOID
*)(UINTN
)AllocateAddress
, PeiUsbDevice
, sizeof (PEI_USB_DEVICE
));
618 PeiUsbDevice
= (PEI_USB_DEVICE
*)((UINTN
)AllocateAddress
);
619 PeiUsbDevice
->AllocateAddress
= (UINTN
)AllocateAddress
;
620 PeiUsbDevice
->UsbIoPpiList
.Ppi
= &PeiUsbDevice
->UsbIoPpi
;
621 PeiUsbDevice
->InterfaceDesc
= PeiUsbDevice
->InterfaceDescList
[InterfaceIndex
];
622 for (EndpointIndex
= 0; EndpointIndex
< PeiUsbDevice
->InterfaceDesc
->NumEndpoints
; EndpointIndex
++) {
623 PeiUsbDevice
->EndpointDesc
[EndpointIndex
] = PeiUsbDevice
->EndpointDescList
[InterfaceIndex
][EndpointIndex
];
626 Status
= PeiServicesInstallPpi (&PeiUsbDevice
->UsbIoPpiList
);
628 if (PeiUsbDevice
->InterfaceDesc
->InterfaceClass
== 0x09) {
629 PeiUsbDevice
->IsHub
= 0x1;
631 Status
= PeiDoHubConfig (PeiServices
, PeiUsbDevice
);
632 if (EFI_ERROR (Status
)) {
636 PeiHubEnumeration (PeiServices
, PeiUsbDevice
, &CurrentAddress
);
641 // Disconnect change happen, currently we don't support
651 Configure new detected usb device.
653 @param PeiServices Describes the list of possible PEI Services.
654 @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.
655 @param Port The port to be configured.
656 @param DeviceAddress The device address to be configured.
658 @retval EFI_SUCCESS The new detected usb device is configured successfully.
659 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.
660 @retval Others Other failure occurs.
664 PeiConfigureUsbDevice (
665 IN EFI_PEI_SERVICES
**PeiServices
,
666 IN PEI_USB_DEVICE
*PeiUsbDevice
,
668 IN OUT UINT8
*DeviceAddress
671 EFI_USB_DEVICE_DESCRIPTOR DeviceDescriptor
;
673 PEI_USB_IO_PPI
*UsbIoPpi
;
676 UsbIoPpi
= &PeiUsbDevice
->UsbIoPpi
;
677 Status
= EFI_SUCCESS
;
678 ZeroMem (&DeviceDescriptor
, sizeof (EFI_USB_DEVICE_DESCRIPTOR
));
680 // Get USB device descriptor
683 for (Retry
= 0; Retry
< 3; Retry
++) {
684 Status
= PeiUsbGetDescriptor (
687 (USB_DT_DEVICE
<< 8),
693 if (!EFI_ERROR (Status
)) {
694 DEBUG ((DEBUG_INFO
, "PeiUsbGet Device Descriptor the %d time Success\n", Retry
));
700 DEBUG ((DEBUG_ERROR
, "PeiUsbGet Device Descriptor fail: %x %r\n", Retry
, Status
));
704 if ((DeviceDescriptor
.BcdUSB
>= 0x0300) && (DeviceDescriptor
.MaxPacketSize0
== 9)) {
705 PeiUsbDevice
->MaxPacketSize0
= 1 << 9;
707 PeiUsbDevice
->MaxPacketSize0
= DeviceDescriptor
.MaxPacketSize0
;
712 Status
= PeiUsbSetDeviceAddress (
718 if (EFI_ERROR (Status
)) {
719 DEBUG ((DEBUG_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 ((DEBUG_ERROR
, "PeiUsbGetDescriptor First Failed\n"));
745 // Get its default configuration and its first interface
747 Status
= PeiUsbGetAllConfiguration (
751 if (EFI_ERROR (Status
)) {
755 MicroSecondDelay (USB_GET_CONFIG_DESCRIPTOR_STALL
);
757 Status
= PeiUsbSetConfiguration (
762 if (EFI_ERROR (Status
)) {
770 Get all configurations from a detected usb device.
772 @param PeiServices Describes the list of possible PEI Services.
773 @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.
775 @retval EFI_SUCCESS The new detected usb device is configured successfully.
776 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.
777 @retval Others Other failure occurs.
781 PeiUsbGetAllConfiguration (
782 IN EFI_PEI_SERVICES
**PeiServices
,
783 IN PEI_USB_DEVICE
*PeiUsbDevice
787 EFI_USB_CONFIG_DESCRIPTOR
*ConfigDesc
;
788 PEI_USB_IO_PPI
*UsbIoPpi
;
789 UINT16 ConfigDescLength
;
793 UINTN InterfaceIndex
;
797 UsbIoPpi
= &PeiUsbDevice
->UsbIoPpi
;
800 // First get its 4-byte configuration descriptor
802 Status
= PeiUsbGetDescriptor (
805 (USB_DT_CONFIG
<< 8), // Value
808 PeiUsbDevice
->ConfigurationData
811 if (EFI_ERROR (Status
)) {
812 DEBUG ((DEBUG_ERROR
, "PeiUsbGet Config Descriptor First Failed\n"));
816 MicroSecondDelay (USB_GET_CONFIG_DESCRIPTOR_STALL
);
818 ConfigDesc
= (EFI_USB_CONFIG_DESCRIPTOR
*)PeiUsbDevice
->ConfigurationData
;
819 ConfigDescLength
= ConfigDesc
->TotalLength
;
822 // Reject if TotalLength even cannot cover itself.
824 if (ConfigDescLength
< OFFSET_OF (EFI_USB_CONFIG_DESCRIPTOR
, TotalLength
) + sizeof (ConfigDesc
->TotalLength
)) {
825 return EFI_DEVICE_ERROR
;
829 // Reject if TotalLength exceeds the PeiUsbDevice->ConfigurationData.
831 if (ConfigDescLength
> sizeof (PeiUsbDevice
->ConfigurationData
)) {
832 return EFI_DEVICE_ERROR
;
836 // Then we get the total descriptors for this configuration
838 Status
= PeiUsbGetDescriptor (
841 (USB_DT_CONFIG
<< 8),
844 PeiUsbDevice
->ConfigurationData
847 if (EFI_ERROR (Status
)) {
848 DEBUG ((DEBUG_ERROR
, "PeiUsbGet Config Descriptor all Failed\n"));
853 // Parse this configuration descriptor
854 // First get the current config descriptor;
856 Status
= GetExpectedDescriptor (
857 PeiUsbDevice
->ConfigurationData
,
860 (UINT8
)sizeof (EFI_USB_CONFIG_DESCRIPTOR
),
864 if (EFI_ERROR (Status
)) {
868 Ptr
= PeiUsbDevice
->ConfigurationData
+ SkipBytes
;
869 PeiUsbDevice
->ConfigDesc
= (EFI_USB_CONFIG_DESCRIPTOR
*)Ptr
;
871 Ptr
+= sizeof (EFI_USB_CONFIG_DESCRIPTOR
);
872 LengthLeft
= ConfigDescLength
- SkipBytes
- sizeof (EFI_USB_CONFIG_DESCRIPTOR
);
874 for (InterfaceIndex
= 0; InterfaceIndex
< PeiUsbDevice
->ConfigDesc
->NumInterfaces
; InterfaceIndex
++) {
876 // Get the interface descriptor
878 Status
= GetExpectedDescriptor (
882 (UINT8
)sizeof (EFI_USB_INTERFACE_DESCRIPTOR
),
886 if (EFI_ERROR (Status
)) {
891 if (InterfaceIndex
== 0) {
892 PeiUsbDevice
->InterfaceDesc
= (EFI_USB_INTERFACE_DESCRIPTOR
*)Ptr
;
895 PeiUsbDevice
->InterfaceDescList
[InterfaceIndex
] = (EFI_USB_INTERFACE_DESCRIPTOR
*)Ptr
;
897 Ptr
+= sizeof (EFI_USB_INTERFACE_DESCRIPTOR
);
898 LengthLeft
-= SkipBytes
;
899 LengthLeft
-= sizeof (EFI_USB_INTERFACE_DESCRIPTOR
);
902 // Parse all the endpoint descriptor within this interface
904 NumOfEndpoint
= PeiUsbDevice
->InterfaceDescList
[InterfaceIndex
]->NumEndpoints
;
905 ASSERT (NumOfEndpoint
<= MAX_ENDPOINT
);
907 for (Index
= 0; Index
< NumOfEndpoint
; Index
++) {
909 // Get the endpoint descriptor
911 Status
= GetExpectedDescriptor (
915 (UINT8
)sizeof (EFI_USB_ENDPOINT_DESCRIPTOR
),
919 if (EFI_ERROR (Status
)) {
924 if (InterfaceIndex
== 0) {
925 PeiUsbDevice
->EndpointDesc
[Index
] = (EFI_USB_ENDPOINT_DESCRIPTOR
*)Ptr
;
928 PeiUsbDevice
->EndpointDescList
[InterfaceIndex
][Index
] = (EFI_USB_ENDPOINT_DESCRIPTOR
*)Ptr
;
930 Ptr
+= sizeof (EFI_USB_ENDPOINT_DESCRIPTOR
);
931 LengthLeft
-= SkipBytes
;
932 LengthLeft
-= sizeof (EFI_USB_ENDPOINT_DESCRIPTOR
);
940 Get the start position of next wanted descriptor.
942 @param Buffer Buffer containing data to parse.
943 @param Length Buffer length.
944 @param DescType Descriptor type.
945 @param DescLength Descriptor length.
946 @param ParsedBytes Bytes has been parsed.
948 @retval EFI_SUCCESS Get wanted descriptor successfully.
949 @retval EFI_DEVICE_ERROR Error occurred.
953 GetExpectedDescriptor (
958 OUT UINTN
*ParsedBytes
965 // Total length is too small that cannot hold the single descriptor header plus data.
967 if (Length
<= sizeof (USB_DESC_HEAD
)) {
968 DEBUG ((DEBUG_ERROR
, "GetExpectedDescriptor: met mal-format descriptor, total length = %d!\n", Length
));
969 return EFI_DEVICE_ERROR
;
973 // All the descriptor has a common LTV (Length, Type, Value)
974 // format. Skip the descriptor that isn't of this Type
977 Head
= (USB_DESC_HEAD
*)Buffer
;
978 while (Offset
< Length
- sizeof (USB_DESC_HEAD
)) {
980 // Above condition make sure Head->Len and Head->Type are safe to access
982 Head
= (USB_DESC_HEAD
*)&Buffer
[Offset
];
984 if (Head
->Len
== 0) {
985 DEBUG ((DEBUG_ERROR
, "GetExpectedDescriptor: met mal-format descriptor, Head->Len = 0!\n"));
986 return EFI_DEVICE_ERROR
;
990 // Make sure no overflow when adding Head->Len to Offset.
992 if (Head
->Len
> MAX_UINTN
- Offset
) {
993 DEBUG ((DEBUG_ERROR
, "GetExpectedDescriptor: met mal-format descriptor, Head->Len = %d!\n", Head
->Len
));
994 return EFI_DEVICE_ERROR
;
997 if (Head
->Type
== DescType
) {
1001 Offset
+= Head
->Len
;
1005 // Head->Len is invalid resulting data beyond boundary, or
1006 // Descriptor cannot be found: No such type.
1008 if (Length
< Offset
) {
1009 DEBUG ((DEBUG_ERROR
, "GetExpectedDescriptor: met mal-format descriptor, Offset/Len = %d/%d!\n", Offset
, Length
));
1010 return EFI_DEVICE_ERROR
;
1013 if ((Head
->Type
!= DescType
) || (Head
->Len
< DescLength
)) {
1014 DEBUG ((DEBUG_ERROR
, "GetExpectedDescriptor: descriptor cannot be found, Header(T/L) = %d/%d!\n", Head
->Type
, Head
->Len
));
1015 return EFI_DEVICE_ERROR
;
1018 *ParsedBytes
= Offset
;
1023 Send reset signal over the given root hub port.
1025 @param PeiServices Describes the list of possible PEI Services.
1026 @param UsbHcPpi The pointer of PEI_USB_HOST_CONTROLLER_PPI instance.
1027 @param Usb2HcPpi The pointer of PEI_USB2_HOST_CONTROLLER_PPI instance.
1028 @param PortNum The port to be reset.
1029 @param RetryIndex The retry times.
1034 IN EFI_PEI_SERVICES
**PeiServices
,
1035 IN PEI_USB_HOST_CONTROLLER_PPI
*UsbHcPpi
,
1036 IN PEI_USB2_HOST_CONTROLLER_PPI
*Usb2HcPpi
,
1043 EFI_USB_PORT_STATUS PortStatus
;
1045 if (Usb2HcPpi
!= NULL
) {
1046 MicroSecondDelay (200 * 1000);
1051 Status
= Usb2HcPpi
->SetRootHubPortFeature (
1058 if (EFI_ERROR (Status
)) {
1059 DEBUG ((DEBUG_ERROR
, "SetRootHubPortFeature EfiUsbPortReset Failed\n"));
1064 // Drive the reset signal for at least 50ms. Check USB 2.0 Spec
1065 // section 7.1.7.5 for timing requirements.
1067 MicroSecondDelay (USB_SET_ROOT_PORT_RESET_STALL
);
1070 // clear reset root port
1072 Status
= Usb2HcPpi
->ClearRootHubPortFeature (
1079 if (EFI_ERROR (Status
)) {
1080 DEBUG ((DEBUG_ERROR
, "ClearRootHubPortFeature EfiUsbPortReset Failed\n"));
1084 MicroSecondDelay (USB_CLR_ROOT_PORT_RESET_STALL
);
1087 // USB host controller won't clear the RESET bit until
1088 // reset is actually finished.
1090 ZeroMem (&PortStatus
, sizeof (EFI_USB_PORT_STATUS
));
1092 for (Index
= 0; Index
< USB_WAIT_PORT_STS_CHANGE_LOOP
; Index
++) {
1093 Status
= Usb2HcPpi
->GetRootHubPortStatus (
1099 if (EFI_ERROR (Status
)) {
1103 if (!USB_BIT_IS_SET (PortStatus
.PortStatus
, USB_PORT_STAT_RESET
)) {
1107 MicroSecondDelay (USB_WAIT_PORT_STS_CHANGE_STALL
);
1110 if (Index
== USB_WAIT_PORT_STS_CHANGE_LOOP
) {
1111 DEBUG ((DEBUG_ERROR
, "ResetRootPort: reset not finished in time on port %d\n", PortNum
));
1115 Usb2HcPpi
->ClearRootHubPortFeature (
1119 EfiUsbPortResetChange
1122 Usb2HcPpi
->ClearRootHubPortFeature (
1126 EfiUsbPortConnectChange
1132 Usb2HcPpi
->SetRootHubPortFeature (
1139 Usb2HcPpi
->ClearRootHubPortFeature (
1143 EfiUsbPortEnableChange
1146 MicroSecondDelay ((RetryIndex
+ 1) * 50 * 1000);
1148 MicroSecondDelay (200 * 1000);
1153 Status
= UsbHcPpi
->SetRootHubPortFeature (
1160 if (EFI_ERROR (Status
)) {
1161 DEBUG ((DEBUG_ERROR
, "SetRootHubPortFeature EfiUsbPortReset Failed\n"));
1166 // Drive the reset signal for at least 50ms. Check USB 2.0 Spec
1167 // section 7.1.7.5 for timing requirements.
1169 MicroSecondDelay (USB_SET_ROOT_PORT_RESET_STALL
);
1172 // clear reset root port
1174 Status
= UsbHcPpi
->ClearRootHubPortFeature (
1181 if (EFI_ERROR (Status
)) {
1182 DEBUG ((DEBUG_ERROR
, "ClearRootHubPortFeature EfiUsbPortReset Failed\n"));
1186 MicroSecondDelay (USB_CLR_ROOT_PORT_RESET_STALL
);
1189 // USB host controller won't clear the RESET bit until
1190 // reset is actually finished.
1192 ZeroMem (&PortStatus
, sizeof (EFI_USB_PORT_STATUS
));
1194 for (Index
= 0; Index
< USB_WAIT_PORT_STS_CHANGE_LOOP
; Index
++) {
1195 Status
= UsbHcPpi
->GetRootHubPortStatus (
1201 if (EFI_ERROR (Status
)) {
1205 if (!USB_BIT_IS_SET (PortStatus
.PortStatus
, USB_PORT_STAT_RESET
)) {
1209 MicroSecondDelay (USB_WAIT_PORT_STS_CHANGE_STALL
);
1212 if (Index
== USB_WAIT_PORT_STS_CHANGE_LOOP
) {
1213 DEBUG ((DEBUG_ERROR
, "ResetRootPort: reset not finished in time on port %d\n", PortNum
));
1217 UsbHcPpi
->ClearRootHubPortFeature (
1221 EfiUsbPortResetChange
1224 UsbHcPpi
->ClearRootHubPortFeature (
1228 EfiUsbPortConnectChange
1234 UsbHcPpi
->SetRootHubPortFeature (
1241 UsbHcPpi
->ClearRootHubPortFeature (
1245 EfiUsbPortEnableChange
1248 MicroSecondDelay ((RetryIndex
+ 1) * 50 * 1000);