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 - 2013, 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 resoruce 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 contruct 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 availabe.
   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_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
   1311     if (Configuration == NULL) {
   1312       return EFI_OUT_OF_RESOURCES;
   1313     }
   1314 
   1315     Ptr               = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) (Configuration);
   1316     Ptr->Desc         = ACPI_ADDRESS_SPACE_DESCRIPTOR;
   1317 
   1318     PtrEnd            = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Ptr + 1);
   1319     PtrEnd->Desc      = ACPI_END_TAG_DESCRIPTOR;
   1320     PtrEnd->Checksum  = 0;
   1321   }
   1322 
   1323   *Config = Configuration;
   1324 
   1325   return EFI_SUCCESS;
   1326 }
   1327 
   1328 /**
   1329   Get resource base from an acpi configuration descriptor.
   1330 
   1331   @param Config       An acpi configuration descriptor.
   1332   @param IoBase       Output of I/O resource base address.
   1333   @param Mem32Base    Output of 32-bit memory base address.
   1334   @param PMem32Base   Output of 32-bit prefetchable memory base address.
   1335   @param Mem64Base    Output of 64-bit memory base address.
   1336   @param PMem64Base   Output of 64-bit prefetchable memory base address.
   1337 
   1338 **/
   1339 VOID
   1340 GetResourceBase (
   1341   IN VOID     *Config,
   1342   OUT UINT64  *IoBase,
   1343   OUT UINT64  *Mem32Base,
   1344   OUT UINT64  *PMem32Base,
   1345   OUT UINT64  *Mem64Base,
   1346   OUT UINT64  *PMem64Base
   1347   )
   1348 {
   1349   UINT8                             *Temp;
   1350   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
   1351   UINT64                            ResStatus;
   1352 
   1353   ASSERT (Config != NULL);
   1354 
   1355   *IoBase     = 0xFFFFFFFFFFFFFFFFULL;
   1356   *Mem32Base  = 0xFFFFFFFFFFFFFFFFULL;
   1357   *PMem32Base = 0xFFFFFFFFFFFFFFFFULL;
   1358   *Mem64Base  = 0xFFFFFFFFFFFFFFFFULL;
   1359   *PMem64Base = 0xFFFFFFFFFFFFFFFFULL;
   1360 
   1361   Temp        = (UINT8 *) Config;
   1362 
   1363   while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
   1364 
   1365     Ptr       = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;
   1366     ResStatus = Ptr->AddrTranslationOffset;
   1367 
   1368     if (ResStatus == EFI_RESOURCE_SATISFIED) {
   1369 
   1370       switch (Ptr->ResType) {
   1371 
   1372       //
   1373       // Memory type aperture
   1374       //
   1375       case 0:
   1376 
   1377         //
   1378         // Check to see the granularity
   1379         //
   1380         if (Ptr->AddrSpaceGranularity == 32) {
   1381           if ((Ptr->SpecificFlag & 0x06) != 0) {
   1382             *PMem32Base = Ptr->AddrRangeMin;
   1383           } else {
   1384             *Mem32Base = Ptr->AddrRangeMin;
   1385           }
   1386         }
   1387 
   1388         if (Ptr->AddrSpaceGranularity == 64) {
   1389           if ((Ptr->SpecificFlag & 0x06) != 0) {
   1390             *PMem64Base = Ptr->AddrRangeMin;
   1391           } else {
   1392             *Mem64Base = Ptr->AddrRangeMin;
   1393           }
   1394         }
   1395         break;
   1396 
   1397       case 1:
   1398 
   1399         //
   1400         // Io type aperture
   1401         //
   1402         *IoBase = Ptr->AddrRangeMin;
   1403         break;
   1404 
   1405       default:
   1406         break;
   1407 
   1408       }
   1409       //
   1410       // End switch
   1411       //
   1412     }
   1413     //
   1414     // End for
   1415     //
   1416     Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
   1417   }
   1418 }
   1419 
   1420 /**
   1421   Enumerate pci bridge, allocate resource and determine attribute
   1422   for devices on this bridge.
   1423 
   1424   @param BridgeDev    Pointer to instance of bridge device.
   1425 
   1426   @retval EFI_SUCCESS Successfully enumerated PCI bridge.
   1427   @retval other       Failed to enumerate.
   1428 
   1429 **/
   1430 EFI_STATUS
   1431 PciBridgeEnumerator (
   1432   IN PCI_IO_DEVICE                                     *BridgeDev
   1433   )
   1434 {
   1435   UINT8               SubBusNumber;
   1436   UINT8               StartBusNumber;
   1437   EFI_PCI_IO_PROTOCOL *PciIo;
   1438   EFI_STATUS          Status;
   1439 
   1440   SubBusNumber    = 0;
   1441   StartBusNumber  = 0;
   1442   PciIo           = &(BridgeDev->PciIo);
   1443   Status          = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x19, 1, &StartBusNumber);
   1444 
   1445   if (EFI_ERROR (Status)) {
   1446     return Status;
   1447   }
   1448 
   1449   Status = PciAssignBusNumber (
   1450             BridgeDev,
   1451             StartBusNumber,
   1452             &SubBusNumber
   1453             );
   1454 
   1455   if (EFI_ERROR (Status)) {
   1456     return Status;
   1457   }
   1458 
   1459   Status = PciPciDeviceInfoCollector (BridgeDev, StartBusNumber);
   1460 
   1461   if (EFI_ERROR (Status)) {
   1462     return Status;
   1463   }
   1464 
   1465   Status = PciBridgeResourceAllocator (BridgeDev);
   1466 
   1467   if (EFI_ERROR (Status)) {
   1468     return Status;
   1469   }
   1470 
   1471   Status = DetermineDeviceAttribute (BridgeDev);
   1472 
   1473   if (EFI_ERROR (Status)) {
   1474     return Status;
   1475   }
   1476 
   1477   return EFI_SUCCESS;
   1478 
   1479 }
   1480 
   1481 /**
   1482   Allocate all kinds of resource for PCI bridge.
   1483 
   1484   @param  Bridge      Pointer to bridge instance.
   1485 
   1486   @retval EFI_SUCCESS Successfully allocated resource for PCI bridge.
   1487   @retval other       Failed to allocate resource for bridge.
   1488 
   1489 **/
   1490 EFI_STATUS
   1491 PciBridgeResourceAllocator (
   1492   IN PCI_IO_DEVICE  *Bridge
   1493   )
   1494 {
   1495   PCI_RESOURCE_NODE *IoBridge;
   1496   PCI_RESOURCE_NODE *Mem32Bridge;
   1497   PCI_RESOURCE_NODE *PMem32Bridge;
   1498   PCI_RESOURCE_NODE *Mem64Bridge;
   1499   PCI_RESOURCE_NODE *PMem64Bridge;
   1500   UINT64            IoBase;
   1501   UINT64            Mem32Base;
   1502   UINT64            PMem32Base;
   1503   UINT64            Mem64Base;
   1504   UINT64            PMem64Base;
   1505   EFI_STATUS        Status;
   1506 
   1507   IoBridge = CreateResourceNode (
   1508                Bridge,
   1509                0,
   1510                Bridge->BridgeIoAlignment,
   1511                0,
   1512                PciBarTypeIo16,
   1513                PciResUsageTypical
   1514                );
   1515 
   1516   Mem32Bridge = CreateResourceNode (
   1517                   Bridge,
   1518                   0,
   1519                   0xFFFFF,
   1520                   0,
   1521                   PciBarTypeMem32,
   1522                   PciResUsageTypical
   1523                   );
   1524 
   1525   PMem32Bridge = CreateResourceNode (
   1526                    Bridge,
   1527                    0,
   1528                    0xFFFFF,
   1529                    0,
   1530                    PciBarTypePMem32,
   1531                    PciResUsageTypical
   1532                    );
   1533 
   1534   Mem64Bridge = CreateResourceNode (
   1535                   Bridge,
   1536                   0,
   1537                   0xFFFFF,
   1538                   0,
   1539                   PciBarTypeMem64,
   1540                   PciResUsageTypical
   1541                   );
   1542 
   1543   PMem64Bridge = CreateResourceNode (
   1544                    Bridge,
   1545                    0,
   1546                    0xFFFFF,
   1547                    0,
   1548                    PciBarTypePMem64,
   1549                    PciResUsageTypical
   1550                    );
   1551 
   1552   //
   1553   // Create resourcemap by going through all the devices subject to this root bridge
   1554   //
   1555   CreateResourceMap (
   1556     Bridge,
   1557     IoBridge,
   1558     Mem32Bridge,
   1559     PMem32Bridge,
   1560     Mem64Bridge,
   1561     PMem64Bridge
   1562     );
   1563 
   1564   Status = GetResourceBaseFromBridge (
   1565              Bridge,
   1566              &IoBase,
   1567              &Mem32Base,
   1568              &PMem32Base,
   1569              &Mem64Base,
   1570              &PMem64Base
   1571              );
   1572 
   1573   if (EFI_ERROR (Status)) {
   1574     return Status;
   1575   }
   1576 
   1577   //
   1578   // Program IO resources
   1579   //
   1580   ProgramResource (
   1581     IoBase,
   1582     IoBridge
   1583     );
   1584 
   1585   //
   1586   // Program Mem32 resources
   1587   //
   1588   ProgramResource (
   1589     Mem32Base,
   1590     Mem32Bridge
   1591     );
   1592 
   1593   //
   1594   // Program PMem32 resources
   1595   //
   1596   ProgramResource (
   1597     PMem32Base,
   1598     PMem32Bridge
   1599     );
   1600 
   1601   //
   1602   // Program Mem64 resources
   1603   //
   1604   ProgramResource (
   1605     Mem64Base,
   1606     Mem64Bridge
   1607     );
   1608 
   1609   //
   1610   // Program PMem64 resources
   1611   //
   1612   ProgramResource (
   1613     PMem64Base,
   1614     PMem64Bridge
   1615     );
   1616 
   1617   DestroyResourceTree (IoBridge);
   1618   DestroyResourceTree (Mem32Bridge);
   1619   DestroyResourceTree (PMem32Bridge);
   1620   DestroyResourceTree (PMem64Bridge);
   1621   DestroyResourceTree (Mem64Bridge);
   1622 
   1623   gBS->FreePool (IoBridge);
   1624   gBS->FreePool (Mem32Bridge);
   1625   gBS->FreePool (PMem32Bridge);
   1626   gBS->FreePool (PMem64Bridge);
   1627   gBS->FreePool (Mem64Bridge);
   1628 
   1629   return EFI_SUCCESS;
   1630 }
   1631 
   1632 /**
   1633   Get resource base address for a pci bridge device.
   1634 
   1635   @param Bridge     Given Pci driver instance.
   1636   @param IoBase     Output for base address of I/O type resource.
   1637   @param Mem32Base  Output for base address of 32-bit memory type resource.
   1638   @param PMem32Base Ooutput for base address of 32-bit Pmemory type resource.
   1639   @param Mem64Base  Output for base address of 64-bit memory type resource.
   1640   @param PMem64Base Output for base address of 64-bit Pmemory type resource.
   1641 
   1642   @retval EFI_SUCCESS           Successfully got resource base address.
   1643   @retval EFI_OUT_OF_RESOURCES  PCI bridge is not available.
   1644 
   1645 **/
   1646 EFI_STATUS
   1647 GetResourceBaseFromBridge (
   1648   IN  PCI_IO_DEVICE *Bridge,
   1649   OUT UINT64        *IoBase,
   1650   OUT UINT64        *Mem32Base,
   1651   OUT UINT64        *PMem32Base,
   1652   OUT UINT64        *Mem64Base,
   1653   OUT UINT64        *PMem64Base
   1654   )
   1655 {
   1656   if (!Bridge->Allocated) {
   1657     return EFI_OUT_OF_RESOURCES;
   1658   }
   1659 
   1660   *IoBase     = gAllOne;
   1661   *Mem32Base  = gAllOne;
   1662   *PMem32Base = gAllOne;
   1663   *Mem64Base  = gAllOne;
   1664   *PMem64Base = gAllOne;
   1665 
   1666   if (IS_PCI_BRIDGE (&Bridge->Pci)) {
   1667 
   1668     if (Bridge->PciBar[PPB_IO_RANGE].Length > 0) {
   1669       *IoBase = Bridge->PciBar[PPB_IO_RANGE].BaseAddress;
   1670     }
   1671 
   1672     if (Bridge->PciBar[PPB_MEM32_RANGE].Length > 0) {
   1673       *Mem32Base = Bridge->PciBar[PPB_MEM32_RANGE].BaseAddress;
   1674     }
   1675 
   1676     if (Bridge->PciBar[PPB_PMEM32_RANGE].Length > 0) {
   1677       *PMem32Base = Bridge->PciBar[PPB_PMEM32_RANGE].BaseAddress;
   1678     }
   1679 
   1680     if (Bridge->PciBar[PPB_PMEM64_RANGE].Length > 0) {
   1681       *PMem64Base = Bridge->PciBar[PPB_PMEM64_RANGE].BaseAddress;
   1682     } else {
   1683       *PMem64Base = gAllOne;
   1684     }
   1685 
   1686   }
   1687 
   1688   if (IS_CARDBUS_BRIDGE (&Bridge->Pci)) {
   1689     if (Bridge->PciBar[P2C_IO_1].Length > 0) {
   1690       *IoBase = Bridge->PciBar[P2C_IO_1].BaseAddress;
   1691     } else {
   1692       if (Bridge->PciBar[P2C_IO_2].Length > 0) {
   1693         *IoBase = Bridge->PciBar[P2C_IO_2].BaseAddress;
   1694       }
   1695     }
   1696 
   1697     if (Bridge->PciBar[P2C_MEM_1].Length > 0) {
   1698       if (Bridge->PciBar[P2C_MEM_1].BarType == PciBarTypePMem32) {
   1699         *PMem32Base = Bridge->PciBar[P2C_MEM_1].BaseAddress;
   1700       }
   1701 
   1702       if (Bridge->PciBar[P2C_MEM_1].BarType == PciBarTypeMem32) {
   1703         *Mem32Base = Bridge->PciBar[P2C_MEM_1].BaseAddress;
   1704       }
   1705     }
   1706 
   1707     if (Bridge->PciBar[P2C_MEM_2].Length > 0) {
   1708       if (Bridge->PciBar[P2C_MEM_2].BarType == PciBarTypePMem32) {
   1709         *PMem32Base = Bridge->PciBar[P2C_MEM_2].BaseAddress;
   1710       }
   1711 
   1712       if (Bridge->PciBar[P2C_MEM_2].BarType == PciBarTypeMem32) {
   1713         *Mem32Base = Bridge->PciBar[P2C_MEM_2].BaseAddress;
   1714       }
   1715     }
   1716   }
   1717 
   1718   return EFI_SUCCESS;
   1719 }
   1720 
   1721 /**
   1722    These are the notifications from the PCI bus driver that it is about to enter a certain
   1723    phase of the PCI enumeration process.
   1724 
   1725    This member function can be used to notify the host bridge driver to perform specific actions,
   1726    including any chipset-specific initialization, so that the chipset is ready to enter the next phase.
   1727    Eight notification points are defined at this time. See belows:
   1728    EfiPciHostBridgeBeginEnumeration       Resets the host bridge PCI apertures and internal data
   1729                                           structures. The PCI enumerator should issue this notification
   1730                                           before starting a fresh enumeration process. Enumeration cannot
   1731                                           be restarted after sending any other notification such as
   1732                                           EfiPciHostBridgeBeginBusAllocation.
   1733    EfiPciHostBridgeBeginBusAllocation     The bus allocation phase is about to begin. No specific action is
   1734                                           required here. This notification can be used to perform any
   1735                                           chipset-specific programming.
   1736    EfiPciHostBridgeEndBusAllocation       The bus allocation and bus programming phase is complete. No
   1737                                           specific action is required here. This notification can be used to
   1738                                           perform any chipset-specific programming.
   1739    EfiPciHostBridgeBeginResourceAllocation
   1740                                           The resource allocation phase is about to begin. No specific
   1741                                           action is required here. This notification can be used to perform
   1742                                           any chipset-specific programming.
   1743    EfiPciHostBridgeAllocateResources      Allocates resources per previously submitted requests for all the PCI
   1744                                           root bridges. These resource settings are returned on the next call to
   1745                                           GetProposedResources(). Before calling NotifyPhase() with a Phase of
   1746                                           EfiPciHostBridgeAllocateResource, the PCI bus enumerator is responsible
   1747                                           for gathering I/O and memory requests for
   1748                                           all the PCI root bridges and submitting these requests using
   1749                                           SubmitResources(). This function pads the resource amount
   1750                                           to suit the root bridge hardware, takes care of dependencies between
   1751                                           the PCI root bridges, and calls the Global Coherency Domain (GCD)
   1752                                           with the allocation request. In the case of padding, the allocated range
   1753                                           could be bigger than what was requested.
   1754    EfiPciHostBridgeSetResources           Programs the host bridge hardware to decode previously allocated
   1755                                           resources (proposed resources) for all the PCI root bridges. After the
   1756                                           hardware is programmed, reassigning resources will not be supported.
   1757                                           The bus settings are not affected.
   1758    EfiPciHostBridgeFreeResources          Deallocates resources that were previously allocated for all the PCI
   1759                                           root bridges and resets the I/O and memory apertures to their initial
   1760                                           state. The bus settings are not affected. If the request to allocate
   1761                                           resources fails, the PCI enumerator can use this notification to
   1762                                           deallocate previous resources, adjust the requests, and retry
   1763                                           allocation.
   1764    EfiPciHostBridgeEndResourceAllocation  The resource allocation phase is completed. No specific action is
   1765                                           required here. This notification can be used to perform any chipsetspecific
   1766                                           programming.
   1767 
   1768    @param[in] PciResAlloc         The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
   1769    @param[in] Phase               The phase during enumeration
   1770 
   1771    @retval EFI_NOT_READY          This phase cannot be entered at this time. For example, this error
   1772                                   is valid for a Phase of EfiPciHostBridgeAllocateResources if
   1773                                   SubmitResources() has not been called for one or more
   1774                                   PCI root bridges before this call
   1775    @retval EFI_DEVICE_ERROR       Programming failed due to a hardware error. This error is valid
   1776                                   for a Phase of EfiPciHostBridgeSetResources.
   1777    @retval EFI_INVALID_PARAMETER  Invalid phase parameter
   1778    @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
   1779                                   This error is valid for a Phase of EfiPciHostBridgeAllocateResources if the
   1780                                   previously submitted resource requests cannot be fulfilled or
   1781                                   were only partially fulfilled.
   1782    @retval EFI_SUCCESS            The notification was accepted without any errors.
   1783 
   1784 **/
   1785 EFI_STATUS
   1786 NotifyPhase (
   1787   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,
   1788   EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE       Phase
   1789   )
   1790 {
   1791   EFI_HANDLE                      HostBridgeHandle;
   1792   EFI_HANDLE                      RootBridgeHandle;
   1793   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
   1794   EFI_STATUS                      Status;
   1795 
   1796   HostBridgeHandle  = NULL;
   1797   RootBridgeHandle  = NULL;
   1798   if (gPciPlatformProtocol != NULL) {
   1799     //
   1800     // Get Host Bridge Handle.
   1801     //
   1802     PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle);
   1803 
   1804     //
   1805     // Get the rootbridge Io protocol to find the host bridge handle
   1806     //
   1807     Status = gBS->HandleProtocol (
   1808                     RootBridgeHandle,
   1809                     &gEfiPciRootBridgeIoProtocolGuid,
   1810                     (VOID **) &PciRootBridgeIo
   1811                     );
   1812 
   1813     if (EFI_ERROR (Status)) {
   1814       return EFI_NOT_FOUND;
   1815     }
   1816 
   1817     HostBridgeHandle = PciRootBridgeIo->ParentHandle;
   1818 
   1819     //
   1820     // Call PlatformPci::PlatformNotify() if the protocol is present.
   1821     //
   1822     gPciPlatformProtocol->PlatformNotify (
   1823                             gPciPlatformProtocol,
   1824                             HostBridgeHandle,
   1825                             Phase,
   1826                             ChipsetEntry
   1827                             );
   1828   } else if (gPciOverrideProtocol != NULL){
   1829     //
   1830     // Get Host Bridge Handle.
   1831     //
   1832     PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle);
   1833 
   1834     //
   1835     // Get the rootbridge Io protocol to find the host bridge handle
   1836     //
   1837     Status = gBS->HandleProtocol (
   1838                     RootBridgeHandle,
   1839                     &gEfiPciRootBridgeIoProtocolGuid,
   1840                     (VOID **) &PciRootBridgeIo
   1841                     );
   1842 
   1843     if (EFI_ERROR (Status)) {
   1844       return EFI_NOT_FOUND;
   1845     }
   1846 
   1847     HostBridgeHandle = PciRootBridgeIo->ParentHandle;
   1848 
   1849     //
   1850     // Call PlatformPci::PhaseNotify() if the protocol is present.
   1851     //
   1852     gPciOverrideProtocol->PlatformNotify (
   1853                             gPciOverrideProtocol,
   1854                             HostBridgeHandle,
   1855                             Phase,
   1856                             ChipsetEntry
   1857                             );
   1858   }
   1859 
   1860   Status = PciResAlloc->NotifyPhase (
   1861                           PciResAlloc,
   1862                           Phase
   1863                           );
   1864 
   1865   if (gPciPlatformProtocol != NULL) {
   1866     //
   1867     // Call PlatformPci::PlatformNotify() if the protocol is present.
   1868     //
   1869     gPciPlatformProtocol->PlatformNotify (
   1870                             gPciPlatformProtocol,
   1871                             HostBridgeHandle,
   1872                             Phase,
   1873                             ChipsetExit
   1874                             );
   1875 
   1876   } else if (gPciOverrideProtocol != NULL) {
   1877     //
   1878     // Call PlatformPci::PhaseNotify() if the protocol is present.
   1879     //
   1880     gPciOverrideProtocol->PlatformNotify (
   1881                             gPciOverrideProtocol,
   1882                             HostBridgeHandle,
   1883                             Phase,
   1884                             ChipsetExit
   1885                             );
   1886   }
   1887 
   1888   return Status;
   1889 }
   1890 
   1891 /**
   1892   Provides the hooks from the PCI bus driver to every PCI controller (device/function) at various
   1893   stages of the PCI enumeration process that allow the host bridge driver to preinitialize individual
   1894   PCI controllers before enumeration.
   1895 
   1896   This function is called during the PCI enumeration process. No specific action is expected from this
   1897   member function. It allows the host bridge driver to preinitialize individual PCI controllers before
   1898   enumeration.
   1899 
   1900   @param Bridge            Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
   1901   @param Bus               The bus number of the pci device.
   1902   @param Device            The device number of the pci device.
   1903   @param Func              The function number of the pci device.
   1904   @param Phase             The phase of the PCI device enumeration.
   1905 
   1906   @retval EFI_SUCCESS              The requested parameters were returned.
   1907   @retval EFI_INVALID_PARAMETER    RootBridgeHandle is not a valid root bridge handle.
   1908   @retval EFI_INVALID_PARAMETER    Phase is not a valid phase that is defined in
   1909                                    EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE.
   1910   @retval EFI_DEVICE_ERROR         Programming failed due to a hardware error. The PCI enumerator should
   1911                                    not enumerate this device, including its child devices if it is a PCI-to-PCI
   1912                                    bridge.
   1913 
   1914 **/
   1915 EFI_STATUS
   1916 PreprocessController (
   1917   IN PCI_IO_DEVICE                                    *Bridge,
   1918   IN UINT8                                            Bus,
   1919   IN UINT8                                            Device,
   1920   IN UINT8                                            Func,
   1921   IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE     Phase
   1922   )
   1923 {
   1924   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS       RootBridgePciAddress;
   1925   EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *PciResAlloc;
   1926   EFI_HANDLE                                        RootBridgeHandle;
   1927   EFI_HANDLE                                        HostBridgeHandle;
   1928   EFI_STATUS                                        Status;
   1929 
   1930   //
   1931   // Get the host bridge handle
   1932   //
   1933   HostBridgeHandle = Bridge->PciRootBridgeIo->ParentHandle;
   1934 
   1935   //
   1936   // Get the pci host bridge resource allocation protocol
   1937   //
   1938   Status = gBS->OpenProtocol (
   1939                   HostBridgeHandle,
   1940                   &gEfiPciHostBridgeResourceAllocationProtocolGuid,
   1941                   (VOID **) &PciResAlloc,
   1942                   NULL,
   1943                   NULL,
   1944                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
   1945                   );
   1946 
   1947   if (EFI_ERROR (Status)) {
   1948     return EFI_UNSUPPORTED;
   1949   }
   1950 
   1951   //
   1952   // Get Root Brige Handle
   1953   //
   1954   while (Bridge->Parent != NULL) {
   1955     Bridge = Bridge->Parent;
   1956   }
   1957 
   1958   RootBridgeHandle                      = Bridge->Handle;
   1959 
   1960   RootBridgePciAddress.Register         = 0;
   1961   RootBridgePciAddress.Function         = Func;
   1962   RootBridgePciAddress.Device           = Device;
   1963   RootBridgePciAddress.Bus              = Bus;
   1964   RootBridgePciAddress.ExtendedRegister = 0;
   1965 
   1966   if (gPciPlatformProtocol != NULL) {
   1967     //
   1968     // Call PlatformPci::PrepController() if the protocol is present.
   1969     //
   1970     gPciPlatformProtocol->PlatformPrepController (
   1971                             gPciPlatformProtocol,
   1972                             HostBridgeHandle,
   1973                             RootBridgeHandle,
   1974                             RootBridgePciAddress,
   1975                             Phase,
   1976                             ChipsetEntry
   1977                             );
   1978   } else if (gPciOverrideProtocol != NULL) {
   1979     //
   1980     // Call PlatformPci::PrepController() if the protocol is present.
   1981     //
   1982     gPciOverrideProtocol->PlatformPrepController (
   1983                             gPciOverrideProtocol,
   1984                             HostBridgeHandle,
   1985                             RootBridgeHandle,
   1986                             RootBridgePciAddress,
   1987                             Phase,
   1988                             ChipsetEntry
   1989                             );
   1990   }
   1991 
   1992   Status = PciResAlloc->PreprocessController (
   1993                           PciResAlloc,
   1994                           RootBridgeHandle,
   1995                           RootBridgePciAddress,
   1996                           Phase
   1997                           );
   1998 
   1999   if (gPciPlatformProtocol != NULL) {
   2000     //
   2001     // Call PlatformPci::PrepController() if the protocol is present.
   2002     //
   2003     gPciPlatformProtocol->PlatformPrepController (
   2004                             gPciPlatformProtocol,
   2005                             HostBridgeHandle,
   2006                             RootBridgeHandle,
   2007                             RootBridgePciAddress,
   2008                             Phase,
   2009                             ChipsetExit
   2010                             );
   2011   } else if (gPciOverrideProtocol != NULL) {
   2012     //
   2013     // Call PlatformPci::PrepController() if the protocol is present.
   2014     //
   2015     gPciOverrideProtocol->PlatformPrepController (
   2016                             gPciOverrideProtocol,
   2017                             HostBridgeHandle,
   2018                             RootBridgeHandle,
   2019                             RootBridgePciAddress,
   2020                             Phase,
   2021                             ChipsetExit
   2022                             );
   2023   }
   2024 
   2025   return EFI_SUCCESS;
   2026 }
   2027 
   2028 /**
   2029   This function allows the PCI bus driver to be notified to act as requested when a hot-plug event has
   2030   happened on the hot-plug controller. Currently, the operations include add operation and remove operation..
   2031 
   2032   @param This                 A pointer to the hot plug request protocol.
   2033   @param Operation            The operation the PCI bus driver is requested to make.
   2034   @param Controller           The handle of the hot-plug controller.
   2035   @param RemainingDevicePath  The remaining device path for the PCI-like hot-plug device.
   2036   @param NumberOfChildren     The number of child handles.
   2037                               For a add operation, it is an output parameter.
   2038                               For a remove operation, it's an input parameter.
   2039   @param ChildHandleBuffer    The buffer which contains the child handles.
   2040 
   2041   @retval EFI_INVALID_PARAMETER  Operation is not a legal value.
   2042                                  Controller is NULL or not a valid handle.
   2043                                  NumberOfChildren is NULL.
   2044                                  ChildHandleBuffer is NULL while Operation is add.
   2045   @retval EFI_OUT_OF_RESOURCES   There are no enough resources to start the devices.
   2046   @retval EFI_NOT_FOUND          Can not find bridge according to controller handle.
   2047   @retval EFI_SUCCESS            The handles for the specified device have been created or destroyed
   2048                                  as requested, and for an add operation, the new handles are
   2049                                  returned in ChildHandleBuffer.
   2050 **/
   2051 EFI_STATUS
   2052 EFIAPI
   2053 PciHotPlugRequestNotify (
   2054   IN EFI_PCI_HOTPLUG_REQUEST_PROTOCOL * This,
   2055   IN EFI_PCI_HOTPLUG_OPERATION        Operation,
   2056   IN EFI_HANDLE                       Controller,
   2057   IN EFI_DEVICE_PATH_PROTOCOL         * RemainingDevicePath OPTIONAL,
   2058   IN OUT UINT8                        *NumberOfChildren,
   2059   IN OUT EFI_HANDLE                   * ChildHandleBuffer
   2060   )
   2061 {
   2062   PCI_IO_DEVICE       *Bridge;
   2063   PCI_IO_DEVICE       *Temp;
   2064   EFI_PCI_IO_PROTOCOL *PciIo;
   2065   UINTN               Index;
   2066   EFI_HANDLE          RootBridgeHandle;
   2067   EFI_STATUS          Status;
   2068 
   2069   //
   2070   // Check input parameter validity
   2071   //
   2072   if ((Controller == NULL) || (NumberOfChildren == NULL)){
   2073     return EFI_INVALID_PARAMETER;
   2074   }
   2075 
   2076   if ((Operation != EfiPciHotPlugRequestAdd) && (Operation != EfiPciHotplugRequestRemove)) {
   2077     return EFI_INVALID_PARAMETER;
   2078   }
   2079 
   2080   if (Operation == EfiPciHotPlugRequestAdd){
   2081     if (ChildHandleBuffer == NULL) {
   2082       return EFI_INVALID_PARAMETER;
   2083     }
   2084   } else if ((Operation == EfiPciHotplugRequestRemove) && (*NumberOfChildren != 0)) {
   2085     if (ChildHandleBuffer == NULL) {
   2086       return EFI_INVALID_PARAMETER;
   2087     }
   2088   }
   2089 
   2090   Status = gBS->OpenProtocol (
   2091                   Controller,
   2092                   &gEfiPciIoProtocolGuid,
   2093                   (VOID **) &PciIo,
   2094                   gPciBusDriverBinding.DriverBindingHandle,
   2095                   Controller,
   2096                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
   2097                   );
   2098 
   2099   if (EFI_ERROR (Status)) {
   2100     return EFI_NOT_FOUND;
   2101   }
   2102 
   2103   Bridge = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo);
   2104 
   2105   //
   2106   // Get root bridge handle
   2107   //
   2108   Temp = Bridge;
   2109   while (Temp->Parent != NULL) {
   2110     Temp = Temp->Parent;
   2111   }
   2112 
   2113   RootBridgeHandle = Temp->Handle;
   2114 
   2115   if (Operation == EfiPciHotPlugRequestAdd) {
   2116     //
   2117     // Report Status Code to indicate hot plug happens
   2118     //
   2119     REPORT_STATUS_CODE_WITH_DEVICE_PATH (
   2120       EFI_PROGRESS_CODE,
   2121       (EFI_IO_BUS_PCI | EFI_IOB_PC_HOTPLUG),
   2122       Temp->DevicePath
   2123       );
   2124 
   2125     if (NumberOfChildren != NULL) {
   2126       *NumberOfChildren = 0;
   2127     }
   2128 
   2129     if (IsListEmpty (&Bridge->ChildList)) {
   2130 
   2131       Status = PciBridgeEnumerator (Bridge);
   2132 
   2133       if (EFI_ERROR (Status)) {
   2134         return Status;
   2135       }
   2136     }
   2137 
   2138     Status = StartPciDevicesOnBridge (
   2139               RootBridgeHandle,
   2140               Bridge,
   2141               RemainingDevicePath,
   2142               NumberOfChildren,
   2143               ChildHandleBuffer
   2144               );
   2145 
   2146     return Status;
   2147   }
   2148 
   2149   if (Operation == EfiPciHotplugRequestRemove) {
   2150 
   2151     if (*NumberOfChildren == 0) {
   2152       //
   2153       // Remove all devices on the bridge
   2154       //
   2155       RemoveAllPciDeviceOnBridge (RootBridgeHandle, Bridge);
   2156       return EFI_SUCCESS;
   2157 
   2158     }
   2159 
   2160     for (Index = 0; Index < *NumberOfChildren; Index++) {
   2161       //
   2162       // De register all the pci device
   2163       //
   2164       Status = DeRegisterPciDevice (RootBridgeHandle, ChildHandleBuffer[Index]);
   2165 
   2166       if (EFI_ERROR (Status)) {
   2167         return Status;
   2168       }
   2169 
   2170     }
   2171     //
   2172     // End for
   2173     //
   2174     return EFI_SUCCESS;
   2175   }
   2176 
   2177   return EFI_SUCCESS;
   2178 }
   2179 
   2180 /**
   2181   Search hostbridge according to given handle
   2182 
   2183   @param RootBridgeHandle  Host bridge handle.
   2184 
   2185   @retval TRUE             Found host bridge handle.
   2186   @retval FALSE            Not found hot bridge handle.
   2187 
   2188 **/
   2189 BOOLEAN
   2190 SearchHostBridgeHandle (
   2191   IN EFI_HANDLE RootBridgeHandle
   2192   )
   2193 {
   2194   EFI_HANDLE                      HostBridgeHandle;
   2195   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
   2196   UINTN                           Index;
   2197   EFI_STATUS                      Status;
   2198 
   2199   //
   2200   // Get the rootbridge Io protocol to find the host bridge handle
   2201   //
   2202   Status = gBS->OpenProtocol (
   2203                   RootBridgeHandle,
   2204                   &gEfiPciRootBridgeIoProtocolGuid,
   2205                   (VOID **) &PciRootBridgeIo,
   2206                   gPciBusDriverBinding.DriverBindingHandle,
   2207                   RootBridgeHandle,
   2208                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
   2209                   );
   2210 
   2211   if (EFI_ERROR (Status)) {
   2212     return FALSE;
   2213   }
   2214 
   2215   HostBridgeHandle = PciRootBridgeIo->ParentHandle;
   2216   for (Index = 0; Index < gPciHostBridgeNumber; Index++) {
   2217     if (HostBridgeHandle == gPciHostBrigeHandles[Index]) {
   2218       return TRUE;
   2219     }
   2220   }
   2221 
   2222   return FALSE;
   2223 }
   2224 
   2225 /**
   2226   Add host bridge handle to global variable for enumerating.
   2227 
   2228   @param HostBridgeHandle   Host bridge handle.
   2229 
   2230   @retval EFI_SUCCESS       Successfully added host bridge.
   2231   @retval EFI_ABORTED       Host bridge is NULL, or given host bridge
   2232                             has been in host bridge list.
   2233 
   2234 **/
   2235 EFI_STATUS
   2236 AddHostBridgeEnumerator (
   2237   IN EFI_HANDLE HostBridgeHandle
   2238   )
   2239 {
   2240   UINTN Index;
   2241 
   2242   if (HostBridgeHandle == NULL) {
   2243     return EFI_ABORTED;
   2244   }
   2245 
   2246   for (Index = 0; Index < gPciHostBridgeNumber; Index++) {
   2247     if (HostBridgeHandle == gPciHostBrigeHandles[Index]) {
   2248       return EFI_ABORTED;
   2249     }
   2250   }
   2251 
   2252   if (Index < PCI_MAX_HOST_BRIDGE_NUM) {
   2253     gPciHostBrigeHandles[Index] = HostBridgeHandle;
   2254     gPciHostBridgeNumber++;
   2255   }
   2256 
   2257   return EFI_SUCCESS;
   2258 }
   2259 
   2260