Home | History | Annotate | Download | only in PciBusDxe
      1 /** @file
      2   Internal library implementation for PCI Bus module.
      3 
      4 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
      5 (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
      6 This program and the accompanying materials
      7 are licensed and made available under the terms and conditions of the BSD License
      8 which accompanies this distribution.  The full text of the license may be found at
      9 http://opensource.org/licenses/bsd-license.php
     10 
     11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 #include "PciBus.h"
     17 
     18 GLOBAL_REMOVE_IF_UNREFERENCED
     19 CHAR16 *mBarTypeStr[] = {
     20   L"Unknow",
     21   L"  Io16",
     22   L"  Io32",
     23   L" Mem32",
     24   L"PMem32",
     25   L" Mem64",
     26   L"PMem64",
     27   L"    Io",
     28   L"   Mem",
     29   L"Unknow"
     30   };
     31 
     32 /**
     33   Retrieve the PCI Card device BAR information via PciIo interface.
     34 
     35   @param PciIoDevice        PCI Card device instance.
     36 
     37 **/
     38 VOID
     39 GetBackPcCardBar (
     40   IN  PCI_IO_DEVICE                  *PciIoDevice
     41   )
     42 {
     43   UINT32  Address;
     44 
     45   if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
     46     return;
     47   }
     48 
     49   //
     50   // Read PciBar information from the bar register
     51   //
     52   if (!gFullEnumeration) {
     53     Address = 0;
     54     PciIoDevice->PciIo.Pci.Read (
     55                              &(PciIoDevice->PciIo),
     56                              EfiPciIoWidthUint32,
     57                              PCI_CARD_MEMORY_BASE_0,
     58                              1,
     59                              &Address
     60                              );
     61 
     62     (PciIoDevice->PciBar)[P2C_MEM_1].BaseAddress  = (UINT64) (Address);
     63     (PciIoDevice->PciBar)[P2C_MEM_1].Length       = 0x2000000;
     64     (PciIoDevice->PciBar)[P2C_MEM_1].BarType      = PciBarTypeMem32;
     65 
     66     Address = 0;
     67     PciIoDevice->PciIo.Pci.Read (
     68                              &(PciIoDevice->PciIo),
     69                              EfiPciIoWidthUint32,
     70                              PCI_CARD_MEMORY_BASE_1,
     71                              1,
     72                              &Address
     73                              );
     74     (PciIoDevice->PciBar)[P2C_MEM_2].BaseAddress  = (UINT64) (Address);
     75     (PciIoDevice->PciBar)[P2C_MEM_2].Length       = 0x2000000;
     76     (PciIoDevice->PciBar)[P2C_MEM_2].BarType      = PciBarTypePMem32;
     77 
     78     Address = 0;
     79     PciIoDevice->PciIo.Pci.Read (
     80                              &(PciIoDevice->PciIo),
     81                              EfiPciIoWidthUint32,
     82                              PCI_CARD_IO_BASE_0_LOWER,
     83                              1,
     84                              &Address
     85                              );
     86     (PciIoDevice->PciBar)[P2C_IO_1].BaseAddress = (UINT64) (Address);
     87     (PciIoDevice->PciBar)[P2C_IO_1].Length      = 0x100;
     88     (PciIoDevice->PciBar)[P2C_IO_1].BarType     = PciBarTypeIo16;
     89 
     90     Address = 0;
     91     PciIoDevice->PciIo.Pci.Read (
     92                              &(PciIoDevice->PciIo),
     93                              EfiPciIoWidthUint32,
     94                              PCI_CARD_IO_BASE_1_LOWER,
     95                              1,
     96                              &Address
     97                              );
     98     (PciIoDevice->PciBar)[P2C_IO_2].BaseAddress = (UINT64) (Address);
     99     (PciIoDevice->PciBar)[P2C_IO_2].Length      = 0x100;
    100     (PciIoDevice->PciBar)[P2C_IO_2].BarType     = PciBarTypeIo16;
    101 
    102   }
    103 
    104   if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
    105     GetResourcePaddingForHpb (PciIoDevice);
    106   }
    107 }
    108 
    109 /**
    110   Remove rejected pci device from specific root bridge
    111   handle.
    112 
    113   @param RootBridgeHandle  Specific parent root bridge handle.
    114   @param Bridge            Bridge device instance.
    115 
    116 **/
    117 VOID
    118 RemoveRejectedPciDevices (
    119   IN EFI_HANDLE        RootBridgeHandle,
    120   IN PCI_IO_DEVICE     *Bridge
    121   )
    122 {
    123   PCI_IO_DEVICE   *Temp;
    124   LIST_ENTRY      *CurrentLink;
    125   LIST_ENTRY      *LastLink;
    126 
    127   if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
    128     return;
    129   }
    130 
    131   CurrentLink = Bridge->ChildList.ForwardLink;
    132 
    133   while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {
    134 
    135     Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
    136 
    137     if (IS_PCI_BRIDGE (&Temp->Pci)) {
    138       //
    139       // Remove rejected devices recusively
    140       //
    141       RemoveRejectedPciDevices (RootBridgeHandle, Temp);
    142     } else {
    143       //
    144       // Skip rejection for all PPBs, while detect rejection for others
    145       //
    146       if (IsPciDeviceRejected (Temp)) {
    147 
    148         //
    149         // For P2C, remove all devices on it
    150         //
    151         if (!IsListEmpty (&Temp->ChildList)) {
    152           RemoveAllPciDeviceOnBridge (RootBridgeHandle, Temp);
    153         }
    154 
    155         //
    156         // Finally remove itself
    157         //
    158         LastLink = CurrentLink->BackLink;
    159         RemoveEntryList (CurrentLink);
    160         FreePciDevice (Temp);
    161 
    162         CurrentLink = LastLink;
    163       }
    164     }
    165 
    166     CurrentLink = CurrentLink->ForwardLink;
    167   }
    168 }
    169 
    170 /**
    171   Dump the resourc map of the bridge device.
    172 
    173   @param[in] BridgeResource   Resource descriptor of the bridge device.
    174 **/
    175 VOID
    176 DumpBridgeResource (
    177   IN PCI_RESOURCE_NODE     *BridgeResource
    178   )
    179 {
    180   LIST_ENTRY               *Link;
    181   PCI_RESOURCE_NODE        *Resource;
    182   PCI_BAR                  *Bar;
    183 
    184   if ((BridgeResource != NULL) && (BridgeResource->Length != 0)) {
    185     DEBUG ((
    186       EFI_D_INFO, "Type = %s; Base = 0x%lx;\tLength = 0x%lx;\tAlignment = 0x%lx\n",
    187       mBarTypeStr[MIN (BridgeResource->ResType, PciBarTypeMaxType)],
    188       BridgeResource->PciDev->PciBar[BridgeResource->Bar].BaseAddress,
    189       BridgeResource->Length, BridgeResource->Alignment
    190       ));
    191     for ( Link = GetFirstNode (&BridgeResource->ChildList)
    192         ; !IsNull (&BridgeResource->ChildList, Link)
    193         ; Link = GetNextNode (&BridgeResource->ChildList, Link)
    194         ) {
    195       Resource = RESOURCE_NODE_FROM_LINK (Link);
    196       if (Resource->ResourceUsage == PciResUsageTypical) {
    197         Bar = Resource->Virtual ? Resource->PciDev->VfPciBar : Resource->PciDev->PciBar;
    198         DEBUG ((
    199           EFI_D_INFO, "   Base = 0x%lx;\tLength = 0x%lx;\tAlignment = 0x%lx;\tOwner = %s [%02x|%02x|%02x:",
    200           Bar[Resource->Bar].BaseAddress, Resource->Length, Resource->Alignment,
    201           IS_PCI_BRIDGE (&Resource->PciDev->Pci)     ? L"PPB" :
    202           IS_CARDBUS_BRIDGE (&Resource->PciDev->Pci) ? L"P2C" :
    203                                                        L"PCI",
    204           Resource->PciDev->BusNumber, Resource->PciDev->DeviceNumber,
    205           Resource->PciDev->FunctionNumber
    206           ));
    207 
    208         if ((!IS_PCI_BRIDGE (&Resource->PciDev->Pci) && !IS_CARDBUS_BRIDGE (&Resource->PciDev->Pci)) ||
    209             (IS_PCI_BRIDGE (&Resource->PciDev->Pci) && (Resource->Bar < PPB_IO_RANGE)) ||
    210             (IS_CARDBUS_BRIDGE (&Resource->PciDev->Pci) && (Resource->Bar < P2C_MEM_1))
    211             ) {
    212           //
    213           // The resource requirement comes from the device itself.
    214           //
    215           DEBUG ((EFI_D_INFO, "%02x]", Bar[Resource->Bar].Offset));
    216         } else {
    217           //
    218           // The resource requirement comes from the subordinate devices.
    219           //
    220           DEBUG ((EFI_D_INFO, "**]"));
    221         }
    222       } else {
    223         DEBUG ((EFI_D_INFO, "   Base = Padding;\tLength = 0x%lx;\tAlignment = 0x%lx", Resource->Length, Resource->Alignment));
    224       }
    225       if (BridgeResource->ResType != Resource->ResType) {
    226         DEBUG ((EFI_D_INFO, "; Type = %s", mBarTypeStr[MIN (Resource->ResType, PciBarTypeMaxType)]));
    227       }
    228       DEBUG ((EFI_D_INFO, "\n"));
    229     }
    230   }
    231 }
    232 
    233 /**
    234   Find the corresponding resource node for the Device in child list of BridgeResource.
    235 
    236   @param[in]  Device          Pointer to PCI_IO_DEVICE.
    237   @param[in]  BridgeResource  Pointer to PCI_RESOURCE_NODE.
    238   @param[out] DeviceResources Pointer to a buffer to receive resources for the Device.
    239 
    240   @return Count of the resource descriptors returned.
    241 **/
    242 UINTN
    243 FindResourceNode (
    244   IN  PCI_IO_DEVICE     *Device,
    245   IN  PCI_RESOURCE_NODE *BridgeResource,
    246   OUT PCI_RESOURCE_NODE **DeviceResources OPTIONAL
    247   )
    248 {
    249   LIST_ENTRY               *Link;
    250   PCI_RESOURCE_NODE        *Resource;
    251   UINTN                    Count;
    252 
    253   Count = 0;
    254   for ( Link = BridgeResource->ChildList.ForwardLink
    255       ; Link != &BridgeResource->ChildList
    256       ; Link = Link->ForwardLink
    257       ) {
    258     Resource = RESOURCE_NODE_FROM_LINK (Link);
    259     if (Resource->PciDev == Device) {
    260       if (DeviceResources != NULL) {
    261         DeviceResources[Count] = Resource;
    262       }
    263       Count++;
    264     }
    265   }
    266 
    267   return Count;
    268 }
    269 
    270 /**
    271   Dump the resource map of all the devices under Bridge.
    272 
    273   @param[in] Bridge        Bridge device instance.
    274   @param[in] Resources     Resource descriptors for the bridge device.
    275   @param[in] ResourceCount Count of resource descriptors.
    276 **/
    277 VOID
    278 DumpResourceMap (
    279   IN PCI_IO_DEVICE     *Bridge,
    280   IN PCI_RESOURCE_NODE **Resources,
    281   IN UINTN             ResourceCount
    282   )
    283 {
    284   EFI_STATUS           Status;
    285   LIST_ENTRY           *Link;
    286   PCI_IO_DEVICE        *Device;
    287   UINTN                Index;
    288   CHAR16               *Str;
    289   PCI_RESOURCE_NODE    **ChildResources;
    290   UINTN                ChildResourceCount;
    291 
    292   DEBUG ((EFI_D_INFO, "PciBus: Resource Map for "));
    293 
    294   Status = gBS->OpenProtocol (
    295                   Bridge->Handle,
    296                   &gEfiPciRootBridgeIoProtocolGuid,
    297                   NULL,
    298                   NULL,
    299                   NULL,
    300                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL
    301                   );
    302   if (EFI_ERROR (Status)) {
    303     DEBUG ((
    304       EFI_D_INFO, "Bridge [%02x|%02x|%02x]\n",
    305       Bridge->BusNumber, Bridge->DeviceNumber, Bridge->FunctionNumber
    306       ));
    307   } else {
    308     Str = ConvertDevicePathToText (
    309             DevicePathFromHandle (Bridge->Handle),
    310             FALSE,
    311             FALSE
    312             );
    313     DEBUG ((EFI_D_INFO, "Root Bridge %s\n", Str != NULL ? Str : L""));
    314     if (Str != NULL) {
    315       FreePool (Str);
    316     }
    317   }
    318 
    319   for (Index = 0; Index < ResourceCount; Index++) {
    320     DumpBridgeResource (Resources[Index]);
    321   }
    322   DEBUG ((EFI_D_INFO, "\n"));
    323 
    324   for ( Link = Bridge->ChildList.ForwardLink
    325       ; Link != &Bridge->ChildList
    326       ; Link = Link->ForwardLink
    327       ) {
    328     Device = PCI_IO_DEVICE_FROM_LINK (Link);
    329     if (IS_PCI_BRIDGE (&Device->Pci)) {
    330 
    331       ChildResourceCount = 0;
    332       for (Index = 0; Index < ResourceCount; Index++) {
    333         ChildResourceCount += FindResourceNode (Device, Resources[Index], NULL);
    334       }
    335       ChildResources = AllocatePool (sizeof (PCI_RESOURCE_NODE *) * ChildResourceCount);
    336       ASSERT (ChildResources != NULL);
    337       ChildResourceCount = 0;
    338       for (Index = 0; Index < ResourceCount; Index++) {
    339         ChildResourceCount += FindResourceNode (Device, Resources[Index], &ChildResources[ChildResourceCount]);
    340       }
    341 
    342       DumpResourceMap (Device, ChildResources, ChildResourceCount);
    343       FreePool (ChildResources);
    344     }
    345   }
    346 }
    347 
    348 /**
    349   Submits the I/O and memory resource requirements for the specified PCI Host Bridge.
    350 
    351   @param PciResAlloc  Point to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
    352 
    353   @retval EFI_SUCCESS           Successfully finished resource allocation.
    354   @retval EFI_NOT_FOUND         Cannot get root bridge instance.
    355   @retval EFI_OUT_OF_RESOURCES  Platform failed to program the resources if no hot plug supported.
    356   @retval other                 Some error occurred when allocating resources for the PCI Host Bridge.
    357 
    358   @note   Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
    359 
    360 **/
    361 EFI_STATUS
    362 PciHostBridgeResourceAllocator (
    363   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
    364   )
    365 {
    366   PCI_IO_DEVICE                                  *RootBridgeDev;
    367   EFI_HANDLE                                     RootBridgeHandle;
    368   VOID                                           *AcpiConfig;
    369   EFI_STATUS                                     Status;
    370   UINT64                                         IoBase;
    371   UINT64                                         Mem32Base;
    372   UINT64                                         PMem32Base;
    373   UINT64                                         Mem64Base;
    374   UINT64                                         PMem64Base;
    375   UINT64                                         IoResStatus;
    376   UINT64                                         Mem32ResStatus;
    377   UINT64                                         PMem32ResStatus;
    378   UINT64                                         Mem64ResStatus;
    379   UINT64                                         PMem64ResStatus;
    380   UINT64                                         MaxOptionRomSize;
    381   PCI_RESOURCE_NODE                              *IoBridge;
    382   PCI_RESOURCE_NODE                              *Mem32Bridge;
    383   PCI_RESOURCE_NODE                              *PMem32Bridge;
    384   PCI_RESOURCE_NODE                              *Mem64Bridge;
    385   PCI_RESOURCE_NODE                              *PMem64Bridge;
    386   PCI_RESOURCE_NODE                              IoPool;
    387   PCI_RESOURCE_NODE                              Mem32Pool;
    388   PCI_RESOURCE_NODE                              PMem32Pool;
    389   PCI_RESOURCE_NODE                              Mem64Pool;
    390   PCI_RESOURCE_NODE                              PMem64Pool;
    391   BOOLEAN                                        ReAllocate;
    392   EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD        HandleExtendedData;
    393   EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD  AllocFailExtendedData;
    394 
    395   //
    396   // Reallocate flag
    397   //
    398   ReAllocate = FALSE;
    399 
    400   //
    401   // It may try several times if the resource allocation fails
    402   //
    403   while (TRUE) {
    404     //
    405     // Initialize resource pool
    406     //
    407     InitializeResourcePool (&IoPool, PciBarTypeIo16);
    408     InitializeResourcePool (&Mem32Pool, PciBarTypeMem32);
    409     InitializeResourcePool (&PMem32Pool, PciBarTypePMem32);
    410     InitializeResourcePool (&Mem64Pool, PciBarTypeMem64);
    411     InitializeResourcePool (&PMem64Pool, PciBarTypePMem64);
    412 
    413     RootBridgeDev     = NULL;
    414     RootBridgeHandle  = 0;
    415 
    416     while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
    417       //
    418       // Get Root Bridge Device by handle
    419       //
    420       RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
    421 
    422       if (RootBridgeDev == NULL) {
    423         return EFI_NOT_FOUND;
    424       }
    425 
    426       //
    427       // Create the entire system resource map from the information collected by
    428       // enumerator. Several resource tree was created
    429       //
    430 
    431       //
    432       // If non-standard PCI Bridge I/O window alignment is supported,
    433       // set I/O aligment to minimum possible alignment for root bridge.
    434       //
    435       IoBridge = CreateResourceNode (
    436                    RootBridgeDev,
    437                    0,
    438                    FeaturePcdGet (PcdPciBridgeIoAlignmentProbe) ? 0x1FF: 0xFFF,
    439                    RB_IO_RANGE,
    440                    PciBarTypeIo16,
    441                    PciResUsageTypical
    442                    );
    443 
    444       Mem32Bridge = CreateResourceNode (
    445                       RootBridgeDev,
    446                       0,
    447                       0xFFFFF,
    448                       RB_MEM32_RANGE,
    449                       PciBarTypeMem32,
    450                       PciResUsageTypical
    451                       );
    452 
    453       PMem32Bridge = CreateResourceNode (
    454                        RootBridgeDev,
    455                        0,
    456                        0xFFFFF,
    457                        RB_PMEM32_RANGE,
    458                        PciBarTypePMem32,
    459                        PciResUsageTypical
    460                        );
    461 
    462       Mem64Bridge = CreateResourceNode (
    463                       RootBridgeDev,
    464                       0,
    465                       0xFFFFF,
    466                       RB_MEM64_RANGE,
    467                       PciBarTypeMem64,
    468                       PciResUsageTypical
    469                       );
    470 
    471       PMem64Bridge = CreateResourceNode (
    472                        RootBridgeDev,
    473                        0,
    474                        0xFFFFF,
    475                        RB_PMEM64_RANGE,
    476                        PciBarTypePMem64,
    477                        PciResUsageTypical
    478                        );
    479 
    480       //
    481       // Create resourcemap by going through all the devices subject to this root bridge
    482       //
    483       CreateResourceMap (
    484         RootBridgeDev,
    485         IoBridge,
    486         Mem32Bridge,
    487         PMem32Bridge,
    488         Mem64Bridge,
    489         PMem64Bridge
    490         );
    491 
    492       //
    493       // Get the max ROM size that the root bridge can process
    494       //
    495       RootBridgeDev->RomSize = Mem32Bridge->Length;
    496 
    497       //
    498       // Skip to enlarge the resource request during realloction
    499       //
    500       if (!ReAllocate) {
    501         //
    502         // Get Max Option Rom size for current root bridge
    503         //
    504         MaxOptionRomSize = GetMaxOptionRomSize (RootBridgeDev);
    505 
    506         //
    507         // Enlarger the mem32 resource to accomdate the option rom
    508         // if the mem32 resource is not enough to hold the rom
    509         //
    510         if (MaxOptionRomSize > Mem32Bridge->Length) {
    511 
    512           Mem32Bridge->Length     = MaxOptionRomSize;
    513           RootBridgeDev->RomSize  = MaxOptionRomSize;
    514 
    515           //
    516           // Alignment should be adjusted as well
    517           //
    518           if (Mem32Bridge->Alignment < MaxOptionRomSize - 1) {
    519             Mem32Bridge->Alignment = MaxOptionRomSize - 1;
    520           }
    521         }
    522       }
    523 
    524       //
    525       // Based on the all the resource tree, construct ACPI resource node to
    526       // submit the resource aperture to pci host bridge protocol
    527       //
    528       Status = ConstructAcpiResourceRequestor (
    529                  RootBridgeDev,
    530                  IoBridge,
    531                  Mem32Bridge,
    532                  PMem32Bridge,
    533                  Mem64Bridge,
    534                  PMem64Bridge,
    535                  &AcpiConfig
    536                  );
    537 
    538       //
    539       // Insert these resource nodes into the database
    540       //
    541       InsertResourceNode (&IoPool, IoBridge);
    542       InsertResourceNode (&Mem32Pool, Mem32Bridge);
    543       InsertResourceNode (&PMem32Pool, PMem32Bridge);
    544       InsertResourceNode (&Mem64Pool, Mem64Bridge);
    545       InsertResourceNode (&PMem64Pool, PMem64Bridge);
    546 
    547       if (Status == EFI_SUCCESS) {
    548         //
    549         // Submit the resource requirement
    550         //
    551         Status = PciResAlloc->SubmitResources (
    552                                 PciResAlloc,
    553                                 RootBridgeDev->Handle,
    554                                 AcpiConfig
    555                                 );
    556         //
    557         // If SubmitResources returns error, PciBus isn't able to start.
    558         // It's a fatal error so assertion is added.
    559         //
    560         DEBUG ((EFI_D_INFO, "PciBus: HostBridge->SubmitResources() - %r\n", Status));
    561         ASSERT_EFI_ERROR (Status);
    562       }
    563 
    564       //
    565       // Free acpi resource node
    566       //
    567       if (AcpiConfig != NULL) {
    568         FreePool (AcpiConfig);
    569       }
    570 
    571       if (EFI_ERROR (Status)) {
    572         //
    573         // Destroy all the resource tree
    574         //
    575         DestroyResourceTree (&IoPool);
    576         DestroyResourceTree (&Mem32Pool);
    577         DestroyResourceTree (&PMem32Pool);
    578         DestroyResourceTree (&Mem64Pool);
    579         DestroyResourceTree (&PMem64Pool);
    580         return Status;
    581       }
    582     }
    583     //
    584     // End while, at least one Root Bridge should be found.
    585     //
    586     ASSERT (RootBridgeDev != NULL);
    587 
    588     //
    589     // Notify platform to start to program the resource
    590     //
    591     Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeAllocateResources);
    592     DEBUG ((EFI_D_INFO, "PciBus: HostBridge->NotifyPhase(AllocateResources) - %r\n", Status));
    593     if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
    594       //
    595       // If Hot Plug is not supported
    596       //
    597       if (EFI_ERROR (Status)) {
    598         //
    599         // Allocation failed, then return
    600         //
    601         return EFI_OUT_OF_RESOURCES;
    602       }
    603       //
    604       // Allocation succeed.
    605       // Get host bridge handle for status report, and then skip the main while
    606       //
    607       HandleExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;
    608 
    609       break;
    610 
    611     } else {
    612       //
    613       // If Hot Plug is supported
    614       //
    615       if (!EFI_ERROR (Status)) {
    616         //
    617         // Allocation succeed, then continue the following
    618         //
    619         break;
    620       }
    621 
    622       //
    623       // If the resource allocation is unsuccessful, free resources on bridge
    624       //
    625 
    626       RootBridgeDev     = NULL;
    627       RootBridgeHandle  = 0;
    628 
    629       IoResStatus       = EFI_RESOURCE_SATISFIED;
    630       Mem32ResStatus    = EFI_RESOURCE_SATISFIED;
    631       PMem32ResStatus   = EFI_RESOURCE_SATISFIED;
    632       Mem64ResStatus    = EFI_RESOURCE_SATISFIED;
    633       PMem64ResStatus   = EFI_RESOURCE_SATISFIED;
    634 
    635       while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
    636         //
    637         // Get RootBridg Device by handle
    638         //
    639         RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
    640         if (RootBridgeDev == NULL) {
    641           return EFI_NOT_FOUND;
    642         }
    643 
    644         //
    645         // Get host bridge handle for status report
    646         //
    647         HandleExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;
    648 
    649         //
    650         // Get acpi resource node for all the resource types
    651         //
    652         AcpiConfig = NULL;
    653 
    654         Status = PciResAlloc->GetProposedResources (
    655                                 PciResAlloc,
    656                                 RootBridgeDev->Handle,
    657                                 &AcpiConfig
    658                                 );
    659 
    660         if (EFI_ERROR (Status)) {
    661           return Status;
    662         }
    663 
    664         if (AcpiConfig != NULL) {
    665           //
    666           // Adjust resource allocation policy for each RB
    667           //
    668           GetResourceAllocationStatus (
    669             AcpiConfig,
    670             &IoResStatus,
    671             &Mem32ResStatus,
    672             &PMem32ResStatus,
    673             &Mem64ResStatus,
    674             &PMem64ResStatus
    675             );
    676           FreePool (AcpiConfig);
    677         }
    678       }
    679       //
    680       // End while
    681       //
    682 
    683       //
    684       // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
    685       //
    686       //
    687       // It is very difficult to follow the spec here
    688       // Device path , Bar index can not be get here
    689       //
    690       ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData));
    691 
    692       REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
    693             EFI_PROGRESS_CODE,
    694             EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT,
    695             (VOID *) &AllocFailExtendedData,
    696             sizeof (AllocFailExtendedData)
    697             );
    698 
    699       Status = PciHostBridgeAdjustAllocation (
    700                  &IoPool,
    701                  &Mem32Pool,
    702                  &PMem32Pool,
    703                  &Mem64Pool,
    704                  &PMem64Pool,
    705                  IoResStatus,
    706                  Mem32ResStatus,
    707                  PMem32ResStatus,
    708                  Mem64ResStatus,
    709                  PMem64ResStatus
    710                  );
    711 
    712       //
    713       // Destroy all the resource tree
    714       //
    715       DestroyResourceTree (&IoPool);
    716       DestroyResourceTree (&Mem32Pool);
    717       DestroyResourceTree (&PMem32Pool);
    718       DestroyResourceTree (&Mem64Pool);
    719       DestroyResourceTree (&PMem64Pool);
    720 
    721       NotifyPhase (PciResAlloc, EfiPciHostBridgeFreeResources);
    722 
    723       if (EFI_ERROR (Status)) {
    724         return Status;
    725       }
    726 
    727       ReAllocate = TRUE;
    728     }
    729   }
    730   //
    731   // End main while
    732   //
    733 
    734   //
    735   // Raise the EFI_IOB_PCI_RES_ALLOC status code
    736   //
    737   REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
    738         EFI_PROGRESS_CODE,
    739         EFI_IO_BUS_PCI | EFI_IOB_PCI_RES_ALLOC,
    740         (VOID *) &HandleExtendedData,
    741         sizeof (HandleExtendedData)
    742         );
    743 
    744   //
    745   // Notify pci bus driver starts to program the resource
    746   //
    747   Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeSetResources);
    748 
    749   if (EFI_ERROR (Status)) {
    750     return Status;
    751   }
    752 
    753   RootBridgeDev     = NULL;
    754 
    755   RootBridgeHandle  = 0;
    756 
    757   while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
    758     //
    759     // Get RootBridg Device by handle
    760     //
    761     RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
    762 
    763     if (RootBridgeDev == NULL) {
    764       return EFI_NOT_FOUND;
    765     }
    766 
    767     //
    768     // Get acpi resource node for all the resource types
    769     //
    770     AcpiConfig = NULL;
    771     Status = PciResAlloc->GetProposedResources (
    772                             PciResAlloc,
    773                             RootBridgeDev->Handle,
    774                             &AcpiConfig
    775                             );
    776 
    777     if (EFI_ERROR (Status)) {
    778       return Status;
    779     }
    780 
    781     //
    782     // Get the resource base by interpreting acpi resource node
    783     //
    784     //
    785     GetResourceBase (
    786       AcpiConfig,
    787       &IoBase,
    788       &Mem32Base,
    789       &PMem32Base,
    790       &Mem64Base,
    791       &PMem64Base
    792       );
    793 
    794     //
    795     // Process option rom for this root bridge
    796     //
    797     ProcessOptionRom (RootBridgeDev, Mem32Base, RootBridgeDev->RomSize);
    798 
    799     //
    800     // Create the entire system resource map from the information collected by
    801     // enumerator. Several resource tree was created
    802     //
    803     FindResourceNode (RootBridgeDev, &IoPool, &IoBridge);
    804     FindResourceNode (RootBridgeDev, &Mem32Pool, &Mem32Bridge);
    805     FindResourceNode (RootBridgeDev, &PMem32Pool, &PMem32Bridge);
    806     FindResourceNode (RootBridgeDev, &Mem64Pool, &Mem64Bridge);
    807     FindResourceNode (RootBridgeDev, &PMem64Pool, &PMem64Bridge);
    808 
    809     ASSERT (IoBridge     != NULL);
    810     ASSERT (Mem32Bridge  != NULL);
    811     ASSERT (PMem32Bridge != NULL);
    812     ASSERT (Mem64Bridge  != NULL);
    813     ASSERT (PMem64Bridge != NULL);
    814 
    815     //
    816     // Program IO resources
    817     //
    818     ProgramResource (
    819       IoBase,
    820       IoBridge
    821       );
    822 
    823     //
    824     // Program Mem32 resources
    825     //
    826     ProgramResource (
    827       Mem32Base,
    828       Mem32Bridge
    829       );
    830 
    831     //
    832     // Program PMem32 resources
    833     //
    834     ProgramResource (
    835       PMem32Base,
    836       PMem32Bridge
    837       );
    838 
    839     //
    840     // Program Mem64 resources
    841     //
    842     ProgramResource (
    843       Mem64Base,
    844       Mem64Bridge
    845       );
    846 
    847     //
    848     // Program PMem64 resources
    849     //
    850     ProgramResource (
    851       PMem64Base,
    852       PMem64Bridge
    853       );
    854 
    855     IoBridge    ->PciDev->PciBar[IoBridge    ->Bar].BaseAddress = IoBase;
    856     Mem32Bridge ->PciDev->PciBar[Mem32Bridge ->Bar].BaseAddress = Mem32Base;
    857     PMem32Bridge->PciDev->PciBar[PMem32Bridge->Bar].BaseAddress = PMem32Base;
    858     Mem64Bridge ->PciDev->PciBar[Mem64Bridge ->Bar].BaseAddress = Mem64Base;
    859     PMem64Bridge->PciDev->PciBar[PMem64Bridge->Bar].BaseAddress = PMem64Base;
    860 
    861     //
    862     // Dump the resource map for current root bridge
    863     //
    864     DEBUG_CODE (
    865       PCI_RESOURCE_NODE *Resources[5];
    866       Resources[0] = IoBridge;
    867       Resources[1] = Mem32Bridge;
    868       Resources[2] = PMem32Bridge;
    869       Resources[3] = Mem64Bridge;
    870       Resources[4] = PMem64Bridge;
    871       DumpResourceMap (RootBridgeDev, Resources, ARRAY_SIZE (Resources));
    872     );
    873 
    874     FreePool (AcpiConfig);
    875   }
    876 
    877   //
    878   // Destroy all the resource tree
    879   //
    880   DestroyResourceTree (&IoPool);
    881   DestroyResourceTree (&Mem32Pool);
    882   DestroyResourceTree (&PMem32Pool);
    883   DestroyResourceTree (&Mem64Pool);
    884   DestroyResourceTree (&PMem64Pool);
    885 
    886   //
    887   // Notify the resource allocation phase is to end
    888   //
    889   Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeEndResourceAllocation);
    890 
    891   return Status;
    892 }
    893 
    894 /**
    895   Allocate NumberOfBuses buses and return the next available PCI bus number.
    896 
    897   @param  Bridge           Bridge device instance.
    898   @param  StartBusNumber   Current available PCI bus number.
    899   @param  NumberOfBuses    Number of buses enumerated below the StartBusNumber.
    900   @param  NextBusNumber    Next available PCI bus number.
    901 
    902   @retval EFI_SUCCESS           Available bus number resource is enough. Next available PCI bus number
    903                                 is returned in NextBusNumber.
    904   @retval EFI_OUT_OF_RESOURCES  Available bus number resource is not enough for allocation.
    905 
    906 **/
    907 EFI_STATUS
    908 PciAllocateBusNumber (
    909   IN PCI_IO_DEVICE                      *Bridge,
    910   IN UINT8                              StartBusNumber,
    911   IN UINT8                              NumberOfBuses,
    912   OUT UINT8                             *NextBusNumber
    913   )
    914 {
    915   PCI_IO_DEVICE                      *RootBridge;
    916   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  *BusNumberRanges;
    917   UINT8                              NextNumber;
    918   UINT64                             MaxNumberInRange;
    919 
    920   //
    921   // Get PCI Root Bridge device
    922   //
    923   RootBridge = Bridge;
    924   while (RootBridge->Parent != NULL) {
    925     RootBridge = RootBridge->Parent;
    926   }
    927 
    928   //
    929   // Get next available PCI bus number
    930   //
    931   BusNumberRanges = RootBridge->BusNumberRanges;
    932   while (BusNumberRanges->Desc != ACPI_END_TAG_DESCRIPTOR) {
    933     MaxNumberInRange = BusNumberRanges->AddrRangeMin + BusNumberRanges->AddrLen - 1;
    934     if (StartBusNumber >= BusNumberRanges->AddrRangeMin && StartBusNumber <=  MaxNumberInRange) {
    935       NextNumber = (UINT8)(StartBusNumber + NumberOfBuses);
    936       while (NextNumber > MaxNumberInRange) {
    937         ++BusNumberRanges;
    938         if (BusNumberRanges->Desc == ACPI_END_TAG_DESCRIPTOR) {
    939           return EFI_OUT_OF_RESOURCES;
    940         }
    941         NextNumber = (UINT8)(NextNumber + (BusNumberRanges->AddrRangeMin - (MaxNumberInRange + 1)));
    942         MaxNumberInRange = BusNumberRanges->AddrRangeMin + BusNumberRanges->AddrLen - 1;
    943       }
    944       *NextBusNumber = NextNumber;
    945       return EFI_SUCCESS;
    946     }
    947     BusNumberRanges++;
    948   }
    949   return EFI_OUT_OF_RESOURCES;
    950 }
    951 
    952 /**
    953   Scan pci bus and assign bus number to the given PCI bus system.
    954 
    955   @param  Bridge           Bridge device instance.
    956   @param  StartBusNumber   start point.
    957   @param  SubBusNumber     Point to sub bus number.
    958   @param  PaddedBusRange   Customized bus number.
    959 
    960   @retval EFI_SUCCESS      Successfully scanned and assigned bus number.
    961   @retval other            Some error occurred when scanning pci bus.
    962 
    963   @note   Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
    964 
    965 **/
    966 EFI_STATUS
    967 PciScanBus (
    968   IN PCI_IO_DEVICE                      *Bridge,
    969   IN UINT8                              StartBusNumber,
    970   OUT UINT8                             *SubBusNumber,
    971   OUT UINT8                             *PaddedBusRange
    972   )
    973 {
    974   EFI_STATUS                        Status;
    975   PCI_TYPE00                        Pci;
    976   UINT8                             Device;
    977   UINT8                             Func;
    978   UINT64                            Address;
    979   UINT8                             SecondBus;
    980   UINT8                             PaddedSubBus;
    981   UINT16                            Register;
    982   UINTN                             HpIndex;
    983   PCI_IO_DEVICE                     *PciDevice;
    984   EFI_EVENT                         Event;
    985   EFI_HPC_STATE                     State;
    986   UINT64                            PciAddress;
    987   EFI_HPC_PADDING_ATTRIBUTES        Attributes;
    988   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
    989   UINT16                            BusRange;
    990   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL   *PciRootBridgeIo;
    991   BOOLEAN                           BusPadding;
    992   UINT32                            TempReservedBusNum;
    993 
    994   PciRootBridgeIo = Bridge->PciRootBridgeIo;
    995   SecondBus       = 0;
    996   Register        = 0;
    997   State           = 0;
    998   Attributes      = (EFI_HPC_PADDING_ATTRIBUTES) 0;
    999   BusRange        = 0;
   1000   BusPadding      = FALSE;
   1001   PciDevice       = NULL;
   1002   PciAddress      = 0;
   1003 
   1004   for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
   1005     TempReservedBusNum = 0;
   1006     for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
   1007 
   1008       //
   1009       // Check to see whether a pci device is present
   1010       //
   1011       Status = PciDevicePresent (
   1012                 PciRootBridgeIo,
   1013                 &Pci,
   1014                 StartBusNumber,
   1015                 Device,
   1016                 Func
   1017                 );
   1018 
   1019       if (EFI_ERROR (Status) && Func == 0) {
   1020         //
   1021         // go to next device if there is no Function 0
   1022         //
   1023         break;
   1024       }
   1025 
   1026       if (EFI_ERROR (Status)) {
   1027         continue;
   1028       }
   1029 
   1030       //
   1031       // Get the PCI device information
   1032       //
   1033       Status = PciSearchDevice (
   1034                 Bridge,
   1035                 &Pci,
   1036                 StartBusNumber,
   1037                 Device,
   1038                 Func,
   1039                 &PciDevice
   1040                 );
   1041 
   1042       ASSERT (!EFI_ERROR (Status));
   1043 
   1044       PciAddress = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0);
   1045 
   1046       if (!IS_PCI_BRIDGE (&Pci)) {
   1047         //
   1048         // PCI bridges will be called later
   1049         // Here just need for PCI device or PCI to cardbus controller
   1050         // EfiPciBeforeChildBusEnumeration for PCI Device Node
   1051         //
   1052         PreprocessController (
   1053             PciDevice,
   1054             PciDevice->BusNumber,
   1055             PciDevice->DeviceNumber,
   1056             PciDevice->FunctionNumber,
   1057             EfiPciBeforeChildBusEnumeration
   1058             );
   1059       }
   1060 
   1061       if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
   1062         //
   1063         // For Pci Hotplug controller devcie only
   1064         //
   1065         if (gPciHotPlugInit != NULL) {
   1066           //
   1067           // Check if it is a Hotplug PCI controller
   1068           //
   1069           if (IsRootPciHotPlugController (PciDevice->DevicePath, &HpIndex)) {
   1070             gPciRootHpcData[HpIndex].Found = TRUE;
   1071 
   1072             if (!gPciRootHpcData[HpIndex].Initialized) {
   1073 
   1074               Status = CreateEventForHpc (HpIndex, &Event);
   1075 
   1076               ASSERT (!EFI_ERROR (Status));
   1077 
   1078               Status = gPciHotPlugInit->InitializeRootHpc (
   1079                                           gPciHotPlugInit,
   1080                                           gPciRootHpcPool[HpIndex].HpcDevicePath,
   1081                                           PciAddress,
   1082                                           Event,
   1083                                           &State
   1084                                           );
   1085 
   1086               PreprocessController (
   1087                 PciDevice,
   1088                 PciDevice->BusNumber,
   1089                 PciDevice->DeviceNumber,
   1090                 PciDevice->FunctionNumber,
   1091                 EfiPciBeforeChildBusEnumeration
   1092               );
   1093             }
   1094           }
   1095         }
   1096       }
   1097 
   1098       if (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci)) {
   1099         //
   1100         // For PPB
   1101         //
   1102         if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
   1103           //
   1104           // If Hot Plug is not supported,
   1105           // get the bridge information
   1106           //
   1107           Status = PciSearchDevice (
   1108                     Bridge,
   1109                     &Pci,
   1110                     StartBusNumber,
   1111                     Device,
   1112                     Func,
   1113                     &PciDevice
   1114                     );
   1115 
   1116           if (EFI_ERROR (Status)) {
   1117             return Status;
   1118           }
   1119         } else {
   1120           //
   1121           // If Hot Plug is supported,
   1122           // Get the bridge information
   1123           //
   1124           BusPadding = FALSE;
   1125           if (gPciHotPlugInit != NULL) {
   1126 
   1127             if (IsRootPciHotPlugBus (PciDevice->DevicePath, &HpIndex)) {
   1128 
   1129               //
   1130               // If it is initialized, get the padded bus range
   1131               //
   1132               Status = gPciHotPlugInit->GetResourcePadding (
   1133                                           gPciHotPlugInit,
   1134                                           gPciRootHpcPool[HpIndex].HpbDevicePath,
   1135                                           PciAddress,
   1136                                           &State,
   1137                                           (VOID **) &Descriptors,
   1138                                           &Attributes
   1139                                           );
   1140 
   1141               if (EFI_ERROR (Status)) {
   1142                 return Status;
   1143               }
   1144 
   1145               BusRange = 0;
   1146               Status = PciGetBusRange (
   1147                         &Descriptors,
   1148                         NULL,
   1149                         NULL,
   1150                         &BusRange
   1151                         );
   1152 
   1153               FreePool (Descriptors);
   1154 
   1155               if (EFI_ERROR (Status)) {
   1156                 return Status;
   1157               }
   1158 
   1159               BusPadding = TRUE;
   1160             }
   1161           }
   1162         }
   1163 
   1164         Status = PciAllocateBusNumber (Bridge, *SubBusNumber, 1, SubBusNumber);
   1165         if (EFI_ERROR (Status)) {
   1166           return Status;
   1167         }
   1168         SecondBus = *SubBusNumber;
   1169 
   1170         Register  = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);
   1171         Address   = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET);
   1172 
   1173         Status = PciRootBridgeIo->Pci.Write (
   1174                                         PciRootBridgeIo,
   1175                                         EfiPciWidthUint16,
   1176                                         Address,
   1177                                         1,
   1178                                         &Register
   1179                                         );
   1180 
   1181 
   1182         //
   1183         // If it is PPB, resursively search down this bridge
   1184         //
   1185         if (IS_PCI_BRIDGE (&Pci)) {
   1186 
   1187           //
   1188           // Temporarily initialize SubBusNumber to maximum bus number to ensure the
   1189           // PCI configuration transaction to go through any PPB
   1190           //
   1191           Register  = 0xFF;
   1192           Address   = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);
   1193           Status = PciRootBridgeIo->Pci.Write (
   1194                                           PciRootBridgeIo,
   1195                                           EfiPciWidthUint8,
   1196                                           Address,
   1197                                           1,
   1198                                           &Register
   1199                                           );
   1200 
   1201           //
   1202           // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige
   1203           //
   1204           PreprocessController (
   1205             PciDevice,
   1206             PciDevice->BusNumber,
   1207             PciDevice->DeviceNumber,
   1208             PciDevice->FunctionNumber,
   1209             EfiPciBeforeChildBusEnumeration
   1210             );
   1211 
   1212           Status = PciScanBus (
   1213                     PciDevice,
   1214                     SecondBus,
   1215                     SubBusNumber,
   1216                     PaddedBusRange
   1217                     );
   1218           if (EFI_ERROR (Status)) {
   1219             return Status;
   1220           }
   1221         }
   1222 
   1223         if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport) && BusPadding) {
   1224           //
   1225           // Ensure the device is enabled and initialized
   1226           //
   1227           if ((Attributes == EfiPaddingPciRootBridge) &&
   1228               (State & EFI_HPC_STATE_ENABLED) != 0    &&
   1229               (State & EFI_HPC_STATE_INITIALIZED) != 0) {
   1230             *PaddedBusRange = (UINT8) ((UINT8) (BusRange) + *PaddedBusRange);
   1231           } else {
   1232             //
   1233             // Reserve the larger one between the actual occupied bus number and padded bus number
   1234             //
   1235             Status = PciAllocateBusNumber (PciDevice, SecondBus, (UINT8) (BusRange), &PaddedSubBus);
   1236             if (EFI_ERROR (Status)) {
   1237               return Status;
   1238             }
   1239             *SubBusNumber = MAX (PaddedSubBus, *SubBusNumber);
   1240           }
   1241         }
   1242 
   1243         //
   1244         // Set the current maximum bus number under the PPB
   1245         //
   1246         Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);
   1247 
   1248         Status = PciRootBridgeIo->Pci.Write (
   1249                                         PciRootBridgeIo,
   1250                                         EfiPciWidthUint8,
   1251                                         Address,
   1252                                         1,
   1253                                         SubBusNumber
   1254                                         );
   1255       } else  {
   1256         //
   1257         // It is device. Check PCI IOV for Bus reservation
   1258         // Go through each function, just reserve the MAX ReservedBusNum for one device
   1259         //
   1260         if (PcdGetBool (PcdSrIovSupport) && PciDevice->SrIovCapabilityOffset != 0) {
   1261           if (TempReservedBusNum < PciDevice->ReservedBusNum) {
   1262 
   1263             Status = PciAllocateBusNumber (PciDevice, *SubBusNumber, (UINT8) (PciDevice->ReservedBusNum - TempReservedBusNum), SubBusNumber);
   1264             if (EFI_ERROR (Status)) {
   1265               return Status;
   1266             }
   1267             TempReservedBusNum = PciDevice->ReservedBusNum;
   1268 
   1269             if (Func == 0) {
   1270               DEBUG ((EFI_D_INFO, "PCI-IOV ScanBus - SubBusNumber - 0x%x\n", *SubBusNumber));
   1271             } else {
   1272               DEBUG ((EFI_D_INFO, "PCI-IOV ScanBus - SubBusNumber - 0x%x (Update)\n", *SubBusNumber));
   1273             }
   1274           }
   1275         }
   1276       }
   1277 
   1278       if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
   1279 
   1280         //
   1281         // Skip sub functions, this is not a multi function device
   1282         //
   1283 
   1284         Func = PCI_MAX_FUNC;
   1285       }
   1286     }
   1287   }
   1288 
   1289   return EFI_SUCCESS;
   1290 }
   1291 
   1292 /**
   1293   Process Option Rom on the specified root bridge.
   1294 
   1295   @param Bridge  Pci root bridge device instance.
   1296 
   1297   @retval EFI_SUCCESS   Success process.
   1298   @retval other         Some error occurred when processing Option Rom on the root bridge.
   1299 
   1300 **/
   1301 EFI_STATUS
   1302 PciRootBridgeP2CProcess (
   1303   IN PCI_IO_DEVICE *Bridge
   1304   )
   1305 {
   1306   LIST_ENTRY      *CurrentLink;
   1307   PCI_IO_DEVICE   *Temp;
   1308   EFI_HPC_STATE   State;
   1309   UINT64          PciAddress;
   1310   EFI_STATUS      Status;
   1311 
   1312   CurrentLink = Bridge->ChildList.ForwardLink;
   1313 
   1314   while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {
   1315 
   1316     Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
   1317 
   1318     if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {
   1319 
   1320       if (gPciHotPlugInit != NULL && Temp->Allocated && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
   1321 
   1322         //
   1323         // Raise the EFI_IOB_PCI_HPC_INIT status code
   1324         //
   1325         REPORT_STATUS_CODE_WITH_DEVICE_PATH (
   1326           EFI_PROGRESS_CODE,
   1327           EFI_IO_BUS_PCI | EFI_IOB_PCI_HPC_INIT,
   1328           Temp->DevicePath
   1329           );
   1330 
   1331         PciAddress = EFI_PCI_ADDRESS (Temp->BusNumber, Temp->DeviceNumber, Temp->FunctionNumber, 0);
   1332         Status = gPciHotPlugInit->InitializeRootHpc (
   1333                                     gPciHotPlugInit,
   1334                                     Temp->DevicePath,
   1335                                     PciAddress,
   1336                                     NULL,
   1337                                     &State
   1338                                     );
   1339 
   1340         if (!EFI_ERROR (Status)) {
   1341           Status = PciBridgeEnumerator (Temp);
   1342 
   1343           if (EFI_ERROR (Status)) {
   1344             return Status;
   1345           }
   1346         }
   1347 
   1348         CurrentLink = CurrentLink->ForwardLink;
   1349         continue;
   1350 
   1351       }
   1352     }
   1353 
   1354     if (!IsListEmpty (&Temp->ChildList)) {
   1355       Status = PciRootBridgeP2CProcess (Temp);
   1356     }
   1357 
   1358     CurrentLink = CurrentLink->ForwardLink;
   1359   }
   1360 
   1361   return EFI_SUCCESS;
   1362 }
   1363 
   1364 /**
   1365   Process Option Rom on the specified host bridge.
   1366 
   1367   @param PciResAlloc    Pointer to instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
   1368 
   1369   @retval EFI_SUCCESS   Success process.
   1370   @retval EFI_NOT_FOUND Can not find the root bridge instance.
   1371   @retval other         Some error occurred when processing Option Rom on the host bridge.
   1372 
   1373 **/
   1374 EFI_STATUS
   1375 PciHostBridgeP2CProcess (
   1376   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
   1377   )
   1378 {
   1379   EFI_HANDLE    RootBridgeHandle;
   1380   PCI_IO_DEVICE *RootBridgeDev;
   1381   EFI_STATUS    Status;
   1382 
   1383   if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
   1384     return EFI_SUCCESS;
   1385   }
   1386 
   1387   RootBridgeHandle = NULL;
   1388 
   1389   while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
   1390 
   1391     //
   1392     // Get RootBridg Device by handle
   1393     //
   1394     RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
   1395 
   1396     if (RootBridgeDev == NULL) {
   1397       return EFI_NOT_FOUND;
   1398     }
   1399 
   1400     Status = PciRootBridgeP2CProcess (RootBridgeDev);
   1401     if (EFI_ERROR (Status)) {
   1402       return Status;
   1403     }
   1404 
   1405   }
   1406 
   1407   return EFI_SUCCESS;
   1408 }
   1409 
   1410 /**
   1411   This function is used to enumerate the entire host bridge
   1412   in a given platform.
   1413 
   1414   @param PciResAlloc   A pointer to the PCI Host Resource Allocation protocol.
   1415 
   1416   @retval EFI_SUCCESS            Successfully enumerated the host bridge.
   1417   @retval EFI_OUT_OF_RESOURCES   No enough memory available.
   1418   @retval other                  Some error occurred when enumerating the host bridge.
   1419 
   1420 **/
   1421 EFI_STATUS
   1422 PciHostBridgeEnumerator (
   1423   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *PciResAlloc
   1424   )
   1425 {
   1426   EFI_HANDLE                        RootBridgeHandle;
   1427   PCI_IO_DEVICE                     *RootBridgeDev;
   1428   EFI_STATUS                        Status;
   1429   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL   *PciRootBridgeIo;
   1430   UINT16                            MinBus;
   1431   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
   1432   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;
   1433   UINT8                             StartBusNumber;
   1434   LIST_ENTRY                        RootBridgeList;
   1435   LIST_ENTRY                        *Link;
   1436 
   1437   if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
   1438     InitializeHotPlugSupport ();
   1439   }
   1440 
   1441   InitializeListHead (&RootBridgeList);
   1442 
   1443   //
   1444   // Notify the bus allocation phase is about to start
   1445   //
   1446   Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);
   1447 
   1448   if (EFI_ERROR (Status)) {
   1449     return Status;
   1450   }
   1451 
   1452   DEBUG((EFI_D_INFO, "PCI Bus First Scanning\n"));
   1453   RootBridgeHandle = NULL;
   1454   while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
   1455 
   1456     //
   1457     // if a root bridge instance is found, create root bridge device for it
   1458     //
   1459 
   1460     RootBridgeDev = CreateRootBridge (RootBridgeHandle);
   1461 
   1462     if (RootBridgeDev == NULL) {
   1463       return EFI_OUT_OF_RESOURCES;
   1464     }
   1465 
   1466     //
   1467     // Enumerate all the buses under this root bridge
   1468     //
   1469     Status = PciRootBridgeEnumerator (
   1470               PciResAlloc,
   1471               RootBridgeDev
   1472               );
   1473 
   1474     if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
   1475       InsertTailList (&RootBridgeList, &(RootBridgeDev->Link));
   1476     } else {
   1477       DestroyRootBridge (RootBridgeDev);
   1478     }
   1479     if (EFI_ERROR (Status)) {
   1480       return Status;
   1481     }
   1482   }
   1483 
   1484   //
   1485   // Notify the bus allocation phase is finished for the first time
   1486   //
   1487   NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);
   1488 
   1489   if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
   1490     //
   1491     // Reset all assigned PCI bus number in all PPB
   1492     //
   1493     RootBridgeHandle = NULL;
   1494     Link = GetFirstNode (&RootBridgeList);
   1495     while ((PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) &&
   1496       (!IsNull (&RootBridgeList, Link))) {
   1497       RootBridgeDev = PCI_IO_DEVICE_FROM_LINK (Link);
   1498       //
   1499       // Get the Bus information
   1500       //
   1501       Status = PciResAlloc->StartBusEnumeration (
   1502                               PciResAlloc,
   1503                               RootBridgeHandle,
   1504                               (VOID **) &Configuration
   1505                               );
   1506       if (EFI_ERROR (Status)) {
   1507         return Status;
   1508       }
   1509 
   1510       //
   1511       // Get the bus number to start with
   1512       //
   1513       StartBusNumber  = (UINT8) (Configuration->AddrRangeMin);
   1514 
   1515       ResetAllPpbBusNumber (
   1516         RootBridgeDev,
   1517         StartBusNumber
   1518       );
   1519 
   1520       FreePool (Configuration);
   1521       Link = RemoveEntryList (Link);
   1522       DestroyRootBridge (RootBridgeDev);
   1523     }
   1524 
   1525     //
   1526     // Wait for all HPC initialized
   1527     //
   1528     Status = AllRootHPCInitialized (STALL_1_SECOND * 15);
   1529 
   1530     if (EFI_ERROR (Status)) {
   1531       DEBUG ((EFI_D_ERROR, "Some root HPC failed to initialize\n"));
   1532       return Status;
   1533     }
   1534 
   1535     //
   1536     // Notify the bus allocation phase is about to start for the 2nd time
   1537     //
   1538     Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);
   1539 
   1540     if (EFI_ERROR (Status)) {
   1541       return Status;
   1542     }
   1543 
   1544     DEBUG((EFI_D_INFO, "PCI Bus Second Scanning\n"));
   1545     RootBridgeHandle = NULL;
   1546     while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
   1547 
   1548       //
   1549       // if a root bridge instance is found, create root bridge device for it
   1550       //
   1551       RootBridgeDev = CreateRootBridge (RootBridgeHandle);
   1552 
   1553       if (RootBridgeDev == NULL) {
   1554         return EFI_OUT_OF_RESOURCES;
   1555       }
   1556 
   1557       //
   1558       // Enumerate all the buses under this root bridge
   1559       //
   1560       Status = PciRootBridgeEnumerator (
   1561                 PciResAlloc,
   1562                 RootBridgeDev
   1563                 );
   1564 
   1565       DestroyRootBridge (RootBridgeDev);
   1566       if (EFI_ERROR (Status)) {
   1567         return Status;
   1568       }
   1569     }
   1570 
   1571     //
   1572     // Notify the bus allocation phase is to end for the 2nd time
   1573     //
   1574     NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);
   1575   }
   1576 
   1577   //
   1578   // Notify the resource allocation phase is to start
   1579   //
   1580   Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginResourceAllocation);
   1581 
   1582   if (EFI_ERROR (Status)) {
   1583     return Status;
   1584   }
   1585 
   1586   RootBridgeHandle = NULL;
   1587   while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
   1588 
   1589     //
   1590     // if a root bridge instance is found, create root bridge device for it
   1591     //
   1592     RootBridgeDev = CreateRootBridge (RootBridgeHandle);
   1593 
   1594     if (RootBridgeDev == NULL) {
   1595       return EFI_OUT_OF_RESOURCES;
   1596     }
   1597 
   1598     Status = StartManagingRootBridge (RootBridgeDev);
   1599 
   1600     if (EFI_ERROR (Status)) {
   1601       return Status;
   1602     }
   1603 
   1604     PciRootBridgeIo = RootBridgeDev->PciRootBridgeIo;
   1605     Status          = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);
   1606 
   1607     if (EFI_ERROR (Status)) {
   1608       return Status;
   1609     }
   1610 
   1611     Status = PciGetBusRange (&Descriptors, &MinBus, NULL, NULL);
   1612 
   1613     if (EFI_ERROR (Status)) {
   1614       return Status;
   1615     }
   1616 
   1617     //
   1618     // Determine root bridge attribute by calling interface of Pcihostbridge
   1619     // protocol
   1620     //
   1621     DetermineRootBridgeAttributes (
   1622       PciResAlloc,
   1623       RootBridgeDev
   1624       );
   1625 
   1626     //
   1627     // Collect all the resource information under this root bridge
   1628     // A database that records all the information about pci device subject to this
   1629     // root bridge will then be created
   1630     //
   1631     Status = PciPciDeviceInfoCollector (
   1632               RootBridgeDev,
   1633               (UINT8) MinBus
   1634               );
   1635 
   1636     if (EFI_ERROR (Status)) {
   1637       return Status;
   1638     }
   1639 
   1640     InsertRootBridge (RootBridgeDev);
   1641 
   1642     //
   1643     // Record the hostbridge handle
   1644     //
   1645     AddHostBridgeEnumerator (RootBridgeDev->PciRootBridgeIo->ParentHandle);
   1646   }
   1647 
   1648   return EFI_SUCCESS;
   1649 }
   1650