]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
MdeModulePkg: Add generic PciHostBridgeDxe driver.
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / PciHostBridgeDxe / PciHostBridge.c
diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
new file mode 100644 (file)
index 0000000..08285d8
--- /dev/null
@@ -0,0 +1,1134 @@
+/** @file\r
+\r
+  Provides the basic interfaces to abstract a PCI Host Bridge Resource Allocation.\r
+\r
+Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR>\r
+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
+**/\r
+\r
+#include "PciHostBridge.h"\r
+#include "PciRootBridge.h"\r
+#include "PciHostResource.h"\r
+\r
+\r
+EFI_METRONOME_ARCH_PROTOCOL *mMetronome;\r
+EFI_CPU_IO2_PROTOCOL        *mCpuIo;\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mAcpiAddressSpaceTypeStr[] = {\r
+  L"Mem", L"I/O", L"Bus"\r
+};\r
+GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mPciResourceTypeStr[] = {\r
+  L"I/O", L"Mem", L"PMem", L"Mem64", L"PMem64", L"Bus"\r
+};\r
+\r
+/**\r
+\r
+  Entry point of this driver.\r
+\r
+  @param ImageHandle  Image handle of this driver.\r
+  @param SystemTable  Pointer to standard EFI system table.\r
+\r
+  @retval EFI_SUCCESS       Succeed.\r
+  @retval EFI_DEVICE_ERROR  Fail to install PCI_ROOT_BRIDGE_IO protocol.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InitializePciHostBridge (\r
+  IN EFI_HANDLE         ImageHandle,\r
+  IN EFI_SYSTEM_TABLE   *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  PCI_HOST_BRIDGE_INSTANCE    *HostBridge;\r
+  PCI_ROOT_BRIDGE_INSTANCE    *RootBridge;\r
+  PCI_ROOT_BRIDGE             *RootBridges;\r
+  UINTN                       RootBridgeCount;\r
+  UINTN                       Index;\r
+  PCI_ROOT_BRIDGE_APERTURE    *MemApertures[4];\r
+  UINTN                       MemApertureIndex;\r
+\r
+  RootBridges = PciHostBridgeGetRootBridges (&RootBridgeCount);\r
+  if ((RootBridges == NULL) || (RootBridgeCount == 0)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Status = gBS->LocateProtocol (&gEfiMetronomeArchProtocolGuid, NULL, (VOID **) &mMetronome);\r
+  ASSERT_EFI_ERROR (Status);\r
+  Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL, (VOID **) &mCpuIo);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Most systems in the world including complex servers have only one Host Bridge.\r
+  //\r
+  HostBridge = AllocateZeroPool (sizeof (PCI_HOST_BRIDGE_INSTANCE));\r
+  ASSERT (HostBridge != NULL);\r
+\r
+  HostBridge->Signature        = PCI_HOST_BRIDGE_SIGNATURE;\r
+  HostBridge->CanRestarted     = TRUE;\r
+  InitializeListHead (&HostBridge->RootBridges);\r
+\r
+  HostBridge->ResAlloc.NotifyPhase          = NotifyPhase;\r
+  HostBridge->ResAlloc.GetNextRootBridge    = GetNextRootBridge;\r
+  HostBridge->ResAlloc.GetAllocAttributes   = GetAttributes;\r
+  HostBridge->ResAlloc.StartBusEnumeration  = StartBusEnumeration;\r
+  HostBridge->ResAlloc.SetBusNumbers        = SetBusNumbers;\r
+  HostBridge->ResAlloc.SubmitResources      = SubmitResources;\r
+  HostBridge->ResAlloc.GetProposedResources = GetProposedResources;\r
+  HostBridge->ResAlloc.PreprocessController = PreprocessController;\r
+\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &HostBridge->Handle,\r
+                  &gEfiPciHostBridgeResourceAllocationProtocolGuid, &HostBridge->ResAlloc,\r
+                  NULL\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    FreePool (HostBridge);\r
+    PciHostBridgeFreeRootBridges (RootBridges, RootBridgeCount);\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Create Root Bridge Device Handle in this Host Bridge\r
+  //\r
+  for (Index = 0; Index < RootBridgeCount; Index++) {\r
+    //\r
+    // Create Root Bridge Handle Instance\r
+    //\r
+    RootBridge = CreateRootBridge (&RootBridges[Index], HostBridge->Handle);\r
+    ASSERT (RootBridge != NULL);\r
+    if (RootBridge == NULL) {\r
+      continue;\r
+    }\r
+\r
+    if (RootBridges[Index].Io.Limit > RootBridges[Index].Io.Base) {\r
+      Status = gDS->AddIoSpace (\r
+                      EfiGcdIoTypeIo,\r
+                      RootBridges[Index].Io.Base,\r
+                      RootBridges[Index].Io.Limit - RootBridges[Index].Io.Base + 1\r
+                      );\r
+      ASSERT_EFI_ERROR (Status);\r
+    }\r
+\r
+    //\r
+    // Add all the Mem/PMem aperture to GCD\r
+    // Mem/PMem shouldn't overlap with each other\r
+    // Root bridge which needs to combine MEM and PMEM should only report\r
+    // the MEM aperture in Mem\r
+    //\r
+    MemApertures[0] = &RootBridges[Index].Mem;\r
+    MemApertures[1] = &RootBridges[Index].MemAbove4G;\r
+    MemApertures[2] = &RootBridges[Index].PMem;\r
+    MemApertures[3] = &RootBridges[Index].PMemAbove4G;\r
+\r
+    for (MemApertureIndex = 0; MemApertureIndex < sizeof (MemApertures) / sizeof (MemApertures[0]); MemApertureIndex++) {\r
+      if (MemApertures[MemApertureIndex]->Limit > MemApertures[MemApertureIndex]->Base) {\r
+        Status = gDS->AddMemorySpace (\r
+                        EfiGcdMemoryTypeMemoryMappedIo,\r
+                        MemApertures[MemApertureIndex]->Base,\r
+                        MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,\r
+                        EFI_MEMORY_UC\r
+                        );\r
+        ASSERT_EFI_ERROR (Status);\r
+        Status = gDS->SetMemorySpaceAttributes (\r
+                        MemApertures[MemApertureIndex]->Base,\r
+                        MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,\r
+                        EFI_MEMORY_UC\r
+                        );\r
+        ASSERT_EFI_ERROR (Status);\r
+      }\r
+    }\r
+    //\r
+    // Insert Root Bridge Handle Instance\r
+    //\r
+    Status = gBS->InstallMultipleProtocolInterfaces (\r
+                    &RootBridge->Handle,\r
+                    &gEfiDevicePathProtocolGuid, RootBridge->DevicePath,\r
+                    &gEfiPciRootBridgeIoProtocolGuid, &RootBridge->RootBridgeIo,\r
+                    NULL\r
+                    );\r
+    ASSERT_EFI_ERROR (Status);\r
+    InsertTailList (&HostBridge->RootBridges, &RootBridge->Link);\r
+  }\r
+  PciHostBridgeFreeRootBridges (RootBridges, RootBridgeCount);\r
+  return Status;\r
+}\r
+\r
+/**\r
+  This routine constructs the resource descriptors for all root bridges and call PciHostBridgeResourceConflict().\r
+\r
+  @param HostBridge The Host Bridge Instance where the resource adjustment happens.\r
+**/\r
+VOID\r
+ResourceConflict (\r
+  IN  PCI_HOST_BRIDGE_INSTANCE *HostBridge\r
+  )\r
+{\r
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Resources;\r
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
+  EFI_ACPI_END_TAG_DESCRIPTOR       *End;\r
+  PCI_ROOT_BRIDGE_INSTANCE          *RootBridge;\r
+  LIST_ENTRY                        *Link;\r
+  UINTN                             RootBridgeCount;\r
+  PCI_RESOURCE_TYPE                 Index;\r
+  PCI_RES_NODE                      *ResAllocNode;\r
+\r
+  RootBridgeCount = 0;\r
+  for (Link = GetFirstNode (&HostBridge->RootBridges)\r
+       ; !IsNull (&HostBridge->RootBridges, Link)\r
+       ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
+       ) {\r
+    RootBridgeCount++;\r
+  }\r
+\r
+  Resources = AllocatePool (\r
+                RootBridgeCount * (TypeMax * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)) +\r
+                sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)\r
+                );\r
+  ASSERT (Resources != NULL);\r
+\r
+  for (Link = GetFirstNode (&HostBridge->RootBridges), Descriptor = Resources\r
+       ; !IsNull (&HostBridge->RootBridges, Link)\r
+       ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
+       ) {\r
+    RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
+    for (Index = TypeIo; Index < TypeMax; Index++) {\r
+      ResAllocNode = &RootBridge->ResAllocNode[Index];\r
+\r
+      Descriptor->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
+      Descriptor->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
+      Descriptor->AddrRangeMin = ResAllocNode->Base;\r
+      Descriptor->AddrRangeMax = ResAllocNode->Alignment;\r
+      Descriptor->AddrLen = ResAllocNode->Length;\r
+      switch (ResAllocNode->Type) {\r
+\r
+      case TypeIo:\r
+        Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;\r
+        break;\r
+\r
+      case TypePMem32:\r
+        Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;\r
+      case TypeMem32:\r
+        Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+        Descriptor->AddrSpaceGranularity = 32;\r
+        break;\r
+\r
+      case TypePMem64:\r
+        Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;\r
+      case TypeMem64:\r
+        Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+        Descriptor->AddrSpaceGranularity = 64;\r
+        break;\r
+\r
+      case TypeBus:\r
+        Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;\r
+        break;\r
+\r
+      default:\r
+        break;\r
+      }\r
+\r
+      Descriptor++;\r
+    }\r
+    //\r
+    // Terminate the root bridge resources.\r
+    //\r
+    End = (EFI_ACPI_END_TAG_DESCRIPTOR *) Descriptor;\r
+    End->Desc = ACPI_END_TAG_DESCRIPTOR;\r
+    End->Checksum = 0x0;\r
+\r
+    Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) (End + 1);\r
+  }\r
+  //\r
+  // Terminate the host bridge resources.\r
+  //\r
+  End = (EFI_ACPI_END_TAG_DESCRIPTOR *) Descriptor;\r
+  End->Desc = ACPI_END_TAG_DESCRIPTOR;\r
+  End->Checksum = 0x0;\r
+\r
+  DEBUG ((DEBUG_ERROR, "Call PciHostBridgeResourceConflict().\n"));\r
+  PciHostBridgeResourceConflict (HostBridge->Handle, Resources);\r
+  FreePool (Resources);\r
+}\r
+\r
+UINT64\r
+AllocateResource (\r
+  BOOLEAN Mmio,\r
+  UINT64  Length,\r
+  UINTN   BitsOfAlignment,\r
+  UINT64  BaseAddress,\r
+  UINT64  Limit\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+\r
+  if (BaseAddress < Limit) {\r
+    //\r
+    // Have to make sure Aligment is handled since we are doing direct address allocation\r
+    //\r
+    BaseAddress = ALIGN_VALUE (BaseAddress, LShiftU64 (1, BitsOfAlignment));\r
+\r
+    while (BaseAddress + Length <= Limit + 1) {\r
+      if (Mmio) {\r
+        Status = gDS->AllocateMemorySpace (\r
+                        EfiGcdAllocateAddress,\r
+                        EfiGcdMemoryTypeMemoryMappedIo,\r
+                        BitsOfAlignment,\r
+                        Length,\r
+                        &BaseAddress,\r
+                        gImageHandle,\r
+                        NULL\r
+                        );\r
+      } else {\r
+        Status = gDS->AllocateIoSpace (\r
+                        EfiGcdAllocateAddress,\r
+                        EfiGcdIoTypeIo,\r
+                        BitsOfAlignment,\r
+                        Length,\r
+                        &BaseAddress,\r
+                        gImageHandle,\r
+                        NULL\r
+                        );\r
+      }\r
+\r
+      if (!EFI_ERROR (Status)) {\r
+        return BaseAddress;\r
+      }\r
+      BaseAddress += LShiftU64 (1, BitsOfAlignment);\r
+    }\r
+  }\r
+  return MAX_UINT64;\r
+}\r
+/**\r
+\r
+  Enter a certain phase of the PCI enumeration process.\r
+\r
+  @param This   The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.\r
+  @param Phase  The phase during enumeration.\r
+\r
+  @retval EFI_SUCCESS            Succeed.\r
+  @retval EFI_INVALID_PARAMETER  Wrong phase parameter passed in.\r
+  @retval EFI_NOT_READY          Resources have not been submitted yet.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NotifyPhase (\r
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE    Phase\r
+  )\r
+{\r
+  PCI_HOST_BRIDGE_INSTANCE              *HostBridge;\r
+  PCI_ROOT_BRIDGE_INSTANCE              *RootBridge;\r
+  LIST_ENTRY                            *Link;\r
+  EFI_PHYSICAL_ADDRESS                  BaseAddress;\r
+  UINT64                                AddrLen;\r
+  UINTN                                 BitsOfAlignment;\r
+  UINT64                                Alignment;\r
+  EFI_STATUS                            Status;\r
+  EFI_STATUS                            ReturnStatus;\r
+  PCI_RESOURCE_TYPE                     Index;\r
+  PCI_RESOURCE_TYPE                     Index1;\r
+  PCI_RESOURCE_TYPE                     Index2;\r
+  BOOLEAN                               ResNodeHandled[TypeMax];\r
+  UINT64                                MaxAlignment;\r
+\r
+  HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
+\r
+  switch (Phase) {\r
+  case EfiPciHostBridgeBeginEnumeration:\r
+    if (!HostBridge->CanRestarted) {\r
+      return EFI_NOT_READY;\r
+    }\r
+    //\r
+    // Reset Root Bridge\r
+    //\r
+    for (Link = GetFirstNode (&HostBridge->RootBridges)\r
+          ; !IsNull (&HostBridge->RootBridges, Link)\r
+          ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
+          ) {\r
+      RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
+      for (Index = TypeIo; Index < TypeMax; Index++) {\r
+        RootBridge->ResAllocNode[Index].Type   = Index;\r
+        RootBridge->ResAllocNode[Index].Base   = 0;\r
+        RootBridge->ResAllocNode[Index].Length = 0;\r
+        RootBridge->ResAllocNode[Index].Status = ResNone;\r
+\r
+        RootBridge->ResourceSubmitted = FALSE;\r
+      }\r
+    }\r
+\r
+    HostBridge->CanRestarted = TRUE;\r
+    break;\r
+\r
+  case EfiPciHostBridgeBeginBusAllocation:\r
+    //\r
+    // No specific action is required here, can perform any chipset specific programing\r
+    //\r
+    HostBridge->CanRestarted = FALSE;\r
+    break;\r
+\r
+  case EfiPciHostBridgeEndBusAllocation:\r
+    //\r
+    // No specific action is required here, can perform any chipset specific programing\r
+    //\r
+    break;\r
+\r
+  case EfiPciHostBridgeBeginResourceAllocation:\r
+    //\r
+    // No specific action is required here, can perform any chipset specific programing\r
+    //\r
+    break;\r
+\r
+  case EfiPciHostBridgeAllocateResources:\r
+    ReturnStatus = EFI_SUCCESS;\r
+\r
+    //\r
+    // Make sure the resource for all root bridges has been submitted.\r
+    //\r
+    for (Link = GetFirstNode (&HostBridge->RootBridges)\r
+         ; !IsNull (&HostBridge->RootBridges, Link)\r
+         ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
+         ) {\r
+      RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
+      if (!RootBridge->ResourceSubmitted) {\r
+        return EFI_NOT_READY;\r
+      }\r
+    }\r
+\r
+    DEBUG ((EFI_D_INFO, "PciHostBridge: NotifyPhase (AllocateResources)\n"));\r
+    for (Link = GetFirstNode (&HostBridge->RootBridges)\r
+         ; !IsNull (&HostBridge->RootBridges, Link)\r
+         ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
+         ) {\r
+      for (Index = TypeIo; Index < TypeBus; Index++) {\r
+        ResNodeHandled[Index] = FALSE;\r
+      }\r
+\r
+      RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
+      DEBUG ((EFI_D_INFO, " RootBridge: %s\n", RootBridge->DevicePathStr));\r
+\r
+      for (Index1 = TypeIo; Index1 < TypeBus; Index1++) {\r
+        if (RootBridge->ResAllocNode[Index1].Status == ResNone) {\r
+          ResNodeHandled[Index1] = TRUE;\r
+        } else {\r
+          //\r
+          // Allocate the resource node with max alignment at first\r
+          //\r
+          MaxAlignment = 0;\r
+          Index = TypeMax;\r
+          for (Index2 = TypeIo; Index2 < TypeBus; Index2++) {\r
+            if (ResNodeHandled[Index2]) {\r
+              continue;\r
+            }\r
+            if (MaxAlignment <= RootBridge->ResAllocNode[Index2].Alignment) {\r
+              MaxAlignment = RootBridge->ResAllocNode[Index2].Alignment;\r
+              Index = Index2;\r
+            }\r
+          }\r
+\r
+          ASSERT (Index < TypeMax);\r
+          ResNodeHandled[Index] = TRUE;\r
+          AddrLen = RootBridge->ResAllocNode[Index].Length;\r
+          Alignment = RootBridge->ResAllocNode[Index].Alignment;\r
+          BitsOfAlignment = LowBitSet64 (Alignment + 1);\r
+          BaseAddress = MAX_UINT64;\r
+\r
+          switch (Index) {\r
+          case TypeIo:\r
+            BaseAddress = AllocateResource (\r
+                            FALSE,\r
+                            RootBridge->ResAllocNode[Index].Length,\r
+                            MIN (15, BitsOfAlignment),\r
+                            ALIGN_VALUE (RootBridge->Io.Base, Alignment + 1),\r
+                            RootBridge->Io.Limit\r
+                            );\r
+            break;\r
+\r
+          case TypeMem64:\r
+            BaseAddress = AllocateResource (\r
+                            TRUE,\r
+                            RootBridge->ResAllocNode[Index].Length,\r
+                            MIN (63, BitsOfAlignment),\r
+                            ALIGN_VALUE (RootBridge->MemAbove4G.Base, Alignment + 1),\r
+                            RootBridge->MemAbove4G.Limit\r
+                            );\r
+            if (BaseAddress != MAX_UINT64) {\r
+              break;\r
+            }\r
+            //\r
+            // If memory above 4GB is not available, try memory below 4GB\r
+            //\r
+\r
+          case TypeMem32:\r
+            BaseAddress = AllocateResource (\r
+                            TRUE,\r
+                            RootBridge->ResAllocNode[Index].Length,\r
+                            MIN (31, BitsOfAlignment),\r
+                            ALIGN_VALUE (RootBridge->Mem.Base, Alignment + 1),\r
+                            RootBridge->Mem.Limit\r
+                            );\r
+            break;\r
+\r
+          case TypePMem64:\r
+            BaseAddress = AllocateResource (\r
+                            TRUE,\r
+                            RootBridge->ResAllocNode[Index].Length,\r
+                            MIN (63, BitsOfAlignment),\r
+                            ALIGN_VALUE (RootBridge->PMemAbove4G.Base, Alignment + 1),\r
+                            RootBridge->PMemAbove4G.Limit\r
+                            );\r
+            if (BaseAddress != MAX_UINT64) {\r
+              break;\r
+            }\r
+            //\r
+            // If memory above 4GB is not available, try memory below 4GB\r
+            //\r
+          case TypePMem32:\r
+            BaseAddress = AllocateResource (\r
+                            TRUE,\r
+                            RootBridge->ResAllocNode[Index].Length,\r
+                            MIN (31, BitsOfAlignment),\r
+                            ALIGN_VALUE (RootBridge->PMem.Base, Alignment + 1),\r
+                            RootBridge->PMem.Limit\r
+                            );\r
+            break;\r
+\r
+          default:\r
+            ASSERT (FALSE);\r
+            break;\r
+          }\r
+\r
+          DEBUG ((DEBUG_INFO, "  %s: Base/Length/Alignment = %lx/%lx/%lx - ",\r
+                  mPciResourceTypeStr[Index], BaseAddress, RootBridge->ResAllocNode[Index].Length, Alignment));\r
+          if (BaseAddress != MAX_UINT64) {\r
+            RootBridge->ResAllocNode[Index].Base = BaseAddress;\r
+            RootBridge->ResAllocNode[Index].Status = ResAllocated;\r
+            DEBUG ((DEBUG_INFO, "Success\n"));\r
+          } else {\r
+            ReturnStatus = EFI_OUT_OF_RESOURCES;\r
+            DEBUG ((DEBUG_ERROR, "Out Of Resource!\n"));\r
+          }\r
+        }\r
+      }\r
+    }\r
+\r
+    if (ReturnStatus == EFI_OUT_OF_RESOURCES) {\r
+      ResourceConflict (HostBridge);\r
+    }\r
+\r
+    //\r
+    // Set resource to zero for nodes where allocation fails\r
+    //\r
+    for (Link = GetFirstNode (&HostBridge->RootBridges)\r
+          ; !IsNull (&HostBridge->RootBridges, Link)\r
+          ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
+          ) {\r
+      RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
+      for (Index = TypeIo; Index < TypeBus; Index++) {\r
+        if (RootBridge->ResAllocNode[Index].Status != ResAllocated) {\r
+          RootBridge->ResAllocNode[Index].Length = 0;\r
+        }\r
+      }\r
+    }\r
+    return ReturnStatus;\r
+\r
+  case EfiPciHostBridgeSetResources:\r
+    //\r
+    // HostBridgeInstance->CanRestarted = FALSE;\r
+    //\r
+    break;\r
+\r
+  case EfiPciHostBridgeFreeResources:\r
+    //\r
+    // HostBridgeInstance->CanRestarted = FALSE;\r
+    //\r
+    ReturnStatus = EFI_SUCCESS;\r
+    for (Link = GetFirstNode (&HostBridge->RootBridges)\r
+         ; !IsNull (&HostBridge->RootBridges, Link)\r
+         ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
+         ) {\r
+      RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
+      for (Index = TypeIo; Index < TypeBus; Index++) {\r
+        if (RootBridge->ResAllocNode[Index].Status == ResAllocated) {\r
+          switch (Index) {\r
+          case TypeIo:\r
+            Status = gDS->FreeIoSpace (RootBridge->ResAllocNode[Index].Base, RootBridge->ResAllocNode[Index].Length);\r
+            if (EFI_ERROR (Status)) {\r
+              ReturnStatus = Status;\r
+            }\r
+            break;\r
+\r
+          case TypeMem32:\r
+          case TypePMem32:\r
+          case TypeMem64:\r
+          case TypePMem64:\r
+            Status = gDS->FreeMemorySpace (RootBridge->ResAllocNode[Index].Base, RootBridge->ResAllocNode[Index].Length);\r
+            if (EFI_ERROR (Status)) {\r
+              ReturnStatus = Status;\r
+            }\r
+            break;\r
+\r
+          default:\r
+            ASSERT (FALSE);\r
+            break;\r
+          }\r
+\r
+          RootBridge->ResAllocNode[Index].Type = Index;\r
+          RootBridge->ResAllocNode[Index].Base = 0;\r
+          RootBridge->ResAllocNode[Index].Length = 0;\r
+          RootBridge->ResAllocNode[Index].Status = ResNone;\r
+        }\r
+      }\r
+\r
+      RootBridge->ResourceSubmitted = FALSE;\r
+    }\r
+\r
+    HostBridge->CanRestarted = TRUE;\r
+    return ReturnStatus;\r
+\r
+  case EfiPciHostBridgeEndResourceAllocation:\r
+    //\r
+    // The resource allocation phase is completed.  No specific action is required\r
+    // here. This notification can be used to perform any chipset specific programming.\r
+    //\r
+    break;\r
+\r
+  case EfiPciHostBridgeEndEnumeration:\r
+    //\r
+    // The Host Bridge Enumeration is completed. No specific action is required here.\r
+    // This notification can be used to perform any chipset specific programming.\r
+    //\r
+    break;\r
+\r
+  default:\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+\r
+  Return the device handle of the next PCI root bridge that is associated with\r
+  this Host Bridge.\r
+\r
+  @param This              The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
+  @param RootBridgeHandle  Returns the device handle of the next PCI Root Bridge.\r
+                           On input, it holds the RootBridgeHandle returned by the most\r
+                           recent call to GetNextRootBridge().The handle for the first\r
+                           PCI Root Bridge is returned if RootBridgeHandle is NULL on input.\r
+\r
+  @retval EFI_SUCCESS            Succeed.\r
+  @retval EFI_NOT_FOUND          Next PCI root bridge not found.\r
+  @retval EFI_INVALID_PARAMETER  Wrong parameter passed in.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetNextRootBridge (\r
+  IN     EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
+  IN OUT EFI_HANDLE                                       *RootBridgeHandle\r
+  )\r
+{\r
+  BOOLEAN                   ReturnNext;\r
+  LIST_ENTRY                *Link;\r
+  PCI_HOST_BRIDGE_INSTANCE  *HostBridge;\r
+  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;\r
+\r
+  if (RootBridgeHandle == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
+  ReturnNext = (BOOLEAN) (*RootBridgeHandle == NULL);\r
+\r
+  for (Link = GetFirstNode (&HostBridge->RootBridges)\r
+      ; !IsNull (&HostBridge->RootBridges, Link)\r
+      ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
+      ) {\r
+    RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
+    if (ReturnNext) {\r
+      *RootBridgeHandle = RootBridge->Handle;\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
+    ReturnNext = (BOOLEAN) (*RootBridgeHandle == RootBridge->Handle);\r
+  }\r
+\r
+  if (ReturnNext) {\r
+    ASSERT (IsNull (&HostBridge->RootBridges, Link));\r
+    return EFI_NOT_FOUND;\r
+  } else {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+}\r
+\r
+/**\r
+\r
+  Returns the attributes of a PCI Root Bridge.\r
+\r
+  @param This              The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
+  @param RootBridgeHandle  The device handle of the PCI Root Bridge\r
+                           that the caller is interested in.\r
+  @param Attributes        The pointer to attributes of the PCI Root Bridge.\r
+\r
+  @retval EFI_SUCCESS            Succeed.\r
+  @retval EFI_INVALID_PARAMETER  Attributes parameter passed in is NULL or\r
+                                 RootBridgeHandle is not an EFI_HANDLE\r
+                                 that was returned on a previous call to\r
+                                 GetNextRootBridge().\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetAttributes (\r
+  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
+  IN  EFI_HANDLE                                       RootBridgeHandle,\r
+  OUT UINT64                                           *Attributes\r
+  )\r
+{\r
+  LIST_ENTRY                *Link;\r
+  PCI_HOST_BRIDGE_INSTANCE  *HostBridge;\r
+  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;\r
+\r
+  if (Attributes == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
+  for (Link = GetFirstNode (&HostBridge->RootBridges)\r
+      ; !IsNull (&HostBridge->RootBridges, Link)\r
+      ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
+      ) {\r
+    RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
+    if (RootBridgeHandle == RootBridge->Handle) {\r
+      *Attributes = RootBridge->AllocationAttributes;\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  return EFI_INVALID_PARAMETER;\r
+}\r
+\r
+/**\r
+\r
+  This is the request from the PCI enumerator to set up\r
+  the specified PCI Root Bridge for bus enumeration process.\r
+\r
+  @param This              The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
+  @param RootBridgeHandle  The PCI Root Bridge to be set up.\r
+  @param Configuration     Pointer to the pointer to the PCI bus resource descriptor.\r
+\r
+  @retval EFI_SUCCESS            Succeed.\r
+  @retval EFI_OUT_OF_RESOURCES   Not enough pool to be allocated.\r
+  @retval EFI_INVALID_PARAMETER  RootBridgeHandle is not a valid handle.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+StartBusEnumeration (\r
+  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
+  IN  EFI_HANDLE                                       RootBridgeHandle,\r
+  OUT VOID                                             **Configuration\r
+  )\r
+{\r
+  LIST_ENTRY                *Link;\r
+  PCI_HOST_BRIDGE_INSTANCE  *HostBridge;\r
+  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;\r
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
+  EFI_ACPI_END_TAG_DESCRIPTOR       *End;\r
+\r
+  if (Configuration == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
+  for (Link = GetFirstNode (&HostBridge->RootBridges)\r
+       ; !IsNull (&HostBridge->RootBridges, Link)\r
+       ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
+       ) {\r
+    RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
+    if (RootBridgeHandle == RootBridge->Handle) {\r
+      *Configuration = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
+      if (*Configuration == NULL) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+\r
+      Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) *Configuration;\r
+      Descriptor->Desc                  = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
+      Descriptor->Len                   = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
+      Descriptor->ResType               = ACPI_ADDRESS_SPACE_TYPE_BUS;\r
+      Descriptor->GenFlag               = 0;\r
+      Descriptor->SpecificFlag          = 0;\r
+      Descriptor->AddrSpaceGranularity  = 0;\r
+      Descriptor->AddrRangeMin          = RootBridge->Bus.Base;\r
+      Descriptor->AddrRangeMax          = 0;\r
+      Descriptor->AddrTranslationOffset = 0;\r
+      Descriptor->AddrLen               = RootBridge->Bus.Limit - RootBridge->Bus.Base + 1;\r
+\r
+      End = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Descriptor + 1);\r
+      End->Desc = ACPI_END_TAG_DESCRIPTOR;\r
+      End->Checksum = 0x0;\r
+\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  return EFI_INVALID_PARAMETER;\r
+}\r
+\r
+/**\r
+\r
+  This function programs the PCI Root Bridge hardware so that\r
+  it decodes the specified PCI bus range.\r
+\r
+  @param This              The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
+  @param RootBridgeHandle  The PCI Root Bridge whose bus range is to be programmed.\r
+  @param Configuration     The pointer to the PCI bus resource descriptor.\r
+\r
+  @retval EFI_SUCCESS            Succeed.\r
+  @retval EFI_INVALID_PARAMETER  Wrong parameters passed in.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SetBusNumbers (\r
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
+  IN EFI_HANDLE                                       RootBridgeHandle,\r
+  IN VOID                                             *Configuration\r
+  )\r
+{\r
+  LIST_ENTRY                *Link;\r
+  PCI_HOST_BRIDGE_INSTANCE  *HostBridge;\r
+  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;\r
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
+  EFI_ACPI_END_TAG_DESCRIPTOR       *End;\r
+  UINTN                     BusStart;\r
+  UINTN                     BusEnd;\r
+  UINTN                     BusLen;\r
+\r
+  if (Configuration == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;\r
+  End = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Descriptor + 1);\r
+\r
+  //\r
+  // Check the Configuration is valid\r
+  //\r
+  if ((Descriptor->Desc != ACPI_ADDRESS_SPACE_DESCRIPTOR) ||\r
+      (Descriptor->ResType != ACPI_ADDRESS_SPACE_TYPE_BUS) ||\r
+      (End->Desc != ACPI_END_TAG_DESCRIPTOR)\r
+     ) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
+  for (Link = GetFirstNode (&HostBridge->RootBridges)\r
+       ; !IsNull (&HostBridge->RootBridges, Link)\r
+       ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
+       ) {\r
+    RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
+    if (RootBridgeHandle == RootBridge->Handle) {\r
+      BusStart  = (UINTN) Descriptor->AddrRangeMin;\r
+      BusLen    = (UINTN) Descriptor->AddrLen;\r
+      BusEnd    = BusStart + BusLen - 1;\r
+\r
+      if (Descriptor->AddrLen == 0) {\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+\r
+      if ((Descriptor->AddrRangeMin < RootBridge->Bus.Base) ||\r
+          (Descriptor->AddrRangeMin + Descriptor->AddrLen - 1 > RootBridge->Bus.Limit)\r
+         ) {\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+      //\r
+      // Update the Bus Range\r
+      //\r
+      RootBridge->ResAllocNode[TypeBus].Base    = Descriptor->AddrRangeMin;\r
+      RootBridge->ResAllocNode[TypeBus].Length  = Descriptor->AddrLen;\r
+      RootBridge->ResAllocNode[TypeBus].Status  = ResAllocated;\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  return EFI_INVALID_PARAMETER;\r
+}\r
+\r
+/**\r
+\r
+  Submits the I/O and memory resource requirements for the specified PCI Root Bridge.\r
+\r
+  @param This              The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
+  @param RootBridgeHandle  The PCI Root Bridge whose I/O and memory resource requirements.\r
+                           are being submitted.\r
+  @param Configuration     The pointer to the PCI I/O and PCI memory resource descriptor.\r
+\r
+  @retval EFI_SUCCESS            Succeed.\r
+  @retval EFI_INVALID_PARAMETER  Wrong parameters passed in.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SubmitResources (\r
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
+  IN EFI_HANDLE                                       RootBridgeHandle,\r
+  IN VOID                                             *Configuration\r
+  )\r
+{\r
+  LIST_ENTRY                        *Link;\r
+  PCI_HOST_BRIDGE_INSTANCE          *HostBridge;\r
+  PCI_ROOT_BRIDGE_INSTANCE          *RootBridge;\r
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
+  PCI_RESOURCE_TYPE                 Type;\r
+\r
+  //\r
+  // Check the input parameter: Configuration\r
+  //\r
+  if (Configuration == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
+  for (Link = GetFirstNode (&HostBridge->RootBridges)\r
+       ; !IsNull (&HostBridge->RootBridges, Link)\r
+       ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
+       ) {\r
+    RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
+    if (RootBridgeHandle == RootBridge->Handle) {\r
+      DEBUG ((EFI_D_INFO, "PciHostBridge: SubmitResources for %s\n", RootBridge->DevicePathStr));\r
+      //\r
+      // Check the resource descriptors.\r
+      // If the Configuration includes one or more invalid resource descriptors, all the resource\r
+      // descriptors are ignored and the function returns EFI_INVALID_PARAMETER.\r
+      //\r
+      for (Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {\r
+        if (Descriptor->ResType > ACPI_ADDRESS_SPACE_TYPE_BUS) {\r
+          return EFI_INVALID_PARAMETER;\r
+        }\r
+\r
+        DEBUG ((EFI_D_INFO, " %s: Granularity/SpecificFlag = %ld / %02x%s\n",\r
+                mAcpiAddressSpaceTypeStr[Descriptor->ResType], Descriptor->AddrSpaceGranularity, Descriptor->SpecificFlag,\r
+                (Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0 ? L" (Prefetchable)" : L""\r
+                ));\r
+        DEBUG ((EFI_D_INFO, "      Length/Alignment = 0x%lx / 0x%lx\n", Descriptor->AddrLen, Descriptor->AddrRangeMax));\r
+        switch (Descriptor->ResType) {\r
+        case ACPI_ADDRESS_SPACE_TYPE_MEM:\r
+          if (Descriptor->AddrSpaceGranularity != 32 && Descriptor->AddrSpaceGranularity != 64) {\r
+            return EFI_INVALID_PARAMETER;\r
+          }\r
+          if (Descriptor->AddrSpaceGranularity == 32 && Descriptor->AddrLen >= SIZE_4GB) {\r
+            return EFI_INVALID_PARAMETER;\r
+          }\r
+          //\r
+          // If the PCI root bridge does not support separate windows for nonprefetchable and\r
+          // prefetchable memory, then the PCI bus driver needs to include requests for\r
+          // prefetchable memory in the nonprefetchable memory pool.\r
+          //\r
+          if (((RootBridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0) &&\r
+              ((Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0)\r
+             ) {\r
+            return EFI_INVALID_PARAMETER;\r
+          }\r
+        case ACPI_ADDRESS_SPACE_TYPE_IO:\r
+          //\r
+          // Check aligment, it should be of the form 2^n-1\r
+          //\r
+          if (GetPowerOfTwo64 (Descriptor->AddrRangeMax + 1) != (Descriptor->AddrRangeMax + 1)) {\r
+            return EFI_INVALID_PARAMETER;\r
+          }\r
+          break;\r
+        default:\r
+          ASSERT (FALSE);\r
+          break;\r
+        }\r
+      }\r
+      if (Descriptor->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+\r
+      for (Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {\r
+        if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {\r
+          if (Descriptor->AddrSpaceGranularity == 32) {\r
+            if ((Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0) {\r
+              Type = TypePMem32;\r
+            } else {\r
+              Type = TypeMem32;\r
+            }\r
+          } else {\r
+            ASSERT (Descriptor->AddrSpaceGranularity == 64);\r
+            if ((Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0) {\r
+              Type = TypePMem64;\r
+            } else {\r
+              Type = TypeMem64;\r
+            }\r
+          }\r
+        } else {\r
+          ASSERT (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_IO);\r
+          Type = TypeIo;\r
+        }\r
+        RootBridge->ResAllocNode[Type].Length    = Descriptor->AddrLen;\r
+        RootBridge->ResAllocNode[Type].Alignment = Descriptor->AddrRangeMax;\r
+        RootBridge->ResAllocNode[Type].Status    = ResSubmitted;\r
+      }\r
+      RootBridge->ResourceSubmitted = TRUE;\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  return EFI_INVALID_PARAMETER;\r
+}\r
+\r
+/**\r
+\r
+  This function returns the proposed resource settings for the specified\r
+  PCI Root Bridge.\r
+\r
+  @param This              The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
+  @param RootBridgeHandle  The PCI Root Bridge handle.\r
+  @param Configuration     The pointer to the pointer to the PCI I/O\r
+                           and memory resource descriptor.\r
+\r
+  @retval EFI_SUCCESS            Succeed.\r
+  @retval EFI_OUT_OF_RESOURCES   Not enough pool to be allocated.\r
+  @retval EFI_INVALID_PARAMETER  RootBridgeHandle is not a valid handle.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetProposedResources (\r
+  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
+  IN  EFI_HANDLE                                       RootBridgeHandle,\r
+  OUT VOID                                             **Configuration\r
+  )\r
+{\r
+  LIST_ENTRY                        *Link;\r
+  PCI_HOST_BRIDGE_INSTANCE          *HostBridge;\r
+  PCI_ROOT_BRIDGE_INSTANCE          *RootBridge;\r
+  UINTN                             Index;\r
+  UINTN                             Number;\r
+  VOID                              *Buffer;\r
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
+  EFI_ACPI_END_TAG_DESCRIPTOR       *End;\r
+  UINT64                            ResStatus;\r
+\r
+  HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
+  for (Link = GetFirstNode (&HostBridge->RootBridges)\r
+      ; !IsNull (&HostBridge->RootBridges, Link)\r
+      ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
+      ) {\r
+    RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
+    if (RootBridgeHandle == RootBridge->Handle) {\r
+      for (Index = 0, Number = 0; Index < TypeBus; Index++) {\r
+        if (RootBridge->ResAllocNode[Index].Status != ResNone) {\r
+          Number++;\r
+        }\r
+      }\r
+\r
+      Buffer = AllocateZeroPool (Number * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
+      if (Buffer == NULL) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+\r
+      Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Buffer;\r
+      for (Index = 0; Index < TypeBus; Index++) {\r
+        ResStatus = RootBridge->ResAllocNode[Index].Status;\r
+        if (ResStatus != ResNone) {\r
+          Descriptor->Desc                  = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
+          Descriptor->Len                   = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;;\r
+          Descriptor->GenFlag               = 0;\r
+          Descriptor->AddrRangeMin          = RootBridge->ResAllocNode[Index].Base;\r
+          Descriptor->AddrRangeMax          = 0;\r
+          Descriptor->AddrTranslationOffset = (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : PCI_RESOURCE_LESS;\r
+          Descriptor->AddrLen               = RootBridge->ResAllocNode[Index].Length;\r
+\r
+          switch (Index) {\r
+\r
+          case TypeIo:\r
+            Descriptor->ResType              = ACPI_ADDRESS_SPACE_TYPE_IO;\r
+            break;\r
+\r
+          case TypePMem32:\r
+            Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;\r
+          case TypeMem32:\r
+            Descriptor->ResType              = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+            Descriptor->AddrSpaceGranularity = 32;\r
+            break;\r
+\r
+          case TypePMem64:\r
+            Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;\r
+          case TypeMem64:\r
+            Descriptor->ResType              = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+            Descriptor->AddrSpaceGranularity = 64;\r
+            break;\r
+          }\r
+\r
+          Descriptor++;\r
+        }\r
+      }\r
+      End = (EFI_ACPI_END_TAG_DESCRIPTOR *) Descriptor;\r
+      End->Desc      = ACPI_END_TAG_DESCRIPTOR;\r
+      End->Checksum  = 0;\r
+\r
+      *Configuration = Buffer;\r
+\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  return EFI_INVALID_PARAMETER;\r
+}\r
+\r
+/**\r
+\r
+  This function is called for all the PCI controllers that the PCI\r
+  bus driver finds. Can be used to Preprogram the controller.\r
+\r
+  @param This              The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
+  @param RootBridgeHandle  The PCI Root Bridge handle.\r
+  @param PciAddress        Address of the controller on the PCI bus.\r
+  @param Phase             The Phase during resource allocation.\r
+\r
+  @retval EFI_SUCCESS            Succeed.\r
+  @retval EFI_INVALID_PARAMETER  RootBridgeHandle is not a valid handle.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PreprocessController (\r
+  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL          *This,\r
+  IN  EFI_HANDLE                                                RootBridgeHandle,\r
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS               PciAddress,\r
+  IN  EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE              Phase\r
+  )\r
+{\r
+  LIST_ENTRY                *Link;\r
+  PCI_HOST_BRIDGE_INSTANCE  *HostBridge;\r
+  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;\r
+\r
+  if ((UINT32) Phase > EfiPciBeforeResourceCollection) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
+  for (Link = GetFirstNode (&HostBridge->RootBridges)\r
+       ; !IsNull (&HostBridge->RootBridges, Link)\r
+       ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
+       ) {\r
+    RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
+    if (RootBridgeHandle == RootBridge->Handle) {\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  return EFI_INVALID_PARAMETER;\r
+}\r