11/** @file
22The module to produce Usb Bus PPI.
33
4+ Copyright (C) 2025 Advanced Micro Devices, Inc. All rights reserved.<BR>
45Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
56
67SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -428,6 +429,7 @@ PeiUsbEnumeration (
428429 UINT8 CurrentAddress ;
429430 UINTN InterfaceIndex ;
430431 UINTN EndpointIndex ;
432+ UINT8 UsbEnumLoop ;
431433
432434 CurrentAddress = 0 ;
433435 if (Usb2HcPpi != NULL ) {
@@ -449,179 +451,149 @@ PeiUsbEnumeration (
449451
450452 DEBUG ((DEBUG_INFO , "PeiUsbEnumeration: NumOfRootPort: %x\n" , NumOfRootPort ));
451453
452- for (Index = 0 ; Index < NumOfRootPort ; Index ++ ) {
453- //
454- // First get root port status to detect changes happen
455- //
456- if (Usb2HcPpi != NULL ) {
457- Usb2HcPpi -> GetRootHubPortStatus (
458- PeiServices ,
459- Usb2HcPpi ,
460- (UINT8 )Index ,
461- & PortStatus
462- );
463- } else {
464- UsbHcPpi -> GetRootHubPortStatus (
465- PeiServices ,
466- UsbHcPpi ,
467- (UINT8 )Index ,
468- & PortStatus
469- );
470- }
471-
472- DEBUG ((DEBUG_INFO , "USB Status --- Port: %x ConnectChange[%04x] Status[%04x]\n" , Index , PortStatus .PortChangeStatus , PortStatus .PortStatus ));
473- //
474- // Only handle connection/enable/overcurrent/reset change.
475- //
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 ) {
477- continue ;
478- } else {
479- if (IsPortConnect (PortStatus .PortStatus )) {
480- MemPages = sizeof (PEI_USB_DEVICE ) / EFI_PAGE_SIZE + 1 ;
481- Status = PeiServicesAllocatePages (
482- EfiBootServicesCode ,
483- MemPages ,
484- & AllocateAddress
454+ //
455+ // USB3.x devices initially appear in USB2.0 ports. When the USB2.0 port is reset, the USB3.x device disappears
456+ // from the USB2.0 port and appears on the USB3.0 port. The USB3.x device won't be enumerated if the USB2.0 port
457+ // number is greater than the USB3.0 port number. Re-enumerate USB to make sure USB3.x devices in this case.
458+ //
459+ for (UsbEnumLoop = 0 ; UsbEnumLoop < 2 ; UsbEnumLoop ++ ) {
460+ for (Index = 0 ; Index < NumOfRootPort ; Index ++ ) {
461+ //
462+ // First get root port status to detect changes happen
463+ //
464+ if (Usb2HcPpi != NULL ) {
465+ Usb2HcPpi -> GetRootHubPortStatus (
466+ PeiServices ,
467+ Usb2HcPpi ,
468+ (UINT8 )Index ,
469+ & PortStatus
485470 );
486- if (EFI_ERROR (Status )) {
487- return EFI_OUT_OF_RESOURCES ;
488- }
471+ } else {
472+ UsbHcPpi -> GetRootHubPortStatus (
473+ PeiServices ,
474+ UsbHcPpi ,
475+ (UINT8 )Index ,
476+ & PortStatus
477+ );
478+ }
489479
490- PeiUsbDevice = (PEI_USB_DEVICE * )((UINTN )AllocateAddress );
491- ZeroMem (PeiUsbDevice , sizeof (PEI_USB_DEVICE ));
480+ DEBUG ((DEBUG_INFO , "USB Status --- Port: %x ConnectChange[%04x] Status[%04x]\n" , Index , PortStatus .PortChangeStatus , PortStatus .PortStatus ));
481+ //
482+ // Only handle connection/enable/overcurrent/reset change.
483+ //
484+ if ((PortStatus .PortChangeStatus & (USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE | USB_PORT_STAT_C_OVERCURRENT | USB_PORT_STAT_C_RESET )) == 0 ) {
485+ continue ;
486+ } else {
487+ if (IsPortConnect (PortStatus .PortStatus )) {
488+ MemPages = sizeof (PEI_USB_DEVICE ) / EFI_PAGE_SIZE + 1 ;
489+ Status = PeiServicesAllocatePages (
490+ EfiBootServicesCode ,
491+ MemPages ,
492+ & AllocateAddress
493+ );
494+ if (EFI_ERROR (Status )) {
495+ return EFI_OUT_OF_RESOURCES ;
496+ }
492497
493- PeiUsbDevice -> Signature = PEI_USB_DEVICE_SIGNATURE ;
494- PeiUsbDevice -> DeviceAddress = 0 ;
495- PeiUsbDevice -> MaxPacketSize0 = 8 ;
496- PeiUsbDevice -> DataToggle = 0 ;
497- CopyMem (
498- & (PeiUsbDevice -> UsbIoPpi ),
499- & mUsbIoPpi ,
500- sizeof (PEI_USB_IO_PPI )
501- );
502- CopyMem (
503- & (PeiUsbDevice -> UsbIoPpiList ),
504- & mUsbIoPpiList ,
505- sizeof (EFI_PEI_PPI_DESCRIPTOR )
506- );
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 ;
498+ PeiUsbDevice = (PEI_USB_DEVICE * )((UINTN )AllocateAddress );
499+ ZeroMem (PeiUsbDevice , sizeof (PEI_USB_DEVICE ));
513500
514- if (((PortStatus .PortChangeStatus & USB_PORT_STAT_C_RESET ) == 0 ) ||
515- ((PortStatus .PortStatus & (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE )) == 0 ))
516- {
517- //
518- // If the port already has reset change flag and is connected and enabled, skip the port reset logic.
519- //
520- ResetRootPort (
521- PeiServices ,
522- PeiUsbDevice -> UsbHcPpi ,
523- PeiUsbDevice -> Usb2HcPpi ,
524- Index ,
525- 0
501+ PeiUsbDevice -> Signature = PEI_USB_DEVICE_SIGNATURE ;
502+ PeiUsbDevice -> DeviceAddress = 0 ;
503+ PeiUsbDevice -> MaxPacketSize0 = 8 ;
504+ PeiUsbDevice -> DataToggle = 0 ;
505+ CopyMem (
506+ & (PeiUsbDevice -> UsbIoPpi ),
507+ & mUsbIoPpi ,
508+ sizeof (PEI_USB_IO_PPI )
526509 );
527-
528- if (Usb2HcPpi != NULL ) {
529- Usb2HcPpi -> GetRootHubPortStatus (
530- PeiServices ,
531- Usb2HcPpi ,
532- (UINT8 )Index ,
533- & PortStatus
534- );
535- } else {
536- UsbHcPpi -> GetRootHubPortStatus (
537- PeiServices ,
538- UsbHcPpi ,
539- (UINT8 )Index ,
540- & PortStatus
541- );
542- }
543- } else {
544- if (Usb2HcPpi != NULL ) {
545- Usb2HcPpi -> ClearRootHubPortFeature (
546- PeiServices ,
547- Usb2HcPpi ,
548- (UINT8 )Index ,
549- EfiUsbPortResetChange
550- );
510+ CopyMem (
511+ & (PeiUsbDevice -> UsbIoPpiList ),
512+ & mUsbIoPpiList ,
513+ sizeof (EFI_PEI_PPI_DESCRIPTOR )
514+ );
515+ PeiUsbDevice -> UsbIoPpiList .Ppi = & PeiUsbDevice -> UsbIoPpi ;
516+ PeiUsbDevice -> AllocateAddress = (UINTN )AllocateAddress ;
517+ PeiUsbDevice -> UsbHcPpi = UsbHcPpi ;
518+ PeiUsbDevice -> Usb2HcPpi = Usb2HcPpi ;
519+ PeiUsbDevice -> IsHub = 0x0 ;
520+ PeiUsbDevice -> DownStreamPortNo = 0x0 ;
521+
522+ if (((PortStatus .PortChangeStatus & USB_PORT_STAT_C_RESET ) == 0 ) ||
523+ ((PortStatus .PortStatus & (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE )) == 0 ))
524+ {
525+ //
526+ // If the port already has reset change flag and is connected and enabled, skip the port reset logic.
527+ //
528+ ResetRootPort (
529+ PeiServices ,
530+ PeiUsbDevice -> UsbHcPpi ,
531+ PeiUsbDevice -> Usb2HcPpi ,
532+ Index ,
533+ 0
534+ );
535+
536+ if (Usb2HcPpi != NULL ) {
537+ Usb2HcPpi -> GetRootHubPortStatus (
538+ PeiServices ,
539+ Usb2HcPpi ,
540+ (UINT8 )Index ,
541+ & PortStatus
542+ );
543+ } else {
544+ UsbHcPpi -> GetRootHubPortStatus (
545+ PeiServices ,
546+ UsbHcPpi ,
547+ (UINT8 )Index ,
548+ & PortStatus
549+ );
550+ }
551551 } else {
552- UsbHcPpi -> ClearRootHubPortFeature (
553- PeiServices ,
554- UsbHcPpi ,
555- (UINT8 )Index ,
556- EfiUsbPortResetChange
557- );
552+ if (Usb2HcPpi != NULL ) {
553+ Usb2HcPpi -> ClearRootHubPortFeature (
554+ PeiServices ,
555+ Usb2HcPpi ,
556+ (UINT8 )Index ,
557+ EfiUsbPortResetChange
558+ );
559+ } else {
560+ UsbHcPpi -> ClearRootHubPortFeature (
561+ PeiServices ,
562+ UsbHcPpi ,
563+ (UINT8 )Index ,
564+ EfiUsbPortResetChange
565+ );
566+ }
558567 }
559- }
560568
561- PeiUsbDevice -> DeviceSpeed = (UINT8 )PeiUsbGetDeviceSpeed (PortStatus .PortStatus );
562- DEBUG ((DEBUG_INFO , "Device Speed =%d\n" , PeiUsbDevice -> DeviceSpeed ));
569+ PeiUsbDevice -> DeviceSpeed = (UINT8 )PeiUsbGetDeviceSpeed (PortStatus .PortStatus );
570+ DEBUG ((DEBUG_INFO , "Device Speed =%d\n" , PeiUsbDevice -> DeviceSpeed ));
563571
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 ;
570- } else {
571- PeiUsbDevice -> MaxPacketSize0 = 8 ;
572- }
573-
574- //
575- // Configure that Usb Device
576- //
577- Status = PeiConfigureUsbDevice (
578- PeiServices ,
579- PeiUsbDevice ,
580- Index ,
581- & CurrentAddress
582- );
583-
584- if (EFI_ERROR (Status )) {
585- continue ;
586- }
587-
588- DEBUG ((DEBUG_INFO , "PeiUsbEnumeration: PeiConfigureUsbDevice Success\n" ));
589-
590- Status = PeiServicesInstallPpi (& PeiUsbDevice -> UsbIoPpiList );
591-
592- if (PeiUsbDevice -> InterfaceDesc -> InterfaceClass == 0x09 ) {
593- PeiUsbDevice -> IsHub = 0x1 ;
594-
595- Status = PeiDoHubConfig (PeiServices , PeiUsbDevice );
596- if (EFI_ERROR (Status )) {
597- return Status ;
572+ if (USB_BIT_IS_SET (PortStatus .PortStatus , USB_PORT_STAT_SUPER_SPEED )) {
573+ PeiUsbDevice -> MaxPacketSize0 = 512 ;
574+ } else if (USB_BIT_IS_SET (PortStatus .PortStatus , USB_PORT_STAT_HIGH_SPEED )) {
575+ PeiUsbDevice -> MaxPacketSize0 = 64 ;
576+ } else if (USB_BIT_IS_SET (PortStatus .PortStatus , USB_PORT_STAT_LOW_SPEED )) {
577+ PeiUsbDevice -> MaxPacketSize0 = 8 ;
578+ } else {
579+ PeiUsbDevice -> MaxPacketSize0 = 8 ;
598580 }
599581
600- PeiHubEnumeration (PeiServices , PeiUsbDevice , & CurrentAddress );
601- }
602-
603- for (InterfaceIndex = 1 ; InterfaceIndex < PeiUsbDevice -> ConfigDesc -> NumInterfaces ; InterfaceIndex ++ ) {
604582 //
605- // Begin to deal with the new device
583+ // Configure that Usb Device
606584 //
607- MemPages = sizeof (PEI_USB_DEVICE ) / EFI_PAGE_SIZE + 1 ;
608- Status = PeiServicesAllocatePages (
609- EfiBootServicesCode ,
610- MemPages ,
611- & AllocateAddress
612- );
585+ Status = PeiConfigureUsbDevice (
586+ PeiServices ,
587+ PeiUsbDevice ,
588+ Index ,
589+ & CurrentAddress
590+ );
591+
613592 if (EFI_ERROR (Status )) {
614- return EFI_OUT_OF_RESOURCES ;
593+ continue ;
615594 }
616595
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 ];
624- }
596+ DEBUG ((DEBUG_INFO , "PeiUsbEnumeration: PeiConfigureUsbDevice Success\n" ));
625597
626598 Status = PeiServicesInstallPpi (& PeiUsbDevice -> UsbIoPpiList );
627599
@@ -635,11 +607,48 @@ PeiUsbEnumeration (
635607
636608 PeiHubEnumeration (PeiServices , PeiUsbDevice , & CurrentAddress );
637609 }
610+
611+ for (InterfaceIndex = 1 ; InterfaceIndex < PeiUsbDevice -> ConfigDesc -> NumInterfaces ; InterfaceIndex ++ ) {
612+ //
613+ // Begin to deal with the new device
614+ //
615+ MemPages = sizeof (PEI_USB_DEVICE ) / EFI_PAGE_SIZE + 1 ;
616+ Status = PeiServicesAllocatePages (
617+ EfiBootServicesCode ,
618+ MemPages ,
619+ & AllocateAddress
620+ );
621+ if (EFI_ERROR (Status )) {
622+ return EFI_OUT_OF_RESOURCES ;
623+ }
624+
625+ CopyMem ((VOID * )(UINTN )AllocateAddress , PeiUsbDevice , sizeof (PEI_USB_DEVICE ));
626+ PeiUsbDevice = (PEI_USB_DEVICE * )((UINTN )AllocateAddress );
627+ PeiUsbDevice -> AllocateAddress = (UINTN )AllocateAddress ;
628+ PeiUsbDevice -> UsbIoPpiList .Ppi = & PeiUsbDevice -> UsbIoPpi ;
629+ PeiUsbDevice -> InterfaceDesc = PeiUsbDevice -> InterfaceDescList [InterfaceIndex ];
630+ for (EndpointIndex = 0 ; EndpointIndex < PeiUsbDevice -> InterfaceDesc -> NumEndpoints ; EndpointIndex ++ ) {
631+ PeiUsbDevice -> EndpointDesc [EndpointIndex ] = PeiUsbDevice -> EndpointDescList [InterfaceIndex ][EndpointIndex ];
632+ }
633+
634+ Status = PeiServicesInstallPpi (& PeiUsbDevice -> UsbIoPpiList );
635+
636+ if (PeiUsbDevice -> InterfaceDesc -> InterfaceClass == 0x09 ) {
637+ PeiUsbDevice -> IsHub = 0x1 ;
638+
639+ Status = PeiDoHubConfig (PeiServices , PeiUsbDevice );
640+ if (EFI_ERROR (Status )) {
641+ return Status ;
642+ }
643+
644+ PeiHubEnumeration (PeiServices , PeiUsbDevice , & CurrentAddress );
645+ }
646+ }
647+ } else {
648+ //
649+ // Disconnect change happen, currently we don't support
650+ //
638651 }
639- } else {
640- //
641- // Disconnect change happen, currently we don't support
642- //
643652 }
644653 }
645654 }
0 commit comments