Home | History | Annotate | Download | only in PciBusDxe
      1 /** @file
      2   PCI resouces support functions implemntation for PCI Bus module.
      3 
      4 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
      5 This program and the accompanying materials
      6 are licensed and made available under the terms and conditions of the BSD License
      7 which accompanies this distribution.  The full text of the license may be found at
      8 http://opensource.org/licenses/bsd-license.php
      9 
     10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include "PciBus.h"
     16 
     17 //
     18 // The default policy for the PCI bus driver is NOT to reserve I/O ranges for both ISA aliases and VGA aliases.
     19 //
     20 BOOLEAN mReserveIsaAliases = FALSE;
     21 BOOLEAN mReserveVgaAliases = FALSE;
     22 BOOLEAN mPolicyDetermined  = FALSE;
     23 
     24 /**
     25   The function is used to skip VGA range.
     26 
     27   @param Start    Returned start address including VGA range.
     28   @param Length   The length of VGA range.
     29 
     30 **/
     31 VOID
     32 SkipVGAAperture (
     33   OUT UINT64   *Start,
     34   IN  UINT64   Length
     35   )
     36 {
     37   UINT64  Original;
     38   UINT64  Mask;
     39   UINT64  StartOffset;
     40   UINT64  LimitOffset;
     41 
     42   ASSERT (Start != NULL);
     43   //
     44   // For legacy VGA, bit 10 to bit 15 is not decoded
     45   //
     46   Mask        = 0x3FF;
     47 
     48   Original    = *Start;
     49   StartOffset = Original & Mask;
     50   LimitOffset = ((*Start) + Length - 1) & Mask;
     51   if (LimitOffset >= VGABASE1) {
     52     *Start = *Start - StartOffset + VGALIMIT2 + 1;
     53   }
     54 }
     55 
     56 /**
     57   This function is used to skip ISA aliasing aperture.
     58 
     59   @param Start    Returned start address including ISA aliasing aperture.
     60   @param Length   The length of ISA aliasing aperture.
     61 
     62 **/
     63 VOID
     64 SkipIsaAliasAperture (
     65   OUT UINT64   *Start,
     66   IN  UINT64   Length
     67   )
     68 {
     69 
     70   UINT64  Original;
     71   UINT64  Mask;
     72   UINT64  StartOffset;
     73   UINT64  LimitOffset;
     74 
     75   ASSERT (Start != NULL);
     76 
     77   //
     78   // For legacy ISA, bit 10 to bit 15 is not decoded
     79   //
     80   Mask        = 0x3FF;
     81 
     82   Original    = *Start;
     83   StartOffset = Original & Mask;
     84   LimitOffset = ((*Start) + Length - 1) & Mask;
     85 
     86   if (LimitOffset >= ISABASE) {
     87     *Start = *Start - StartOffset + ISALIMIT + 1;
     88   }
     89 }
     90 
     91 /**
     92   This function inserts a resource node into the resource list.
     93   The resource list is sorted in descend order.
     94 
     95   @param Bridge  PCI resource node for bridge.
     96   @param ResNode Resource node want to be inserted.
     97 
     98 **/
     99 VOID
    100 InsertResourceNode (
    101   IN OUT PCI_RESOURCE_NODE   *Bridge,
    102   IN     PCI_RESOURCE_NODE   *ResNode
    103   )
    104 {
    105   LIST_ENTRY        *CurrentLink;
    106   PCI_RESOURCE_NODE *Temp;
    107   UINT64            ResNodeAlignRest;
    108   UINT64            TempAlignRest;
    109 
    110   ASSERT (Bridge  != NULL);
    111   ASSERT (ResNode != NULL);
    112 
    113   InsertHeadList (&Bridge->ChildList, &ResNode->Link);
    114 
    115   CurrentLink = Bridge->ChildList.ForwardLink->ForwardLink;
    116   while (CurrentLink != &Bridge->ChildList) {
    117     Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
    118 
    119     if (ResNode->Alignment > Temp->Alignment) {
    120       break;
    121     } else if (ResNode->Alignment == Temp->Alignment) {
    122       ResNodeAlignRest  = ResNode->Length & ResNode->Alignment;
    123       TempAlignRest     = Temp->Length & Temp->Alignment;
    124       if ((ResNodeAlignRest == 0) || (ResNodeAlignRest >= TempAlignRest)) {
    125         break;
    126       }
    127     }
    128 
    129     SwapListEntries (&ResNode->Link, CurrentLink);
    130 
    131     CurrentLink = ResNode->Link.ForwardLink;
    132   }
    133 }
    134 
    135 /**
    136   This routine is used to merge two different resource trees in need of
    137   resoure degradation.
    138 
    139   For example, if an upstream PPB doesn't support,
    140   prefetchable memory decoding, the PCI bus driver will choose to call this function
    141   to merge prefectchable memory resource list into normal memory list.
    142 
    143   If the TypeMerge is TRUE, Res resource type is changed to the type of destination resource
    144   type.
    145   If Dst is NULL or Res is NULL, ASSERT ().
    146 
    147   @param Dst        Point to destination resource tree.
    148   @param Res        Point to source resource tree.
    149   @param TypeMerge  If the TypeMerge is TRUE, Res resource type is changed to the type of
    150                     destination resource type.
    151 
    152 **/
    153 VOID
    154 MergeResourceTree (
    155   IN PCI_RESOURCE_NODE   *Dst,
    156   IN PCI_RESOURCE_NODE   *Res,
    157   IN BOOLEAN             TypeMerge
    158   )
    159 {
    160 
    161   LIST_ENTRY        *CurrentLink;
    162   PCI_RESOURCE_NODE *Temp;
    163 
    164   ASSERT (Dst != NULL);
    165   ASSERT (Res != NULL);
    166 
    167   while (!IsListEmpty (&Res->ChildList)) {
    168     CurrentLink = Res->ChildList.ForwardLink;
    169 
    170     Temp        = RESOURCE_NODE_FROM_LINK (CurrentLink);
    171 
    172     if (TypeMerge) {
    173       Temp->ResType = Dst->ResType;
    174     }
    175 
    176     RemoveEntryList (CurrentLink);
    177     InsertResourceNode (Dst, Temp);
    178   }
    179 }
    180 
    181 /**
    182   This function is used to calculate the IO16 aperture
    183   for a bridge.
    184 
    185   @param Bridge    PCI resource node for bridge.
    186 
    187 **/
    188 VOID
    189 CalculateApertureIo16 (
    190   IN PCI_RESOURCE_NODE    *Bridge
    191   )
    192 {
    193   EFI_STATUS              Status;
    194   UINT64                  Aperture;
    195   LIST_ENTRY              *CurrentLink;
    196   PCI_RESOURCE_NODE       *Node;
    197   UINT64                  Offset;
    198   EFI_PCI_PLATFORM_POLICY PciPolicy;
    199   UINT64                  PaddingAperture;
    200 
    201   if (!mPolicyDetermined) {
    202     //
    203     // Check PciPlatform policy
    204     //
    205     Status = EFI_NOT_FOUND;
    206     PciPolicy = 0;
    207     if (gPciPlatformProtocol != NULL) {
    208       Status = gPciPlatformProtocol->GetPlatformPolicy (
    209                                        gPciPlatformProtocol,
    210                                        &PciPolicy
    211                                        );
    212     }
    213 
    214     if (EFI_ERROR (Status) && gPciOverrideProtocol != NULL) {
    215       Status = gPciOverrideProtocol->GetPlatformPolicy (
    216                                        gPciOverrideProtocol,
    217                                        &PciPolicy
    218                                        );
    219     }
    220 
    221     if (!EFI_ERROR (Status)) {
    222       if ((PciPolicy & EFI_RESERVE_ISA_IO_ALIAS) != 0) {
    223         mReserveIsaAliases = TRUE;
    224       }
    225       if ((PciPolicy & EFI_RESERVE_VGA_IO_ALIAS) != 0) {
    226         mReserveVgaAliases = TRUE;
    227       }
    228     }
    229     mPolicyDetermined = TRUE;
    230   }
    231 
    232   Aperture        = 0;
    233   PaddingAperture = 0;
    234 
    235   if (Bridge == NULL) {
    236     return ;
    237   }
    238 
    239   //
    240   // Assume the bridge is aligned
    241   //
    242   for ( CurrentLink = GetFirstNode (&Bridge->ChildList)
    243       ; !IsNull (&Bridge->ChildList, CurrentLink)
    244       ; CurrentLink = GetNextNode (&Bridge->ChildList, CurrentLink)
    245       ) {
    246 
    247     Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
    248     if (Node->ResourceUsage == PciResUsagePadding) {
    249       ASSERT (PaddingAperture == 0);
    250       PaddingAperture = Node->Length;
    251       continue;
    252     }
    253     //
    254     // Consider the aperture alignment
    255     //
    256     Offset = Aperture & (Node->Alignment);
    257 
    258     if (Offset != 0) {
    259 
    260       Aperture = Aperture + (Node->Alignment + 1) - Offset;
    261 
    262     }
    263 
    264     //
    265     // IsaEnable and VGAEnable can not be implemented now.
    266     // If both of them are enabled, then the IO resource would
    267     // become too limited to meet the requirement of most of devices.
    268     //
    269     if (mReserveIsaAliases || mReserveVgaAliases) {
    270       if (!IS_PCI_BRIDGE (&(Node->PciDev->Pci)) && !IS_CARDBUS_BRIDGE (&(Node->PciDev->Pci))) {
    271         //
    272         // Check if there is need to support ISA/VGA decoding
    273         // If so, we need to avoid isa/vga aliasing range
    274         //
    275         if (mReserveIsaAliases) {
    276           SkipIsaAliasAperture (
    277             &Aperture,
    278             Node->Length
    279             );
    280           Offset = Aperture & (Node->Alignment);
    281           if (Offset != 0) {
    282             Aperture = Aperture + (Node->Alignment + 1) - Offset;
    283           }
    284         } else if (mReserveVgaAliases) {
    285           SkipVGAAperture (
    286             &Aperture,
    287             Node->Length
    288             );
    289           Offset = Aperture & (Node->Alignment);
    290           if (Offset != 0) {
    291             Aperture = Aperture + (Node->Alignment + 1) - Offset;
    292           }
    293         }
    294       }
    295     }
    296 
    297     Node->Offset = Aperture;
    298 
    299     //
    300     // Increment aperture by the length of node
    301     //
    302     Aperture += Node->Length;
    303   }
    304 
    305   //
    306   // Adjust the aperture with the bridge's alignment
    307   //
    308   Offset = Aperture & (Bridge->Alignment);
    309 
    310   if (Offset != 0) {
    311     Aperture = Aperture + (Bridge->Alignment + 1) - Offset;
    312   }
    313 
    314   Bridge->Length = Aperture;
    315   //
    316   // At last, adjust the bridge's alignment to the first child's alignment
    317   // if the bridge has at least one child
    318   //
    319   CurrentLink = Bridge->ChildList.ForwardLink;
    320   if (CurrentLink != &Bridge->ChildList) {
    321     Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
    322     if (Node->Alignment > Bridge->Alignment) {
    323       Bridge->Alignment = Node->Alignment;
    324     }
    325   }
    326 
    327   //
    328   // Hotplug controller needs padding resources.
    329   // Use the larger one between the padding resource and actual occupied resource.
    330   //
    331   Bridge->Length = MAX (Bridge->Length, PaddingAperture);
    332 }
    333 
    334 /**
    335   This function is used to calculate the resource aperture
    336   for a given bridge device.
    337 
    338   @param Bridge      PCI resouce node for given bridge device.
    339 
    340 **/
    341 VOID
    342 CalculateResourceAperture (
    343   IN PCI_RESOURCE_NODE    *Bridge
    344   )
    345 {
    346   UINT64            Aperture;
    347   LIST_ENTRY        *CurrentLink;
    348   PCI_RESOURCE_NODE *Node;
    349   UINT64            PaddingAperture;
    350   UINT64            Offset;
    351 
    352   Aperture        = 0;
    353   PaddingAperture = 0;
    354 
    355   if (Bridge == NULL) {
    356     return ;
    357   }
    358 
    359   if (Bridge->ResType == PciBarTypeIo16) {
    360 
    361     CalculateApertureIo16 (Bridge);
    362     return ;
    363   }
    364 
    365   //
    366   // Assume the bridge is aligned
    367   //
    368   for ( CurrentLink = GetFirstNode (&Bridge->ChildList)
    369       ; !IsNull (&Bridge->ChildList, CurrentLink)
    370       ; CurrentLink = GetNextNode (&Bridge->ChildList, CurrentLink)
    371       ) {
    372 
    373     Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
    374     if (Node->ResourceUsage == PciResUsagePadding) {
    375       ASSERT (PaddingAperture == 0);
    376       PaddingAperture = Node->Length;
    377       continue;
    378     }
    379 
    380     //
    381     // Apply padding resource if available
    382     //
    383     Offset = Aperture & (Node->Alignment);
    384 
    385     if (Offset != 0) {
    386 
    387       Aperture = Aperture + (Node->Alignment + 1) - Offset;
    388 
    389     }
    390 
    391     //
    392     // Recode current aperture as a offset
    393     // this offset will be used in future real allocation
    394     //
    395     Node->Offset = Aperture;
    396 
    397     //
    398     // Increment aperture by the length of node
    399     //
    400     Aperture += Node->Length;
    401   }
    402 
    403   //
    404   // At last, adjust the aperture with the bridge's
    405   // alignment
    406   //
    407   Offset = Aperture & (Bridge->Alignment);
    408   if (Offset != 0) {
    409     Aperture = Aperture + (Bridge->Alignment + 1) - Offset;
    410   }
    411 
    412   //
    413   // If the bridge has already padded the resource and the
    414   // amount of padded resource is larger, then keep the
    415   // padded resource
    416   //
    417   if (Bridge->Length < Aperture) {
    418     Bridge->Length = Aperture;
    419   }
    420 
    421   //
    422   // Adjust the bridge's alignment to the first child's alignment
    423   // if the bridge has at least one child
    424   //
    425   CurrentLink = Bridge->ChildList.ForwardLink;
    426   if (CurrentLink != &Bridge->ChildList) {
    427     Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
    428     if (Node->Alignment > Bridge->Alignment) {
    429       Bridge->Alignment = Node->Alignment;
    430     }
    431   }
    432 
    433   //
    434   // Hotplug controller needs padding resources.
    435   // Use the larger one between the padding resource and actual occupied resource.
    436   //
    437   Bridge->Length = MAX (Bridge->Length, PaddingAperture);
    438 }
    439 
    440 /**
    441   Get IO/Memory resource infor for given PCI device.
    442 
    443   @param PciDev     Pci device instance.
    444   @param IoNode     Resource info node for IO .
    445   @param Mem32Node  Resource info node for 32-bit memory.
    446   @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
    447   @param Mem64Node  Resource info node for 64-bit memory.
    448   @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
    449 
    450 **/
    451 VOID
    452 GetResourceFromDevice (
    453   IN     PCI_IO_DEVICE     *PciDev,
    454   IN OUT PCI_RESOURCE_NODE *IoNode,
    455   IN OUT PCI_RESOURCE_NODE *Mem32Node,
    456   IN OUT PCI_RESOURCE_NODE *PMem32Node,
    457   IN OUT PCI_RESOURCE_NODE *Mem64Node,
    458   IN OUT PCI_RESOURCE_NODE *PMem64Node
    459   )
    460 {
    461 
    462   UINT8             Index;
    463   PCI_RESOURCE_NODE *Node;
    464   BOOLEAN           ResourceRequested;
    465 
    466   Node              = NULL;
    467   ResourceRequested = FALSE;
    468 
    469   for (Index = 0; Index < PCI_MAX_BAR; Index++) {
    470 
    471     switch ((PciDev->PciBar)[Index].BarType) {
    472 
    473     case PciBarTypeMem32:
    474 
    475       Node = CreateResourceNode (
    476               PciDev,
    477               (PciDev->PciBar)[Index].Length,
    478               (PciDev->PciBar)[Index].Alignment,
    479               Index,
    480               PciBarTypeMem32,
    481               PciResUsageTypical
    482               );
    483 
    484       InsertResourceNode (
    485         Mem32Node,
    486         Node
    487         );
    488 
    489       ResourceRequested = TRUE;
    490       break;
    491 
    492     case PciBarTypeMem64:
    493 
    494       Node = CreateResourceNode (
    495               PciDev,
    496               (PciDev->PciBar)[Index].Length,
    497               (PciDev->PciBar)[Index].Alignment,
    498               Index,
    499               PciBarTypeMem64,
    500               PciResUsageTypical
    501               );
    502 
    503       InsertResourceNode (
    504         Mem64Node,
    505         Node
    506         );
    507 
    508       ResourceRequested = TRUE;
    509       break;
    510 
    511     case PciBarTypePMem64:
    512 
    513       Node = CreateResourceNode (
    514               PciDev,
    515               (PciDev->PciBar)[Index].Length,
    516               (PciDev->PciBar)[Index].Alignment,
    517               Index,
    518               PciBarTypePMem64,
    519               PciResUsageTypical
    520               );
    521 
    522       InsertResourceNode (
    523         PMem64Node,
    524         Node
    525         );
    526 
    527       ResourceRequested = TRUE;
    528       break;
    529 
    530     case PciBarTypePMem32:
    531 
    532       Node = CreateResourceNode (
    533               PciDev,
    534               (PciDev->PciBar)[Index].Length,
    535               (PciDev->PciBar)[Index].Alignment,
    536               Index,
    537               PciBarTypePMem32,
    538               PciResUsageTypical
    539               );
    540 
    541       InsertResourceNode (
    542         PMem32Node,
    543         Node
    544         );
    545       ResourceRequested = TRUE;
    546       break;
    547 
    548     case PciBarTypeIo16:
    549     case PciBarTypeIo32:
    550 
    551       Node = CreateResourceNode (
    552               PciDev,
    553               (PciDev->PciBar)[Index].Length,
    554               (PciDev->PciBar)[Index].Alignment,
    555               Index,
    556               PciBarTypeIo16,
    557               PciResUsageTypical
    558               );
    559 
    560       InsertResourceNode (
    561         IoNode,
    562         Node
    563         );
    564       ResourceRequested = TRUE;
    565       break;
    566 
    567     case PciBarTypeUnknown:
    568       break;
    569 
    570     default:
    571       break;
    572     }
    573   }
    574 
    575   //
    576   // Add VF resource
    577   //
    578   for (Index = 0; Index < PCI_MAX_BAR; Index++) {
    579 
    580     switch ((PciDev->VfPciBar)[Index].BarType) {
    581 
    582     case PciBarTypeMem32:
    583 
    584       Node = CreateVfResourceNode (
    585               PciDev,
    586               (PciDev->VfPciBar)[Index].Length,
    587               (PciDev->VfPciBar)[Index].Alignment,
    588               Index,
    589               PciBarTypeMem32,
    590               PciResUsageTypical
    591               );
    592 
    593       InsertResourceNode (
    594         Mem32Node,
    595         Node
    596         );
    597 
    598       break;
    599 
    600     case PciBarTypeMem64:
    601 
    602       Node = CreateVfResourceNode (
    603               PciDev,
    604               (PciDev->VfPciBar)[Index].Length,
    605               (PciDev->VfPciBar)[Index].Alignment,
    606               Index,
    607               PciBarTypeMem64,
    608               PciResUsageTypical
    609               );
    610 
    611       InsertResourceNode (
    612         Mem64Node,
    613         Node
    614         );
    615 
    616       break;
    617 
    618     case PciBarTypePMem64:
    619 
    620       Node = CreateVfResourceNode (
    621               PciDev,
    622               (PciDev->VfPciBar)[Index].Length,
    623               (PciDev->VfPciBar)[Index].Alignment,
    624               Index,
    625               PciBarTypePMem64,
    626               PciResUsageTypical
    627               );
    628 
    629       InsertResourceNode (
    630         PMem64Node,
    631         Node
    632         );
    633 
    634       break;
    635 
    636     case PciBarTypePMem32:
    637 
    638       Node = CreateVfResourceNode (
    639               PciDev,
    640               (PciDev->VfPciBar)[Index].Length,
    641               (PciDev->VfPciBar)[Index].Alignment,
    642               Index,
    643               PciBarTypePMem32,
    644               PciResUsageTypical
    645               );
    646 
    647       InsertResourceNode (
    648         PMem32Node,
    649         Node
    650         );
    651       break;
    652 
    653     case PciBarTypeIo16:
    654     case PciBarTypeIo32:
    655       break;
    656 
    657     case PciBarTypeUnknown:
    658       break;
    659 
    660     default:
    661       break;
    662     }
    663   }
    664   // If there is no resource requested from this device,
    665   // then we indicate this device has been allocated naturally.
    666   //
    667   if (!ResourceRequested) {
    668     PciDev->Allocated = TRUE;
    669   }
    670 }
    671 
    672 /**
    673   This function is used to create a resource node.
    674 
    675   @param PciDev       Pci device instance.
    676   @param Length       Length of Io/Memory resource.
    677   @param Alignment    Alignment of resource.
    678   @param Bar          Bar index.
    679   @param ResType      Type of resource: IO/Memory.
    680   @param ResUsage     Resource usage.
    681 
    682   @return PCI resource node created for given PCI device.
    683           NULL means PCI resource node is not created.
    684 
    685 **/
    686 PCI_RESOURCE_NODE *
    687 CreateResourceNode (
    688   IN PCI_IO_DEVICE         *PciDev,
    689   IN UINT64                Length,
    690   IN UINT64                Alignment,
    691   IN UINT8                 Bar,
    692   IN PCI_BAR_TYPE          ResType,
    693   IN PCI_RESOURCE_USAGE    ResUsage
    694   )
    695 {
    696   PCI_RESOURCE_NODE *Node;
    697 
    698   Node    = NULL;
    699 
    700   Node    = AllocateZeroPool (sizeof (PCI_RESOURCE_NODE));
    701   ASSERT (Node != NULL);
    702   if (Node == NULL) {
    703     return NULL;
    704   }
    705 
    706   Node->Signature     = PCI_RESOURCE_SIGNATURE;
    707   Node->PciDev        = PciDev;
    708   Node->Length        = Length;
    709   Node->Alignment     = Alignment;
    710   Node->Bar           = Bar;
    711   Node->ResType       = ResType;
    712   Node->Reserved      = FALSE;
    713   Node->ResourceUsage = ResUsage;
    714   InitializeListHead (&Node->ChildList);
    715 
    716   return Node;
    717 }
    718 
    719 /**
    720   This function is used to create a IOV VF resource node.
    721 
    722   @param PciDev       Pci device instance.
    723   @param Length       Length of Io/Memory resource.
    724   @param Alignment    Alignment of resource.
    725   @param Bar          Bar index.
    726   @param ResType      Type of resource: IO/Memory.
    727   @param ResUsage     Resource usage.
    728 
    729   @return PCI resource node created for given VF PCI device.
    730           NULL means PCI resource node is not created.
    731 
    732 **/
    733 PCI_RESOURCE_NODE *
    734 CreateVfResourceNode (
    735   IN PCI_IO_DEVICE         *PciDev,
    736   IN UINT64                Length,
    737   IN UINT64                Alignment,
    738   IN UINT8                 Bar,
    739   IN PCI_BAR_TYPE          ResType,
    740   IN PCI_RESOURCE_USAGE    ResUsage
    741   )
    742 {
    743   PCI_RESOURCE_NODE *Node;
    744 
    745   Node = CreateResourceNode (PciDev, Length, Alignment, Bar, ResType, ResUsage);
    746   if (Node == NULL) {
    747     return Node;
    748   }
    749 
    750   Node->Virtual = TRUE;
    751 
    752   return Node;
    753 }
    754 
    755 /**
    756   This function is used to extract resource request from
    757   device node list.
    758 
    759   @param Bridge     Pci device instance.
    760   @param IoNode     Resource info node for IO.
    761   @param Mem32Node  Resource info node for 32-bit memory.
    762   @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
    763   @param Mem64Node  Resource info node for 64-bit memory.
    764   @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
    765 
    766 **/
    767 VOID
    768 CreateResourceMap (
    769   IN     PCI_IO_DEVICE     *Bridge,
    770   IN OUT PCI_RESOURCE_NODE *IoNode,
    771   IN OUT PCI_RESOURCE_NODE *Mem32Node,
    772   IN OUT PCI_RESOURCE_NODE *PMem32Node,
    773   IN OUT PCI_RESOURCE_NODE *Mem64Node,
    774   IN OUT PCI_RESOURCE_NODE *PMem64Node
    775   )
    776 {
    777   PCI_IO_DEVICE     *Temp;
    778   PCI_RESOURCE_NODE *IoBridge;
    779   PCI_RESOURCE_NODE *Mem32Bridge;
    780   PCI_RESOURCE_NODE *PMem32Bridge;
    781   PCI_RESOURCE_NODE *Mem64Bridge;
    782   PCI_RESOURCE_NODE *PMem64Bridge;
    783   LIST_ENTRY        *CurrentLink;
    784 
    785   CurrentLink = Bridge->ChildList.ForwardLink;
    786 
    787   while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {
    788 
    789     Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
    790 
    791     //
    792     // Create resource nodes for this device by scanning the
    793     // Bar array in the device private data
    794     // If the upstream bridge doesn't support this device,
    795     // no any resource node will be created for this device
    796     //
    797     GetResourceFromDevice (
    798       Temp,
    799       IoNode,
    800       Mem32Node,
    801       PMem32Node,
    802       Mem64Node,
    803       PMem64Node
    804       );
    805 
    806     if (IS_PCI_BRIDGE (&Temp->Pci)) {
    807 
    808       //
    809       // If the device has children, create a bridge resource node for this PPB
    810       // Note: For PPB, memory aperture is aligned with 1MB and IO aperture
    811       // is aligned with 4KB (smaller alignments may be supported).
    812       //
    813       IoBridge = CreateResourceNode (
    814                    Temp,
    815                    0,
    816                    Temp->BridgeIoAlignment,
    817                    PPB_IO_RANGE,
    818                    PciBarTypeIo16,
    819                    PciResUsageTypical
    820                    );
    821 
    822       Mem32Bridge = CreateResourceNode (
    823                       Temp,
    824                       0,
    825                       0xFFFFF,
    826                       PPB_MEM32_RANGE,
    827                       PciBarTypeMem32,
    828                       PciResUsageTypical
    829                       );
    830 
    831       PMem32Bridge = CreateResourceNode (
    832                        Temp,
    833                        0,
    834                        0xFFFFF,
    835                        PPB_PMEM32_RANGE,
    836                        PciBarTypePMem32,
    837                        PciResUsageTypical
    838                        );
    839 
    840       Mem64Bridge = CreateResourceNode (
    841                       Temp,
    842                       0,
    843                       0xFFFFF,
    844                       PPB_MEM64_RANGE,
    845                       PciBarTypeMem64,
    846                       PciResUsageTypical
    847                       );
    848 
    849       PMem64Bridge = CreateResourceNode (
    850                        Temp,
    851                        0,
    852                        0xFFFFF,
    853                        PPB_PMEM64_RANGE,
    854                        PciBarTypePMem64,
    855                        PciResUsageTypical
    856                        );
    857 
    858       //
    859       // Recursively create resouce map on this bridge
    860       //
    861       CreateResourceMap (
    862         Temp,
    863         IoBridge,
    864         Mem32Bridge,
    865         PMem32Bridge,
    866         Mem64Bridge,
    867         PMem64Bridge
    868         );
    869 
    870       if (ResourceRequestExisted (IoBridge)) {
    871         InsertResourceNode (
    872           IoNode,
    873           IoBridge
    874           );
    875       } else {
    876         FreePool (IoBridge);
    877         IoBridge = NULL;
    878       }
    879 
    880       //
    881       // If there is node under this resource bridge,
    882       // then calculate bridge's aperture of this type
    883       // and insert it into the respective resource tree.
    884       // If no, delete this resource bridge
    885       //
    886       if (ResourceRequestExisted (Mem32Bridge)) {
    887         InsertResourceNode (
    888           Mem32Node,
    889           Mem32Bridge
    890           );
    891       } else {
    892         FreePool (Mem32Bridge);
    893         Mem32Bridge = NULL;
    894       }
    895 
    896       //
    897       // If there is node under this resource bridge,
    898       // then calculate bridge's aperture of this type
    899       // and insert it into the respective resource tree.
    900       // If no, delete this resource bridge
    901       //
    902       if (ResourceRequestExisted (PMem32Bridge)) {
    903         InsertResourceNode (
    904           PMem32Node,
    905           PMem32Bridge
    906           );
    907       } else {
    908         FreePool (PMem32Bridge);
    909         PMem32Bridge = NULL;
    910       }
    911 
    912       //
    913       // If there is node under this resource bridge,
    914       // then calculate bridge's aperture of this type
    915       // and insert it into the respective resource tree.
    916       // If no, delete this resource bridge
    917       //
    918       if (ResourceRequestExisted (Mem64Bridge)) {
    919         InsertResourceNode (
    920           Mem64Node,
    921           Mem64Bridge
    922           );
    923       } else {
    924         FreePool (Mem64Bridge);
    925         Mem64Bridge = NULL;
    926       }
    927 
    928       //
    929       // If there is node under this resource bridge,
    930       // then calculate bridge's aperture of this type
    931       // and insert it into the respective resource tree.
    932       // If no, delete this resource bridge
    933       //
    934       if (ResourceRequestExisted (PMem64Bridge)) {
    935         InsertResourceNode (
    936           PMem64Node,
    937           PMem64Bridge
    938           );
    939       } else {
    940         FreePool (PMem64Bridge);
    941         PMem64Bridge = NULL;
    942       }
    943 
    944     }
    945 
    946     //
    947     // If it is P2C, apply hard coded resource padding
    948     //
    949     if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {
    950       ResourcePaddingForCardBusBridge (
    951         Temp,
    952         IoNode,
    953         Mem32Node,
    954         PMem32Node,
    955         Mem64Node,
    956         PMem64Node
    957         );
    958     }
    959 
    960     CurrentLink = CurrentLink->ForwardLink;
    961   }
    962 
    963   //
    964   // To do some platform specific resource padding ...
    965   //
    966   ResourcePaddingPolicy (
    967     Bridge,
    968     IoNode,
    969     Mem32Node,
    970     PMem32Node,
    971     Mem64Node,
    972     PMem64Node
    973     );
    974 
    975   //
    976   // Degrade resource if necessary
    977   //
    978   DegradeResource (
    979     Bridge,
    980     Mem32Node,
    981     PMem32Node,
    982     Mem64Node,
    983     PMem64Node
    984     );
    985 
    986   //
    987   // Calculate resource aperture for this bridge device
    988   //
    989   CalculateResourceAperture (Mem32Node);
    990   CalculateResourceAperture (PMem32Node);
    991   CalculateResourceAperture (Mem64Node);
    992   CalculateResourceAperture (PMem64Node);
    993   CalculateResourceAperture (IoNode);
    994 }
    995 
    996 /**
    997   This function is used to do the resource padding for a specific platform.
    998 
    999   @param PciDev     Pci device instance.
   1000   @param IoNode     Resource info node for IO.
   1001   @param Mem32Node  Resource info node for 32-bit memory.
   1002   @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
   1003   @param Mem64Node  Resource info node for 64-bit memory.
   1004   @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
   1005 
   1006 **/
   1007 VOID
   1008 ResourcePaddingPolicy (
   1009   IN PCI_IO_DEVICE     *PciDev,
   1010   IN PCI_RESOURCE_NODE *IoNode,
   1011   IN PCI_RESOURCE_NODE *Mem32Node,
   1012   IN PCI_RESOURCE_NODE *PMem32Node,
   1013   IN PCI_RESOURCE_NODE *Mem64Node,
   1014   IN PCI_RESOURCE_NODE *PMem64Node
   1015   )
   1016 {
   1017   //
   1018   // Create padding resource node
   1019   //
   1020   if (PciDev->ResourcePaddingDescriptors != NULL) {
   1021     ApplyResourcePadding (
   1022       PciDev,
   1023       IoNode,
   1024       Mem32Node,
   1025       PMem32Node,
   1026       Mem64Node,
   1027       PMem64Node
   1028       );
   1029   }
   1030 }
   1031 
   1032 /**
   1033   This function is used to degrade resource if the upstream bridge
   1034   doesn't support certain resource. Degradation path is
   1035   PMEM64 -> MEM64  -> MEM32
   1036   PMEM64 -> PMEM32 -> MEM32
   1037   IO32   -> IO16.
   1038 
   1039   @param Bridge     Pci device instance.
   1040   @param Mem32Node  Resource info node for 32-bit memory.
   1041   @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
   1042   @param Mem64Node  Resource info node for 64-bit memory.
   1043   @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
   1044 
   1045 **/
   1046 VOID
   1047 DegradeResource (
   1048   IN PCI_IO_DEVICE     *Bridge,
   1049   IN PCI_RESOURCE_NODE *Mem32Node,
   1050   IN PCI_RESOURCE_NODE *PMem32Node,
   1051   IN PCI_RESOURCE_NODE *Mem64Node,
   1052   IN PCI_RESOURCE_NODE *PMem64Node
   1053   )
   1054 {
   1055   PCI_IO_DEVICE        *PciIoDevice;
   1056   LIST_ENTRY           *ChildDeviceLink;
   1057   LIST_ENTRY           *ChildNodeLink;
   1058   LIST_ENTRY           *NextChildNodeLink;
   1059   PCI_RESOURCE_NODE    *ResourceNode;
   1060 
   1061   if (FeaturePcdGet (PcdPciDegradeResourceForOptionRom)) {
   1062     //
   1063     // If any child device has both option ROM and 64-bit BAR, degrade its PMEM64/MEM64
   1064     // requests in case that if a legacy option ROM image can not access 64-bit resources.
   1065     //
   1066     ChildDeviceLink = Bridge->ChildList.ForwardLink;
   1067     while (ChildDeviceLink != NULL && ChildDeviceLink != &Bridge->ChildList) {
   1068       PciIoDevice = PCI_IO_DEVICE_FROM_LINK (ChildDeviceLink);
   1069       if (PciIoDevice->RomSize != 0) {
   1070         if (!IsListEmpty (&Mem64Node->ChildList)) {
   1071           ChildNodeLink = Mem64Node->ChildList.ForwardLink;
   1072           while (ChildNodeLink != &Mem64Node->ChildList) {
   1073             ResourceNode = RESOURCE_NODE_FROM_LINK (ChildNodeLink);
   1074             NextChildNodeLink = ChildNodeLink->ForwardLink;
   1075 
   1076             if ((ResourceNode->PciDev == PciIoDevice) &&
   1077                 (ResourceNode->Virtual || !PciIoDevice->PciBar[ResourceNode->Bar].BarTypeFixed)
   1078                 ) {
   1079               RemoveEntryList (ChildNodeLink);
   1080               InsertResourceNode (Mem32Node, ResourceNode);
   1081             }
   1082             ChildNodeLink = NextChildNodeLink;
   1083           }
   1084         }
   1085 
   1086         if (!IsListEmpty (&PMem64Node->ChildList)) {
   1087           ChildNodeLink = PMem64Node->ChildList.ForwardLink;
   1088           while (ChildNodeLink != &PMem64Node->ChildList) {
   1089             ResourceNode = RESOURCE_NODE_FROM_LINK (ChildNodeLink);
   1090             NextChildNodeLink = ChildNodeLink->ForwardLink;
   1091 
   1092             if ((ResourceNode->PciDev == PciIoDevice) &&
   1093                 (ResourceNode->Virtual || !PciIoDevice->PciBar[ResourceNode->Bar].BarTypeFixed)
   1094                 ) {
   1095               RemoveEntryList (ChildNodeLink);
   1096               InsertResourceNode (PMem32Node, ResourceNode);
   1097             }
   1098             ChildNodeLink = NextChildNodeLink;
   1099           }
   1100         }
   1101 
   1102       }
   1103       ChildDeviceLink = ChildDeviceLink->ForwardLink;
   1104     }
   1105   }
   1106 
   1107   //
   1108   // If firmware is in 32-bit mode,
   1109   // then degrade PMEM64/MEM64 requests
   1110   //
   1111   if (sizeof (UINTN) <= 4) {
   1112     MergeResourceTree (
   1113       Mem32Node,
   1114       Mem64Node,
   1115       TRUE
   1116       );
   1117 
   1118     MergeResourceTree (
   1119       PMem32Node,
   1120       PMem64Node,
   1121       TRUE
   1122       );
   1123   } else {
   1124     //
   1125     // if the bridge does not support MEM64, degrade MEM64 to MEM32
   1126     //
   1127     if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_MEM64_DECODE_SUPPORTED)) {
   1128         MergeResourceTree (
   1129           Mem32Node,
   1130           Mem64Node,
   1131           TRUE
   1132           );
   1133     }
   1134 
   1135     //
   1136     // if the bridge does not support PMEM64, degrade PMEM64 to PMEM32
   1137     //
   1138     if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM64_DECODE_SUPPORTED)) {
   1139       MergeResourceTree (
   1140         PMem32Node,
   1141         PMem64Node,
   1142         TRUE
   1143         );
   1144     }
   1145 
   1146     //
   1147     // if both PMEM64 and PMEM32 requests from child devices, which can not be satisfied
   1148     // by a P2P bridge simultaneously, keep PMEM64 and degrade PMEM32 to MEM32.
   1149     //
   1150     if (!IsListEmpty (&PMem64Node->ChildList) && Bridge->Parent != NULL) {
   1151       MergeResourceTree (
   1152         Mem32Node,
   1153         PMem32Node,
   1154         TRUE
   1155         );
   1156     }
   1157   }
   1158 
   1159   //
   1160   // If bridge doesn't support Pmem32
   1161   // degrade it to mem32
   1162   //
   1163   if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM32_DECODE_SUPPORTED)) {
   1164     MergeResourceTree (
   1165       Mem32Node,
   1166       PMem32Node,
   1167       TRUE
   1168       );
   1169   }
   1170 
   1171   //
   1172   // if root bridge supports combined Pmem Mem decoding
   1173   // merge these two type of resource
   1174   //
   1175   if (BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED)) {
   1176     MergeResourceTree (
   1177       Mem32Node,
   1178       PMem32Node,
   1179       FALSE
   1180       );
   1181 
   1182     //
   1183     // No need to check if to degrade MEM64 after merge, because
   1184     // if there are PMEM64 still here, 64-bit decode should be supported
   1185     // by the root bride.
   1186     //
   1187     MergeResourceTree (
   1188       Mem64Node,
   1189       PMem64Node,
   1190       FALSE
   1191       );
   1192   }
   1193 }
   1194 
   1195 /**
   1196   Test whether bridge device support decode resource.
   1197 
   1198   @param Bridge    Bridge device instance.
   1199   @param Decode    Decode type according to resource type.
   1200 
   1201   @return TRUE     The bridge device support decode resource.
   1202   @return FALSE    The bridge device don't support decode resource.
   1203 
   1204 **/
   1205 BOOLEAN
   1206 BridgeSupportResourceDecode (
   1207   IN PCI_IO_DEVICE *Bridge,
   1208   IN UINT32        Decode
   1209   )
   1210 {
   1211   if (((Bridge->Decodes) & Decode) != 0) {
   1212     return TRUE;
   1213   }
   1214 
   1215   return FALSE;
   1216 }
   1217 
   1218 /**
   1219   This function is used to program the resource allocated
   1220   for each resource node under specified bridge.
   1221 
   1222   @param Base     Base address of resource to be progammed.
   1223   @param Bridge   PCI resource node for the bridge device.
   1224 
   1225   @retval EFI_SUCCESS            Successfully to program all resouces
   1226                                  on given PCI bridge device.
   1227   @retval EFI_OUT_OF_RESOURCES   Base is all one.
   1228 
   1229 **/
   1230 EFI_STATUS
   1231 ProgramResource (
   1232   IN UINT64            Base,
   1233   IN PCI_RESOURCE_NODE *Bridge
   1234   )
   1235 {
   1236   LIST_ENTRY        *CurrentLink;
   1237   PCI_RESOURCE_NODE *Node;
   1238   EFI_STATUS        Status;
   1239 
   1240   if (Base == gAllOne) {
   1241     return EFI_OUT_OF_RESOURCES;
   1242   }
   1243 
   1244   CurrentLink = Bridge->ChildList.ForwardLink;
   1245 
   1246   while (CurrentLink != &Bridge->ChildList) {
   1247 
   1248     Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
   1249 
   1250     if (!IS_PCI_BRIDGE (&(Node->PciDev->Pci))) {
   1251 
   1252       if (IS_CARDBUS_BRIDGE (&(Node->PciDev->Pci))) {
   1253         //
   1254         // Program the PCI Card Bus device
   1255         //
   1256         ProgramP2C (Base, Node);
   1257       } else {
   1258         //
   1259         // Program the PCI device BAR
   1260         //
   1261         ProgramBar (Base, Node);
   1262       }
   1263     } else {
   1264       //
   1265       // Program the PCI devices under this bridge
   1266       //
   1267       Status = ProgramResource (Base + Node->Offset, Node);
   1268       if (EFI_ERROR (Status)) {
   1269         return Status;
   1270       }
   1271 
   1272       ProgramPpbApperture (Base, Node);
   1273     }
   1274 
   1275     CurrentLink = CurrentLink->ForwardLink;
   1276   }
   1277 
   1278   return EFI_SUCCESS;
   1279 }
   1280 
   1281 /**
   1282   Program Bar register for PCI device.
   1283 
   1284   @param Base  Base address for PCI device resource to be progammed.
   1285   @param Node  Point to resoure node structure.
   1286 
   1287 **/
   1288 VOID
   1289 ProgramBar (
   1290   IN UINT64            Base,
   1291   IN PCI_RESOURCE_NODE *Node
   1292   )
   1293 {
   1294   EFI_PCI_IO_PROTOCOL *PciIo;
   1295   UINT64              Address;
   1296   UINT32              Address32;
   1297 
   1298   ASSERT (Node->Bar < PCI_MAX_BAR);
   1299 
   1300   //
   1301   // Check VF BAR
   1302   //
   1303   if (Node->Virtual) {
   1304     ProgramVfBar (Base, Node);
   1305     return;
   1306   }
   1307 
   1308   Address = 0;
   1309   PciIo   = &(Node->PciDev->PciIo);
   1310 
   1311   Address = Base + Node->Offset;
   1312 
   1313   //
   1314   // Indicate pci bus driver has allocated
   1315   // resource for this device
   1316   // It might be a temporary solution here since
   1317   // pci device could have multiple bar
   1318   //
   1319   Node->PciDev->Allocated = TRUE;
   1320 
   1321   switch ((Node->PciDev->PciBar[Node->Bar]).BarType) {
   1322 
   1323   case PciBarTypeIo16:
   1324   case PciBarTypeIo32:
   1325   case PciBarTypeMem32:
   1326   case PciBarTypePMem32:
   1327 
   1328     PciIo->Pci.Write (
   1329                  PciIo,
   1330                  EfiPciIoWidthUint32,
   1331                  (Node->PciDev->PciBar[Node->Bar]).Offset,
   1332                  1,
   1333                  &Address
   1334                  );
   1335 
   1336     Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
   1337 
   1338     break;
   1339 
   1340   case PciBarTypeMem64:
   1341   case PciBarTypePMem64:
   1342 
   1343     Address32 = (UINT32) (Address & 0x00000000FFFFFFFF);
   1344 
   1345     PciIo->Pci.Write (
   1346                  PciIo,
   1347                  EfiPciIoWidthUint32,
   1348                  (Node->PciDev->PciBar[Node->Bar]).Offset,
   1349                  1,
   1350                  &Address32
   1351                  );
   1352 
   1353     Address32 = (UINT32) RShiftU64 (Address, 32);
   1354 
   1355     PciIo->Pci.Write (
   1356                  PciIo,
   1357                  EfiPciIoWidthUint32,
   1358                  (UINT8) ((Node->PciDev->PciBar[Node->Bar]).Offset + 4),
   1359                  1,
   1360                  &Address32
   1361                  );
   1362 
   1363     Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
   1364 
   1365     break;
   1366 
   1367   default:
   1368     break;
   1369   }
   1370 }
   1371 
   1372 /**
   1373   Program IOV VF Bar register for PCI device.
   1374 
   1375   @param Base  Base address for PCI device resource to be progammed.
   1376   @param Node  Point to resoure node structure.
   1377 
   1378 **/
   1379 EFI_STATUS
   1380 ProgramVfBar (
   1381   IN UINT64            Base,
   1382   IN PCI_RESOURCE_NODE *Node
   1383   )
   1384 {
   1385   EFI_PCI_IO_PROTOCOL *PciIo;
   1386   UINT64              Address;
   1387   UINT32              Address32;
   1388 
   1389   ASSERT (Node->Bar < PCI_MAX_BAR);
   1390   ASSERT (Node->Virtual);
   1391 
   1392   Address = 0;
   1393   PciIo   = &(Node->PciDev->PciIo);
   1394 
   1395   Address = Base + Node->Offset;
   1396 
   1397   //
   1398   // Indicate pci bus driver has allocated
   1399   // resource for this device
   1400   // It might be a temporary solution here since
   1401   // pci device could have multiple bar
   1402   //
   1403   Node->PciDev->Allocated = TRUE;
   1404 
   1405   switch ((Node->PciDev->VfPciBar[Node->Bar]).BarType) {
   1406 
   1407   case PciBarTypeMem32:
   1408   case PciBarTypePMem32:
   1409 
   1410     PciIo->Pci.Write (
   1411                 PciIo,
   1412                 EfiPciIoWidthUint32,
   1413                 (Node->PciDev->VfPciBar[Node->Bar]).Offset,
   1414                 1,
   1415                 &Address
   1416                 );
   1417 
   1418     Node->PciDev->VfPciBar[Node->Bar].BaseAddress = Address;
   1419     break;
   1420 
   1421   case PciBarTypeMem64:
   1422   case PciBarTypePMem64:
   1423 
   1424     Address32 = (UINT32) (Address & 0x00000000FFFFFFFF);
   1425 
   1426     PciIo->Pci.Write (
   1427                 PciIo,
   1428                 EfiPciIoWidthUint32,
   1429                 (Node->PciDev->VfPciBar[Node->Bar]).Offset,
   1430                 1,
   1431                 &Address32
   1432                 );
   1433 
   1434     Address32 = (UINT32) RShiftU64 (Address, 32);
   1435 
   1436     PciIo->Pci.Write (
   1437                 PciIo,
   1438                 EfiPciIoWidthUint32,
   1439                 ((Node->PciDev->VfPciBar[Node->Bar]).Offset + 4),
   1440                 1,
   1441                 &Address32
   1442                 );
   1443 
   1444     Node->PciDev->VfPciBar[Node->Bar].BaseAddress = Address;
   1445     break;
   1446 
   1447   case PciBarTypeIo16:
   1448   case PciBarTypeIo32:
   1449     break;
   1450 
   1451   default:
   1452     break;
   1453   }
   1454 
   1455   return EFI_SUCCESS;
   1456 }
   1457 
   1458 /**
   1459   Program PCI-PCI bridge apperture.
   1460 
   1461   @param Base  Base address for resource.
   1462   @param Node  Point to resoure node structure.
   1463 
   1464 **/
   1465 VOID
   1466 ProgramPpbApperture (
   1467   IN UINT64            Base,
   1468   IN PCI_RESOURCE_NODE *Node
   1469   )
   1470 {
   1471   EFI_PCI_IO_PROTOCOL *PciIo;
   1472   UINT64              Address;
   1473   UINT32              Address32;
   1474 
   1475   Address = 0;
   1476   //
   1477   // If no device resource of this PPB, return anyway
   1478   // Apperture is set default in the initialization code
   1479   //
   1480   if (Node->Length == 0 || Node->ResourceUsage == PciResUsagePadding) {
   1481     //
   1482     // For padding resource node, just ignore when programming
   1483     //
   1484     return ;
   1485   }
   1486 
   1487   PciIo   = &(Node->PciDev->PciIo);
   1488   Address = Base + Node->Offset;
   1489 
   1490   //
   1491   // Indicate the PPB resource has been allocated
   1492   //
   1493   Node->PciDev->Allocated = TRUE;
   1494 
   1495   switch (Node->Bar) {
   1496 
   1497   case PPB_BAR_0:
   1498   case PPB_BAR_1:
   1499     switch ((Node->PciDev->PciBar[Node->Bar]).BarType) {
   1500 
   1501       case PciBarTypeIo16:
   1502       case PciBarTypeIo32:
   1503       case PciBarTypeMem32:
   1504       case PciBarTypePMem32:
   1505 
   1506         PciIo->Pci.Write (
   1507                  PciIo,
   1508                  EfiPciIoWidthUint32,
   1509                  (Node->PciDev->PciBar[Node->Bar]).Offset,
   1510                  1,
   1511                  &Address
   1512                  );
   1513 
   1514         Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
   1515         Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;
   1516         break;
   1517 
   1518       case PciBarTypeMem64:
   1519       case PciBarTypePMem64:
   1520 
   1521         Address32 = (UINT32) (Address & 0x00000000FFFFFFFF);
   1522 
   1523         PciIo->Pci.Write (
   1524                  PciIo,
   1525                  EfiPciIoWidthUint32,
   1526                  (Node->PciDev->PciBar[Node->Bar]).Offset,
   1527                  1,
   1528                  &Address32
   1529                  );
   1530 
   1531         Address32 = (UINT32) RShiftU64 (Address, 32);
   1532 
   1533         PciIo->Pci.Write (
   1534                  PciIo,
   1535                  EfiPciIoWidthUint32,
   1536                  (UINT8) ((Node->PciDev->PciBar[Node->Bar]).Offset + 4),
   1537                  1,
   1538                  &Address32
   1539                  );
   1540 
   1541         Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
   1542         Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;
   1543         break;
   1544 
   1545       default:
   1546         break;
   1547     }
   1548     break;
   1549 
   1550   case PPB_IO_RANGE:
   1551 
   1552     Address32 = ((UINT32) (Address)) >> 8;
   1553     PciIo->Pci.Write (
   1554                  PciIo,
   1555                  EfiPciIoWidthUint8,
   1556                  0x1C,
   1557                  1,
   1558                  &Address32
   1559                  );
   1560 
   1561     Address32 >>= 8;
   1562     PciIo->Pci.Write (
   1563                  PciIo,
   1564                  EfiPciIoWidthUint16,
   1565                  0x30,
   1566                  1,
   1567                  &Address32
   1568                  );
   1569 
   1570     Address32 = (UINT32) (Address + Node->Length - 1);
   1571     Address32 = ((UINT32) (Address32)) >> 8;
   1572     PciIo->Pci.Write (
   1573                  PciIo,
   1574                  EfiPciIoWidthUint8,
   1575                  0x1D,
   1576                  1,
   1577                  &Address32
   1578                  );
   1579 
   1580     Address32 >>= 8;
   1581     PciIo->Pci.Write (
   1582                  PciIo,
   1583                  EfiPciIoWidthUint16,
   1584                  0x32,
   1585                  1,
   1586                  &Address32
   1587                  );
   1588 
   1589     Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
   1590     Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;
   1591     break;
   1592 
   1593   case PPB_MEM32_RANGE:
   1594 
   1595     Address32 = ((UINT32) (Address)) >> 16;
   1596     PciIo->Pci.Write (
   1597                  PciIo,
   1598                  EfiPciIoWidthUint16,
   1599                  0x20,
   1600                  1,
   1601                  &Address32
   1602                  );
   1603 
   1604     Address32 = (UINT32) (Address + Node->Length - 1);
   1605     Address32 = ((UINT32) (Address32)) >> 16;
   1606     PciIo->Pci.Write (
   1607                  PciIo,
   1608                  EfiPciIoWidthUint16,
   1609                  0x22,
   1610                  1,
   1611                  &Address32
   1612                  );
   1613 
   1614     Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
   1615     Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;
   1616     break;
   1617 
   1618   case PPB_PMEM32_RANGE:
   1619   case PPB_PMEM64_RANGE:
   1620 
   1621     Address32 = ((UINT32) (Address)) >> 16;
   1622     PciIo->Pci.Write (
   1623                  PciIo,
   1624                  EfiPciIoWidthUint16,
   1625                  0x24,
   1626                  1,
   1627                  &Address32
   1628                  );
   1629 
   1630     Address32 = (UINT32) (Address + Node->Length - 1);
   1631     Address32 = ((UINT32) (Address32)) >> 16;
   1632     PciIo->Pci.Write (
   1633                  PciIo,
   1634                  EfiPciIoWidthUint16,
   1635                  0x26,
   1636                  1,
   1637                  &Address32
   1638                  );
   1639 
   1640     Address32 = (UINT32) RShiftU64 (Address, 32);
   1641     PciIo->Pci.Write (
   1642                  PciIo,
   1643                  EfiPciIoWidthUint32,
   1644                  0x28,
   1645                  1,
   1646                  &Address32
   1647                  );
   1648 
   1649     Address32 = (UINT32) RShiftU64 ((Address + Node->Length - 1), 32);
   1650     PciIo->Pci.Write (
   1651                  PciIo,
   1652                  EfiPciIoWidthUint32,
   1653                  0x2C,
   1654                  1,
   1655                  &Address32
   1656                  );
   1657 
   1658     Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
   1659     Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;
   1660     break;
   1661 
   1662   default:
   1663     break;
   1664   }
   1665 }
   1666 
   1667 /**
   1668   Program parent bridge for Option Rom.
   1669 
   1670   @param PciDevice      Pci deivce instance.
   1671   @param OptionRomBase  Base address for Optiona Rom.
   1672   @param Enable         Enable or disable PCI memory.
   1673 
   1674 **/
   1675 VOID
   1676 ProgrameUpstreamBridgeForRom (
   1677   IN PCI_IO_DEVICE   *PciDevice,
   1678   IN UINT32          OptionRomBase,
   1679   IN BOOLEAN         Enable
   1680   )
   1681 {
   1682   PCI_IO_DEVICE     *Parent;
   1683   PCI_RESOURCE_NODE Node;
   1684   //
   1685   // For root bridge, just return.
   1686   //
   1687   Parent = PciDevice->Parent;
   1688   ZeroMem (&Node, sizeof (Node));
   1689   while (Parent != NULL) {
   1690     if (!IS_PCI_BRIDGE (&Parent->Pci)) {
   1691       break;
   1692     }
   1693 
   1694     Node.PciDev     = Parent;
   1695     Node.Length     = PciDevice->RomSize;
   1696     Node.Alignment  = 0;
   1697     Node.Bar        = PPB_MEM32_RANGE;
   1698     Node.ResType    = PciBarTypeMem32;
   1699     Node.Offset     = 0;
   1700 
   1701     //
   1702     // Program PPB to only open a single <= 16MB apperture
   1703     //
   1704     if (Enable) {
   1705       ProgramPpbApperture (OptionRomBase, &Node);
   1706       PCI_ENABLE_COMMAND_REGISTER (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);
   1707     } else {
   1708       InitializePpb (Parent);
   1709       PCI_DISABLE_COMMAND_REGISTER (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);
   1710     }
   1711 
   1712     Parent = Parent->Parent;
   1713   }
   1714 }
   1715 
   1716 /**
   1717   Test whether resource exists for a bridge.
   1718 
   1719   @param Bridge  Point to resource node for a bridge.
   1720 
   1721   @retval TRUE   There is resource on the given bridge.
   1722   @retval FALSE  There isn't resource on the given bridge.
   1723 
   1724 **/
   1725 BOOLEAN
   1726 ResourceRequestExisted (
   1727   IN PCI_RESOURCE_NODE    *Bridge
   1728   )
   1729 {
   1730   if (Bridge != NULL) {
   1731     if (!IsListEmpty (&Bridge->ChildList) || Bridge->Length != 0) {
   1732       return TRUE;
   1733     }
   1734   }
   1735 
   1736   return FALSE;
   1737 }
   1738 
   1739 /**
   1740   Initialize resource pool structure.
   1741 
   1742   @param ResourcePool Point to resource pool structure. This pool
   1743                       is reset to all zero when returned.
   1744   @param ResourceType Type of resource.
   1745 
   1746 **/
   1747 VOID
   1748 InitializeResourcePool (
   1749   IN OUT PCI_RESOURCE_NODE   *ResourcePool,
   1750   IN     PCI_BAR_TYPE        ResourceType
   1751   )
   1752 {
   1753   ZeroMem (ResourcePool, sizeof (PCI_RESOURCE_NODE));
   1754   ResourcePool->ResType   = ResourceType;
   1755   ResourcePool->Signature = PCI_RESOURCE_SIGNATURE;
   1756   InitializeListHead (&ResourcePool->ChildList);
   1757 }
   1758 
   1759 /**
   1760   Destory given resource tree.
   1761 
   1762   @param Bridge  PCI resource root node of resource tree.
   1763 
   1764 **/
   1765 VOID
   1766 DestroyResourceTree (
   1767   IN PCI_RESOURCE_NODE *Bridge
   1768   )
   1769 {
   1770   PCI_RESOURCE_NODE *Temp;
   1771   LIST_ENTRY        *CurrentLink;
   1772 
   1773   while (!IsListEmpty (&Bridge->ChildList)) {
   1774 
   1775     CurrentLink = Bridge->ChildList.ForwardLink;
   1776 
   1777     Temp        = RESOURCE_NODE_FROM_LINK (CurrentLink);
   1778     ASSERT (Temp);
   1779 
   1780     RemoveEntryList (CurrentLink);
   1781 
   1782     if (IS_PCI_BRIDGE (&(Temp->PciDev->Pci))) {
   1783       DestroyResourceTree (Temp);
   1784     }
   1785 
   1786     FreePool (Temp);
   1787   }
   1788 }
   1789 
   1790 /**
   1791   Insert resource padding for P2C.
   1792 
   1793   @param PciDev     Pci device instance.
   1794   @param IoNode     Resource info node for IO.
   1795   @param Mem32Node  Resource info node for 32-bit memory.
   1796   @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
   1797   @param Mem64Node  Resource info node for 64-bit memory.
   1798   @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
   1799 
   1800 **/
   1801 VOID
   1802 ResourcePaddingForCardBusBridge (
   1803   IN PCI_IO_DEVICE        *PciDev,
   1804   IN PCI_RESOURCE_NODE    *IoNode,
   1805   IN PCI_RESOURCE_NODE    *Mem32Node,
   1806   IN PCI_RESOURCE_NODE    *PMem32Node,
   1807   IN PCI_RESOURCE_NODE    *Mem64Node,
   1808   IN PCI_RESOURCE_NODE    *PMem64Node
   1809   )
   1810 {
   1811   PCI_RESOURCE_NODE *Node;
   1812 
   1813   Node = NULL;
   1814 
   1815   //
   1816   // Memory Base/Limit Register 0
   1817   // Bar 1 denodes memory range 0
   1818   //
   1819   Node = CreateResourceNode (
   1820            PciDev,
   1821            0x2000000,
   1822            0x1ffffff,
   1823            1,
   1824            PciBarTypeMem32,
   1825            PciResUsagePadding
   1826            );
   1827 
   1828   InsertResourceNode (
   1829     Mem32Node,
   1830     Node
   1831     );
   1832 
   1833   //
   1834   // Memory Base/Limit Register 1
   1835   // Bar 2 denodes memory range1
   1836   //
   1837   Node = CreateResourceNode (
   1838            PciDev,
   1839            0x2000000,
   1840            0x1ffffff,
   1841            2,
   1842            PciBarTypePMem32,
   1843            PciResUsagePadding
   1844            );
   1845 
   1846   InsertResourceNode (
   1847     PMem32Node,
   1848     Node
   1849     );
   1850 
   1851   //
   1852   // Io Base/Limit
   1853   // Bar 3 denodes io range 0
   1854   //
   1855   Node = CreateResourceNode (
   1856            PciDev,
   1857            0x100,
   1858            0xff,
   1859            3,
   1860            PciBarTypeIo16,
   1861            PciResUsagePadding
   1862            );
   1863 
   1864   InsertResourceNode (
   1865     IoNode,
   1866     Node
   1867     );
   1868 
   1869   //
   1870   // Io Base/Limit
   1871   // Bar 4 denodes io range 0
   1872   //
   1873   Node = CreateResourceNode (
   1874            PciDev,
   1875            0x100,
   1876            0xff,
   1877            4,
   1878            PciBarTypeIo16,
   1879            PciResUsagePadding
   1880            );
   1881 
   1882   InsertResourceNode (
   1883     IoNode,
   1884     Node
   1885     );
   1886 }
   1887 
   1888 /**
   1889   Program PCI Card device register for given resource node.
   1890 
   1891   @param Base    Base address of PCI Card device to be programmed.
   1892   @param Node    Given resource node.
   1893 
   1894 **/
   1895 VOID
   1896 ProgramP2C (
   1897   IN UINT64            Base,
   1898   IN PCI_RESOURCE_NODE *Node
   1899   )
   1900 {
   1901   EFI_PCI_IO_PROTOCOL *PciIo;
   1902   UINT64              Address;
   1903   UINT64              TempAddress;
   1904   UINT16              BridgeControl;
   1905 
   1906   Address = 0;
   1907   PciIo   = &(Node->PciDev->PciIo);
   1908 
   1909   Address = Base + Node->Offset;
   1910 
   1911   //
   1912   // Indicate pci bus driver has allocated
   1913   // resource for this device
   1914   // It might be a temporary solution here since
   1915   // pci device could have multiple bar
   1916   //
   1917   Node->PciDev->Allocated = TRUE;
   1918 
   1919   switch (Node->Bar) {
   1920 
   1921   case P2C_BAR_0:
   1922     PciIo->Pci.Write (
   1923                  PciIo,
   1924                  EfiPciIoWidthUint32,
   1925                  (Node->PciDev->PciBar[Node->Bar]).Offset,
   1926                  1,
   1927                  &Address
   1928                  );
   1929 
   1930     Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
   1931     Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;
   1932     break;
   1933 
   1934   case P2C_MEM_1:
   1935     PciIo->Pci.Write (
   1936                  PciIo,
   1937                  EfiPciIoWidthUint32,
   1938                  PCI_CARD_MEMORY_BASE_0,
   1939                  1,
   1940                  &Address
   1941                  );
   1942 
   1943     TempAddress = Address + Node->Length - 1;
   1944     PciIo->Pci.Write (
   1945                  PciIo,
   1946                  EfiPciIoWidthUint32,
   1947                  PCI_CARD_MEMORY_LIMIT_0,
   1948                  1,
   1949                  &TempAddress
   1950                  );
   1951 
   1952     if (Node->ResType == PciBarTypeMem32) {
   1953       //
   1954       // Set non-prefetchable bit
   1955       //
   1956       PciIo->Pci.Read (
   1957                    PciIo,
   1958                    EfiPciIoWidthUint16,
   1959                    PCI_CARD_BRIDGE_CONTROL,
   1960                    1,
   1961                    &BridgeControl
   1962                    );
   1963 
   1964       BridgeControl &= (UINT16) ~PCI_CARD_PREFETCHABLE_MEMORY_0_ENABLE;
   1965       PciIo->Pci.Write (
   1966                    PciIo,
   1967                    EfiPciIoWidthUint16,
   1968                    PCI_CARD_BRIDGE_CONTROL,
   1969                    1,
   1970                    &BridgeControl
   1971                    );
   1972 
   1973     } else {
   1974       //
   1975       // Set pre-fetchable bit
   1976       //
   1977       PciIo->Pci.Read (
   1978                    PciIo,
   1979                    EfiPciIoWidthUint16,
   1980                    PCI_CARD_BRIDGE_CONTROL,
   1981                    1,
   1982                    &BridgeControl
   1983                    );
   1984 
   1985       BridgeControl |= PCI_CARD_PREFETCHABLE_MEMORY_0_ENABLE;
   1986       PciIo->Pci.Write (
   1987                    PciIo,
   1988                    EfiPciIoWidthUint16,
   1989                    PCI_CARD_BRIDGE_CONTROL,
   1990                    1,
   1991                    &BridgeControl
   1992                    );
   1993     }
   1994 
   1995     Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
   1996     Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;
   1997     Node->PciDev->PciBar[Node->Bar].BarType     = Node->ResType;
   1998 
   1999     break;
   2000 
   2001   case P2C_MEM_2:
   2002     PciIo->Pci.Write (
   2003                  PciIo,
   2004                  EfiPciIoWidthUint32,
   2005                  PCI_CARD_MEMORY_BASE_1,
   2006                  1,
   2007                  &Address
   2008                  );
   2009 
   2010     TempAddress = Address + Node->Length - 1;
   2011 
   2012     PciIo->Pci.Write (
   2013                  PciIo,
   2014                  EfiPciIoWidthUint32,
   2015                  PCI_CARD_MEMORY_LIMIT_1,
   2016                  1,
   2017                  &TempAddress
   2018                  );
   2019 
   2020     if (Node->ResType == PciBarTypeMem32) {
   2021 
   2022       //
   2023       // Set non-prefetchable bit
   2024       //
   2025       PciIo->Pci.Read (
   2026                    PciIo,
   2027                    EfiPciIoWidthUint16,
   2028                    PCI_CARD_BRIDGE_CONTROL,
   2029                    1,
   2030                    &BridgeControl
   2031                    );
   2032 
   2033       BridgeControl &= (UINT16) ~(PCI_CARD_PREFETCHABLE_MEMORY_1_ENABLE);
   2034       PciIo->Pci.Write (
   2035                    PciIo,
   2036                    EfiPciIoWidthUint16,
   2037                    PCI_CARD_BRIDGE_CONTROL,
   2038                    1,
   2039                    &BridgeControl
   2040                    );
   2041 
   2042     } else {
   2043 
   2044       //
   2045       // Set pre-fetchable bit
   2046       //
   2047       PciIo->Pci.Read (
   2048                    PciIo,
   2049                    EfiPciIoWidthUint16,
   2050                    PCI_CARD_BRIDGE_CONTROL,
   2051                    1,
   2052                    &BridgeControl
   2053                    );
   2054 
   2055       BridgeControl |= PCI_CARD_PREFETCHABLE_MEMORY_1_ENABLE;
   2056       PciIo->Pci.Write (
   2057                    PciIo,
   2058                    EfiPciIoWidthUint16,
   2059                    PCI_CARD_BRIDGE_CONTROL,
   2060                    1,
   2061                    &BridgeControl
   2062                    );
   2063     }
   2064 
   2065     Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
   2066     Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;
   2067     Node->PciDev->PciBar[Node->Bar].BarType     = Node->ResType;
   2068     break;
   2069 
   2070   case P2C_IO_1:
   2071     PciIo->Pci.Write (
   2072                  PciIo,
   2073                  EfiPciIoWidthUint32,
   2074                  PCI_CARD_IO_BASE_0_LOWER,
   2075                  1,
   2076                  &Address
   2077                  );
   2078 
   2079     TempAddress = Address + Node->Length - 1;
   2080     PciIo->Pci.Write (
   2081                  PciIo,
   2082                  EfiPciIoWidthUint32,
   2083                  PCI_CARD_IO_LIMIT_0_LOWER,
   2084                  1,
   2085                  &TempAddress
   2086                  );
   2087 
   2088     Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
   2089     Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;
   2090     Node->PciDev->PciBar[Node->Bar].BarType     = Node->ResType;
   2091 
   2092     break;
   2093 
   2094   case P2C_IO_2:
   2095     PciIo->Pci.Write (
   2096                  PciIo,
   2097                  EfiPciIoWidthUint32,
   2098                  PCI_CARD_IO_BASE_1_LOWER,
   2099                  1,
   2100                  &Address
   2101                  );
   2102 
   2103     TempAddress = Address + Node->Length - 1;
   2104     PciIo->Pci.Write (
   2105                  PciIo,
   2106                  EfiPciIoWidthUint32,
   2107                  PCI_CARD_IO_LIMIT_1_LOWER,
   2108                  1,
   2109                  &TempAddress
   2110                  );
   2111 
   2112     Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
   2113     Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;
   2114     Node->PciDev->PciBar[Node->Bar].BarType     = Node->ResType;
   2115     break;
   2116 
   2117   default:
   2118     break;
   2119   }
   2120 }
   2121 
   2122 /**
   2123   Create padding resource node.
   2124 
   2125   @param PciDev     Pci device instance.
   2126   @param IoNode     Resource info node for IO.
   2127   @param Mem32Node  Resource info node for 32-bit memory.
   2128   @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
   2129   @param Mem64Node  Resource info node for 64-bit memory.
   2130   @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
   2131 
   2132 **/
   2133 VOID
   2134 ApplyResourcePadding (
   2135   IN PCI_IO_DEVICE         *PciDev,
   2136   IN PCI_RESOURCE_NODE     *IoNode,
   2137   IN PCI_RESOURCE_NODE     *Mem32Node,
   2138   IN PCI_RESOURCE_NODE     *PMem32Node,
   2139   IN PCI_RESOURCE_NODE     *Mem64Node,
   2140   IN PCI_RESOURCE_NODE     *PMem64Node
   2141   )
   2142 {
   2143   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
   2144   PCI_RESOURCE_NODE                 *Node;
   2145   UINT8                             DummyBarIndex;
   2146 
   2147   DummyBarIndex = 0;
   2148   Ptr           = PciDev->ResourcePaddingDescriptors;
   2149 
   2150   while (((EFI_ACPI_END_TAG_DESCRIPTOR *) Ptr)->Desc != ACPI_END_TAG_DESCRIPTOR) {
   2151 
   2152     if (Ptr->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_IO) {
   2153       if (Ptr->AddrLen != 0) {
   2154 
   2155         Node = CreateResourceNode (
   2156                 PciDev,
   2157                 Ptr->AddrLen,
   2158                 Ptr->AddrRangeMax,
   2159                 DummyBarIndex,
   2160                 PciBarTypeIo16,
   2161                 PciResUsagePadding
   2162                 );
   2163         InsertResourceNode (
   2164           IoNode,
   2165           Node
   2166           );
   2167       }
   2168 
   2169       Ptr++;
   2170       continue;
   2171     }
   2172 
   2173     if (Ptr->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
   2174 
   2175       if (Ptr->AddrSpaceGranularity == 32) {
   2176 
   2177         //
   2178         // prefechable
   2179         //
   2180         if (Ptr->SpecificFlag == 0x6) {
   2181           if (Ptr->AddrLen != 0) {
   2182             Node = CreateResourceNode (
   2183                     PciDev,
   2184                     Ptr->AddrLen,
   2185                     Ptr->AddrRangeMax,
   2186                     DummyBarIndex,
   2187                     PciBarTypePMem32,
   2188                     PciResUsagePadding
   2189                     );
   2190             InsertResourceNode (
   2191               PMem32Node,
   2192               Node
   2193               );
   2194           }
   2195 
   2196           Ptr++;
   2197           continue;
   2198         }
   2199 
   2200         //
   2201         // Non-prefechable
   2202         //
   2203         if (Ptr->SpecificFlag == 0) {
   2204           if (Ptr->AddrLen != 0) {
   2205             Node = CreateResourceNode (
   2206                     PciDev,
   2207                     Ptr->AddrLen,
   2208                     Ptr->AddrRangeMax,
   2209                     DummyBarIndex,
   2210                     PciBarTypeMem32,
   2211                     PciResUsagePadding
   2212                     );
   2213             InsertResourceNode (
   2214               Mem32Node,
   2215               Node
   2216               );
   2217           }
   2218 
   2219           Ptr++;
   2220           continue;
   2221         }
   2222       }
   2223 
   2224       if (Ptr->AddrSpaceGranularity == 64) {
   2225 
   2226         //
   2227         // prefechable
   2228         //
   2229         if (Ptr->SpecificFlag == 0x6) {
   2230           if (Ptr->AddrLen != 0) {
   2231             Node = CreateResourceNode (
   2232                     PciDev,
   2233                     Ptr->AddrLen,
   2234                     Ptr->AddrRangeMax,
   2235                     DummyBarIndex,
   2236                     PciBarTypePMem64,
   2237                     PciResUsagePadding
   2238                     );
   2239             InsertResourceNode (
   2240               PMem64Node,
   2241               Node
   2242               );
   2243           }
   2244 
   2245           Ptr++;
   2246           continue;
   2247         }
   2248 
   2249         //
   2250         // Non-prefechable
   2251         //
   2252         if (Ptr->SpecificFlag == 0) {
   2253           if (Ptr->AddrLen != 0) {
   2254             Node = CreateResourceNode (
   2255                     PciDev,
   2256                     Ptr->AddrLen,
   2257                     Ptr->AddrRangeMax,
   2258                     DummyBarIndex,
   2259                     PciBarTypeMem64,
   2260                     PciResUsagePadding
   2261                     );
   2262             InsertResourceNode (
   2263               Mem64Node,
   2264               Node
   2265               );
   2266           }
   2267 
   2268           Ptr++;
   2269           continue;
   2270         }
   2271       }
   2272     }
   2273 
   2274     Ptr++;
   2275   }
   2276 }
   2277 
   2278 /**
   2279   Get padding resource for PCI-PCI bridge.
   2280 
   2281   @param  PciIoDevice     PCI-PCI bridge device instance.
   2282 
   2283   @note   Feature flag PcdPciBusHotplugDeviceSupport determines
   2284           whether need to pad resource for them.
   2285 **/
   2286 VOID
   2287 GetResourcePaddingPpb (
   2288   IN  PCI_IO_DEVICE                  *PciIoDevice
   2289   )
   2290 {
   2291   if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
   2292     if (PciIoDevice->ResourcePaddingDescriptors == NULL) {
   2293       GetResourcePaddingForHpb (PciIoDevice);
   2294     }
   2295   }
   2296 }
   2297 
   2298