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
158 PeiUsbEnumeration ((EFI_PEI_SERVICES
**) PeiServices
, UsbHcPpi
, NULL
);
164 // Then try to get Usb2HcPpi.
167 Status
= PeiServicesLocatePpi (
168 &gPeiUsb2HostControllerPpiGuid
,
173 if (EFI_ERROR (Status
)) {
175 // No more host controller, break out
179 PeiUsbEnumeration ((EFI_PEI_SERVICES
**) PeiServices
, NULL
, Usb2HcPpi
);
185 return EFI_UNSUPPORTED
;
192 The Hub Enumeration just scans the hub ports one time. It also
193 doesn't support hot-plug.
195 @param PeiServices Describes the list of possible PEI Services.
196 @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.
197 @param CurrentAddress The DeviceAddress of usb device.
199 @retval EFI_SUCCESS The usb hub is enumerated successfully.
200 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.
201 @retval Others Other failure occurs.
206 IN EFI_PEI_SERVICES
**PeiServices
,
207 IN PEI_USB_DEVICE
*PeiUsbDevice
,
208 IN UINT8
*CurrentAddress
213 PEI_USB_IO_PPI
*UsbIoPpi
;
214 EFI_USB_PORT_STATUS PortStatus
;
216 EFI_PHYSICAL_ADDRESS AllocateAddress
;
217 PEI_USB_DEVICE
*NewPeiUsbDevice
;
218 UINTN InterfaceIndex
;
222 UsbIoPpi
= &PeiUsbDevice
->UsbIoPpi
;
224 DEBUG ((EFI_D_INFO
, "PeiHubEnumeration: DownStreamPortNo: %x\n", PeiUsbDevice
->DownStreamPortNo
));
226 for (Index
= 0; Index
< PeiUsbDevice
->DownStreamPortNo
; Index
++) {
228 Status
= PeiHubGetPortStatus (
232 (UINT32
*) &PortStatus
235 if (EFI_ERROR (Status
)) {
239 DEBUG ((EFI_D_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)) {
288 // If the port already has reset change flag and is connected and enabled, skip the port reset logic.
290 PeiResetHubPort (PeiServices
, UsbIoPpi
, (UINT8
)(Index
+ 1));
292 PeiHubGetPortStatus (
296 (UINT32
*) &PortStatus
299 PeiHubClearPortFeature (
303 EfiUsbPortResetChange
307 NewPeiUsbDevice
->DeviceSpeed
= (UINT8
) PeiUsbGetDeviceSpeed (PortStatus
.PortStatus
);
308 DEBUG ((EFI_D_INFO
, "Device Speed =%d\n", PeiUsbDevice
->DeviceSpeed
));
310 if (USB_BIT_IS_SET (PortStatus
.PortStatus
, USB_PORT_STAT_SUPER_SPEED
)){
311 NewPeiUsbDevice
->MaxPacketSize0
= 512;
312 } else if (USB_BIT_IS_SET (PortStatus
.PortStatus
, USB_PORT_STAT_HIGH_SPEED
)) {
313 NewPeiUsbDevice
->MaxPacketSize0
= 64;
314 } else if (USB_BIT_IS_SET (PortStatus
.PortStatus
, USB_PORT_STAT_LOW_SPEED
)) {
315 NewPeiUsbDevice
->MaxPacketSize0
= 8;
317 NewPeiUsbDevice
->MaxPacketSize0
= 8;
320 if(NewPeiUsbDevice
->DeviceSpeed
!= EFI_USB_SPEED_HIGH
) {
321 if (PeiUsbDevice
->DeviceSpeed
== EFI_USB_SPEED_HIGH
) {
322 NewPeiUsbDevice
->Translator
.TranslatorPortNumber
= (UINT8
)Index
;
323 NewPeiUsbDevice
->Translator
.TranslatorHubAddress
= *CurrentAddress
;
325 CopyMem(&(NewPeiUsbDevice
->Translator
), &(PeiUsbDevice
->Translator
), sizeof(EFI_USB2_HC_TRANSACTION_TRANSLATOR
));
330 // Configure that Usb Device
332 Status
= PeiConfigureUsbDevice (
339 if (EFI_ERROR (Status
)) {
342 DEBUG ((EFI_D_INFO
, "PeiHubEnumeration: PeiConfigureUsbDevice Success\n"));
344 Status
= PeiServicesInstallPpi (&NewPeiUsbDevice
->UsbIoPpiList
);
346 if (NewPeiUsbDevice
->InterfaceDesc
->InterfaceClass
== 0x09) {
347 NewPeiUsbDevice
->IsHub
= 0x1;
349 Status
= PeiDoHubConfig (PeiServices
, NewPeiUsbDevice
);
350 if (EFI_ERROR (Status
)) {
354 PeiHubEnumeration (PeiServices
, NewPeiUsbDevice
, CurrentAddress
);
357 for (InterfaceIndex
= 1; InterfaceIndex
< NewPeiUsbDevice
->ConfigDesc
->NumInterfaces
; InterfaceIndex
++) {
359 // Begin to deal with the new device
361 MemPages
= sizeof (PEI_USB_DEVICE
) / EFI_PAGE_SIZE
+ 1;
362 Status
= PeiServicesAllocatePages (
367 if (EFI_ERROR (Status
)) {
368 return EFI_OUT_OF_RESOURCES
;
370 CopyMem ((VOID
*)(UINTN
)AllocateAddress
, NewPeiUsbDevice
, sizeof (PEI_USB_DEVICE
));
371 NewPeiUsbDevice
= (PEI_USB_DEVICE
*) ((UINTN
) AllocateAddress
);
372 NewPeiUsbDevice
->AllocateAddress
= (UINTN
) AllocateAddress
;
373 NewPeiUsbDevice
->UsbIoPpiList
.Ppi
= &NewPeiUsbDevice
->UsbIoPpi
;
374 NewPeiUsbDevice
->InterfaceDesc
= NewPeiUsbDevice
->InterfaceDescList
[InterfaceIndex
];
375 for (EndpointIndex
= 0; EndpointIndex
< NewPeiUsbDevice
->InterfaceDesc
->NumEndpoints
; EndpointIndex
++) {
376 NewPeiUsbDevice
->EndpointDesc
[EndpointIndex
] = NewPeiUsbDevice
->EndpointDescList
[InterfaceIndex
][EndpointIndex
];
379 Status
= PeiServicesInstallPpi (&NewPeiUsbDevice
->UsbIoPpiList
);
381 if (NewPeiUsbDevice
->InterfaceDesc
->InterfaceClass
== 0x09) {
382 NewPeiUsbDevice
->IsHub
= 0x1;
384 Status
= PeiDoHubConfig (PeiServices
, NewPeiUsbDevice
);
385 if (EFI_ERROR (Status
)) {
389 PeiHubEnumeration (PeiServices
, NewPeiUsbDevice
, CurrentAddress
);
401 The enumeration routine to detect device change.
403 @param PeiServices Describes the list of possible PEI Services.
404 @param UsbHcPpi The pointer of PEI_USB_HOST_CONTROLLER_PPI instance.
405 @param Usb2HcPpi The pointer of PEI_USB2_HOST_CONTROLLER_PPI instance.
407 @retval EFI_SUCCESS The usb is enumerated successfully.
408 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.
409 @retval Others Other failure occurs.
414 IN EFI_PEI_SERVICES
**PeiServices
,
415 IN PEI_USB_HOST_CONTROLLER_PPI
*UsbHcPpi
,
416 IN PEI_USB2_HOST_CONTROLLER_PPI
*Usb2HcPpi
422 EFI_USB_PORT_STATUS PortStatus
;
423 PEI_USB_DEVICE
*PeiUsbDevice
;
425 EFI_PHYSICAL_ADDRESS AllocateAddress
;
426 UINT8 CurrentAddress
;
427 UINTN InterfaceIndex
;
431 if (Usb2HcPpi
!= NULL
) {
432 Usb2HcPpi
->GetRootHubPortNumber (
435 (UINT8
*) &NumOfRootPort
437 } else if (UsbHcPpi
!= NULL
) {
438 UsbHcPpi
->GetRootHubPortNumber (
441 (UINT8
*) &NumOfRootPort
445 return EFI_INVALID_PARAMETER
;
448 DEBUG ((EFI_D_INFO
, "PeiUsbEnumeration: NumOfRootPort: %x\n", NumOfRootPort
));
450 for (Index
= 0; Index
< NumOfRootPort
; Index
++) {
452 // First get root port status to detect changes happen
454 if (Usb2HcPpi
!= NULL
) {
455 Usb2HcPpi
->GetRootHubPortStatus (
462 UsbHcPpi
->GetRootHubPortStatus (
469 DEBUG ((EFI_D_INFO
, "USB Status --- Port: %x ConnectChange[%04x] Status[%04x]\n", Index
, PortStatus
.PortChangeStatus
, PortStatus
.PortStatus
));
471 // Only handle connection/enable/overcurrent/reset change.
473 if ((PortStatus
.PortChangeStatus
& (USB_PORT_STAT_C_CONNECTION
| USB_PORT_STAT_C_ENABLE
| USB_PORT_STAT_C_OVERCURRENT
| USB_PORT_STAT_C_RESET
)) == 0) {
476 if (IsPortConnect (PortStatus
.PortStatus
)) {
477 MemPages
= sizeof (PEI_USB_DEVICE
) / EFI_PAGE_SIZE
+ 1;
478 Status
= PeiServicesAllocatePages (
483 if (EFI_ERROR (Status
)) {
484 return EFI_OUT_OF_RESOURCES
;
487 PeiUsbDevice
= (PEI_USB_DEVICE
*) ((UINTN
) AllocateAddress
);
488 ZeroMem (PeiUsbDevice
, sizeof (PEI_USB_DEVICE
));
490 PeiUsbDevice
->Signature
= PEI_USB_DEVICE_SIGNATURE
;
491 PeiUsbDevice
->DeviceAddress
= 0;
492 PeiUsbDevice
->MaxPacketSize0
= 8;
493 PeiUsbDevice
->DataToggle
= 0;
495 &(PeiUsbDevice
->UsbIoPpi
),
497 sizeof (PEI_USB_IO_PPI
)
500 &(PeiUsbDevice
->UsbIoPpiList
),
502 sizeof (EFI_PEI_PPI_DESCRIPTOR
)
504 PeiUsbDevice
->UsbIoPpiList
.Ppi
= &PeiUsbDevice
->UsbIoPpi
;
505 PeiUsbDevice
->AllocateAddress
= (UINTN
) AllocateAddress
;
506 PeiUsbDevice
->UsbHcPpi
= UsbHcPpi
;
507 PeiUsbDevice
->Usb2HcPpi
= Usb2HcPpi
;
508 PeiUsbDevice
->IsHub
= 0x0;
509 PeiUsbDevice
->DownStreamPortNo
= 0x0;
511 if (((PortStatus
.PortChangeStatus
& USB_PORT_STAT_C_RESET
) == 0) ||
512 ((PortStatus
.PortStatus
& (USB_PORT_STAT_CONNECTION
| USB_PORT_STAT_ENABLE
)) == 0)) {
514 // If the port already has reset change flag and is connected and enabled, skip the port reset logic.
518 PeiUsbDevice
->UsbHcPpi
,
519 PeiUsbDevice
->Usb2HcPpi
,
524 if (Usb2HcPpi
!= NULL
) {
525 Usb2HcPpi
->GetRootHubPortStatus (
532 UsbHcPpi
->GetRootHubPortStatus (
540 if (Usb2HcPpi
!= NULL
) {
541 Usb2HcPpi
->ClearRootHubPortFeature (
545 EfiUsbPortResetChange
548 UsbHcPpi
->ClearRootHubPortFeature (
552 EfiUsbPortResetChange
557 PeiUsbDevice
->DeviceSpeed
= (UINT8
) PeiUsbGetDeviceSpeed (PortStatus
.PortStatus
);
558 DEBUG ((EFI_D_INFO
, "Device Speed =%d\n", PeiUsbDevice
->DeviceSpeed
));
560 if (USB_BIT_IS_SET (PortStatus
.PortStatus
, USB_PORT_STAT_SUPER_SPEED
)){
561 PeiUsbDevice
->MaxPacketSize0
= 512;
562 } else if (USB_BIT_IS_SET (PortStatus
.PortStatus
, USB_PORT_STAT_HIGH_SPEED
)) {
563 PeiUsbDevice
->MaxPacketSize0
= 64;
564 } else if (USB_BIT_IS_SET (PortStatus
.PortStatus
, USB_PORT_STAT_LOW_SPEED
)) {
565 PeiUsbDevice
->MaxPacketSize0
= 8;
567 PeiUsbDevice
->MaxPacketSize0
= 8;
571 // Configure that Usb Device
573 Status
= PeiConfigureUsbDevice (
580 if (EFI_ERROR (Status
)) {
583 DEBUG ((EFI_D_INFO
, "PeiUsbEnumeration: PeiConfigureUsbDevice Success\n"));
585 Status
= PeiServicesInstallPpi (&PeiUsbDevice
->UsbIoPpiList
);
587 if (PeiUsbDevice
->InterfaceDesc
->InterfaceClass
== 0x09) {
588 PeiUsbDevice
->IsHub
= 0x1;
590 Status
= PeiDoHubConfig (PeiServices
, PeiUsbDevice
);
591 if (EFI_ERROR (Status
)) {
595 PeiHubEnumeration (PeiServices
, PeiUsbDevice
, &CurrentAddress
);
598 for (InterfaceIndex
= 1; InterfaceIndex
< PeiUsbDevice
->ConfigDesc
->NumInterfaces
; InterfaceIndex
++) {
600 // Begin to deal with the new device
602 MemPages
= sizeof (PEI_USB_DEVICE
) / EFI_PAGE_SIZE
+ 1;
603 Status
= PeiServicesAllocatePages (
608 if (EFI_ERROR (Status
)) {
609 return EFI_OUT_OF_RESOURCES
;
611 CopyMem ((VOID
*)(UINTN
)AllocateAddress
, PeiUsbDevice
, sizeof (PEI_USB_DEVICE
));
612 PeiUsbDevice
= (PEI_USB_DEVICE
*) ((UINTN
) AllocateAddress
);
613 PeiUsbDevice
->AllocateAddress
= (UINTN
) AllocateAddress
;
614 PeiUsbDevice
->UsbIoPpiList
.Ppi
= &PeiUsbDevice
->UsbIoPpi
;
615 PeiUsbDevice
->InterfaceDesc
= PeiUsbDevice
->InterfaceDescList
[InterfaceIndex
];
616 for (EndpointIndex
= 0; EndpointIndex
< PeiUsbDevice
->InterfaceDesc
->NumEndpoints
; EndpointIndex
++) {
617 PeiUsbDevice
->EndpointDesc
[EndpointIndex
] = PeiUsbDevice
->EndpointDescList
[InterfaceIndex
][EndpointIndex
];
620 Status
= PeiServicesInstallPpi (&PeiUsbDevice
->UsbIoPpiList
);
622 if (PeiUsbDevice
->InterfaceDesc
->InterfaceClass
== 0x09) {
623 PeiUsbDevice
->IsHub
= 0x1;
625 Status
= PeiDoHubConfig (PeiServices
, PeiUsbDevice
);
626 if (EFI_ERROR (Status
)) {
630 PeiHubEnumeration (PeiServices
, PeiUsbDevice
, &CurrentAddress
);
635 // Disconnect change happen, currently we don't support
645 Configure new detected usb device.
647 @param PeiServices Describes the list of possible PEI Services.
648 @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.
649 @param Port The port to be configured.
650 @param DeviceAddress The device address to be configured.
652 @retval EFI_SUCCESS The new detected usb device is configured successfully.
653 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.
654 @retval Others Other failure occurs.
658 PeiConfigureUsbDevice (
659 IN EFI_PEI_SERVICES
**PeiServices
,
660 IN PEI_USB_DEVICE
*PeiUsbDevice
,
662 IN OUT UINT8
*DeviceAddress
665 EFI_USB_DEVICE_DESCRIPTOR DeviceDescriptor
;
667 PEI_USB_IO_PPI
*UsbIoPpi
;
670 UsbIoPpi
= &PeiUsbDevice
->UsbIoPpi
;
671 Status
= EFI_SUCCESS
;
672 ZeroMem (&DeviceDescriptor
, sizeof (EFI_USB_DEVICE_DESCRIPTOR
));
674 // Get USB device descriptor
677 for (Retry
= 0; Retry
< 3; Retry
++) {
678 Status
= PeiUsbGetDescriptor (
681 (USB_DT_DEVICE
<< 8),
687 if (!EFI_ERROR (Status
)) {
688 DEBUG ((EFI_D_INFO
, "PeiUsbGet Device Descriptor the %d time Success\n", Retry
));
694 DEBUG ((EFI_D_ERROR
, "PeiUsbGet Device Descriptor fail: %x %r\n", Retry
, Status
));
698 if ((DeviceDescriptor
.BcdUSB
>= 0x0300) && (DeviceDescriptor
.MaxPacketSize0
== 9)) {
699 PeiUsbDevice
->MaxPacketSize0
= 1 << 9;
701 PeiUsbDevice
->MaxPacketSize0
= DeviceDescriptor
.MaxPacketSize0
;
706 Status
= PeiUsbSetDeviceAddress (
712 if (EFI_ERROR (Status
)) {
713 DEBUG ((EFI_D_ERROR
, "PeiUsbSetDeviceAddress Failed: %r\n", Status
));
716 MicroSecondDelay (USB_SET_DEVICE_ADDRESS_STALL
);
718 PeiUsbDevice
->DeviceAddress
= *DeviceAddress
;
721 // Get whole USB device descriptor
723 Status
= PeiUsbGetDescriptor (
726 (USB_DT_DEVICE
<< 8),
728 (UINT16
) sizeof (EFI_USB_DEVICE_DESCRIPTOR
),
732 if (EFI_ERROR (Status
)) {
733 DEBUG ((EFI_D_ERROR
, "PeiUsbGetDescriptor First Failed\n"));
738 // Get its default configuration and its first interface
740 Status
= PeiUsbGetAllConfiguration (
744 if (EFI_ERROR (Status
)) {
747 MicroSecondDelay (USB_GET_CONFIG_DESCRIPTOR_STALL
);
749 Status
= PeiUsbSetConfiguration (
754 if (EFI_ERROR (Status
)) {
762 Get all configurations from a detected usb device.
764 @param PeiServices Describes the list of possible PEI Services.
765 @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.
767 @retval EFI_SUCCESS The new detected usb device is configured successfully.
768 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.
769 @retval Others Other failure occurs.
773 PeiUsbGetAllConfiguration (
774 IN EFI_PEI_SERVICES
**PeiServices
,
775 IN PEI_USB_DEVICE
*PeiUsbDevice
779 EFI_USB_CONFIG_DESCRIPTOR
*ConfigDesc
;
780 PEI_USB_IO_PPI
*UsbIoPpi
;
781 UINT16 ConfigDescLength
;
785 UINTN InterfaceIndex
;
789 UsbIoPpi
= &PeiUsbDevice
->UsbIoPpi
;
792 // First get its 4-byte configuration descriptor
794 Status
= PeiUsbGetDescriptor (
797 (USB_DT_CONFIG
<< 8), // Value
800 PeiUsbDevice
->ConfigurationData
803 if (EFI_ERROR (Status
)) {
804 DEBUG ((EFI_D_ERROR
, "PeiUsbGet Config Descriptor First Failed\n"));
807 MicroSecondDelay (USB_GET_CONFIG_DESCRIPTOR_STALL
);
809 ConfigDesc
= (EFI_USB_CONFIG_DESCRIPTOR
*) PeiUsbDevice
->ConfigurationData
;
810 ConfigDescLength
= ConfigDesc
->TotalLength
;
813 // Reject if TotalLength even cannot cover itself.
815 if (ConfigDescLength
< OFFSET_OF (EFI_USB_CONFIG_DESCRIPTOR
, TotalLength
) + sizeof (ConfigDesc
->TotalLength
)) {
816 return EFI_DEVICE_ERROR
;
820 // Reject if TotalLength exceeds the PeiUsbDevice->ConfigurationData.
822 if (ConfigDescLength
> sizeof (PeiUsbDevice
->ConfigurationData
)) {
823 return EFI_DEVICE_ERROR
;
827 // Then we get the total descriptors for this configuration
829 Status
= PeiUsbGetDescriptor (
832 (USB_DT_CONFIG
<< 8),
835 PeiUsbDevice
->ConfigurationData
838 if (EFI_ERROR (Status
)) {
839 DEBUG ((EFI_D_ERROR
, "PeiUsbGet Config Descriptor all Failed\n"));
843 // Parse this configuration descriptor
844 // First get the current config descriptor;
846 Status
= GetExpectedDescriptor (
847 PeiUsbDevice
->ConfigurationData
,
850 (UINT8
) sizeof (EFI_USB_CONFIG_DESCRIPTOR
),
854 if (EFI_ERROR (Status
)) {
858 Ptr
= PeiUsbDevice
->ConfigurationData
+ SkipBytes
;
859 PeiUsbDevice
->ConfigDesc
= (EFI_USB_CONFIG_DESCRIPTOR
*) Ptr
;
861 Ptr
+= sizeof (EFI_USB_CONFIG_DESCRIPTOR
);
862 LengthLeft
= ConfigDescLength
- SkipBytes
- sizeof (EFI_USB_CONFIG_DESCRIPTOR
);
864 for (InterfaceIndex
= 0; InterfaceIndex
< PeiUsbDevice
->ConfigDesc
->NumInterfaces
; InterfaceIndex
++) {
867 // Get the interface descriptor
869 Status
= GetExpectedDescriptor (
873 (UINT8
) sizeof (EFI_USB_INTERFACE_DESCRIPTOR
),
877 if (EFI_ERROR (Status
)) {
882 if (InterfaceIndex
== 0) {
883 PeiUsbDevice
->InterfaceDesc
= (EFI_USB_INTERFACE_DESCRIPTOR
*) Ptr
;
885 PeiUsbDevice
->InterfaceDescList
[InterfaceIndex
] = (EFI_USB_INTERFACE_DESCRIPTOR
*) Ptr
;
887 Ptr
+= sizeof (EFI_USB_INTERFACE_DESCRIPTOR
);
888 LengthLeft
-= SkipBytes
;
889 LengthLeft
-= sizeof (EFI_USB_INTERFACE_DESCRIPTOR
);
892 // Parse all the endpoint descriptor within this interface
894 NumOfEndpoint
= PeiUsbDevice
->InterfaceDescList
[InterfaceIndex
]->NumEndpoints
;
895 ASSERT (NumOfEndpoint
<= MAX_ENDPOINT
);
897 for (Index
= 0; Index
< NumOfEndpoint
; Index
++) {
899 // Get the endpoint descriptor
901 Status
= GetExpectedDescriptor (
905 (UINT8
) sizeof (EFI_USB_ENDPOINT_DESCRIPTOR
),
909 if (EFI_ERROR (Status
)) {
914 if (InterfaceIndex
== 0) {
915 PeiUsbDevice
->EndpointDesc
[Index
] = (EFI_USB_ENDPOINT_DESCRIPTOR
*) Ptr
;
917 PeiUsbDevice
->EndpointDescList
[InterfaceIndex
][Index
] = (EFI_USB_ENDPOINT_DESCRIPTOR
*) Ptr
;
919 Ptr
+= sizeof (EFI_USB_ENDPOINT_DESCRIPTOR
);
920 LengthLeft
-= SkipBytes
;
921 LengthLeft
-= sizeof (EFI_USB_ENDPOINT_DESCRIPTOR
);
929 Get the start position of next wanted descriptor.
931 @param Buffer Buffer containing data to parse.
932 @param Length Buffer length.
933 @param DescType Descriptor type.
934 @param DescLength Descriptor length.
935 @param ParsedBytes Bytes has been parsed.
937 @retval EFI_SUCCESS Get wanted descriptor successfully.
938 @retval EFI_DEVICE_ERROR Error occurred.
942 GetExpectedDescriptor (
947 OUT UINTN
*ParsedBytes
954 // Total length is too small that cannot hold the single descriptor header plus data.
956 if (Length
<= sizeof (USB_DESC_HEAD
)) {
957 DEBUG ((DEBUG_ERROR
, "GetExpectedDescriptor: met mal-format descriptor, total length = %d!\n", Length
));
958 return EFI_DEVICE_ERROR
;
962 // All the descriptor has a common LTV (Length, Type, Value)
963 // format. Skip the descriptor that isn't of this Type
966 Head
= (USB_DESC_HEAD
*)Buffer
;
967 while (Offset
< Length
- sizeof (USB_DESC_HEAD
)) {
969 // Above condition make sure Head->Len and Head->Type are safe to access
971 Head
= (USB_DESC_HEAD
*)&Buffer
[Offset
];
973 if (Head
->Len
== 0) {
974 DEBUG ((DEBUG_ERROR
, "GetExpectedDescriptor: met mal-format descriptor, Head->Len = 0!\n"));
975 return EFI_DEVICE_ERROR
;
979 // Make sure no overflow when adding Head->Len to Offset.
981 if (Head
->Len
> MAX_UINTN
- Offset
) {
982 DEBUG ((DEBUG_ERROR
, "GetExpectedDescriptor: met mal-format descriptor, Head->Len = %d!\n", Head
->Len
));
983 return EFI_DEVICE_ERROR
;
986 if (Head
->Type
== DescType
) {
994 // Head->Len is invalid resulting data beyond boundary, or
995 // Descriptor cannot be found: No such type.
997 if (Length
< Offset
) {
998 DEBUG ((DEBUG_ERROR
, "GetExpectedDescriptor: met mal-format descriptor, Offset/Len = %d/%d!\n", Offset
, Length
));
999 return EFI_DEVICE_ERROR
;
1002 if ((Head
->Type
!= DescType
) || (Head
->Len
< DescLength
)) {
1003 DEBUG ((DEBUG_ERROR
, "GetExpectedDescriptor: descriptor cannot be found, Header(T/L) = %d/%d!\n", Head
->Type
, Head
->Len
));
1004 return EFI_DEVICE_ERROR
;
1007 *ParsedBytes
= Offset
;
1012 Send reset signal over the given root hub port.
1014 @param PeiServices Describes the list of possible PEI Services.
1015 @param UsbHcPpi The pointer of PEI_USB_HOST_CONTROLLER_PPI instance.
1016 @param Usb2HcPpi The pointer of PEI_USB2_HOST_CONTROLLER_PPI instance.
1017 @param PortNum The port to be reset.
1018 @param RetryIndex The retry times.
1023 IN EFI_PEI_SERVICES
**PeiServices
,
1024 IN PEI_USB_HOST_CONTROLLER_PPI
*UsbHcPpi
,
1025 IN PEI_USB2_HOST_CONTROLLER_PPI
*Usb2HcPpi
,
1032 EFI_USB_PORT_STATUS PortStatus
;
1035 if (Usb2HcPpi
!= NULL
) {
1036 MicroSecondDelay (200 * 1000);
1041 Status
= Usb2HcPpi
->SetRootHubPortFeature (
1048 if (EFI_ERROR (Status
)) {
1049 DEBUG ((EFI_D_ERROR
, "SetRootHubPortFeature EfiUsbPortReset Failed\n"));
1054 // Drive the reset signal for at least 50ms. Check USB 2.0 Spec
1055 // section 7.1.7.5 for timing requirements.
1057 MicroSecondDelay (USB_SET_ROOT_PORT_RESET_STALL
);
1060 // clear reset root port
1062 Status
= Usb2HcPpi
->ClearRootHubPortFeature (
1069 if (EFI_ERROR (Status
)) {
1070 DEBUG ((EFI_D_ERROR
, "ClearRootHubPortFeature EfiUsbPortReset Failed\n"));
1074 MicroSecondDelay (USB_CLR_ROOT_PORT_RESET_STALL
);
1077 // USB host controller won't clear the RESET bit until
1078 // reset is actually finished.
1080 ZeroMem (&PortStatus
, sizeof (EFI_USB_PORT_STATUS
));
1082 for (Index
= 0; Index
< USB_WAIT_PORT_STS_CHANGE_LOOP
; Index
++) {
1083 Status
= Usb2HcPpi
->GetRootHubPortStatus (
1089 if (EFI_ERROR (Status
)) {
1093 if (!USB_BIT_IS_SET (PortStatus
.PortStatus
, USB_PORT_STAT_RESET
)) {
1097 MicroSecondDelay (USB_WAIT_PORT_STS_CHANGE_STALL
);
1100 if (Index
== USB_WAIT_PORT_STS_CHANGE_LOOP
) {
1101 DEBUG ((EFI_D_ERROR
, "ResetRootPort: reset not finished in time on port %d\n", PortNum
));
1105 Usb2HcPpi
->ClearRootHubPortFeature (
1109 EfiUsbPortResetChange
1112 Usb2HcPpi
->ClearRootHubPortFeature (
1116 EfiUsbPortConnectChange
1122 Usb2HcPpi
->SetRootHubPortFeature(
1129 Usb2HcPpi
->ClearRootHubPortFeature (
1133 EfiUsbPortEnableChange
1136 MicroSecondDelay ((RetryIndex
+ 1) * 50 * 1000);
1138 MicroSecondDelay (200 * 1000);
1143 Status
= UsbHcPpi
->SetRootHubPortFeature (
1150 if (EFI_ERROR (Status
)) {
1151 DEBUG ((EFI_D_ERROR
, "SetRootHubPortFeature EfiUsbPortReset Failed\n"));
1156 // Drive the reset signal for at least 50ms. Check USB 2.0 Spec
1157 // section 7.1.7.5 for timing requirements.
1159 MicroSecondDelay (USB_SET_ROOT_PORT_RESET_STALL
);
1162 // clear reset root port
1164 Status
= UsbHcPpi
->ClearRootHubPortFeature (
1171 if (EFI_ERROR (Status
)) {
1172 DEBUG ((EFI_D_ERROR
, "ClearRootHubPortFeature EfiUsbPortReset Failed\n"));
1176 MicroSecondDelay (USB_CLR_ROOT_PORT_RESET_STALL
);
1179 // USB host controller won't clear the RESET bit until
1180 // reset is actually finished.
1182 ZeroMem (&PortStatus
, sizeof (EFI_USB_PORT_STATUS
));
1184 for (Index
= 0; Index
< USB_WAIT_PORT_STS_CHANGE_LOOP
; Index
++) {
1185 Status
= UsbHcPpi
->GetRootHubPortStatus (
1191 if (EFI_ERROR (Status
)) {
1195 if (!USB_BIT_IS_SET (PortStatus
.PortStatus
, USB_PORT_STAT_RESET
)) {
1199 MicroSecondDelay (USB_WAIT_PORT_STS_CHANGE_STALL
);
1202 if (Index
== USB_WAIT_PORT_STS_CHANGE_LOOP
) {
1203 DEBUG ((EFI_D_ERROR
, "ResetRootPort: reset not finished in time on port %d\n", PortNum
));
1207 UsbHcPpi
->ClearRootHubPortFeature (
1211 EfiUsbPortResetChange
1214 UsbHcPpi
->ClearRootHubPortFeature (
1218 EfiUsbPortConnectChange
1224 UsbHcPpi
->SetRootHubPortFeature(
1231 UsbHcPpi
->ClearRootHubPortFeature (
1235 EfiUsbPortEnableChange
1238 MicroSecondDelay ((RetryIndex
+ 1) * 50 * 1000);