Home | History | Annotate | Download | only in PciBusDxe
      1 /** @file
      2   PCI eunmeration implementation on entire PCI bus system 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 /**
     19   This routine is used to enumerate entire pci bus system
     20   in a given platform.
     21 
     22   @param Controller  Parent controller handle.
     23 
     24   @retval EFI_SUCCESS    PCI enumeration finished successfully.
     25   @retval other          Some error occurred when enumerating the pci bus system.
     26 
     27 **/
     28 EFI_STATUS
     29 PciEnumerator (
     30   IN EFI_HANDLE                    Controller
     31   )
     32 {
     33   EFI_HANDLE                                        HostBridgeHandle;
     34   EFI_STATUS                                        Status;
     35   EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *PciResAlloc;
     36   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL                   *PciRootBridgeIo;
     37 
     38   //
     39   // If PCI bus has already done the full enumeration, never do it again
     40   //
     41   if (!gFullEnumeration) {
     42     return PciEnumeratorLight (Controller);
     43   }
     44 
     45   //
     46   // Get the rootbridge Io protocol to find the host bridge handle
     47   //
     48   Status = gBS->OpenProtocol (
     49                   Controller,
     50                   &gEfiPciRootBridgeIoProtocolGuid,
     51                   (VOID **) &PciRootBridgeIo,
     52                   gPciBusDriverBinding.DriverBindingHandle,
     53                   Controller,
     54                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
     55                   );
     56 
     57   if (EFI_ERROR (Status)) {
     58     return Status;
     59   }
     60 
     61   //
     62   // Get the host bridge handle
     63   //
     64   HostBridgeHandle = PciRootBridgeIo->ParentHandle;
     65 
     66   //
     67   // Get the pci host bridge resource allocation protocol
     68   //
     69   Status = gBS->OpenProtocol (
     70                   HostBridgeHandle,
     71                   &gEfiPciHostBridgeResourceAllocationProtocolGuid,
     72                   (VOID **) &PciResAlloc,
     73                   gPciBusDriverBinding.DriverBindingHandle,
     74                   Controller,
     75                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
     76                   );
     77 
     78   if (EFI_ERROR (Status)) {
     79     return Status;
     80   }
     81 
     82   //
     83   // Notify the pci bus enumeration is about to begin
     84   //
     85   Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginEnumeration);
     86 
     87   if (EFI_ERROR (Status)) {
     88     return Status;
     89   }
     90 
     91   //
     92   // Start the bus allocation phase
     93   //
     94   Status = PciHostBridgeEnumerator (PciResAlloc);
     95 
     96   if (EFI_ERROR (Status)) {
     97     return Status;
     98   }
     99 
    100   //
    101   // Submit the resource request
    102   //
    103   Status = PciHostBridgeResourceAllocator (PciResAlloc);
    104 
    105   if (EFI_ERROR (Status)) {
    106     return Status;
    107   }
    108 
    109   //
    110   // Notify the pci bus enumeration is about to complete
    111   //
    112   Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeEndEnumeration);
    113 
    114   if (EFI_ERROR (Status)) {
    115     return Status;
    116   }
    117 
    118   //
    119   // Process P2C
    120   //
    121   Status = PciHostBridgeP2CProcess (PciResAlloc);
    122 
    123   if (EFI_ERROR (Status)) {
    124     return Status;
    125   }
    126 
    127   //
    128   // Process attributes for devices on this host bridge
    129   //
    130   Status = PciHostBridgeDeviceAttribute (PciResAlloc);
    131   if (EFI_ERROR (Status)) {
    132     return Status;
    133   }
    134 
    135   gFullEnumeration = FALSE;
    136 
    137   Status = gBS->InstallProtocolInterface (
    138                   &HostBridgeHandle,
    139                   &gEfiPciEnumerationCompleteProtocolGuid,
    140                   EFI_NATIVE_INTERFACE,
    141                   NULL
    142                   );
    143   if (EFI_ERROR (Status)) {
    144     return Status;
    145   }
    146 
    147   return EFI_SUCCESS;
    148 }
    149 
    150 /**
    151   Enumerate PCI root bridge.
    152 
    153   @param PciResAlloc   Pointer to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
    154   @param RootBridgeDev Instance of root bridge device.
    155 
    156   @retval EFI_SUCCESS  Successfully enumerated root bridge.
    157   @retval other        Failed to enumerate root bridge.
    158 
    159 **/
    160 EFI_STATUS
    161 PciRootBridgeEnumerator (
    162   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *PciResAlloc,
    163   IN PCI_IO_DEVICE                                     *RootBridgeDev
    164   )
    165 {
    166   EFI_STATUS                        Status;
    167   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;
    168   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration1;
    169   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration2;
    170   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration3;
    171   UINT8                             SubBusNumber;
    172   UINT8                             StartBusNumber;
    173   UINT8                             PaddedBusRange;
    174   EFI_HANDLE                        RootBridgeHandle;
    175   UINT8                             Desc;
    176   UINT64                            AddrLen;
    177   UINT64                            AddrRangeMin;
    178 
    179   SubBusNumber    = 0;
    180   StartBusNumber  = 0;
    181   PaddedBusRange  = 0;
    182 
    183   //
    184   // Get the root bridge handle
    185   //
    186   RootBridgeHandle = RootBridgeDev->Handle;
    187 
    188   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
    189     EFI_PROGRESS_CODE,
    190     EFI_IO_BUS_PCI | EFI_IOB_PCI_BUS_ENUM,
    191     RootBridgeDev->DevicePath
    192     );
    193 
    194   //
    195   // Get the Bus information
    196   //
    197   Status = PciResAlloc->StartBusEnumeration (
    198                           PciResAlloc,
    199                           RootBridgeHandle,
    200                           (VOID **) &Configuration
    201                           );
    202 
    203   if (EFI_ERROR (Status)) {
    204     return Status;
    205   }
    206 
    207   if (Configuration == NULL || Configuration->Desc == ACPI_END_TAG_DESCRIPTOR) {
    208     return EFI_INVALID_PARAMETER;
    209   }
    210   RootBridgeDev->BusNumberRanges = Configuration;
    211 
    212   //
    213   // Sort the descriptors in ascending order
    214   //
    215   for (Configuration1 = Configuration; Configuration1->Desc != ACPI_END_TAG_DESCRIPTOR; Configuration1++) {
    216     Configuration2 = Configuration1;
    217     for (Configuration3 = Configuration1 + 1; Configuration3->Desc != ACPI_END_TAG_DESCRIPTOR; Configuration3++) {
    218       if (Configuration2->AddrRangeMin > Configuration3->AddrRangeMin) {
    219         Configuration2 = Configuration3;
    220       }
    221     }
    222     //
    223     // All other fields other than AddrRangeMin and AddrLen are ignored in a descriptor,
    224     // so only need to swap these two fields.
    225     //
    226     if (Configuration2 != Configuration1) {
    227       AddrRangeMin = Configuration1->AddrRangeMin;
    228       Configuration1->AddrRangeMin = Configuration2->AddrRangeMin;
    229       Configuration2->AddrRangeMin = AddrRangeMin;
    230 
    231       AddrLen = Configuration1->AddrLen;
    232       Configuration1->AddrLen = Configuration2->AddrLen;
    233       Configuration2->AddrLen = AddrLen;
    234     }
    235   }
    236 
    237   //
    238   // Get the bus number to start with
    239   //
    240   StartBusNumber = (UINT8) (Configuration->AddrRangeMin);
    241 
    242   //
    243   // Initialize the subordinate bus number
    244   //
    245   SubBusNumber = StartBusNumber;
    246 
    247   //
    248   // Reset all assigned PCI bus number
    249   //
    250   ResetAllPpbBusNumber (
    251     RootBridgeDev,
    252     StartBusNumber
    253   );
    254 
    255   //
    256   // Assign bus number
    257   //
    258   Status = PciScanBus (
    259             RootBridgeDev,
    260             StartBusNumber,
    261             &SubBusNumber,
    262             &PaddedBusRange
    263             );
    264 
    265   if (EFI_ERROR (Status)) {
    266     return Status;
    267   }
    268 
    269 
    270   //
    271   // Assign max bus number scanned
    272   //
    273 
    274   Status = PciAllocateBusNumber (RootBridgeDev, SubBusNumber, PaddedBusRange, &SubBusNumber);
    275   if (EFI_ERROR (Status)) {
    276     return Status;
    277   }
    278 
    279   //
    280   // Find the bus range which contains the higest bus number, then returns the number of buses
    281   // that should be decoded.
    282   //
    283   while (Configuration->AddrRangeMin + Configuration->AddrLen - 1 < SubBusNumber) {
    284     Configuration++;
    285   }
    286   AddrLen = Configuration->AddrLen;
    287   Configuration->AddrLen = SubBusNumber - Configuration->AddrRangeMin + 1;
    288 
    289   //
    290   // Save the Desc field of the next descriptor. Mark the next descriptor as an END descriptor.
    291   //
    292   Configuration++;
    293   Desc = Configuration->Desc;
    294   Configuration->Desc = ACPI_END_TAG_DESCRIPTOR;
    295 
    296   //
    297   // Set bus number
    298   //
    299   Status = PciResAlloc->SetBusNumbers (
    300                           PciResAlloc,
    301                           RootBridgeHandle,
    302                           RootBridgeDev->BusNumberRanges
    303                           );
    304 
    305   //
    306   // Restore changed fields
    307   //
    308   Configuration->Desc = Desc;
    309   (Configuration - 1)->AddrLen = AddrLen;
    310 
    311   return Status;
    312 }
    313 
    314 /**
    315   This routine is used to process all PCI devices' Option Rom
    316   on a certain root bridge.
    317 
    318   @param Bridge     Given parent's root bridge.
    319   @param RomBase    Base address of ROM driver loaded from.
    320   @param MaxLength  Maximum rom size.
    321 
    322 **/
    323 VOID
    324 ProcessOptionRom (
    325   IN PCI_IO_DEVICE *Bridge,
    326   IN UINT64        RomBase,
    327   IN UINT64        MaxLength
    328   )
    329 {
    330   LIST_ENTRY      *CurrentLink;
    331   PCI_IO_DEVICE   *Temp;
    332 
    333   //
    334   // Go through bridges to reach all devices
    335   //
    336   CurrentLink = Bridge->ChildList.ForwardLink;
    337   while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {
    338     Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
    339     if (!IsListEmpty (&Temp->ChildList)) {
    340 
    341       //
    342       // Go further to process the option rom under this bridge
    343       //
    344       ProcessOptionRom (Temp, RomBase, MaxLength);
    345     }
    346 
    347     if (Temp->RomSize != 0 && Temp->RomSize <= MaxLength) {
    348 
    349       //
    350       // Load and process the option rom
    351       //
    352       LoadOpRomImage (Temp, RomBase);
    353     }
    354 
    355     CurrentLink = CurrentLink->ForwardLink;
    356   }
    357 }
    358 
    359 /**
    360   This routine is used to assign bus number to the given PCI bus system
    361 
    362   @param Bridge             Parent root bridge instance.
    363   @param StartBusNumber     Number of beginning.
    364   @param SubBusNumber       The number of sub bus.
    365 
    366   @retval EFI_SUCCESS       Successfully assigned bus number.
    367   @retval EFI_DEVICE_ERROR  Failed to assign bus number.
    368 
    369 **/
    370 EFI_STATUS
    371 PciAssignBusNumber (
    372   IN PCI_IO_DEVICE                      *Bridge,
    373   IN UINT8                              StartBusNumber,
    374   OUT UINT8                             *SubBusNumber
    375   )
    376 {
    377   EFI_STATUS                      Status;
    378   PCI_TYPE00                      Pci;
    379   UINT8                           Device;
    380   UINT8                           Func;
    381   UINT64                          Address;
    382   UINTN                           SecondBus;
    383   UINT16                          Register;
    384   UINT8                           Register8;
    385   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
    386 
    387   PciRootBridgeIo = Bridge->PciRootBridgeIo;
    388 
    389   SecondBus       = 0;
    390   Register        = 0;
    391 
    392   *SubBusNumber = StartBusNumber;
    393 
    394   //
    395   // First check to see whether the parent is ppb
    396   //
    397   for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
    398     for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
    399 
    400       //
    401       // Check to see whether a pci device is present
    402       //
    403       Status = PciDevicePresent (
    404                 PciRootBridgeIo,
    405                 &Pci,
    406                 StartBusNumber,
    407                 Device,
    408                 Func
    409                 );
    410 
    411       if (EFI_ERROR (Status) && Func == 0) {
    412         //
    413         // go to next device if there is no Function 0
    414         //
    415         break;
    416       }
    417 
    418       if (!EFI_ERROR (Status)   &&
    419           (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci))) {
    420 
    421         //
    422         // Reserved one bus for cardbus bridge
    423         //
    424         Status = PciAllocateBusNumber (Bridge, *SubBusNumber, 1, SubBusNumber);
    425         if (EFI_ERROR (Status)) {
    426           return Status;
    427         }
    428         SecondBus = *SubBusNumber;
    429 
    430         Register  = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);
    431 
    432         Address   = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);
    433 
    434         Status = PciRootBridgeIo->Pci.Write (
    435                                         PciRootBridgeIo,
    436                                         EfiPciWidthUint16,
    437                                         Address,
    438                                         1,
    439                                         &Register
    440                                         );
    441 
    442         //
    443         // Initialize SubBusNumber to SecondBus
    444         //
    445         Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
    446         Status = PciRootBridgeIo->Pci.Write (
    447                                         PciRootBridgeIo,
    448                                         EfiPciWidthUint8,
    449                                         Address,
    450                                         1,
    451                                         SubBusNumber
    452                                         );
    453         //
    454         // If it is PPB, resursively search down this bridge
    455         //
    456         if (IS_PCI_BRIDGE (&Pci)) {
    457 
    458           Register8 = 0xFF;
    459           Status = PciRootBridgeIo->Pci.Write (
    460                                           PciRootBridgeIo,
    461                                           EfiPciWidthUint8,
    462                                           Address,
    463                                           1,
    464                                           &Register8
    465                                           );
    466 
    467           Status = PciAssignBusNumber (
    468                     Bridge,
    469                     (UINT8) (SecondBus),
    470                     SubBusNumber
    471                     );
    472 
    473           if (EFI_ERROR (Status)) {
    474             return EFI_DEVICE_ERROR;
    475           }
    476         }
    477 
    478         //
    479         // Set the current maximum bus number under the PPB
    480         //
    481         Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
    482 
    483         Status = PciRootBridgeIo->Pci.Write (
    484                                         PciRootBridgeIo,
    485                                         EfiPciWidthUint8,
    486                                         Address,
    487                                         1,
    488                                         SubBusNumber
    489                                         );
    490 
    491       }
    492 
    493       if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
    494 
    495         //
    496         // Skip sub functions, this is not a multi function device
    497         //
    498         Func = PCI_MAX_FUNC;
    499       }
    500     }
    501   }
    502 
    503   return EFI_SUCCESS;
    504 }
    505 
    506 /**
    507   This routine is used to determine the root bridge attribute by interfacing
    508   the host bridge resource allocation protocol.
    509 
    510   @param PciResAlloc    Protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
    511   @param RootBridgeDev  Root bridge instance
    512 
    513   @retval EFI_SUCCESS  Successfully got root bridge's attribute.
    514   @retval other        Failed to get attribute.
    515 
    516 **/
    517 EFI_STATUS
    518 DetermineRootBridgeAttributes (
    519   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,
    520   IN PCI_IO_DEVICE                                    *RootBridgeDev
    521   )
    522 {
    523   UINT64      Attributes;
    524   EFI_STATUS  Status;
    525   EFI_HANDLE  RootBridgeHandle;
    526 
    527   Attributes        = 0;
    528   RootBridgeHandle  = RootBridgeDev->Handle;
    529 
    530   //
    531   // Get root bridge attribute by calling into pci host bridge resource allocation protocol
    532   //
    533   Status = PciResAlloc->GetAllocAttributes (
    534                           PciResAlloc,
    535                           RootBridgeHandle,
    536                           &Attributes
    537                           );
    538 
    539   if (EFI_ERROR (Status)) {
    540     return Status;
    541   }
    542 
    543   //
    544   // Here is the point where PCI bus driver calls HOST bridge allocation protocol
    545   // Currently we hardcoded for ea815
    546   //
    547   if ((Attributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0) {
    548     RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED;
    549   }
    550 
    551   if ((Attributes & EFI_PCI_HOST_BRIDGE_MEM64_DECODE) != 0) {
    552     RootBridgeDev->Decodes |= EFI_BRIDGE_MEM64_DECODE_SUPPORTED;
    553     RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED;
    554   }
    555 
    556   RootBridgeDev->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED;
    557   RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
    558   RootBridgeDev->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED;
    559 
    560   return EFI_SUCCESS;
    561 }
    562 
    563 /**
    564   Get Max Option Rom size on specified bridge.
    565 
    566   @param Bridge    Given bridge device instance.
    567 
    568   @return Max size of option rom needed.
    569 
    570 **/
    571 UINT64
    572 GetMaxOptionRomSize (
    573   IN PCI_IO_DEVICE   *Bridge
    574   )
    575 {
    576   LIST_ENTRY      *CurrentLink;
    577   PCI_IO_DEVICE   *Temp;
    578   UINT64          MaxOptionRomSize;
    579   UINT64          TempOptionRomSize;
    580 
    581   MaxOptionRomSize = 0;
    582 
    583   //
    584   // Go through bridges to reach all devices
    585   //
    586   CurrentLink = Bridge->ChildList.ForwardLink;
    587   while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {
    588     Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
    589     if (!IsListEmpty (&Temp->ChildList)) {
    590 
    591       //
    592       // Get max option rom size under this bridge
    593       //
    594       TempOptionRomSize = GetMaxOptionRomSize (Temp);
    595 
    596       //
    597       // Compare with the option rom size of the bridge
    598       // Get the larger one
    599       //
    600       if (Temp->RomSize > TempOptionRomSize) {
    601         TempOptionRomSize = Temp->RomSize;
    602       }
    603 
    604     } else {
    605 
    606       //
    607       // For devices get the rom size directly
    608       //
    609       TempOptionRomSize = Temp->RomSize;
    610     }
    611 
    612     //
    613     // Get the largest rom size on this bridge
    614     //
    615     if (TempOptionRomSize > MaxOptionRomSize) {
    616       MaxOptionRomSize = TempOptionRomSize;
    617     }
    618 
    619     CurrentLink = CurrentLink->ForwardLink;
    620   }
    621 
    622   return MaxOptionRomSize;
    623 }
    624 
    625 /**
    626   Process attributes of devices on this host bridge
    627 
    628   @param PciResAlloc Protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
    629 
    630   @retval EFI_SUCCESS   Successfully process attribute.
    631   @retval EFI_NOT_FOUND Can not find the specific root bridge device.
    632   @retval other         Failed to determine the root bridge device's attribute.
    633 
    634 **/
    635 EFI_STATUS
    636 PciHostBridgeDeviceAttribute (
    637   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
    638   )
    639 {
    640   EFI_HANDLE    RootBridgeHandle;
    641   PCI_IO_DEVICE *RootBridgeDev;
    642   EFI_STATUS    Status;
    643 
    644   RootBridgeHandle = NULL;
    645 
    646   while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
    647 
    648     //
    649     // Get RootBridg Device by handle
    650     //
    651     RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
    652 
    653     if (RootBridgeDev == NULL) {
    654       return EFI_NOT_FOUND;
    655     }
    656 
    657     //
    658     // Set the attributes for devcies behind the Root Bridge
    659     //
    660     Status = DetermineDeviceAttribute (RootBridgeDev);
    661     if (EFI_ERROR (Status)) {
    662       return Status;
    663     }
    664 
    665   }
    666 
    667   return EFI_SUCCESS;
    668 }
    669 
    670 /**
    671   Get resource allocation status from the ACPI resource descriptor.
    672 
    673   @param AcpiConfig       Point to Acpi configuration table.
    674   @param IoResStatus      Return the status of I/O resource.
    675   @param Mem32ResStatus   Return the status of 32-bit Memory resource.
    676   @param PMem32ResStatus  Return the status of 32-bit Prefetchable Memory resource.
    677   @param Mem64ResStatus   Return the status of 64-bit Memory resource.
    678   @param PMem64ResStatus  Return the status of 64-bit Prefetchable Memory resource.
    679 
    680 **/
    681 VOID
    682 GetResourceAllocationStatus (
    683   VOID        *AcpiConfig,
    684   OUT UINT64  *IoResStatus,
    685   OUT UINT64  *Mem32ResStatus,
    686   OUT UINT64  *PMem32ResStatus,
    687   OUT UINT64  *Mem64ResStatus,
    688   OUT UINT64  *PMem64ResStatus
    689   )
    690 {
    691   UINT8                             *Temp;
    692   UINT64                            ResStatus;
    693   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *ACPIAddressDesc;
    694 
    695   Temp = (UINT8 *) AcpiConfig;
    696 
    697   while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
    698 
    699     ACPIAddressDesc       = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;
    700     ResStatus = ACPIAddressDesc->AddrTranslationOffset;
    701 
    702     switch (ACPIAddressDesc->ResType) {
    703     case 0:
    704       if (ACPIAddressDesc->AddrSpaceGranularity == 32) {
    705         if (ACPIAddressDesc->SpecificFlag == 0x06) {
    706           //
    707           // Pmem32
    708           //
    709           *PMem32ResStatus = ResStatus;
    710         } else {
    711           //
    712           // Mem32
    713           //
    714           *Mem32ResStatus = ResStatus;
    715         }
    716       }
    717 
    718       if (ACPIAddressDesc->AddrSpaceGranularity == 64) {
    719         if (ACPIAddressDesc->SpecificFlag == 0x06) {
    720           //
    721           // PMem64
    722           //
    723           *PMem64ResStatus = ResStatus;
    724         } else {
    725           //
    726           // Mem64
    727           //
    728           *Mem64ResStatus = ResStatus;
    729         }
    730       }
    731 
    732       break;
    733 
    734     case 1:
    735       //
    736       // Io
    737       //
    738       *IoResStatus = ResStatus;
    739       break;
    740 
    741     default:
    742       break;
    743     }
    744 
    745     Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
    746   }
    747 }
    748 
    749 /**
    750   Remove a PCI device from device pool and mark its bar.
    751 
    752   @param PciDevice Instance of Pci device.
    753 
    754   @retval EFI_SUCCESS Successfully remove the PCI device.
    755   @retval EFI_ABORTED Pci device is a root bridge or a PCI-PCI bridge.
    756 
    757 **/
    758 EFI_STATUS
    759 RejectPciDevice (
    760   IN PCI_IO_DEVICE       *PciDevice
    761   )
    762 {
    763   PCI_IO_DEVICE   *Bridge;
    764   PCI_IO_DEVICE   *Temp;
    765   LIST_ENTRY      *CurrentLink;
    766 
    767   //
    768   // Remove the padding resource from a bridge
    769   //
    770   if ( IS_PCI_BRIDGE(&PciDevice->Pci) &&
    771        PciDevice->ResourcePaddingDescriptors != NULL ) {
    772     FreePool (PciDevice->ResourcePaddingDescriptors);
    773     PciDevice->ResourcePaddingDescriptors = NULL;
    774     return EFI_SUCCESS;
    775   }
    776 
    777   //
    778   // Skip RB and PPB
    779   //
    780   if (IS_PCI_BRIDGE (&PciDevice->Pci) || (PciDevice->Parent == NULL)) {
    781     return EFI_ABORTED;
    782   }
    783 
    784   if (IS_CARDBUS_BRIDGE (&PciDevice->Pci)) {
    785     //
    786     // Get the root bridge device
    787     //
    788     Bridge = PciDevice;
    789     while (Bridge->Parent != NULL) {
    790       Bridge = Bridge->Parent;
    791     }
    792 
    793     RemoveAllPciDeviceOnBridge (Bridge->Handle, PciDevice);
    794 
    795     //
    796     // Mark its bar
    797     //
    798     InitializeP2C (PciDevice);
    799   }
    800 
    801   //
    802   // Remove the device
    803   //
    804   Bridge      = PciDevice->Parent;
    805   CurrentLink = Bridge->ChildList.ForwardLink;
    806   while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {
    807     Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
    808     if (Temp == PciDevice) {
    809       InitializePciDevice (Temp);
    810       RemoveEntryList (CurrentLink);
    811       return EFI_SUCCESS;
    812     }
    813 
    814     CurrentLink = CurrentLink->ForwardLink;
    815   }
    816 
    817   return EFI_ABORTED;
    818 }
    819 
    820 /**
    821   Determine whethter a PCI device can be rejected.
    822 
    823   @param  PciResNode Pointer to Pci resource node instance.
    824 
    825   @retval TRUE  The PCI device can be rejected.
    826   @retval TRUE  The PCI device cannot be rejected.
    827 
    828 **/
    829 BOOLEAN
    830 IsRejectiveDevice (
    831   IN  PCI_RESOURCE_NODE   *PciResNode
    832   )
    833 {
    834   PCI_IO_DEVICE *Temp;
    835 
    836   Temp = PciResNode->PciDev;
    837 
    838   //
    839   // Ensure the device is present
    840   //
    841   if (Temp == NULL) {
    842     return FALSE;
    843   }
    844 
    845   //
    846   // PPB and RB should go ahead
    847   //
    848   if (IS_PCI_BRIDGE (&Temp->Pci) || (Temp->Parent == NULL)) {
    849     return TRUE;
    850   }
    851 
    852   //
    853   // Skip device on Bus0
    854   //
    855   if ((Temp->Parent != NULL) && (Temp->BusNumber == 0)) {
    856     return FALSE;
    857   }
    858 
    859   //
    860   // Skip VGA
    861   //
    862   if (IS_PCI_VGA (&Temp->Pci)) {
    863     return FALSE;
    864   }
    865 
    866   return TRUE;
    867 }
    868 
    869 /**
    870   Compare two resource nodes and get the larger resource consumer.
    871 
    872   @param PciResNode1  resource node 1 want to be compared
    873   @param PciResNode2  resource node 2 want to be compared
    874 
    875   @return Larger resource node.
    876 
    877 **/
    878 PCI_RESOURCE_NODE *
    879 GetLargerConsumerDevice (
    880   IN  PCI_RESOURCE_NODE   *PciResNode1,
    881   IN  PCI_RESOURCE_NODE   *PciResNode2
    882   )
    883 {
    884   if (PciResNode2 == NULL) {
    885     return PciResNode1;
    886   }
    887 
    888   if ((IS_PCI_BRIDGE(&(PciResNode2->PciDev->Pci)) || (PciResNode2->PciDev->Parent == NULL)) \
    889        && (PciResNode2->ResourceUsage != PciResUsagePadding) )
    890   {
    891     return PciResNode1;
    892   }
    893 
    894   if (PciResNode1 == NULL) {
    895     return PciResNode2;
    896   }
    897 
    898   if ((PciResNode1->Length) > (PciResNode2->Length)) {
    899     return PciResNode1;
    900   }
    901 
    902   return PciResNode2;
    903 }
    904 
    905 
    906 /**
    907   Get the max resource consumer in the host resource pool.
    908 
    909   @param ResPool  Pointer to resource pool node.
    910 
    911   @return The max resource consumer in the host resource pool.
    912 
    913 **/
    914 PCI_RESOURCE_NODE *
    915 GetMaxResourceConsumerDevice (
    916   IN  PCI_RESOURCE_NODE   *ResPool
    917   )
    918 {
    919   PCI_RESOURCE_NODE *Temp;
    920   LIST_ENTRY        *CurrentLink;
    921   PCI_RESOURCE_NODE *PciResNode;
    922   PCI_RESOURCE_NODE *PPBResNode;
    923 
    924   PciResNode  = NULL;
    925 
    926   CurrentLink = ResPool->ChildList.ForwardLink;
    927   while (CurrentLink != NULL && CurrentLink != &ResPool->ChildList) {
    928 
    929     Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
    930 
    931     if (!IsRejectiveDevice (Temp)) {
    932       CurrentLink = CurrentLink->ForwardLink;
    933       continue;
    934     }
    935 
    936     if ((IS_PCI_BRIDGE (&(Temp->PciDev->Pci)) || (Temp->PciDev->Parent == NULL)) \
    937           && (Temp->ResourceUsage != PciResUsagePadding))
    938     {
    939       PPBResNode  = GetMaxResourceConsumerDevice (Temp);
    940       PciResNode  = GetLargerConsumerDevice (PciResNode, PPBResNode);
    941     } else {
    942       PciResNode = GetLargerConsumerDevice (PciResNode, Temp);
    943     }
    944 
    945     CurrentLink = CurrentLink->ForwardLink;
    946   }
    947 
    948   return PciResNode;
    949 }
    950 
    951 /**
    952   Adjust host bridge allocation so as to reduce resource requirement
    953 
    954   @param IoPool           Pointer to instance of I/O resource Node.
    955   @param Mem32Pool        Pointer to instance of 32-bit memory resource Node.
    956   @param PMem32Pool       Pointer to instance of 32-bit Prefetchable memory resource node.
    957   @param Mem64Pool        Pointer to instance of 64-bit memory resource node.
    958   @param PMem64Pool       Pointer to instance of 64-bit Prefetchable memory resource node.
    959   @param IoResStatus      Status of I/O resource Node.
    960   @param Mem32ResStatus   Status of 32-bit memory resource Node.
    961   @param PMem32ResStatus  Status of 32-bit Prefetchable memory resource node.
    962   @param Mem64ResStatus   Status of 64-bit memory resource node.
    963   @param PMem64ResStatus  Status of 64-bit Prefetchable memory resource node.
    964 
    965   @retval EFI_SUCCESS     Successfully adjusted resource on host bridge.
    966   @retval EFI_ABORTED     Host bridge hasn't this resource type or no resource be adjusted.
    967 
    968 **/
    969 EFI_STATUS
    970 PciHostBridgeAdjustAllocation (
    971   IN  PCI_RESOURCE_NODE   *IoPool,
    972   IN  PCI_RESOURCE_NODE   *Mem32Pool,
    973   IN  PCI_RESOURCE_NODE   *PMem32Pool,
    974   IN  PCI_RESOURCE_NODE   *Mem64Pool,
    975   IN  PCI_RESOURCE_NODE   *PMem64Pool,
    976   IN  UINT64              IoResStatus,
    977   IN  UINT64              Mem32ResStatus,
    978   IN  UINT64              PMem32ResStatus,
    979   IN  UINT64              Mem64ResStatus,
    980   IN  UINT64              PMem64ResStatus
    981   )
    982 {
    983   BOOLEAN                               AllocationAjusted;
    984   PCI_RESOURCE_NODE                     *PciResNode;
    985   PCI_RESOURCE_NODE                     *ResPool[5];
    986   PCI_IO_DEVICE                         *RemovedPciDev[5];
    987   UINT64                                ResStatus[5];
    988   UINTN                                 RemovedPciDevNum;
    989   UINTN                                 DevIndex;
    990   UINTN                                 ResType;
    991   EFI_STATUS                            Status;
    992   EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData;
    993 
    994   PciResNode = NULL;
    995   ZeroMem (RemovedPciDev, 5 * sizeof (PCI_IO_DEVICE *));
    996   RemovedPciDevNum  = 0;
    997 
    998   ResPool[0]        = IoPool;
    999   ResPool[1]        = Mem32Pool;
   1000   ResPool[2]        = PMem32Pool;
   1001   ResPool[3]        = Mem64Pool;
   1002   ResPool[4]        = PMem64Pool;
   1003 
   1004   ResStatus[0]      = IoResStatus;
   1005   ResStatus[1]      = Mem32ResStatus;
   1006   ResStatus[2]      = PMem32ResStatus;
   1007   ResStatus[3]      = Mem64ResStatus;
   1008   ResStatus[4]      = PMem64ResStatus;
   1009 
   1010   AllocationAjusted = FALSE;
   1011 
   1012   for (ResType = 0; ResType < 5; ResType++) {
   1013 
   1014     if (ResStatus[ResType] == EFI_RESOURCE_SATISFIED) {
   1015       continue;
   1016     }
   1017 
   1018     if (ResStatus[ResType] == EFI_RESOURCE_NOT_SATISFIED) {
   1019       //
   1020       // Host bridge hasn't this resource type
   1021       //
   1022       return EFI_ABORTED;
   1023     }
   1024 
   1025     //
   1026     // Hostbridge hasn't enough resource
   1027     //
   1028     PciResNode = GetMaxResourceConsumerDevice (ResPool[ResType]);
   1029     if (PciResNode == NULL) {
   1030       continue;
   1031     }
   1032 
   1033     //
   1034     // Check if the device has been removed before
   1035     //
   1036     for (DevIndex = 0; DevIndex < RemovedPciDevNum; DevIndex++) {
   1037       if (PciResNode->PciDev == RemovedPciDev[DevIndex]) {
   1038         break;
   1039       }
   1040     }
   1041 
   1042     if (DevIndex != RemovedPciDevNum) {
   1043       continue;
   1044     }
   1045 
   1046     //
   1047     // Remove the device if it isn't in the array
   1048     //
   1049     Status = RejectPciDevice (PciResNode->PciDev);
   1050     if (Status == EFI_SUCCESS) {
   1051       DEBUG ((
   1052         EFI_D_ERROR,
   1053         "PciBus: [%02x|%02x|%02x] was rejected due to resource confliction.\n",
   1054         PciResNode->PciDev->BusNumber, PciResNode->PciDev->DeviceNumber, PciResNode->PciDev->FunctionNumber
   1055         ));
   1056 
   1057       //
   1058       // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
   1059       //
   1060       //
   1061       // Have no way to get ReqRes, AllocRes & Bar here
   1062       //
   1063       ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData));
   1064       AllocFailExtendedData.DevicePathSize = (UINT16) sizeof (EFI_DEVICE_PATH_PROTOCOL);
   1065       AllocFailExtendedData.DevicePath     = (UINT8 *) PciResNode->PciDev->DevicePath;
   1066       AllocFailExtendedData.Bar            = PciResNode->Bar;
   1067 
   1068       REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
   1069             EFI_PROGRESS_CODE,
   1070             EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT,
   1071             (VOID *) &AllocFailExtendedData,
   1072             sizeof (AllocFailExtendedData)
   1073             );
   1074 
   1075       //
   1076       // Add it to the array and indicate at least a device has been rejected
   1077       //
   1078       RemovedPciDev[RemovedPciDevNum++] = PciResNode->PciDev;
   1079       AllocationAjusted                 = TRUE;
   1080     }
   1081   }
   1082   //
   1083   // End for
   1084   //
   1085 
   1086   if (AllocationAjusted) {
   1087     return EFI_SUCCESS;
   1088   } else {
   1089     return EFI_ABORTED;
   1090   }
   1091 }
   1092 
   1093 /**
   1094   Summary requests for all resource type, and construct ACPI resource
   1095   requestor instance.
   1096 
   1097   @param Bridge           detecting bridge
   1098   @param IoNode           Pointer to instance of I/O resource Node
   1099   @param Mem32Node        Pointer to instance of 32-bit memory resource Node
   1100   @param PMem32Node       Pointer to instance of 32-bit Pmemory resource node
   1101   @param Mem64Node        Pointer to instance of 64-bit memory resource node
   1102   @param PMem64Node       Pointer to instance of 64-bit Pmemory resource node
   1103   @param Config           Output buffer holding new constructed APCI resource requestor
   1104 
   1105   @retval EFI_SUCCESS           Successfully constructed ACPI resource.
   1106   @retval EFI_OUT_OF_RESOURCES  No memory available.
   1107 
   1108 **/
   1109 EFI_STATUS
   1110 ConstructAcpiResourceRequestor (
   1111   IN PCI_IO_DEVICE      *Bridge,
   1112   IN PCI_RESOURCE_NODE  *IoNode,
   1113   IN PCI_RESOURCE_NODE  *Mem32Node,
   1114   IN PCI_RESOURCE_NODE  *PMem32Node,
   1115   IN PCI_RESOURCE_NODE  *Mem64Node,
   1116   IN PCI_RESOURCE_NODE  *PMem64Node,
   1117   OUT VOID              **Config
   1118   )
   1119 {
   1120   UINT8                             NumConfig;
   1121   UINT8                             Aperture;
   1122   UINT8                             *Configuration;
   1123   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
   1124   EFI_ACPI_END_TAG_DESCRIPTOR       *PtrEnd;
   1125 
   1126   NumConfig = 0;
   1127   Aperture  = 0;
   1128 
   1129   *Config  = NULL;
   1130 
   1131   //
   1132   // if there is io request, add to the io aperture
   1133   //
   1134   if (ResourceRequestExisted (IoNode)) {
   1135     NumConfig++;
   1136     Aperture |= 0x01;
   1137   }
   1138 
   1139   //
   1140   // if there is mem32 request, add to the mem32 aperture
   1141   //
   1142   if (ResourceRequestExisted (Mem32Node)) {
   1143     NumConfig++;
   1144     Aperture |= 0x02;
   1145   }
   1146 
   1147   //
   1148   // if there is pmem32 request, add to the pmem32 aperture
   1149   //
   1150   if (ResourceRequestExisted (PMem32Node)) {
   1151     NumConfig++;
   1152     Aperture |= 0x04;
   1153   }
   1154 
   1155   //
   1156   // if there is mem64 request, add to the mem64 aperture
   1157   //
   1158   if (ResourceRequestExisted (Mem64Node)) {
   1159     NumConfig++;
   1160     Aperture |= 0x08;
   1161   }
   1162 
   1163   //
   1164   // if there is pmem64 request, add to the pmem64 aperture
   1165   //
   1166   if (ResourceRequestExisted (PMem64Node)) {
   1167     NumConfig++;
   1168     Aperture |= 0x10;
   1169   }
   1170 
   1171   if (NumConfig != 0) {
   1172 
   1173     //
   1174     // If there is at least one type of resource request,
   1175     // allocate a acpi resource node
   1176     //
   1177     Configuration = AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
   1178     if (Configuration == NULL) {
   1179       return EFI_OUT_OF_RESOURCES;
   1180     }
   1181 
   1182     Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
   1183 
   1184     //
   1185     // Deal with io aperture
   1186     //
   1187     if ((Aperture & 0x01) != 0) {
   1188       Ptr->Desc     = ACPI_ADDRESS_SPACE_DESCRIPTOR;
   1189       Ptr->Len      = (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3);
   1190       //
   1191       // Io
   1192       //
   1193       Ptr->ResType  = ACPI_ADDRESS_SPACE_TYPE_IO;
   1194       //
   1195       // non ISA range
   1196       //
   1197       Ptr->SpecificFlag = 1;
   1198       Ptr->AddrLen      = IoNode->Length;
   1199       Ptr->AddrRangeMax = IoNode->Alignment;
   1200 
   1201       Ptr++;
   1202     }
   1203     //
   1204     // Deal with mem32 aperture
   1205     //
   1206     if ((Aperture & 0x02) != 0) {
   1207       Ptr->Desc     = ACPI_ADDRESS_SPACE_DESCRIPTOR;
   1208       Ptr->Len      = (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3);
   1209       //
   1210       // Mem
   1211       //
   1212       Ptr->ResType  = ACPI_ADDRESS_SPACE_TYPE_MEM;
   1213       //
   1214       // Nonprefechable
   1215       //
   1216       Ptr->SpecificFlag = 0;
   1217       //
   1218       // 32 bit
   1219       //
   1220       Ptr->AddrSpaceGranularity = 32;
   1221       Ptr->AddrLen      = Mem32Node->Length;
   1222       Ptr->AddrRangeMax = Mem32Node->Alignment;
   1223 
   1224       Ptr++;
   1225     }
   1226 
   1227     //
   1228     // Deal with Pmem32 aperture
   1229     //
   1230     if ((Aperture & 0x04) != 0) {
   1231       Ptr->Desc     = ACPI_ADDRESS_SPACE_DESCRIPTOR;
   1232       Ptr->Len      = (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3);
   1233       //
   1234       // Mem
   1235       //
   1236       Ptr->ResType  = ACPI_ADDRESS_SPACE_TYPE_MEM;
   1237       //
   1238       // prefechable
   1239       //
   1240       Ptr->SpecificFlag = 0x6;
   1241       //
   1242       // 32 bit
   1243       //
   1244       Ptr->AddrSpaceGranularity = 32;
   1245       Ptr->AddrLen      = PMem32Node->Length;
   1246       Ptr->AddrRangeMax = PMem32Node->Alignment;
   1247 
   1248       Ptr++;
   1249     }
   1250     //
   1251     // Deal with mem64 aperture
   1252     //
   1253     if ((Aperture & 0x08) != 0) {
   1254       Ptr->Desc     = ACPI_ADDRESS_SPACE_DESCRIPTOR;
   1255       Ptr->Len      = (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3);
   1256       //
   1257       // Mem
   1258       //
   1259       Ptr->ResType  = ACPI_ADDRESS_SPACE_TYPE_MEM;
   1260       //
   1261       // nonprefechable
   1262       //
   1263       Ptr->SpecificFlag = 0;
   1264       //
   1265       // 64 bit
   1266       //
   1267       Ptr->AddrSpaceGranularity = 64;
   1268       Ptr->AddrLen      = Mem64Node->Length;
   1269       Ptr->AddrRangeMax = Mem64Node->Alignment;
   1270 
   1271       Ptr++;
   1272     }
   1273     //
   1274     // Deal with Pmem64 aperture
   1275     //
   1276     if ((Aperture & 0x10) != 0) {
   1277       Ptr->Desc     = ACPI_ADDRESS_SPACE_DESCRIPTOR;
   1278       Ptr->Len      = (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3);
   1279       //
   1280       // Mem
   1281       //
   1282       Ptr->ResType  = ACPI_ADDRESS_SPACE_TYPE_MEM;
   1283       //
   1284       // prefechable
   1285       //
   1286       Ptr->SpecificFlag = 0x06;
   1287       //
   1288       // 64 bit
   1289       //
   1290       Ptr->AddrSpaceGranularity = 64;
   1291       Ptr->AddrLen      = PMem64Node->Length;
   1292       Ptr->AddrRangeMax = PMem64Node->Alignment;
   1293 
   1294       Ptr++;
   1295     }
   1296 
   1297     //
   1298     // put the checksum
   1299     //
   1300     PtrEnd            = (EFI_ACPI_END_TAG_DESCRIPTOR *) Ptr;
   1301 
   1302     PtrEnd->Desc      = ACPI_END_TAG_DESCRIPTOR;
   1303     PtrEnd->Checksum  = 0;
   1304 
   1305   } else {
   1306 
   1307     //
   1308     // If there is no resource request
   1309     //
   1310     Configuration = AllocateZeroPool (sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
   1311     if (Configuration == NULL) {
   1312       return EFI_OUT_OF_RESOURCES;
   1313     }
   1314 
   1315     PtrEnd            = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Configuration);
   1316     PtrEnd->Desc      = ACPI_END_TAG_DESCRIPTOR;
   1317     PtrEnd->Checksum  = 0;
   1318   }
   1319 
   1320   *Config = Configuration;
   1321 
   1322   return EFI_SUCCESS;
   1323 }
   1324 
   1325 /**
   1326   Get resource base from an acpi configuration descriptor.
   1327 
   1328   @param Config       An acpi configuration descriptor.
   1329   @param IoBase       Output of I/O resource base address.
   1330   @param Mem32Base    Output of 32-bit memory base address.
   1331   @param PMem32Base   Output of 32-bit prefetchable memory base address.
   1332   @param Mem64Base    Output of 64-bit memory base address.
   1333   @param PMem64Base   Output of 64-bit prefetchable memory base address.
   1334 
   1335 **/
   1336 VOID
   1337 GetResourceBase (
   1338   IN VOID     *Config,
   1339   OUT UINT64  *IoBase,
   1340   OUT UINT64  *Mem32Base,
   1341   OUT UINT64  *PMem32Base,
   1342   OUT UINT64  *Mem64Base,
   1343   OUT UINT64  *PMem64Base
   1344   )
   1345 {
   1346   UINT8                             *Temp;
   1347   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
   1348   UINT64                            ResStatus;
   1349 
   1350   ASSERT (Config != NULL);
   1351 
   1352   *IoBase     = 0xFFFFFFFFFFFFFFFFULL;
   1353   *Mem32Base  = 0xFFFFFFFFFFFFFFFFULL;
   1354   *PMem32Base = 0xFFFFFFFFFFFFFFFFULL;
   1355   *Mem64Base  = 0xFFFFFFFFFFFFFFFFULL;
   1356   *PMem64Base = 0xFFFFFFFFFFFFFFFFULL;
   1357 
   1358   Temp        = (UINT8 *) Config;
   1359 
   1360   while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
   1361 
   1362     Ptr       = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;
   1363     ResStatus = Ptr->AddrTranslationOffset;
   1364 
   1365     if (ResStatus == EFI_RESOURCE_SATISFIED) {
   1366 
   1367       switch (Ptr->ResType) {
   1368 
   1369       //
   1370       // Memory type aperture
   1371       //
   1372       case 0:
   1373 
   1374         //
   1375         // Check to see the granularity
   1376         //
   1377         if (Ptr->AddrSpaceGranularity == 32) {
   1378           if ((Ptr->SpecificFlag & 0x06) != 0) {
   1379             *PMem32Base = Ptr->AddrRangeMin;
   1380           } else {
   1381             *Mem32Base = Ptr->AddrRangeMin;
   1382           }
   1383         }
   1384 
   1385         if (Ptr->AddrSpaceGranularity == 64) {
   1386           if ((Ptr->SpecificFlag & 0x06) != 0) {
   1387             *PMem64Base = Ptr->AddrRangeMin;
   1388           } else {
   1389             *Mem64Base = Ptr->AddrRangeMin;
   1390           }
   1391         }
   1392         break;
   1393 
   1394       case 1:
   1395 
   1396         //
   1397         // Io type aperture
   1398         //
   1399         *IoBase = Ptr->AddrRangeMin;
   1400         break;
   1401 
   1402       default:
   1403         break;
   1404 
   1405       }
   1406       //
   1407       // End switch
   1408       //
   1409     }
   1410     //
   1411     // End for
   1412     //
   1413     Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
   1414   }
   1415 }
   1416 
   1417 /**
   1418   Enumerate pci bridge, allocate resource and determine attribute
   1419   for devices on this bridge.
   1420 
   1421   @param BridgeDev    Pointer to instance of bridge device.
   1422 
   1423   @retval EFI_SUCCESS Successfully enumerated PCI bridge.
   1424   @retval other       Failed to enumerate.
   1425 
   1426 **/
   1427 EFI_STATUS
   1428 PciBridgeEnumerator (
   1429   IN PCI_IO_DEVICE                                     *BridgeDev
   1430   )
   1431 {
   1432   UINT8               SubBusNumber;
   1433   UINT8               StartBusNumber;
   1434   EFI_PCI_IO_PROTOCOL *PciIo;
   1435   EFI_STATUS          Status;
   1436 
   1437   SubBusNumber    = 0;
   1438   StartBusNumber  = 0;
   1439   PciIo           = &(BridgeDev->PciIo);
   1440   Status          = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x19, 1, &StartBusNumber);
   1441 
   1442   if (EFI_ERROR (Status)) {
   1443     return Status;
   1444   }
   1445 
   1446   Status = PciAssignBusNumber (
   1447             BridgeDev,
   1448             StartBusNumber,
   1449             &SubBusNumber
   1450             );
   1451 
   1452   if (EFI_ERROR (Status)) {
   1453     return Status;
   1454   }
   1455 
   1456   Status = PciPciDeviceInfoCollector (BridgeDev, StartBusNumber);
   1457 
   1458   if (EFI_ERROR (Status)) {
   1459     return Status;
   1460   }
   1461 
   1462   Status = PciBridgeResourceAllocator (BridgeDev);
   1463 
   1464   if (EFI_ERROR (Status)) {
   1465     return Status;
   1466   }
   1467 
   1468   Status = DetermineDeviceAttribute (BridgeDev);
   1469 
   1470   if (EFI_ERROR (Status)) {
   1471     return Status;
   1472   }
   1473 
   1474   return EFI_SUCCESS;
   1475 
   1476 }
   1477 
   1478 /**
   1479   Allocate all kinds of resource for PCI bridge.
   1480 
   1481   @param  Bridge      Pointer to bridge instance.
   1482 
   1483   @retval EFI_SUCCESS Successfully allocated resource for PCI bridge.
   1484   @retval other       Failed to allocate resource for bridge.
   1485 
   1486 **/
   1487 EFI_STATUS
   1488 PciBridgeResourceAllocator (
   1489   IN PCI_IO_DEVICE  *Bridge
   1490   )
   1491 {
   1492   PCI_RESOURCE_NODE *IoBridge;
   1493   PCI_RESOURCE_NODE *Mem32Bridge;
   1494   PCI_RESOURCE_NODE *PMem32Bridge;
   1495   PCI_RESOURCE_NODE *Mem64Bridge;
   1496   PCI_RESOURCE_NODE *PMem64Bridge;
   1497   UINT64            IoBase;
   1498   UINT64            Mem32Base;
   1499   UINT64            PMem32Base;
   1500   UINT64            Mem64Base;
   1501   UINT64            PMem64Base;
   1502   EFI_STATUS        Status;
   1503 
   1504   IoBridge = CreateResourceNode (
   1505                Bridge,
   1506                0,
   1507                Bridge->BridgeIoAlignment,
   1508                0,
   1509                PciBarTypeIo16,
   1510                PciResUsageTypical
   1511                );
   1512 
   1513   Mem32Bridge = CreateResourceNode (
   1514                   Bridge,
   1515                   0,
   1516                   0xFFFFF,
   1517                   0,
   1518                   PciBarTypeMem32,
   1519                   PciResUsageTypical
   1520                   );
   1521 
   1522   PMem32Bridge = CreateResourceNode (
   1523                    Bridge,
   1524                    0,
   1525                    0xFFFFF,
   1526                    0,
   1527                    PciBarTypePMem32,
   1528                    PciResUsageTypical
   1529                    );
   1530 
   1531   Mem64Bridge = CreateResourceNode (
   1532                   Bridge,
   1533                   0,
   1534                   0xFFFFF,
   1535                   0,
   1536                   PciBarTypeMem64,
   1537                   PciResUsageTypical
   1538                   );
   1539 
   1540   PMem64Bridge = CreateResourceNode (
   1541                    Bridge,
   1542                    0,
   1543                    0xFFFFF,
   1544                    0,
   1545                    PciBarTypePMem64,
   1546                    PciResUsageTypical
   1547                    );
   1548 
   1549   //
   1550   // Create resourcemap by going through all the devices subject to this root bridge
   1551   //
   1552   CreateResourceMap (
   1553     Bridge,
   1554     IoBridge,
   1555     Mem32Bridge,
   1556     PMem32Bridge,
   1557     Mem64Bridge,
   1558     PMem64Bridge
   1559     );
   1560 
   1561   Status = GetResourceBaseFromBridge (
   1562              Bridge,
   1563              &IoBase,
   1564              &Mem32Base,
   1565              &PMem32Base,
   1566              &Mem64Base,
   1567              &PMem64Base
   1568              );
   1569 
   1570   if (EFI_ERROR (Status)) {
   1571     return Status;
   1572   }
   1573 
   1574   //
   1575   // Program IO resources
   1576   //
   1577   ProgramResource (
   1578     IoBase,
   1579     IoBridge
   1580     );
   1581 
   1582   //
   1583   // Program Mem32 resources
   1584   //
   1585   ProgramResource (
   1586     Mem32Base,
   1587     Mem32Bridge
   1588     );
   1589 
   1590   //
   1591   // Program PMem32 resources
   1592   //
   1593   ProgramResource (
   1594     PMem32Base,
   1595     PMem32Bridge
   1596     );
   1597 
   1598   //
   1599   // Program Mem64 resources
   1600   //
   1601   ProgramResource (
   1602     Mem64Base,
   1603     Mem64Bridge
   1604     );
   1605 
   1606   //
   1607   // Program PMem64 resources
   1608   //
   1609   ProgramResource (
   1610     PMem64Base,
   1611     PMem64Bridge
   1612     );
   1613 
   1614   DestroyResourceTree (IoBridge);
   1615   DestroyResourceTree (Mem32Bridge);
   1616   DestroyResourceTree (PMem32Bridge);
   1617   DestroyResourceTree (PMem64Bridge);
   1618   DestroyResourceTree (Mem64Bridge);
   1619 
   1620   gBS->FreePool (IoBridge);
   1621   gBS->FreePool (Mem32Bridge);
   1622   gBS->FreePool (PMem32Bridge);
   1623   gBS->FreePool (PMem64Bridge);
   1624   gBS->FreePool (Mem64Bridge);
   1625 
   1626   return EFI_SUCCESS;
   1627 }
   1628 
   1629 /**
   1630   Get resource base address for a pci bridge device.
   1631 
   1632   @param Bridge     Given Pci driver instance.
   1633   @param IoBase     Output for base address of I/O type resource.
   1634   @param Mem32Base  Output for base address of 32-bit memory type resource.
   1635   @param PMem32Base Ooutput for base address of 32-bit Pmemory type resource.
   1636   @param Mem64Base  Output for base address of 64-bit memory type resource.
   1637   @param PMem64Base Output for base address of 64-bit Pmemory type resource.
   1638 
   1639   @retval EFI_SUCCESS           Successfully got resource base address.
   1640   @retval EFI_OUT_OF_RESOURCES  PCI bridge is not available.
   1641 
   1642 **/
   1643 EFI_STATUS
   1644 GetResourceBaseFromBridge (
   1645   IN  PCI_IO_DEVICE *Bridge,
   1646   OUT UINT64        *IoBase,
   1647   OUT UINT64        *Mem32Base,
   1648   OUT UINT64        *PMem32Base,
   1649   OUT UINT64        *Mem64Base,
   1650   OUT UINT64        *PMem64Base
   1651   )
   1652 {
   1653   if (!Bridge->Allocated) {
   1654     return EFI_OUT_OF_RESOURCES;
   1655   }
   1656 
   1657   *IoBase     = gAllOne;
   1658   *Mem32Base  = gAllOne;
   1659   *PMem32Base = gAllOne;
   1660   *Mem64Base  = gAllOne;
   1661   *PMem64Base = gAllOne;
   1662 
   1663   if (IS_PCI_BRIDGE (&Bridge->Pci)) {
   1664 
   1665     if (Bridge->PciBar[PPB_IO_RANGE].Length > 0) {
   1666       *IoBase = Bridge->PciBar[PPB_IO_RANGE].BaseAddress;
   1667     }
   1668 
   1669     if (Bridge->PciBar[PPB_MEM32_RANGE].Length > 0) {
   1670       *Mem32Base = Bridge->PciBar[PPB_MEM32_RANGE].BaseAddress;
   1671     }
   1672 
   1673     if (Bridge->PciBar[PPB_PMEM32_RANGE].Length > 0) {
   1674       *PMem32Base = Bridge->PciBar[PPB_PMEM32_RANGE].BaseAddress;
   1675     }
   1676 
   1677     if (Bridge->PciBar[PPB_PMEM64_RANGE].Length > 0) {
   1678       *PMem64Base = Bridge->PciBar[PPB_PMEM64_RANGE].BaseAddress;
   1679     } else {
   1680       *PMem64Base = gAllOne;
   1681     }
   1682 
   1683   }
   1684 
   1685   if (IS_CARDBUS_BRIDGE (&Bridge->Pci)) {
   1686     if (Bridge->PciBar[P2C_IO_1].Length > 0) {
   1687       *IoBase = Bridge->PciBar[P2C_IO_1].BaseAddress;
   1688     } else {
   1689       if (Bridge->PciBar[P2C_IO_2].Length > 0) {
   1690         *IoBase = Bridge->PciBar[P2C_IO_2].BaseAddress;
   1691       }
   1692     }
   1693 
   1694     if (Bridge->PciBar[P2C_MEM_1].Length > 0) {
   1695       if (Bridge->PciBar[P2C_MEM_1].BarType == PciBarTypePMem32) {
   1696         *PMem32Base = Bridge->PciBar[P2C_MEM_1].BaseAddress;
   1697       }
   1698 
   1699       if (Bridge->PciBar[P2C_MEM_1].BarType == PciBarTypeMem32) {
   1700         *Mem32Base = Bridge->PciBar[P2C_MEM_1].BaseAddress;
   1701       }
   1702     }
   1703 
   1704     if (Bridge->PciBar[P2C_MEM_2].Length > 0) {
   1705       if (Bridge->PciBar[P2C_MEM_2].BarType == PciBarTypePMem32) {
   1706         *PMem32Base = Bridge->PciBar[P2C_MEM_2].BaseAddress;
   1707       }
   1708 
   1709       if (Bridge->PciBar[P2C_MEM_2].BarType == PciBarTypeMem32) {
   1710         *Mem32Base = Bridge->PciBar[P2C_MEM_2].BaseAddress;
   1711       }
   1712     }
   1713   }
   1714 
   1715   return EFI_SUCCESS;
   1716 }
   1717 
   1718 /**
   1719    These are the notifications from the PCI bus driver that it is about to enter a certain
   1720    phase of the PCI enumeration process.
   1721 
   1722    This member function can be used to notify the host bridge driver to perform specific actions,
   1723    including any chipset-specific initialization, so that the chipset is ready to enter the next phase.
   1724    Eight notification points are defined at this time. See belows:
   1725    EfiPciHostBridgeBeginEnumeration       Resets the host bridge PCI apertures and internal data
   1726                                           structures. The PCI enumerator should issue this notification
   1727                                           before starting a fresh enumeration process. Enumeration cannot
   1728                                           be restarted after sending any other notification such as
   1729                                           EfiPciHostBridgeBeginBusAllocation.
   1730    EfiPciHostBridgeBeginBusAllocation     The bus allocation phase is about to begin. No specific action is
   1731                                           required here. This notification can be used to perform any
   1732                                           chipset-specific programming.
   1733    EfiPciHostBridgeEndBusAllocation       The bus allocation and bus programming phase is complete. No
   1734                                           specific action is required here. This notification can be used to
   1735                                           perform any chipset-specific programming.
   1736    EfiPciHostBridgeBeginResourceAllocation
   1737                                           The resource allocation phase is about to begin. No specific
   1738                                           action is required here. This notification can be used to perform
   1739                                           any chipset-specific programming.
   1740    EfiPciHostBridgeAllocateResources      Allocates resources per previously submitted requests for all the PCI
   1741                                           root bridges. These resource settings are returned on the next call to
   1742                                           GetProposedResources(). Before calling NotifyPhase() with a Phase of
   1743                                           EfiPciHostBridgeAllocateResource, the PCI bus enumerator is responsible
   1744                                           for gathering I/O and memory requests for
   1745                                           all the PCI root bridges and submitting these requests using
   1746                                           SubmitResources(). This function pads the resource amount
   1747                                           to suit the root bridge hardware, takes care of dependencies between
   1748                                           the PCI root bridges, and calls the Global Coherency Domain (GCD)
   1749                                           with the allocation request. In the case of padding, the allocated range
   1750                                           could be bigger than what was requested.
   1751    EfiPciHostBridgeSetResources           Programs the host bridge hardware to decode previously allocated
   1752                                           resources (proposed resources) for all the PCI root bridges. After the
   1753                                           hardware is programmed, reassigning resources will not be supported.
   1754                                           The bus settings are not affected.
   1755    EfiPciHostBridgeFreeResources          Deallocates resources that were previously allocated for all the PCI
   1756                                           root bridges and resets the I/O and memory apertures to their initial
   1757                                           state. The bus settings are not affected. If the request to allocate
   1758                                           resources fails, the PCI enumerator can use this notification to
   1759                                           deallocate previous resources, adjust the requests, and retry
   1760                                           allocation.
   1761    EfiPciHostBridgeEndResourceAllocation  The resource allocation phase is completed. No specific action is
   1762                                           required here. This notification can be used to perform any chipsetspecific
   1763                                           programming.
   1764 
   1765    @param[in] PciResAlloc         The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
   1766    @param[in] Phase               The phase during enumeration
   1767 
   1768    @retval EFI_NOT_READY          This phase cannot be entered at this time. For example, this error
   1769                                   is valid for a Phase of EfiPciHostBridgeAllocateResources if
   1770                                   SubmitResources() has not been called for one or more
   1771                                   PCI root bridges before this call
   1772    @retval EFI_DEVICE_ERROR       Programming failed due to a hardware error. This error is valid
   1773                                   for a Phase of EfiPciHostBridgeSetResources.
   1774    @retval EFI_INVALID_PARAMETER  Invalid phase parameter
   1775    @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
   1776                                   This error is valid for a Phase of EfiPciHostBridgeAllocateResources if the
   1777                                   previously submitted resource requests cannot be fulfilled or
   1778                                   were only partially fulfilled.
   1779    @retval EFI_SUCCESS            The notification was accepted without any errors.
   1780 
   1781 **/
   1782 EFI_STATUS
   1783 NotifyPhase (
   1784   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,
   1785   EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE       Phase
   1786   )
   1787 {
   1788   EFI_HANDLE                      HostBridgeHandle;
   1789   EFI_HANDLE                      RootBridgeHandle;
   1790   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
   1791   EFI_STATUS                      Status;
   1792 
   1793   HostBridgeHandle  = NULL;
   1794   RootBridgeHandle  = NULL;
   1795   if (gPciPlatformProtocol != NULL) {
   1796     //
   1797     // Get Host Bridge Handle.
   1798     //
   1799     PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle);
   1800 
   1801     //
   1802     // Get the rootbridge Io protocol to find the host bridge handle
   1803     //
   1804     Status = gBS->HandleProtocol (
   1805                     RootBridgeHandle,
   1806                     &gEfiPciRootBridgeIoProtocolGuid,
   1807                     (VOID **) &PciRootBridgeIo
   1808                     );
   1809 
   1810     if (EFI_ERROR (Status)) {
   1811       return EFI_NOT_FOUND;
   1812     }
   1813 
   1814     HostBridgeHandle = PciRootBridgeIo->ParentHandle;
   1815 
   1816     //
   1817     // Call PlatformPci::PlatformNotify() if the protocol is present.
   1818     //
   1819     gPciPlatformProtocol->PlatformNotify (
   1820                             gPciPlatformProtocol,
   1821                             HostBridgeHandle,
   1822                             Phase,
   1823                             ChipsetEntry
   1824                             );
   1825   } else if (gPciOverrideProtocol != NULL){
   1826     //
   1827     // Get Host Bridge Handle.
   1828     //
   1829     PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle);
   1830 
   1831     //
   1832     // Get the rootbridge Io protocol to find the host bridge handle
   1833     //
   1834     Status = gBS->HandleProtocol (
   1835                     RootBridgeHandle,
   1836                     &gEfiPciRootBridgeIoProtocolGuid,
   1837                     (VOID **) &PciRootBridgeIo
   1838                     );
   1839 
   1840     if (EFI_ERROR (Status)) {
   1841       return EFI_NOT_FOUND;
   1842     }
   1843 
   1844     HostBridgeHandle = PciRootBridgeIo->ParentHandle;
   1845 
   1846     //
   1847     // Call PlatformPci::PhaseNotify() if the protocol is present.
   1848     //
   1849     gPciOverrideProtocol->PlatformNotify (
   1850                             gPciOverrideProtocol,
   1851                             HostBridgeHandle,
   1852                             Phase,
   1853                             ChipsetEntry
   1854                             );
   1855   }
   1856 
   1857   Status = PciResAlloc->NotifyPhase (
   1858                           PciResAlloc,
   1859                           Phase
   1860                           );
   1861 
   1862   if (gPciPlatformProtocol != NULL) {
   1863     //
   1864     // Call PlatformPci::PlatformNotify() if the protocol is present.
   1865     //
   1866     gPciPlatformProtocol->PlatformNotify (
   1867                             gPciPlatformProtocol,
   1868                             HostBridgeHandle,
   1869                             Phase,
   1870                             ChipsetExit
   1871                             );
   1872 
   1873   } else if (gPciOverrideProtocol != NULL) {
   1874     //
   1875     // Call PlatformPci::PhaseNotify() if the protocol is present.
   1876     //
   1877     gPciOverrideProtocol->PlatformNotify (
   1878                             gPciOverrideProtocol,
   1879                             HostBridgeHandle,
   1880                             Phase,
   1881                             ChipsetExit
   1882                             );
   1883   }
   1884 
   1885   return Status;
   1886 }
   1887 
   1888 /**
   1889   Provides the hooks from the PCI bus driver to every PCI controller (device/function) at various
   1890   stages of the PCI enumeration process that allow the host bridge driver to preinitialize individual
   1891   PCI controllers before enumeration.
   1892 
   1893   This function is called during the PCI enumeration process. No specific action is expected from this
   1894   member function. It allows the host bridge driver to preinitialize individual PCI controllers before
   1895   enumeration.
   1896 
   1897   @param Bridge            Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
   1898   @param Bus               The bus number of the pci device.
   1899   @param Device            The device number of the pci device.
   1900   @param Func              The function number of the pci device.
   1901   @param Phase             The phase of the PCI device enumeration.
   1902 
   1903   @retval EFI_SUCCESS              The requested parameters were returned.
   1904   @retval EFI_INVALID_PARAMETER    RootBridgeHandle is not a valid root bridge handle.
   1905   @retval EFI_INVALID_PARAMETER    Phase is not a valid phase that is defined in
   1906                                    EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE.
   1907   @retval EFI_DEVICE_ERROR         Programming failed due to a hardware error. The PCI enumerator should
   1908                                    not enumerate this device, including its child devices if it is a PCI-to-PCI
   1909                                    bridge.
   1910 
   1911 **/
   1912 EFI_STATUS
   1913 PreprocessController (
   1914   IN PCI_IO_DEVICE                                    *Bridge,
   1915   IN UINT8                                            Bus,
   1916   IN UINT8                                            Device,
   1917   IN UINT8                                            Func,
   1918   IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE     Phase
   1919   )
   1920 {
   1921   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS       RootBridgePciAddress;
   1922   EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *PciResAlloc;
   1923   EFI_HANDLE                                        RootBridgeHandle;
   1924   EFI_HANDLE                                        HostBridgeHandle;
   1925   EFI_STATUS                                        Status;
   1926 
   1927   //
   1928   // Get the host bridge handle
   1929   //
   1930   HostBridgeHandle = Bridge->PciRootBridgeIo->ParentHandle;
   1931 
   1932   //
   1933   // Get the pci host bridge resource allocation protocol
   1934   //
   1935   Status = gBS->OpenProtocol (
   1936                   HostBridgeHandle,
   1937                   &gEfiPciHostBridgeResourceAllocationProtocolGuid,
   1938                   (VOID **) &PciResAlloc,
   1939                   NULL,
   1940                   NULL,
   1941                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
   1942                   );
   1943 
   1944   if (EFI_ERROR (Status)) {
   1945     return EFI_UNSUPPORTED;
   1946   }
   1947 
   1948   //
   1949   // Get Root Brige Handle
   1950   //
   1951   while (Bridge->Parent != NULL) {
   1952     Bridge = Bridge->Parent;
   1953   }
   1954 
   1955   RootBridgeHandle                      = Bridge->Handle;
   1956 
   1957   RootBridgePciAddress.Register         = 0;
   1958   RootBridgePciAddress.Function         = Func;
   1959   RootBridgePciAddress.Device           = Device;
   1960   RootBridgePciAddress.Bus              = Bus;
   1961   RootBridgePciAddress.ExtendedRegister = 0;
   1962 
   1963   if (gPciPlatformProtocol != NULL) {
   1964     //
   1965     // Call PlatformPci::PrepController() if the protocol is present.
   1966     //
   1967     gPciPlatformProtocol->PlatformPrepController (
   1968                             gPciPlatformProtocol,
   1969                             HostBridgeHandle,
   1970                             RootBridgeHandle,
   1971                             RootBridgePciAddress,
   1972                             Phase,
   1973                             ChipsetEntry
   1974                             );
   1975   } else if (gPciOverrideProtocol != NULL) {
   1976     //
   1977     // Call PlatformPci::PrepController() if the protocol is present.
   1978     //
   1979     gPciOverrideProtocol->PlatformPrepController (
   1980                             gPciOverrideProtocol,
   1981                             HostBridgeHandle,
   1982                             RootBridgeHandle,
   1983                             RootBridgePciAddress,
   1984                             Phase,
   1985                             ChipsetEntry
   1986                             );
   1987   }
   1988 
   1989   Status = PciResAlloc->PreprocessController (
   1990                           PciResAlloc,
   1991                           RootBridgeHandle,
   1992                           RootBridgePciAddress,
   1993                           Phase
   1994                           );
   1995 
   1996   if (gPciPlatformProtocol != NULL) {
   1997     //
   1998     // Call PlatformPci::PrepController() if the protocol is present.
   1999     //
   2000     gPciPlatformProtocol->PlatformPrepController (
   2001                             gPciPlatformProtocol,
   2002                             HostBridgeHandle,
   2003                             RootBridgeHandle,
   2004                             RootBridgePciAddress,
   2005                             Phase,
   2006                             ChipsetExit
   2007                             );
   2008   } else if (gPciOverrideProtocol != NULL) {
   2009     //
   2010     // Call PlatformPci::PrepController() if the protocol is present.
   2011     //
   2012     gPciOverrideProtocol->PlatformPrepController (
   2013                             gPciOverrideProtocol,
   2014                             HostBridgeHandle,
   2015                             RootBridgeHandle,
   2016                             RootBridgePciAddress,
   2017                             Phase,
   2018                             ChipsetExit
   2019                             );
   2020   }
   2021 
   2022   return EFI_SUCCESS;
   2023 }
   2024 
   2025 /**
   2026   This function allows the PCI bus driver to be notified to act as requested when a hot-plug event has
   2027   happened on the hot-plug controller. Currently, the operations include add operation and remove operation..
   2028 
   2029   @param This                 A pointer to the hot plug request protocol.
   2030   @param Operation            The operation the PCI bus driver is requested to make.
   2031   @param Controller           The handle of the hot-plug controller.
   2032   @param RemainingDevicePath  The remaining device path for the PCI-like hot-plug device.
   2033   @param NumberOfChildren     The number of child handles.
   2034                               For a add operation, it is an output parameter.
   2035                               For a remove operation, it's an input parameter.
   2036   @param ChildHandleBuffer    The buffer which contains the child handles.
   2037 
   2038   @retval EFI_INVALID_PARAMETER  Operation is not a legal value.
   2039                                  Controller is NULL or not a valid handle.
   2040                                  NumberOfChildren is NULL.
   2041                                  ChildHandleBuffer is NULL while Operation is add.
   2042   @retval EFI_OUT_OF_RESOURCES   There are no enough resources to start the devices.
   2043   @retval EFI_NOT_FOUND          Can not find bridge according to controller handle.
   2044   @retval EFI_SUCCESS            The handles for the specified device have been created or destroyed
   2045                                  as requested, and for an add operation, the new handles are
   2046                                  returned in ChildHandleBuffer.
   2047 **/
   2048 EFI_STATUS
   2049 EFIAPI
   2050 PciHotPlugRequestNotify (
   2051   IN EFI_PCI_HOTPLUG_REQUEST_PROTOCOL * This,
   2052   IN EFI_PCI_HOTPLUG_OPERATION        Operation,
   2053   IN EFI_HANDLE                       Controller,
   2054   IN EFI_DEVICE_PATH_PROTOCOL         * RemainingDevicePath OPTIONAL,
   2055   IN OUT UINT8                        *NumberOfChildren,
   2056   IN OUT EFI_HANDLE                   * ChildHandleBuffer
   2057   )
   2058 {
   2059   PCI_IO_DEVICE       *Bridge;
   2060   PCI_IO_DEVICE       *Temp;
   2061   EFI_PCI_IO_PROTOCOL *PciIo;
   2062   UINTN               Index;
   2063   EFI_HANDLE          RootBridgeHandle;
   2064   EFI_STATUS          Status;
   2065 
   2066   //
   2067   // Check input parameter validity
   2068   //
   2069   if ((Controller == NULL) || (NumberOfChildren == NULL)){
   2070     return EFI_INVALID_PARAMETER;
   2071   }
   2072 
   2073   if ((Operation != EfiPciHotPlugRequestAdd) && (Operation != EfiPciHotplugRequestRemove)) {
   2074     return EFI_INVALID_PARAMETER;
   2075   }
   2076 
   2077   if (Operation == EfiPciHotPlugRequestAdd){
   2078     if (ChildHandleBuffer == NULL) {
   2079       return EFI_INVALID_PARAMETER;
   2080     }
   2081   } else if ((Operation == EfiPciHotplugRequestRemove) && (*NumberOfChildren != 0)) {
   2082     if (ChildHandleBuffer == NULL) {
   2083       return EFI_INVALID_PARAMETER;
   2084     }
   2085   }
   2086 
   2087   Status = gBS->OpenProtocol (
   2088                   Controller,
   2089                   &gEfiPciIoProtocolGuid,
   2090                   (VOID **) &PciIo,
   2091                   gPciBusDriverBinding.DriverBindingHandle,
   2092                   Controller,
   2093                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
   2094                   );
   2095 
   2096   if (EFI_ERROR (Status)) {
   2097     return EFI_NOT_FOUND;
   2098   }
   2099 
   2100   Bridge = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo);
   2101 
   2102   //
   2103   // Get root bridge handle
   2104   //
   2105   Temp = Bridge;
   2106   while (Temp->Parent != NULL) {
   2107     Temp = Temp->Parent;
   2108   }
   2109 
   2110   RootBridgeHandle = Temp->Handle;
   2111 
   2112   if (Operation == EfiPciHotPlugRequestAdd) {
   2113     //
   2114     // Report Status Code to indicate hot plug happens
   2115     //
   2116     REPORT_STATUS_CODE_WITH_DEVICE_PATH (
   2117       EFI_PROGRESS_CODE,
   2118       (EFI_IO_BUS_PCI | EFI_IOB_PC_HOTPLUG),
   2119       Temp->DevicePath
   2120       );
   2121 
   2122     if (NumberOfChildren != NULL) {
   2123       *NumberOfChildren = 0;
   2124     }
   2125 
   2126     if (IsListEmpty (&Bridge->ChildList)) {
   2127 
   2128       Status = PciBridgeEnumerator (Bridge);
   2129 
   2130       if (EFI_ERROR (Status)) {
   2131         return Status;
   2132       }
   2133     }
   2134 
   2135     Status = StartPciDevicesOnBridge (
   2136               RootBridgeHandle,
   2137               Bridge,
   2138               RemainingDevicePath,
   2139               NumberOfChildren,
   2140               ChildHandleBuffer
   2141               );
   2142 
   2143     return Status;
   2144   }
   2145 
   2146   if (Operation == EfiPciHotplugRequestRemove) {
   2147 
   2148     if (*NumberOfChildren == 0) {
   2149       //
   2150       // Remove all devices on the bridge
   2151       //
   2152       RemoveAllPciDeviceOnBridge (RootBridgeHandle, Bridge);
   2153       return EFI_SUCCESS;
   2154 
   2155     }
   2156 
   2157     for (Index = 0; Index < *NumberOfChildren; Index++) {
   2158       //
   2159       // De register all the pci device
   2160       //
   2161       Status = DeRegisterPciDevice (RootBridgeHandle, ChildHandleBuffer[Index]);
   2162 
   2163       if (EFI_ERROR (Status)) {
   2164         return Status;
   2165       }
   2166 
   2167     }
   2168     //
   2169     // End for
   2170     //
   2171     return EFI_SUCCESS;
   2172   }
   2173 
   2174   return EFI_SUCCESS;
   2175 }
   2176 
   2177 /**
   2178   Search hostbridge according to given handle
   2179 
   2180   @param RootBridgeHandle  Host bridge handle.
   2181 
   2182   @retval TRUE             Found host bridge handle.
   2183   @retval FALSE            Not found hot bridge handle.
   2184 
   2185 **/
   2186 BOOLEAN
   2187 SearchHostBridgeHandle (
   2188   IN EFI_HANDLE RootBridgeHandle
   2189   )
   2190 {
   2191   EFI_HANDLE                      HostBridgeHandle;
   2192   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
   2193   UINTN                           Index;
   2194   EFI_STATUS                      Status;
   2195 
   2196   //
   2197   // Get the rootbridge Io protocol to find the host bridge handle
   2198   //
   2199   Status = gBS->OpenProtocol (
   2200                   RootBridgeHandle,
   2201                   &gEfiPciRootBridgeIoProtocolGuid,
   2202                   (VOID **) &PciRootBridgeIo,
   2203                   gPciBusDriverBinding.DriverBindingHandle,
   2204                   RootBridgeHandle,
   2205                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
   2206                   );
   2207 
   2208   if (EFI_ERROR (Status)) {
   2209     return FALSE;
   2210   }
   2211 
   2212   HostBridgeHandle = PciRootBridgeIo->ParentHandle;
   2213   for (Index = 0; Index < gPciHostBridgeNumber; Index++) {
   2214     if (HostBridgeHandle == gPciHostBrigeHandles[Index]) {
   2215       return TRUE;
   2216     }
   2217   }
   2218 
   2219   return FALSE;
   2220 }
   2221 
   2222 /**
   2223   Add host bridge handle to global variable for enumerating.
   2224 
   2225   @param HostBridgeHandle   Host bridge handle.
   2226 
   2227   @retval EFI_SUCCESS       Successfully added host bridge.
   2228   @retval EFI_ABORTED       Host bridge is NULL, or given host bridge
   2229                             has been in host bridge list.
   2230 
   2231 **/
   2232 EFI_STATUS
   2233 AddHostBridgeEnumerator (
   2234   IN EFI_HANDLE HostBridgeHandle
   2235   )
   2236 {
   2237   UINTN Index;
   2238 
   2239   if (HostBridgeHandle == NULL) {
   2240     return EFI_ABORTED;
   2241   }
   2242 
   2243   for (Index = 0; Index < gPciHostBridgeNumber; Index++) {
   2244     if (HostBridgeHandle == gPciHostBrigeHandles[Index]) {
   2245       return EFI_ABORTED;
   2246     }
   2247   }
   2248 
   2249   if (Index < PCI_MAX_HOST_BRIDGE_NUM) {
   2250     gPciHostBrigeHandles[Index] = HostBridgeHandle;
   2251     gPciHostBridgeNumber++;
   2252   }
   2253 
   2254   return EFI_SUCCESS;
   2255 }
   2256 
   2257