]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciResourceSupport.c
Add PciBus & IdeBus
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Pci / PciBus / Dxe / PciResourceSupport.c
diff --git a/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciResourceSupport.c b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciResourceSupport.c
new file mode 100644 (file)
index 0000000..a6ae80f
--- /dev/null
@@ -0,0 +1,2314 @@
+/*++\r
+\r
+Copyright (c) 2006 - 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+  PciResourceSupport.c\r
+\r
+Abstract:\r
+\r
+  PCI Bus Driver\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#include "pcibus.h"\r
+#include "PciResourceSupport.h"\r
+#include "PciCommand.h"\r
+\r
+EFI_STATUS\r
+SkipVGAAperture (\r
+  OUT UINT64   *Start,\r
+  IN  UINT64   Length\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  The function is used to skip VGA range\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+// TODO:    Start - add argument and description to function comment\r
+// TODO:    Length - add argument and description to function comment\r
+// TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+  UINT64  Original;\r
+  UINT64  Mask;\r
+  UINT64  StartOffset;\r
+  UINT64  LimitOffset;\r
+\r
+  //\r
+  // For legacy VGA, bit 10 to bit 15 is not decoded\r
+  //\r
+  Mask        = 0x3FF;\r
+\r
+  Original    = *Start;\r
+  StartOffset = Original & Mask;\r
+  LimitOffset = ((*Start) + Length - 1) & Mask;\r
+  if (LimitOffset >= VGABASE1) {\r
+    *Start = *Start - StartOffset + VGALIMIT2 + 1;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+SkipIsaAliasAperture (\r
+  OUT UINT64   *Start,\r
+  IN  UINT64   Length\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This function is used to skip ISA aliasing aperture\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+// TODO:    Start - add argument and description to function comment\r
+// TODO:    Length - add argument and description to function comment\r
+// TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+\r
+  UINT64  Original;\r
+  UINT64  Mask;\r
+  UINT64  StartOffset;\r
+  UINT64  LimitOffset;\r
+\r
+  //\r
+  // For legacy ISA, bit 10 to bit 15 is not decoded\r
+  //\r
+  Mask        = 0x3FF;\r
+\r
+  Original    = *Start;\r
+  StartOffset = Original & Mask;\r
+  LimitOffset = ((*Start) + Length - 1) & Mask;\r
+\r
+  if (LimitOffset >= ISABASE) {\r
+    *Start = *Start - StartOffset + ISALIMIT + 1;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+InsertResourceNode (\r
+  PCI_RESOURCE_NODE *Bridge,\r
+  PCI_RESOURCE_NODE *ResNode\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This function inserts a resource node into the resource list.\r
+  The resource list is sorted in descend order.\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+// TODO:    Bridge - add argument and description to function comment\r
+// TODO:    ResNode - add argument and description to function comment\r
+// TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+  LIST_ENTRY        *CurrentLink;\r
+  PCI_RESOURCE_NODE *Temp;\r
+  UINT64            ResNodeAlignRest;\r
+  UINT64            TempAlignRest;\r
+\r
+  InsertHeadList (&Bridge->ChildList, &ResNode->Link);\r
+\r
+  CurrentLink = Bridge->ChildList.ForwardLink->ForwardLink;\r
+  while (CurrentLink != &Bridge->ChildList) {\r
+    Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+\r
+    if (ResNode->Alignment > Temp->Alignment) {\r
+      break;\r
+    } else if (ResNode->Alignment == Temp->Alignment) {\r
+      ResNodeAlignRest  = ResNode->Length & ResNode->Alignment;\r
+      TempAlignRest     = Temp->Length & Temp->Alignment;\r
+      if ((ResNodeAlignRest == 0) || (ResNodeAlignRest >= TempAlignRest)) {\r
+        break;\r
+      }\r
+    }\r
+\r
+    SwapListEntries (&ResNode->Link, CurrentLink);\r
+\r
+    CurrentLink = ResNode->Link.ForwardLink;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+MergeResourceTree (\r
+  PCI_RESOURCE_NODE *Dst,\r
+  PCI_RESOURCE_NODE *Res,\r
+  BOOLEAN           TypeMerge\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This routine is used to merge two different resource tree in need of\r
+  resoure degradation. For example, if a upstream PPB doesn't support,\r
+  prefetchable memory decoding, the PCI bus driver will choose to call this function\r
+  to merge prefectchable memory resource list into normal memory list.\r
+\r
+  If the TypeMerge is TRUE, Res resource type is changed to the type of destination resource\r
+  type.\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+// TODO:    Dst - add argument and description to function comment\r
+// TODO:    Res - add argument and description to function comment\r
+// TODO:    TypeMerge - add argument and description to function comment\r
+// TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+\r
+  LIST_ENTRY        *CurrentLink;\r
+  PCI_RESOURCE_NODE *Temp;\r
+\r
+  while (!IsListEmpty (&Res->ChildList)) {\r
+    CurrentLink = Res->ChildList.ForwardLink;\r
+\r
+    Temp        = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+\r
+    if (TypeMerge) {\r
+      Temp->ResType = Dst->ResType;\r
+    }\r
+\r
+    RemoveEntryList (CurrentLink);\r
+    InsertResourceNode (Dst, Temp);\r
+\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+CalculateApertureIo16 (\r
+  IN PCI_RESOURCE_NODE *Bridge\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This function is used to calculate the IO16 aperture\r
+  for a bridge.\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+// TODO:    Bridge - add argument and description to function comment\r
+// TODO:    EFI_SUCCESS - add return value to function comment\r
+// TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+\r
+  UINT64            Aperture;\r
+  LIST_ENTRY        *CurrentLink;\r
+  PCI_RESOURCE_NODE *Node;\r
+  UINT64            offset;\r
+  BOOLEAN           IsaEnable;\r
+  BOOLEAN           VGAEnable;\r
+\r
+  //\r
+  // Always assume there is ISA device and VGA device on the platform\r
+  // will be customized later\r
+  //\r
+  IsaEnable = FALSE;\r
+  VGAEnable = FALSE;\r
+\r
+  if (FeaturePcdGet (PcdPciIsaEnable)){\r
+    IsaEnable = TRUE;\r
+  }\r
+\r
+  if (FeaturePcdGet (PcdPciVgaEnable)){\r
+    VGAEnable = TRUE;\r
+  }\r
+\r
+  Aperture = 0;\r
+\r
+  if (!Bridge) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  CurrentLink = Bridge->ChildList.ForwardLink;\r
+\r
+  //\r
+  // Assume the bridge is aligned\r
+  //\r
+  while (CurrentLink != &Bridge->ChildList) {\r
+\r
+    Node = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+\r
+    //\r
+    // Consider the aperture alignment\r
+    //\r
+    offset = Aperture & (Node->Alignment);\r
+\r
+    if (offset) {\r
+\r
+      Aperture = Aperture + (Node->Alignment + 1) - offset;\r
+\r
+    }\r
+\r
+    //\r
+    // IsaEnable and VGAEnable can not be implemented now.\r
+    // If both of them are enabled, then the IO resource would\r
+    // become too limited to meet the requirement of most of devices.\r
+    //\r
+\r
+    if (IsaEnable || VGAEnable) {\r
+      if (!IS_PCI_BRIDGE (&(Node->PciDev->Pci)) && !IS_CARDBUS_BRIDGE (&(Node->PciDev->Pci))) {\r
+        //\r
+        // Check if there is need to support ISA/VGA decoding\r
+        // If so, we need to avoid isa/vga aliasing range\r
+        //\r
+        if (IsaEnable) {\r
+          SkipIsaAliasAperture (\r
+            &Aperture,\r
+            Node->Length               \r
+            );\r
+          offset = Aperture & (Node->Alignment);\r
+          if (offset) {\r
+            Aperture = Aperture + (Node->Alignment + 1) - offset;\r
+          }\r
+        } else if (VGAEnable) {\r
+          SkipVGAAperture (\r
+            &Aperture,\r
+            Node->Length\r
+            );\r
+          offset = Aperture & (Node->Alignment);\r
+          if (offset) {\r
+            Aperture = Aperture + (Node->Alignment + 1) - offset;\r
+          }\r
+        }\r
+      }\r
+    }\r
+\r
+    Node->Offset = Aperture;\r
+\r
+    //\r
+    // Increment aperture by the length of node\r
+    //\r
+    Aperture += Node->Length;\r
+\r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+\r
+  //\r
+  // At last, adjust the aperture with the bridge's\r
+  // alignment\r
+  //\r
+  offset = Aperture & (Bridge->Alignment);\r
+\r
+  if (offset) {\r
+    Aperture = Aperture + (Bridge->Alignment + 1) - offset;\r
+  }\r
+\r
+  Bridge->Length = Aperture;\r
+  //\r
+  // At last, adjust the bridge's alignment to the first child's alignment\r
+  // if the bridge has at least one child\r
+  //\r
+  CurrentLink = Bridge->ChildList.ForwardLink;\r
+  if (CurrentLink != &Bridge->ChildList) {\r
+    Node = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+    if (Node->Alignment > Bridge->Alignment) {\r
+      Bridge->Alignment = Node->Alignment;\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+CalculateResourceAperture (\r
+  IN PCI_RESOURCE_NODE *Bridge\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This function is used to calculate the resource aperture\r
+  for a given bridge device\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+// TODO:    Bridge - add argument and description to function comment\r
+// TODO:    EFI_SUCCESS - add return value to function comment\r
+// TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+  UINT64            Aperture;\r
+  LIST_ENTRY        *CurrentLink;\r
+  PCI_RESOURCE_NODE *Node;\r
+\r
+  UINT64            offset;\r
+\r
+  Aperture = 0;\r
+\r
+  if (!Bridge) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  if (Bridge->ResType == PciBarTypeIo16) {\r
+    return CalculateApertureIo16 (Bridge);\r
+  }\r
+\r
+  CurrentLink = Bridge->ChildList.ForwardLink;\r
+\r
+  //\r
+  // Assume the bridge is aligned\r
+  //\r
+  while (CurrentLink != &Bridge->ChildList) {\r
+\r
+    Node = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+\r
+    //\r
+    // Apply padding resource if available\r
+    //\r
+        \r
+    offset = Aperture & (Node->Alignment);\r
+\r
+    if (offset) {\r
+\r
+      Aperture = Aperture + (Node->Alignment + 1) - offset;\r
+\r
+    }\r
+\r
+    //\r
+    // Recode current aperture as a offset\r
+    // this offset will be used in future real allocation\r
+    //\r
+    Node->Offset = Aperture;\r
+\r
+    //\r
+    // Increment aperture by the length of node\r
+    //\r
+    Aperture += Node->Length;\r
+\r
+    //\r
+    // Consider the aperture alignment\r
+    //\r
+    \r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+\r
+  //\r
+  // At last, adjust the aperture with the bridge's\r
+  // alignment\r
+  //\r
+  offset = Aperture & (Bridge->Alignment);\r
+  if (offset) {\r
+    Aperture = Aperture + (Bridge->Alignment + 1) - offset;\r
+  }\r
+\r
+  //\r
+  // If the bridge has already padded the resource and the\r
+  // amount of padded resource is larger, then keep the\r
+  // padded resource\r
+  //\r
+  if (Bridge->Length < Aperture) {\r
+    Bridge->Length = Aperture;\r
+  }\r
+  \r
+  //\r
+  // At last, adjust the bridge's alignment to the first child's alignment\r
+  // if the bridge has at least one child\r
+  //\r
+  CurrentLink = Bridge->ChildList.ForwardLink;\r
+  if (CurrentLink != &Bridge->ChildList) {\r
+    Node = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+    if (Node->Alignment > Bridge->Alignment) {\r
+      Bridge->Alignment = Node->Alignment;\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+GetResourceFromDevice (\r
+  PCI_IO_DEVICE     *PciDev,\r
+  PCI_RESOURCE_NODE *IoNode,\r
+  PCI_RESOURCE_NODE *Mem32Node,\r
+  PCI_RESOURCE_NODE *PMem32Node,\r
+  PCI_RESOURCE_NODE *Mem64Node,\r
+  PCI_RESOURCE_NODE *PMem64Node\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+// TODO:    PciDev - add argument and description to function comment\r
+// TODO:    IoNode - add argument and description to function comment\r
+// TODO:    Mem32Node - add argument and description to function comment\r
+// TODO:    PMem32Node - add argument and description to function comment\r
+// TODO:    Mem64Node - add argument and description to function comment\r
+// TODO:    PMem64Node - add argument and description to function comment\r
+// TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+\r
+  UINT8             Index;\r
+  PCI_RESOURCE_NODE *Node;\r
+  BOOLEAN           ResourceRequested;\r
+\r
+  Node              = NULL;\r
+  ResourceRequested = FALSE;\r
+\r
+  for (Index = 0; Index < PCI_MAX_BAR; Index++) {\r
+\r
+    switch ((PciDev->PciBar)[Index].BarType) {\r
+\r
+    case PciBarTypeMem32:\r
+\r
+      Node = CreateResourceNode (\r
+              PciDev,\r
+              (PciDev->PciBar)[Index].Length,\r
+              (PciDev->PciBar)[Index].Alignment,\r
+              Index,\r
+              PciBarTypeMem32,\r
+              PciResUsageTypical\r
+              );\r
+\r
+      InsertResourceNode (\r
+        Mem32Node,\r
+        Node\r
+        );\r
+\r
+      ResourceRequested = TRUE;\r
+      break;\r
+\r
+    case PciBarTypeMem64:\r
+\r
+      Node = CreateResourceNode (\r
+              PciDev,\r
+              (PciDev->PciBar)[Index].Length,\r
+              (PciDev->PciBar)[Index].Alignment,\r
+              Index,\r
+              PciBarTypeMem64,\r
+              PciResUsageTypical\r
+              );\r
+\r
+      InsertResourceNode (\r
+        Mem64Node,\r
+        Node\r
+        );\r
+\r
+      ResourceRequested = TRUE;\r
+      break;\r
+\r
+    case PciBarTypePMem64:\r
+\r
+      Node = CreateResourceNode (\r
+              PciDev,\r
+              (PciDev->PciBar)[Index].Length,\r
+              (PciDev->PciBar)[Index].Alignment,\r
+              Index,\r
+              PciBarTypePMem64,\r
+              PciResUsageTypical\r
+              );\r
+\r
+      InsertResourceNode (\r
+        PMem64Node,\r
+        Node\r
+        );\r
+\r
+      ResourceRequested = TRUE;\r
+      break;\r
+\r
+    case PciBarTypePMem32:\r
+\r
+      Node = CreateResourceNode (\r
+              PciDev,\r
+              (PciDev->PciBar)[Index].Length,\r
+              (PciDev->PciBar)[Index].Alignment,\r
+              Index,\r
+              PciBarTypePMem32,\r
+              PciResUsageTypical\r
+              );\r
+\r
+      InsertResourceNode (\r
+        PMem32Node,\r
+        Node\r
+        );\r
+      ResourceRequested = TRUE;\r
+      break;\r
+\r
+    case PciBarTypeIo16:\r
+    case PciBarTypeIo32:\r
+\r
+      Node = CreateResourceNode (\r
+              PciDev,\r
+              (PciDev->PciBar)[Index].Length,\r
+              (PciDev->PciBar)[Index].Alignment,\r
+              Index,\r
+              PciBarTypeIo16,\r
+              PciResUsageTypical\r
+              );\r
+\r
+      InsertResourceNode (\r
+        IoNode,\r
+        Node\r
+        );\r
+      ResourceRequested = TRUE;\r
+      break;\r
+\r
+    case PciBarTypeUnknown:\r
+      break;\r
+\r
+    default:\r
+      break;\r
+    }\r
+  }\r
+\r
+  //\r
+  // If there is no resource requested from this device,\r
+  // then we indicate this device has been allocated naturally.\r
+  //\r
+  if (!ResourceRequested) {\r
+    PciDev->Allocated = TRUE;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+PCI_RESOURCE_NODE *\r
+CreateResourceNode (\r
+  IN PCI_IO_DEVICE         *PciDev,\r
+  IN UINT64                Length,\r
+  IN UINT64                Alignment,\r
+  IN UINT8                 Bar,\r
+  IN PCI_BAR_TYPE          ResType,\r
+  IN PCI_RESOURCE_USAGE    ResUsage\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This function is used to create a resource node\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+// TODO:    PciDev - add argument and description to function comment\r
+// TODO:    Length - add argument and description to function comment\r
+// TODO:    Alignment - add argument and description to function comment\r
+// TODO:    Bar - add argument and description to function comment\r
+// TODO:    ResType - add argument and description to function comment\r
+// TODO:    ResUsage - add argument and description to function comment\r
+{\r
+  PCI_RESOURCE_NODE *Node;\r
+\r
+  Node    = NULL;\r
+\r
+  Node    = AllocatePool (sizeof (PCI_RESOURCE_NODE));\r
+  if (Node == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  ZeroMem (Node, sizeof (PCI_RESOURCE_NODE));\r
+\r
+  Node->Signature     = PCI_RESOURCE_SIGNATURE;\r
+  Node->PciDev        = PciDev;\r
+  Node->Length        = Length;\r
+  Node->Alignment     = Alignment;\r
+  Node->Bar           = Bar;\r
+  Node->ResType       = ResType;\r
+  Node->Reserved      = FALSE;\r
+  Node->ResourceUsage = ResUsage;\r
+  InitializeListHead (&Node->ChildList);\r
+  return Node;\r
+}\r
+\r
+EFI_STATUS\r
+CreateResourceMap (\r
+  IN PCI_IO_DEVICE     *Bridge,\r
+  IN PCI_RESOURCE_NODE *IoNode,\r
+  IN PCI_RESOURCE_NODE *Mem32Node,\r
+  IN PCI_RESOURCE_NODE *PMem32Node,\r
+  IN PCI_RESOURCE_NODE *Mem64Node,\r
+  IN PCI_RESOURCE_NODE *PMem64Node\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This routine is used to extract resource request from\r
+  device node list.\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+// TODO:    Bridge - add argument and description to function comment\r
+// TODO:    IoNode - add argument and description to function comment\r
+// TODO:    Mem32Node - add argument and description to function comment\r
+// TODO:    PMem32Node - add argument and description to function comment\r
+// TODO:    Mem64Node - add argument and description to function comment\r
+// TODO:    PMem64Node - add argument and description to function comment\r
+// TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+  PCI_IO_DEVICE     *Temp;\r
+  PCI_RESOURCE_NODE *IoBridge;\r
+  PCI_RESOURCE_NODE *Mem32Bridge;\r
+  PCI_RESOURCE_NODE *PMem32Bridge;\r
+  PCI_RESOURCE_NODE *Mem64Bridge;\r
+  PCI_RESOURCE_NODE *PMem64Bridge;\r
+  LIST_ENTRY        *CurrentLink;\r
+\r
+  CurrentLink = Bridge->ChildList.ForwardLink;\r
+\r
+  while (CurrentLink && CurrentLink != &Bridge->ChildList) {\r
+\r
+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+\r
+    //\r
+    // Create resource nodes for this device by scanning the\r
+    // Bar array in the device private data\r
+    // If the upstream bridge doesn't support this device,\r
+    // no any resource node will be created for this device\r
+    //\r
+    GetResourceFromDevice (\r
+      Temp,\r
+      IoNode,\r
+      Mem32Node,\r
+      PMem32Node,\r
+      Mem64Node,\r
+      PMem64Node\r
+      );\r
+\r
+    if (IS_PCI_BRIDGE (&Temp->Pci)) {\r
+\r
+      //\r
+      // If the device has children, create a bridge resource node for this PPB\r
+      // Note: For PPB, memory aperture is aligned with 1MB and IO aperture\r
+      // is aligned with 4KB\r
+      // This device is typically a bridge device like PPB and P2C\r
+      //\r
+      IoBridge = CreateResourceNode (\r
+                  Temp,\r
+                  0,\r
+                  0xFFF,\r
+                  PPB_IO_RANGE,\r
+                  PciBarTypeIo16,\r
+                  PciResUsageTypical\r
+                  ); //0x1000 aligned\r
+      \r
+      Mem32Bridge = CreateResourceNode (\r
+                      Temp,\r
+                      0,\r
+                      0xFFFFF,\r
+                      PPB_MEM32_RANGE,\r
+                      PciBarTypeMem32,\r
+                      PciResUsageTypical\r
+                      );\r
+\r
+      PMem32Bridge = CreateResourceNode (\r
+                      Temp,\r
+                      0,\r
+                      0xFFFFF,\r
+                      PPB_PMEM32_RANGE,\r
+                      PciBarTypePMem32,\r
+                      PciResUsageTypical\r
+                      );\r
+\r
+      Mem64Bridge = CreateResourceNode (\r
+                      Temp,\r
+                      0,\r
+                      0xFFFFF,\r
+                      PPB_MEM64_RANGE,\r
+                      PciBarTypeMem64,\r
+                      PciResUsageTypical\r
+                      );\r
+\r
+      PMem64Bridge = CreateResourceNode (\r
+                      Temp,\r
+                      0,\r
+                      0xFFFFF,\r
+                      PPB_PMEM64_RANGE,\r
+                      PciBarTypePMem64,\r
+                      PciResUsageTypical\r
+                      );\r
+\r
+      //\r
+      // Recursively create resouce map on this bridge\r
+      //\r
+      CreateResourceMap (\r
+        Temp,\r
+        IoBridge,\r
+        Mem32Bridge,\r
+        PMem32Bridge,\r
+        Mem64Bridge,\r
+        PMem64Bridge\r
+        );\r
+\r
+      if (ResourceRequestExisted (IoBridge)) {\r
+        InsertResourceNode (\r
+          IoNode,\r
+          IoBridge\r
+          );\r
+      } else {\r
+        gBS->FreePool (IoBridge);\r
+        IoBridge = NULL;\r
+      }\r
+\r
+      //\r
+      // If there is node under this resource bridge,\r
+      // then calculate bridge's aperture of this type\r
+      // and insert it into the respective resource tree.\r
+      // If no, delete this resource bridge\r
+      //\r
+      if (ResourceRequestExisted (Mem32Bridge)) {\r
+        InsertResourceNode (\r
+          Mem32Node,\r
+          Mem32Bridge\r
+          );\r
+      } else {\r
+        gBS->FreePool (Mem32Bridge);\r
+        Mem32Bridge = NULL;\r
+      }\r
+\r
+      //\r
+      // If there is node under this resource bridge,\r
+      // then calculate bridge's aperture of this type\r
+      // and insert it into the respective resource tree.\r
+      // If no, delete this resource bridge\r
+      //\r
+      if (ResourceRequestExisted (PMem32Bridge)) {\r
+        InsertResourceNode (\r
+          PMem32Node,\r
+          PMem32Bridge\r
+          );\r
+      } else {\r
+        gBS->FreePool (PMem32Bridge);\r
+        PMem32Bridge = NULL;\r
+      }\r
+\r
+      //\r
+      // If there is node under this resource bridge,\r
+      // then calculate bridge's aperture of this type\r
+      // and insert it into the respective resource tree.\r
+      // If no, delete this resource bridge\r
+      //\r
+      if (ResourceRequestExisted (Mem64Bridge)) {\r
+        InsertResourceNode (\r
+          Mem64Node,\r
+          Mem64Bridge\r
+          );\r
+      } else {\r
+        gBS->FreePool (Mem64Bridge);\r
+        Mem64Bridge = NULL;\r
+      }\r
+\r
+      //\r
+      // If there is node under this resource bridge,\r
+      // then calculate bridge's aperture of this type\r
+      // and insert it into the respective resource tree.\r
+      // If no, delete this resource bridge\r
+      //\r
+      if (ResourceRequestExisted (PMem64Bridge)) {\r
+        InsertResourceNode (\r
+          PMem64Node,\r
+          PMem64Bridge\r
+          );\r
+      } else {\r
+        gBS->FreePool (PMem64Bridge);\r
+        PMem64Bridge = NULL;\r
+      }\r
+\r
+    }\r
+\r
+    //\r
+    // If it is P2C, apply hard coded resource padding\r
+    //\r
+    //\r
+    if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {\r
+      ResourcePaddingForCardBusBridge (\r
+        Temp,\r
+        IoNode,\r
+        Mem32Node,\r
+        PMem32Node,\r
+        Mem64Node,\r
+        PMem64Node\r
+        );\r
+    }\r
+\r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+  //\r
+  //\r
+  // To do some platform specific resource padding ...\r
+  //\r
+  ResourcePaddingPolicy (\r
+    Bridge,\r
+    IoNode,\r
+    Mem32Node,\r
+    PMem32Node,\r
+    Mem64Node,\r
+    PMem64Node\r
+    );\r
+\r
+  //\r
+  // Degrade resource if necessary\r
+  //\r
+  DegradeResource (\r
+    Bridge,\r
+    Mem32Node,\r
+    PMem32Node,\r
+    Mem64Node,\r
+    PMem64Node\r
+    );\r
+\r
+  //\r
+  // Calculate resource aperture for this bridge device\r
+  //\r
+  CalculateResourceAperture (Mem32Node);\r
+  CalculateResourceAperture (PMem32Node);\r
+  CalculateResourceAperture (Mem64Node);\r
+  CalculateResourceAperture (PMem64Node);\r
+  CalculateResourceAperture (IoNode);\r
+\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
+EFI_STATUS\r
+ResourcePaddingPolicy (\r
+  PCI_IO_DEVICE     *PciDev,\r
+  PCI_RESOURCE_NODE *IoNode,\r
+  PCI_RESOURCE_NODE *Mem32Node,\r
+  PCI_RESOURCE_NODE *PMem32Node,\r
+  PCI_RESOURCE_NODE *Mem64Node,\r
+  PCI_RESOURCE_NODE *PMem64Node\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This function is used to do the resource padding for a specific platform\r
+\r
+Arguments:\r
+\r
+  PciDev        - A pointer to the PCI_IO_DEVICE structrue.    \r
+  IoNode        - A pointer to the PCI_RESOURCE_NODE structrue.\r
+  Mem32Node     - A pointer to the PCI_RESOURCE_NODE structrue.\r
+  PMem32Node    - A pointer to the PCI_RESOURCE_NODE structrue.\r
+  Mem64Node     - A pointer to the PCI_RESOURCE_NODE structrue.\r
+  PMem64Node    - A pointer to the PCI_RESOURCE_NODE structrue.\r
+\r
+Returns:\r
+  Status code\r
+\r
+  None\r
+\r
+--*/\r
+// TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+  //\r
+  // Create padding resource node\r
+  //\r
+  if (PciDev->ResourcePaddingDescriptors != NULL) {\r
+    ApplyResourcePadding (\r
+      PciDev,\r
+      IoNode,\r
+      Mem32Node,\r
+      PMem32Node,\r
+      Mem64Node,\r
+      PMem64Node\r
+      );\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
+EFI_STATUS\r
+DegradeResource (\r
+  IN PCI_IO_DEVICE     *Bridge,\r
+  IN PCI_RESOURCE_NODE *Mem32Node,\r
+  IN PCI_RESOURCE_NODE *PMem32Node,\r
+  IN PCI_RESOURCE_NODE *Mem64Node,\r
+  IN PCI_RESOURCE_NODE *PMem64Node\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This function is used to degrade resource if the upstream bridge \r
+  doesn't support certain resource. Degradation path is \r
+  PMEM64 -> MEM64  -> MEM32\r
+  PMEM64 -> PMEM32 -> MEM32\r
+  IO32   -> IO16\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+// TODO:    Bridge - add argument and description to function comment\r
+// TODO:    Mem32Node - add argument and description to function comment\r
+// TODO:    PMem32Node - add argument and description to function comment\r
+// TODO:    Mem64Node - add argument and description to function comment\r
+// TODO:    PMem64Node - add argument and description to function comment\r
+// TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+\r
+  //\r
+  // If bridge doesn't support Prefetchable\r
+  // memory64, degrade it to Prefetchable memory32\r
+  //\r
+  if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM64_DECODE_SUPPORTED)) {\r
+    MergeResourceTree (\r
+      PMem32Node,\r
+      PMem64Node,\r
+      TRUE\r
+      );\r
+  } else {\r
+    //\r
+    // if no PMem32 request, still keep PMem64. Otherwise degrade to PMem32\r
+    //\r
+    if (PMem32Node != NULL) {\r
+      MergeResourceTree (\r
+        PMem32Node,\r
+        PMem64Node,\r
+        TRUE\r
+        );\r
+    }\r
+  }\r
+\r
+\r
+  //\r
+  // If bridge doesn't support Mem64\r
+  // degrade it to mem32\r
+  //\r
+  if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_MEM64_DECODE_SUPPORTED)) {\r
+    MergeResourceTree (\r
+      Mem32Node,\r
+      Mem64Node,\r
+      TRUE\r
+      );\r
+  }\r
+\r
+  //\r
+  // If bridge doesn't support Pmem32\r
+  // degrade it to mem32\r
+  //\r
+  if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM32_DECODE_SUPPORTED)) {\r
+    MergeResourceTree (\r
+      Mem32Node,\r
+      PMem32Node,\r
+      TRUE\r
+      );\r
+  }\r
+\r
+  //\r
+  // if bridge supports combined Pmem Mem decoding\r
+  // merge these two type of resource\r
+  //\r
+  if (BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED)) {\r
+    MergeResourceTree (\r
+      Mem32Node,\r
+      PMem32Node,\r
+      FALSE\r
+      );\r
+\r
+    MergeResourceTree (\r
+      Mem64Node,\r
+      PMem64Node,\r
+      FALSE\r
+      );\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+BOOLEAN\r
+BridgeSupportResourceDecode (\r
+  IN PCI_IO_DEVICE *Bridge,\r
+  IN UINT32        Decode\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  Bridge  - TODO: add argument description\r
+  Decode  - TODO: add argument description\r
+\r
+Returns:\r
+\r
+  TODO: add return values\r
+\r
+--*/\r
+{\r
+  /*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+  \r
+  None\r
+\r
+--*/\r
+  if ((Bridge->Decodes) & Decode) {\r
+    return TRUE;\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+EFI_STATUS\r
+ProgramResource (\r
+  IN UINT64            Base,\r
+  IN PCI_RESOURCE_NODE *Bridge\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This function is used to program the resource allocated \r
+  for each resource node\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+// TODO:    Base - add argument and description to function comment\r
+// TODO:    Bridge - add argument and description to function comment\r
+// TODO:    EFI_OUT_OF_RESOURCES - add return value to function comment\r
+// TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+  LIST_ENTRY        *CurrentLink;\r
+  PCI_RESOURCE_NODE *Node;\r
+  EFI_STATUS        Status;\r
+\r
+  if (Base == gAllOne) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  CurrentLink = Bridge->ChildList.ForwardLink;\r
+\r
+  while (CurrentLink != &Bridge->ChildList) {\r
+\r
+    Node = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+\r
+    if (!IS_PCI_BRIDGE (&(Node->PciDev->Pci))) {\r
+\r
+      if (IS_CARDBUS_BRIDGE (&(Node->PciDev->Pci))) {\r
+        ProgramP2C (Base, Node);\r
+      } else {\r
+        ProgramBar (Base, Node);\r
+      }\r
+    } else {\r
+      Status = ProgramResource (Base + Node->Offset, Node);\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      ProgramPpbApperture (Base, Node);\r
+    }\r
+\r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+ProgramBar (\r
+  IN UINT64            Base,\r
+  IN PCI_RESOURCE_NODE *Node\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+  \r
+  None\r
+\r
+--*/\r
+// TODO:    Base - add argument and description to function comment\r
+// TODO:    Node - add argument and description to function comment\r
+// TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+  EFI_PCI_IO_PROTOCOL *PciIo;\r
+  UINT64              Address;\r
+  UINT32              Address32;\r
+\r
+  Address = 0;\r
+  PciIo   = &(Node->PciDev->PciIo);\r
+\r
+  Address = Base + Node->Offset;\r
+\r
+  //\r
+  // Indicate pci bus driver has allocated\r
+  // resource for this device\r
+  // It might be a temporary solution here since\r
+  // pci device could have multiple bar\r
+  //\r
+  Node->PciDev->Allocated = TRUE;\r
+\r
+  switch ((Node->PciDev->PciBar[Node->Bar]).BarType) {\r
+\r
+  case PciBarTypeIo16:\r
+  case PciBarTypeIo32:\r
+  case PciBarTypeMem32:\r
+  case PciBarTypePMem32:\r
+\r
+    PciIoWrite (\r
+                PciIo,\r
+                EfiPciIoWidthUint32,\r
+                (Node->PciDev->PciBar[Node->Bar]).Offset,\r
+                1,\r
+                &Address\r
+                );\r
+\r
+    Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
+\r
+    break;\r
+\r
+  case PciBarTypeMem64:\r
+  case PciBarTypePMem64:\r
+\r
+    Address32 = (UINT32) (Address & 0x00000000FFFFFFFF);\r
+\r
+    PciIoWrite (\r
+                PciIo,\r
+                EfiPciIoWidthUint32,\r
+                (Node->PciDev->PciBar[Node->Bar]).Offset,\r
+                1,\r
+                &Address32\r
+                );\r
+\r
+    Address32 = (UINT32) RShiftU64 (Address, 32);\r
+\r
+    PciIoWrite (\r
+                PciIo,\r
+                EfiPciIoWidthUint32,\r
+                (UINT8) ((Node->PciDev->PciBar[Node->Bar]).Offset + 4),\r
+                1,\r
+                &Address32\r
+                );\r
+\r
+    Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
+\r
+    break;\r
+\r
+  default:\r
+    break;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+ProgramPpbApperture (\r
+  IN UINT64            Base,\r
+  IN PCI_RESOURCE_NODE *Node\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+  \r
+  None\r
+\r
+--*/\r
+// TODO:    Base - add argument and description to function comment\r
+// TODO:    Node - add argument and description to function comment\r
+// TODO:    EFI_SUCCESS - add return value to function comment\r
+// TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+  EFI_PCI_IO_PROTOCOL *PciIo;\r
+  UINT64              Address;\r
+  UINT32              Address32;\r
+\r
+  Address = 0;\r
+  //\r
+  // if no device south of this PPB, return anyway\r
+  // Apperture is set default in the initialization code\r
+  //\r
+  if (Node->Length == 0 || Node->ResourceUsage == PciResUsagePadding) {\r
+    //\r
+    // For padding resource node, just ignore when programming\r
+    //\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  PciIo   = &(Node->PciDev->PciIo);\r
+  Address = Base + Node->Offset;\r
+\r
+  //\r
+  // Indicate the PPB resource has been allocated\r
+  //\r
+  Node->PciDev->Allocated = TRUE;\r
+\r
+  switch (Node->Bar) {\r
+\r
+  case PPB_BAR_0:\r
+  case PPB_BAR_1:\r
+    PciIoWrite (\r
+                PciIo,\r
+                EfiPciIoWidthUint32,\r
+                (Node->PciDev->PciBar[Node->Bar]).Offset,\r
+                1,\r
+                &Address\r
+                );\r
+\r
+    Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
+    Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;\r
+\r
+    break;\r
+\r
+  case PPB_IO_RANGE:\r
+\r
+    Address32 = ((UINT32) (Address)) >> 8;\r
+    PciIoWrite (\r
+                PciIo,\r
+                EfiPciIoWidthUint8,\r
+                0x1C,\r
+                1,\r
+                &Address32\r
+                );\r
+\r
+    Address32 >>= 8;\r
+    PciIoWrite (\r
+                PciIo,\r
+                EfiPciIoWidthUint16,\r
+                0x30,\r
+                1,\r
+                &Address32\r
+                );\r
+\r
+    Address32 = (UINT32) (Address + Node->Length - 1);\r
+    Address32 = ((UINT32) (Address32)) >> 8;\r
+    PciIoWrite (\r
+                PciIo,\r
+                EfiPciIoWidthUint8,\r
+                0x1D,\r
+                1,\r
+                &Address32\r
+                );\r
+\r
+    Address32 >>= 8;\r
+    PciIoWrite (\r
+                PciIo,\r
+                EfiPciIoWidthUint16,\r
+                0x32,\r
+                1,\r
+                &Address32\r
+                );\r
+\r
+    Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
+    Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;\r
+    break;\r
+\r
+  case PPB_MEM32_RANGE:\r
+\r
+    Address32 = ((UINT32) (Address)) >> 16;\r
+    PciIoWrite (\r
+                PciIo,\r
+                EfiPciIoWidthUint16,\r
+                0x20,\r
+                1,\r
+                &Address32\r
+                );\r
+\r
+    Address32 = (UINT32) (Address + Node->Length - 1);\r
+    Address32 = ((UINT32) (Address32)) >> 16;\r
+    PciIoWrite (\r
+                PciIo,\r
+                EfiPciIoWidthUint16,\r
+                0x22,\r
+                1,\r
+                &Address32\r
+                );\r
+\r
+    Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
+    Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;\r
+    break;\r
+\r
+  case PPB_PMEM32_RANGE:\r
+  case PPB_PMEM64_RANGE:\r
+\r
+    Address32 = ((UINT32) (Address)) >> 16;\r
+    PciIoWrite (\r
+                PciIo,\r
+                EfiPciIoWidthUint16,\r
+                0x24,\r
+                1,\r
+                &Address32\r
+                );\r
+\r
+    Address32 = (UINT32) (Address + Node->Length - 1);\r
+    Address32 = ((UINT32) (Address32)) >> 16;\r
+    PciIoWrite (\r
+                PciIo,\r
+                EfiPciIoWidthUint16,\r
+                0x26,\r
+                1,\r
+                &Address32\r
+                );\r
+\r
+    Address32 = (UINT32) RShiftU64 (Address, 32);\r
+    PciIoWrite (\r
+                PciIo,\r
+                EfiPciIoWidthUint32,\r
+                0x28,\r
+                1,\r
+                &Address32\r
+                );\r
+\r
+    Address32 = (UINT32) RShiftU64 ((Address + Node->Length - 1), 32);\r
+    PciIoWrite (\r
+                PciIo,\r
+                EfiPciIoWidthUint32,\r
+                0x2C,\r
+                1,\r
+                &Address32\r
+                );\r
+\r
+    Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
+    Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;\r
+    break;\r
+\r
+  default:\r
+    break;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+ProgrameUpstreamBridgeForRom (\r
+  IN PCI_IO_DEVICE   *PciDevice,\r
+  IN UINT32          OptionRomBase,\r
+  IN BOOLEAN         Enable\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+--*/\r
+// TODO:    PciDevice - add argument and description to function comment\r
+// TODO:    OptionRomBase - add argument and description to function comment\r
+// TODO:    Enable - add argument and description to function comment\r
+// TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+  PCI_IO_DEVICE     *Parent;\r
+  PCI_RESOURCE_NODE Node;\r
+  //\r
+  // For root bridge, just return.\r
+  //\r
+  Parent = PciDevice->Parent;\r
+  ZeroMem (&Node, sizeof (Node));\r
+  while (Parent) {\r
+    if (!IS_PCI_BRIDGE (&Parent->Pci)) {\r
+      break;\r
+    }\r
+\r
+    Node.PciDev     = Parent;\r
+    Node.Length     = PciDevice->RomSize;\r
+    Node.Alignment  = 0;\r
+    Node.Bar        = PPB_MEM32_RANGE;\r
+    Node.ResType    = PciBarTypeMem32;\r
+    Node.Offset     = 0;\r
+\r
+    //\r
+    // Program PPB to only open a single <= 16<MB apperture\r
+    //\r
+    if (Enable) {\r
+      ProgramPpbApperture (OptionRomBase, &Node);\r
+      PciEnableCommandRegister (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);\r
+    } else {\r
+      InitializePpb (Parent);\r
+      PciDisableCommandRegister (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);\r
+    }\r
+\r
+    Parent = Parent->Parent;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+BOOLEAN\r
+ResourceRequestExisted (\r
+  IN PCI_RESOURCE_NODE *Bridge\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+  Bridge      - A pointer to the PCI_RESOURCE_NODE.\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  if (Bridge != NULL) {\r
+    if (!IsListEmpty (&Bridge->ChildList) || Bridge->Length != 0) {\r
+      return TRUE;\r
+    }\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+EFI_STATUS\r
+InitializeResourcePool (\r
+  PCI_RESOURCE_NODE   *ResourcePool,\r
+  PCI_BAR_TYPE        ResourceType\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+// TODO:    ResourcePool - add argument and description to function comment\r
+// TODO:    ResourceType - add argument and description to function comment\r
+// TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+\r
+  ZeroMem (ResourcePool, sizeof (PCI_RESOURCE_NODE));\r
+  ResourcePool->ResType   = ResourceType;\r
+  ResourcePool->Signature = PCI_RESOURCE_SIGNATURE;\r
+  InitializeListHead (&ResourcePool->ChildList);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+GetResourceMap (\r
+  PCI_IO_DEVICE      *PciDev,\r
+  PCI_RESOURCE_NODE  **IoBridge,\r
+  PCI_RESOURCE_NODE  **Mem32Bridge,\r
+  PCI_RESOURCE_NODE  **PMem32Bridge,\r
+  PCI_RESOURCE_NODE  **Mem64Bridge,\r
+  PCI_RESOURCE_NODE  **PMem64Bridge,\r
+  PCI_RESOURCE_NODE  *IoPool,\r
+  PCI_RESOURCE_NODE  *Mem32Pool,\r
+  PCI_RESOURCE_NODE  *PMem32Pool,\r
+  PCI_RESOURCE_NODE  *Mem64Pool,\r
+  PCI_RESOURCE_NODE  *PMem64Pool\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+// TODO:    PciDev - add argument and description to function comment\r
+// TODO:    IoBridge - add argument and description to function comment\r
+// TODO:    Mem32Bridge - add argument and description to function comment\r
+// TODO:    PMem32Bridge - add argument and description to function comment\r
+// TODO:    Mem64Bridge - add argument and description to function comment\r
+// TODO:    PMem64Bridge - add argument and description to function comment\r
+// TODO:    IoPool - add argument and description to function comment\r
+// TODO:    Mem32Pool - add argument and description to function comment\r
+// TODO:    PMem32Pool - add argument and description to function comment\r
+// TODO:    Mem64Pool - add argument and description to function comment\r
+// TODO:    PMem64Pool - add argument and description to function comment\r
+// TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+\r
+  PCI_RESOURCE_NODE *Temp;\r
+  LIST_ENTRY        *CurrentLink;\r
+\r
+  CurrentLink = IoPool->ChildList.ForwardLink;\r
+\r
+  //\r
+  // Get Io resource map\r
+  //\r
+  while (CurrentLink != &IoPool->ChildList) {\r
+\r
+    Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+\r
+    if (Temp->PciDev == PciDev) {\r
+      *IoBridge = Temp;\r
+    }\r
+\r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+\r
+  //\r
+  // Get Mem32 resource map\r
+  //\r
+  CurrentLink = Mem32Pool->ChildList.ForwardLink;\r
+\r
+  while (CurrentLink != &Mem32Pool->ChildList) {\r
+\r
+    Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+\r
+    if (Temp->PciDev == PciDev) {\r
+      *Mem32Bridge = Temp;\r
+    }\r
+\r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+\r
+  //\r
+  // Get Pmem32 resource map\r
+  //\r
+  CurrentLink = PMem32Pool->ChildList.ForwardLink;\r
+\r
+  while (CurrentLink != &PMem32Pool->ChildList) {\r
+\r
+    Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+\r
+    if (Temp->PciDev == PciDev) {\r
+      *PMem32Bridge = Temp;\r
+    }\r
+\r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+\r
+  //\r
+  // Get Mem64 resource map\r
+  //\r
+  CurrentLink = Mem64Pool->ChildList.ForwardLink;\r
+\r
+  while (CurrentLink != &Mem64Pool->ChildList) {\r
+\r
+    Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+\r
+    if (Temp->PciDev == PciDev) {\r
+      *Mem64Bridge = Temp;\r
+    }\r
+\r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+\r
+  //\r
+  // Get Pmem64 resource map\r
+  //\r
+  CurrentLink = PMem64Pool->ChildList.ForwardLink;\r
+\r
+  while (CurrentLink != &PMem64Pool->ChildList) {\r
+\r
+    Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+\r
+    if (Temp->PciDev == PciDev) {\r
+      *PMem64Bridge = Temp;\r
+    }\r
+\r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+DestroyResourceTree (\r
+  IN PCI_RESOURCE_NODE *Bridge\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+// TODO:    Bridge - add argument and description to function comment\r
+// TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+  PCI_RESOURCE_NODE *Temp;\r
+  LIST_ENTRY        *CurrentLink;\r
+\r
+  while (!IsListEmpty (&Bridge->ChildList)) {\r
+\r
+    CurrentLink = Bridge->ChildList.ForwardLink;\r
+\r
+    Temp        = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+\r
+    RemoveEntryList (CurrentLink);\r
+\r
+    if (IS_PCI_BRIDGE (&(Temp->PciDev->Pci))) {\r
+      DestroyResourceTree (Temp);\r
+    }\r
+\r
+    gBS->FreePool (Temp);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+RecordReservedResource (\r
+  IN UINT64         Base,\r
+  IN UINT64         Length,\r
+  IN PCI_BAR_TYPE   ResType,\r
+  IN PCI_IO_DEVICE  *Bridge\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  \r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+// TODO:    Base - add argument and description to function comment\r
+// TODO:    Length - add argument and description to function comment\r
+// TODO:    ResType - add argument and description to function comment\r
+// TODO:    Bridge - add argument and description to function comment\r
+// TODO:    EFI_OUT_OF_RESOURCES - add return value to function comment\r
+// TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+  PCI_RESERVED_RESOURCE_LIST  *ReservedNode;\r
+\r
+  ReservedNode = AllocatePool (sizeof (PCI_RESERVED_RESOURCE_LIST));\r
+  if (ReservedNode == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  ReservedNode->Signature     = RESERVED_RESOURCE_SIGNATURE;\r
+  ReservedNode->Node.Base     = Base;\r
+  ReservedNode->Node.Length   = Length;\r
+  ReservedNode->Node.ResType  = ResType;\r
+\r
+  InsertTailList (&Bridge->ReservedResourceList, &(ReservedNode->Link));\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+ResourcePaddingForCardBusBridge (\r
+  PCI_IO_DEVICE     *PciDev,\r
+  PCI_RESOURCE_NODE *IoNode,\r
+  PCI_RESOURCE_NODE *Mem32Node,\r
+  PCI_RESOURCE_NODE *PMem32Node,\r
+  PCI_RESOURCE_NODE *Mem64Node,\r
+  PCI_RESOURCE_NODE *PMem64Node\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+// TODO:    PciDev - add argument and description to function comment\r
+// TODO:    IoNode - add argument and description to function comment\r
+// TODO:    Mem32Node - add argument and description to function comment\r
+// TODO:    PMem32Node - add argument and description to function comment\r
+// TODO:    Mem64Node - add argument and description to function comment\r
+// TODO:    PMem64Node - add argument and description to function comment\r
+// TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+  PCI_RESOURCE_NODE *Node;\r
+\r
+  Node = NULL;\r
+\r
+  //\r
+  // Memory Base/Limit Register 0\r
+  // Bar 1 denodes memory range 0\r
+  //\r
+  Node = CreateResourceNode (\r
+          PciDev,\r
+          0x2000000,\r
+          0x1ffffff,\r
+          1,\r
+          PciBarTypeMem32,\r
+          PciResUsagePadding\r
+          );\r
+\r
+  InsertResourceNode (\r
+    Mem32Node,\r
+    Node\r
+    );\r
+\r
+  //\r
+  // Memory Base/Limit Register 1\r
+  // Bar 2 denodes memory range1\r
+  //\r
+  Node = CreateResourceNode (\r
+          PciDev,\r
+          0x2000000,\r
+          0x1ffffff,\r
+          2,\r
+          PciBarTypePMem32,\r
+          PciResUsagePadding\r
+          );\r
+\r
+  InsertResourceNode (\r
+    PMem32Node,\r
+    Node\r
+    );\r
+\r
+  //\r
+  // Io Base/Limit\r
+  // Bar 3 denodes io range 0\r
+  //\r
+  Node = CreateResourceNode (\r
+          PciDev,\r
+          0x100,\r
+          0xff,\r
+          3,\r
+          PciBarTypeIo16,\r
+          PciResUsagePadding\r
+          );\r
+\r
+  InsertResourceNode (\r
+    IoNode,\r
+    Node\r
+    );\r
+\r
+  //\r
+  // Io Base/Limit\r
+  // Bar 4 denodes io range 0\r
+  //\r
+  Node = CreateResourceNode (\r
+          PciDev,\r
+          0x100,\r
+          0xff,\r
+          4,\r
+          PciBarTypeIo16,\r
+          PciResUsagePadding\r
+          );\r
+\r
+  InsertResourceNode (\r
+    IoNode,\r
+    Node\r
+    );\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+ProgramP2C (\r
+  IN UINT64            Base,\r
+  IN PCI_RESOURCE_NODE *Node\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+  \r
+  None\r
+\r
+--*/\r
+// TODO:    Base - add argument and description to function comment\r
+// TODO:    Node - add argument and description to function comment\r
+// TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+  EFI_PCI_IO_PROTOCOL *PciIo;\r
+  UINT64              Address;\r
+  UINT64              TempAddress;\r
+  UINT16              BridgeControl;\r
+\r
+  Address = 0;\r
+  PciIo   = &(Node->PciDev->PciIo);\r
+\r
+  Address = Base + Node->Offset;\r
+\r
+  //\r
+  // Indicate pci bus driver has allocated\r
+  // resource for this device\r
+  // It might be a temporary solution here since\r
+  // pci device could have multiple bar\r
+  //\r
+  Node->PciDev->Allocated = TRUE;\r
+\r
+  switch (Node->Bar) {\r
+\r
+  case P2C_BAR_0:\r
+    PciIoWrite (\r
+                PciIo,\r
+                EfiPciIoWidthUint32,\r
+                (Node->PciDev->PciBar[Node->Bar]).Offset,\r
+                1,\r
+                &Address\r
+                );\r
+\r
+    Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
+    Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;\r
+    break;\r
+\r
+  case P2C_MEM_1:\r
+    PciIoWrite (\r
+                PciIo,\r
+                EfiPciIoWidthUint32,\r
+                0x1c,\r
+                1,\r
+                &Address\r
+                );\r
+\r
+    TempAddress = Address + Node->Length - 1;\r
+    PciIoWrite (\r
+                PciIo,\r
+                EfiPciIoWidthUint32,\r
+                0x20,\r
+                1,\r
+                &TempAddress\r
+                );\r
+\r
+    if (Node->ResType == PciBarTypeMem32) {\r
+\r
+      //\r
+      // Set non-prefetchable bit\r
+      //\r
+      PciIoRead (\r
+                  PciIo,\r
+                  EfiPciIoWidthUint16,\r
+                  0x3e,\r
+                  1,\r
+                  &BridgeControl\r
+                  );\r
+\r
+      BridgeControl &= 0xfeff;\r
+      PciIoWrite (\r
+                  PciIo,\r
+                  EfiPciIoWidthUint16,\r
+                  0x3e,\r
+                  1,\r
+                  &BridgeControl\r
+                  );\r
+\r
+    } else {\r
+\r
+      //\r
+      // Set pre-fetchable bit\r
+      //\r
+      PciIoRead (\r
+                  PciIo,\r
+                  EfiPciIoWidthUint16,\r
+                  0x3e,\r
+                  1,\r
+                  &BridgeControl\r
+                  );\r
+\r
+      BridgeControl |= 0x0100;\r
+      PciIoWrite (\r
+                  PciIo,\r
+                  EfiPciIoWidthUint16,\r
+                  0x3e,\r
+                  1,\r
+                  &BridgeControl\r
+                  );\r
+    }\r
+\r
+    Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
+    Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;\r
+    Node->PciDev->PciBar[Node->Bar].BarType     = Node->ResType;\r
+\r
+    break;\r
+\r
+  case P2C_MEM_2:\r
+    PciIoWrite (\r
+                PciIo,\r
+                EfiPciIoWidthUint32,\r
+                0x24,\r
+                1,\r
+                &Address\r
+                );\r
+\r
+    TempAddress = Address + Node->Length - 1;\r
+\r
+    PciIoWrite (\r
+                PciIo,\r
+                EfiPciIoWidthUint32,\r
+                0x28,\r
+                1,\r
+                &TempAddress\r
+                );\r
+\r
+    if (Node->ResType == PciBarTypeMem32) {\r
+\r
+      //\r
+      // Set non-prefetchable bit\r
+      //\r
+      PciIoRead (\r
+                  PciIo,\r
+                  EfiPciIoWidthUint16,\r
+                  0x3e,\r
+                  1,\r
+                  &BridgeControl\r
+                  );\r
+\r
+      BridgeControl &= 0xfdff;\r
+      PciIoWrite (\r
+                  PciIo,\r
+                  EfiPciIoWidthUint16,\r
+                  0x3e,\r
+                  1,\r
+                  &BridgeControl\r
+                  );\r
+    } else {\r
+\r
+      //\r
+      // Set pre-fetchable bit\r
+      //\r
+      PciIoRead (\r
+                  PciIo,\r
+                  EfiPciIoWidthUint16,\r
+                  0x3e,\r
+                  1,\r
+                  &BridgeControl\r
+                  );\r
+\r
+      BridgeControl |= 0x0200;\r
+      PciIoWrite (\r
+                  PciIo,\r
+                  EfiPciIoWidthUint16,\r
+                  0x3e,\r
+                  1,\r
+                  &BridgeControl\r
+                  );\r
+    }\r
+\r
+    Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
+    Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;\r
+    Node->PciDev->PciBar[Node->Bar].BarType     = Node->ResType;\r
+    break;\r
+\r
+  case P2C_IO_1:\r
+    PciIoWrite (\r
+                PciIo,\r
+                EfiPciIoWidthUint32,\r
+                0x2c,\r
+                1,\r
+                &Address\r
+                );\r
+    TempAddress = Address + Node->Length - 1;\r
+    PciIoWrite (\r
+                PciIo,\r
+                EfiPciIoWidthUint32,\r
+                0x30,\r
+                1,\r
+                &TempAddress\r
+                );\r
+\r
+    Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
+    Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;\r
+    Node->PciDev->PciBar[Node->Bar].BarType     = Node->ResType;\r
+\r
+    break;\r
+\r
+  case P2C_IO_2:\r
+    PciIoWrite (\r
+                PciIo,\r
+                EfiPciIoWidthUint32,\r
+                0x34,\r
+                1,\r
+                &Address\r
+                );\r
+\r
+    TempAddress = Address + Node->Length - 1;\r
+    PciIoWrite (\r
+                PciIo,\r
+                EfiPciIoWidthUint32,\r
+                0x38,\r
+                1,\r
+                &TempAddress\r
+                );\r
+\r
+    Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
+    Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;\r
+    Node->PciDev->PciBar[Node->Bar].BarType     = Node->ResType;\r
+    break;\r
+\r
+  default:\r
+    break;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+ApplyResourcePadding (\r
+  PCI_IO_DEVICE     *PciDev,\r
+  PCI_RESOURCE_NODE *IoNode,\r
+  PCI_RESOURCE_NODE *Mem32Node,\r
+  PCI_RESOURCE_NODE *PMem32Node,\r
+  PCI_RESOURCE_NODE *Mem64Node,\r
+  PCI_RESOURCE_NODE *PMem64Node\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+  \r
+  None\r
+\r
+--*/\r
+// TODO:    PciDev - add argument and description to function comment\r
+// TODO:    IoNode - add argument and description to function comment\r
+// TODO:    Mem32Node - add argument and description to function comment\r
+// TODO:    PMem32Node - add argument and description to function comment\r
+// TODO:    Mem64Node - add argument and description to function comment\r
+// TODO:    PMem64Node - add argument and description to function comment\r
+// TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
+  PCI_RESOURCE_NODE                 *Node;\r
+  UINT8                             DummyBarIndex;\r
+\r
+  DummyBarIndex = 0;\r
+  Ptr           = PciDev->ResourcePaddingDescriptors;\r
+\r
+  while (((EFI_ACPI_END_TAG_DESCRIPTOR *) Ptr)->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
+\r
+    if (Ptr->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_IO) {\r
+      if (Ptr->AddrLen != 0) {\r
+\r
+        Node = CreateResourceNode (\r
+                PciDev,\r
+                Ptr->AddrLen,\r
+                Ptr->AddrRangeMax,\r
+                DummyBarIndex,\r
+                PciBarTypeIo16,\r
+                PciResUsagePadding\r
+                );\r
+        InsertResourceNode (\r
+          IoNode,\r
+          Node\r
+          );\r
+      }\r
+\r
+      Ptr++;\r
+      continue;\r
+    }\r
+\r
+    if (Ptr->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {\r
+\r
+      if (Ptr->AddrSpaceGranularity == 32) {\r
+\r
+        //\r
+        // prefechable\r
+        //\r
+        if (Ptr->SpecificFlag == 0x6) {\r
+          if (Ptr->AddrLen) {\r
+            Node = CreateResourceNode (\r
+                    PciDev,\r
+                    Ptr->AddrLen,\r
+                    Ptr->AddrRangeMax,\r
+                    DummyBarIndex,\r
+                    PciBarTypePMem32,\r
+                    PciResUsagePadding\r
+                    );\r
+            InsertResourceNode (\r
+              PMem32Node,\r
+              Node\r
+              );\r
+          }\r
+\r
+          Ptr++;\r
+          continue;\r
+        }\r
+\r
+        //\r
+        // Non-prefechable\r
+        //\r
+        if (Ptr->SpecificFlag == 0) {\r
+          if (Ptr->AddrLen) {\r
+            Node = CreateResourceNode (\r
+                    PciDev,\r
+                    Ptr->AddrLen,\r
+                    Ptr->AddrRangeMax,\r
+                    DummyBarIndex,\r
+                    PciBarTypeMem32,\r
+                    PciResUsagePadding\r
+                    );\r
+            InsertResourceNode (\r
+              Mem32Node,\r
+              Node\r
+              );\r
+          }\r
+\r
+          Ptr++;\r
+          continue;\r
+        }\r
+      }\r
+\r
+      if (Ptr->AddrSpaceGranularity == 64) {\r
+\r
+        //\r
+        // prefechable\r
+        //\r
+        if (Ptr->SpecificFlag == 0x6) {\r
+          if (Ptr->AddrLen) {\r
+            Node = CreateResourceNode (\r
+                    PciDev,\r
+                    Ptr->AddrLen,\r
+                    Ptr->AddrRangeMax,\r
+                    DummyBarIndex,\r
+                    PciBarTypePMem64,\r
+                    PciResUsagePadding\r
+                    );\r
+            InsertResourceNode (\r
+              PMem64Node,\r
+              Node\r
+              );\r
+          }\r
+\r
+          Ptr++;\r
+          continue;\r
+        }\r
+\r
+        //\r
+        // Non-prefechable\r
+        //\r
+        if (Ptr->SpecificFlag == 0) {\r
+          if (Ptr->AddrLen) {\r
+            Node = CreateResourceNode (\r
+                    PciDev,\r
+                    Ptr->AddrLen,\r
+                    Ptr->AddrRangeMax,\r
+                    DummyBarIndex,\r
+                    PciBarTypeMem64,\r
+                    PciResUsagePadding\r
+                    );\r
+            InsertResourceNode (\r
+              Mem64Node,\r
+              Node\r
+              );\r
+          }\r
+\r
+          Ptr++;\r
+          continue;\r
+        }\r
+      }\r
+    }\r
+\r
+    Ptr++;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+//\r
+// Light PCI bus driver woundn't support hotplug root device\r
+// So no need to pad resource for them\r
+//\r
+VOID\r
+GetResourcePaddingPpb (\r
+  IN  PCI_IO_DEVICE                  *PciIoDevice\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Get resource.\r
+\r
+Arguments:\r
+\r
+  PciIoDevice        A pointer to a pci device.\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  if (gPciHotPlugInit) {\r
+    if (PciIoDevice->ResourcePaddingDescriptors == NULL) {\r
+      GetResourcePaddingForHpb (PciIoDevice);\r
+    }\r
+  }\r
+}\r