public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Nate DeSimone" <nathaniel.l.desimone@intel.com>
To: devel@edk2.groups.io
Cc: Isaac Oram <isaac.w.oram@intel.com>,
	Mohamed Abbas <mohamed.abbas@intel.com>,
	Chasel Chiu <chasel.chiu@intel.com>,
	Michael D Kinney <michael.d.kinney@intel.com>,
	Liming Gao <gaoliming@byosoft.com.cn>,
	Eric Dong <eric.dong@intel.com>,
	Michael Kubacki <Michael.Kubacki@microsoft.com>
Subject: [edk2-platforms] [PATCH V1 12/17] WhitleyOpenBoardPkg: Add Feature Modules
Date: Mon, 12 Jul 2021 17:41:26 -0700	[thread overview]
Message-ID: <20210713004131.1782-13-nathaniel.l.desimone@intel.com> (raw)
In-Reply-To: <20210713004131.1782-1-nathaniel.l.desimone@intel.com>

Signed-off-by: Nate DeSimone <nathaniel.l.desimone@intel.com>
Co-authored-by: Isaac Oram <isaac.w.oram@intel.com>
Co-authored-by: Mohamed Abbas <mohamed.abbas@intel.com>
Cc: Chasel Chiu <chasel.chiu@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Isaac Oram <isaac.w.oram@intel.com>
Cc: Mohamed Abbas <mohamed.abbas@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Michael Kubacki <Michael.Kubacki@microsoft.com>
---
 .../Pci/Dxe/PciHostBridge/PciHostBridge.c     | 1634 ++++++++++++++++
 .../Pci/Dxe/PciHostBridge/PciHostBridge.h     |  300 +++
 .../Pci/Dxe/PciHostBridge/PciHostBridge.inf   |   69 +
 .../Dxe/PciHostBridge/PciHostBridgeSupport.c  |  127 ++
 .../Pci/Dxe/PciHostBridge/PciHostResource.h   |   62 +
 .../Pci/Dxe/PciHostBridge/PciRebalance.c      | 1356 ++++++++++++++
 .../Pci/Dxe/PciHostBridge/PciRebalance.h      |  158 ++
 .../Pci/Dxe/PciHostBridge/PciRebalanceIo.c    |  218 +++
 .../Dxe/PciHostBridge/PciRebalanceMmio32.c    |  163 ++
 .../Dxe/PciHostBridge/PciRebalanceMmio64.c    |  204 ++
 .../Pci/Dxe/PciHostBridge/PciRootBridge.h     |  573 ++++++
 .../Pci/Dxe/PciHostBridge/PciRootBridgeIo.c   | 1664 +++++++++++++++++
 .../Dxe/PciPlatform/PciIovPlatformPolicy.c    |   99 +
 .../Dxe/PciPlatform/PciIovPlatformPolicy.h    |   53 +
 .../Pci/Dxe/PciPlatform/PciPlatform.c         |  541 ++++++
 .../Pci/Dxe/PciPlatform/PciPlatform.h         |  209 +++
 .../Pci/Dxe/PciPlatform/PciPlatform.inf       |   87 +
 .../Pci/Dxe/PciPlatform/PciPlatformHooks.c    |  939 ++++++++++
 .../Pci/Dxe/PciPlatform/PciPlatformHooks.h    |   31 +
 .../Pci/Dxe/PciPlatform/PciSupportLib.c       |  108 ++
 .../Pci/Dxe/PciPlatform/PciSupportLib.h       |   46 +
 .../Pei/PlatformVariableInitPei.c             |  274 +++
 .../Pei/PlatformVariableInitPei.h             |   41 +
 .../Pei/PlatformVariableInitPei.inf           |   58 +
 24 files changed, 9014 insertions(+)
 create mode 100644 Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciHostBridge.c
 create mode 100644 Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciHostBridge.h
 create mode 100644 Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciHostBridge.inf
 create mode 100644 Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciHostBridgeSupport.c
 create mode 100644 Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciHostResource.h
 create mode 100644 Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciRebalance.c
 create mode 100644 Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciRebalance.h
 create mode 100644 Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciRebalanceIo.c
 create mode 100644 Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciRebalanceMmio32.c
 create mode 100644 Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciRebalanceMmio64.c
 create mode 100644 Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciRootBridge.h
 create mode 100644 Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciRootBridgeIo.c
 create mode 100644 Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciPlatform/PciIovPlatformPolicy.c
 create mode 100644 Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciPlatform/PciIovPlatformPolicy.h
 create mode 100644 Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciPlatform/PciPlatform.c
 create mode 100644 Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciPlatform/PciPlatform.h
 create mode 100644 Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciPlatform/PciPlatform.inf
 create mode 100644 Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciPlatform/PciPlatformHooks.c
 create mode 100644 Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciPlatform/PciPlatformHooks.h
 create mode 100644 Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciPlatform/PciSupportLib.c
 create mode 100644 Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciPlatform/PciSupportLib.h
 create mode 100644 Platform/Intel/WhitleyOpenBoardPkg/Features/Variable/PlatformVariable/Pei/PlatformVariableInitPei.c
 create mode 100644 Platform/Intel/WhitleyOpenBoardPkg/Features/Variable/PlatformVariable/Pei/PlatformVariableInitPei.h
 create mode 100644 Platform/Intel/WhitleyOpenBoardPkg/Features/Variable/PlatformVariable/Pei/PlatformVariableInitPei.inf

diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciHostBridge.c b/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciHostBridge.c
new file mode 100644
index 0000000000..a15fff4817
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciHostBridge.c
@@ -0,0 +1,1634 @@
+/** @file
+
+  @copyright
+  Copyright 1999 - 2021 Intel Corporation. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Guid/SocketPciResourceData.h>
+#include <Guid/SocketIioVariable.h>
+#include "PciHostBridge.h"
+#include "PciRootBridge.h"
+#include "PciHostResource.h"
+
+#include <CpuAndRevisionDefines.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Protocol/IioUds.h>
+#include <Upi/KtiHost.h>
+
+#include <Library/SetupLib.h>
+
+#include "PciRebalance.h"
+
+
+/******************************************************************************
+ * Local definitions.
+ ******************************************************************************/
+typedef struct {
+  PCI_ROOT_BRIDGE_INSTANCE        RootBridge;
+  EFI_PCI_ROOT_BRIDGE_DEVICE_PATH RootDevPath;
+} PCI_ROOT_BRIDGE_WITH_PATH;
+
+
+/******************************************************************************
+ * Variables.
+ ******************************************************************************/
+GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mAcpiAddressSpaceTypeStr[] = {
+  L"Mem", L"I/O", L"Bus"
+};
+GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mPciResourceTypeStr[] = {
+  L"I/O", L"Mem32", L"PMem32", L"Mem64", L"PMem64", L"Bus"
+};
+
+//
+// We can hardcode the following for a Simple IIO -
+// Root Bridge Count within the Host bridge
+// Root Bridge's device path
+// Root Bridge's resource appeture
+//
+
+STATIC EFI_PCI_ROOT_BRIDGE_DEVICE_PATH    mEfiPciRootBridgeDevicePathTemplate = {
+      {{ACPI_DEVICE_PATH,
+      ACPI_DP,
+      {(UINT8) (sizeof (ACPI_HID_DEVICE_PATH)),
+      (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8)}},
+      EISA_PNP_ID(0x0A03),
+      0},
+      {END_DEVICE_PATH_TYPE,
+      END_ENTIRE_DEVICE_PATH_SUBTYPE,
+      {END_DEVICE_PATH_LENGTH,
+      0}}
+    };
+
+STATIC EFI_HANDLE                         mDriverImageHandle;
+
+EDKII_IOMMU_PROTOCOL                     *mIoMmu;
+EFI_EVENT                                 mIoMmuEvent;
+VOID                                     *mIoMmuRegistration;
+
+EFI_IIO_UDS_PROTOCOL                     *mIioUds;
+PCI_HOST_BRIDGE_INSTANCE                 *mHostBridge;
+
+/**
+  Event notification that is fired when IOMMU protocol is installed.
+
+  @param  Event                 The Event that is being processed.
+  @param  Context               Event Context.
+
+**/
+VOID
+EFIAPI
+IoMmuProtocolCallback (
+  IN  EFI_EVENT       Event,
+  IN  VOID            *Context
+  )
+{
+  EFI_STATUS   Status;
+
+  Status = gBS->LocateProtocol (&gEdkiiIoMmuProtocolGuid, NULL, (VOID **)&mIoMmu);
+  if (!EFI_ERROR(Status)) {
+    gBS->CloseEvent (mIoMmuEvent);
+  }
+}
+
+
+/**
+
+  Entry point of this driver.
+
+  @param ImageHandle  Image handle of this driver.
+  @param SystemTable  Pointer to standard EFI system table.
+
+  @retval EFI_SUCCESS       Succeed.
+  @retval EFI_DEVICE_ERROR  Fail to install PCI_ROOT_BRIDGE_IO protocol.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializePciHostBridge (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  )
+{
+  EFI_STATUS                  Status;
+  UINTN                       IioIndex;
+  EFI_PHYSICAL_ADDRESS        BaseAddress;
+  UINTN                       IioStack;
+  UINT64                      ResourceLength;
+  PCI_ROOT_BRIDGE_RESOURCE_APERTURE  RbAperture;
+
+  PCI_HOST_BRIDGE_INSTANCE          *HostBridge;
+  PCI_ROOT_BRIDGE_INSTANCE          *RootBridge;
+  EFI_PCI_ROOT_BRIDGE_DEVICE_PATH   *TempDevicePath;
+  STACK_RES                         *CurStackRes;
+
+  mDriverImageHandle = ImageHandle;
+  //
+  // Located the IIO Protocol Interface
+  //
+  Status = gBS->LocateProtocol (&gEfiIioUdsProtocolGuid, NULL, &mIioUds);
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Most systems in the world including complex servers have only one Host Bridge.
+  //
+  HostBridge = AllocateZeroPool (sizeof (PCI_HOST_BRIDGE_INSTANCE));
+  if (HostBridge == NULL) {
+    ASSERT(FALSE);
+    return EFI_OUT_OF_RESOURCES;
+  }
+  HostBridge->Signature         = PCI_HOST_BRIDGE_SIGNATURE;
+  HostBridge->RootBridgeCount   = 0;
+  HostBridge->ResourceSubmited  = FALSE;
+  HostBridge->CanRestarted      = TRUE;
+  InitializeListHead (&HostBridge->RootBridges);
+
+  HostBridge->ResAlloc.NotifyPhase          = NotifyPhase;
+  HostBridge->ResAlloc.GetNextRootBridge    = GetNextRootBridge;
+  HostBridge->ResAlloc.GetAllocAttributes   = GetAttributes;
+  HostBridge->ResAlloc.StartBusEnumeration  = StartBusEnumeration;
+  HostBridge->ResAlloc.SetBusNumbers        = SetBusNumbers;
+  HostBridge->ResAlloc.SubmitResources      = SubmitResources;
+  HostBridge->ResAlloc.GetProposedResources = GetProposedResources;
+  HostBridge->ResAlloc.PreprocessController = PreprocessController;
+
+  Status = gBS->InstallProtocolInterface (
+                    &HostBridge->Handle,
+                    &gEfiPciHostBridgeResourceAllocationProtocolGuid,
+                    EFI_NATIVE_INTERFACE,
+                    &HostBridge->ResAlloc
+                    );
+  if (EFI_ERROR (Status)) {
+    FreePool (HostBridge);
+    return EFI_DEVICE_ERROR;
+  }
+
+  //
+  // Create Root Bridges in this Host Bridge.
+  //
+  for (IioIndex = 0; IioIndex < mIioUds->IioUdsPtr->PlatformData.numofIIO; IioIndex++) {
+
+    if (!mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioIndex].Valid) {
+      continue;
+    } // No guarantee that the valid IIOs are sequential starting at 0!
+
+    for (IioStack = 0; IioStack < MAX_IIO_STACK; IioStack++) {
+
+      if (!(mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[IioIndex].stackPresentBitmap & (1 << IioStack))) {
+        continue;
+      }
+      // Skip stack which is disabled by resource limitation or DEBUG purpose!
+      if (mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioIndex].StackRes[IioStack].Personality >= TYPE_DISABLED) {
+        continue;
+      }
+      //
+      // Create Root Bridge Instance
+      //
+      RootBridge = AllocateZeroPool (sizeof(PCI_ROOT_BRIDGE_WITH_PATH));
+      if (RootBridge == NULL) {
+        ASSERT_EFI_ERROR (EFI_OUT_OF_RESOURCES);
+        return EFI_OUT_OF_RESOURCES;
+      }
+      TempDevicePath = &((PCI_ROOT_BRIDGE_WITH_PATH*)RootBridge)->RootDevPath;
+
+      RootBridge->Signature  = PCI_ROOT_BRIDGE_SIGNATURE;
+      RootBridge->DevicePath = (EFI_DEVICE_PATH_PROTOCOL*)TempDevicePath;
+      CopyMem (TempDevicePath, &mEfiPciRootBridgeDevicePathTemplate, sizeof(*TempDevicePath));
+      TempDevicePath->AcpiDevicePath.UID = (UINT32)(IioIndex * MAX_IIO_STACK + IioStack);
+
+      ZeroMem(&RbAperture, sizeof(RbAperture));
+      {
+        //
+        // Update Root Bridge with UDS resource information
+        //
+        RbAperture.BusBase = mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioIndex].StackRes[IioStack].BusBase;
+        RbAperture.BusLimit = mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioIndex].StackRes[IioStack].BusLimit;
+        RbAperture.Mem32Base = mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioIndex].StackRes[IioStack].PciResourceMem32Base;
+        RbAperture.Mem32Limit = mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioIndex].StackRes[IioStack].PciResourceMem32Limit;
+        RbAperture.BusReserve = 0;
+        if ((mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioIndex].StackRes[IioStack].PciResourceMem64Limit >
+             mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioIndex].StackRes[IioStack].PciResourceMem64Base) &&
+            (mIioUds->IioUdsPtr->PlatformData.Pci64BitResourceAllocation)) {
+          RbAperture.Mem64Base = mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioIndex].StackRes[IioStack].PciResourceMem64Base;
+          RbAperture.Mem64Limit = mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioIndex].StackRes[IioStack].PciResourceMem64Limit;
+        }
+        RbAperture.IoBase = mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioIndex].StackRes[IioStack].PciResourceIoBase;
+        RbAperture.IoLimit = mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioIndex].StackRes[IioStack].PciResourceIoLimit;
+
+        SimpleIioRootBridgeConstructor (&RootBridge->RootBridgeIo, HostBridge->Handle, &RbAperture,
+                                        mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[IioIndex].PcieSegment,
+                                        GetAllocAttributes (HostBridge->RootBridgeCount));
+        DEBUG ((DEBUG_INFO, "[PCI] Create Root Bridge for [%d.%d] in PCI segment %d with below resource:\n", IioIndex, IioStack, RootBridge->RootBridgeIo.SegmentNumber));
+        DEBUG ((DEBUG_INFO, "      Bus:   Base = 0x%08x, Limit = 0x%08x, BusReserve = 0x%08x\n", RootBridge->Aperture.BusBase, RootBridge->Aperture.BusLimit, RootBridge->Aperture.BusReserve));
+        DEBUG ((DEBUG_INFO, "      IO:    Base = 0x%08x, Limit = 0x%08x\n", RootBridge->Aperture.IoBase, RootBridge->Aperture.IoLimit));
+        DEBUG ((DEBUG_INFO, "      Mem32: Base = 0x%08x, Limit = 0x%08x\n", RootBridge->Aperture.Mem32Base, RootBridge->Aperture.Mem32Limit));
+        DEBUG ((DEBUG_INFO, "      Mem64: Base = 0x%lx, Limit = 0x%lx\n", RootBridge->Aperture.Mem64Base, RootBridge->Aperture.Mem64Limit));
+        //
+        // Insert Root Bridge Instance
+        //
+        Status = gBS->InstallMultipleProtocolInterfaces (
+                        &RootBridge->Handle,
+                        &gEfiDevicePathProtocolGuid,
+                        RootBridge->DevicePath,
+                        &gEfiPciRootBridgeIoProtocolGuid,
+                        &RootBridge->RootBridgeIo,
+                        NULL
+                        );
+        ASSERT_EFI_ERROR (Status);
+        InsertTailList (&HostBridge->RootBridges, &RootBridge->Link);
+        mPciRootBridgeTable[IioIndex][IioStack] = RootBridge;
+        HostBridge->RootBridgeCount++;
+      }
+    } // for (IioStack...)
+  } // for (IioIndex...)
+  //
+  // Add PCIE base into Runtime memory so that it can be reported in E820 table
+  //
+  Status = gDS->AddMemorySpace (
+                  EfiGcdMemoryTypeMemoryMappedIo,
+                  mIioUds->IioUdsPtr->PlatformData.PciExpressBase,
+                  mIioUds->IioUdsPtr->PlatformData.PciExpressSize,
+                  EFI_MEMORY_RUNTIME | EFI_MEMORY_UC
+                  );
+  ASSERT_EFI_ERROR(Status);
+
+  BaseAddress = mIioUds->IioUdsPtr->PlatformData.PciExpressBase;
+
+  Status = gDS->AllocateMemorySpace (
+                  EfiGcdAllocateAddress,
+                  EfiGcdMemoryTypeMemoryMappedIo,
+                  0,
+                  mIioUds->IioUdsPtr->PlatformData.PciExpressSize,
+                  &BaseAddress,
+                  ImageHandle,
+                  NULL
+                  );
+  ASSERT_EFI_ERROR(Status);
+
+  Status = gDS->SetMemorySpaceAttributes (
+                  mIioUds->IioUdsPtr->PlatformData.PciExpressBase,
+                  mIioUds->IioUdsPtr->PlatformData.PciExpressSize,
+                  EFI_MEMORY_RUNTIME
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  //s4030180
+  for (IioIndex = 0; IioIndex < mIioUds->IioUdsPtr->PlatformData.numofIIO; IioIndex++) {
+
+    if (!mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioIndex].Valid) {
+      continue;
+    } // No guarantee that the valid IIOs are sequential starting at 0!
+    for (IioStack = 0; IioStack < MAX_IIO_STACK; IioStack++) {
+      if (!(mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[IioIndex].stackPresentBitmap & (1 << IioStack))) {
+        continue;
+      }
+
+      if (mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioIndex].StackRes[IioStack].PciResourceIoLimit >
+           mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioIndex].StackRes[IioStack].PciResourceIoBase) {
+        //
+        // At present, we use up the first 4k for fixed ranges like
+        // ICH GPIO, ACPI and ISA devices. The first 4k is not
+        // tracked through GCD. It should be.
+        //
+        Status = gDS->AddIoSpace (
+                        EfiGcdIoTypeIo,
+                        mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioIndex].StackRes[IioStack].PciResourceIoBase ,
+                        (mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioIndex].StackRes[IioStack].PciResourceIoLimit -
+                         mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioIndex].StackRes[IioStack].PciResourceIoBase + 1)
+                        );
+        ASSERT_EFI_ERROR (Status);
+      }
+
+      CurStackRes = &mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioIndex].StackRes[IioStack];
+      if (CurStackRes->PciResourceMem32Limit > CurStackRes->PciResourceMem32Base) {
+        //
+        // Shouldn't the capabilities be UC?
+        //
+        ResourceLength = CurStackRes->PciResourceMem32Limit - CurStackRes->PciResourceMem32Base + 1;
+        Status = gDS->AddMemorySpace (
+          EfiGcdMemoryTypeMemoryMappedIo,
+          CurStackRes->PciResourceMem32Base,
+          ResourceLength,
+          0
+          );
+        ASSERT_EFI_ERROR (Status);
+        //
+        // Track VT-d bar in GCD.
+        //
+        // We now have a region of memory x-z associated with this stack
+        // and there is also subregion y-z that is the VT-d space (x <= y <= z)
+        BaseAddress = CurStackRes->VtdBarAddress;
+        ResourceLength = CurStackRes->PciResourceMem32Limit - BaseAddress + 1;
+        Status = gDS->AllocateMemorySpace (
+          EfiGcdAllocateAddress,
+          EfiGcdMemoryTypeMemoryMappedIo,
+          0,
+          ResourceLength,
+          &BaseAddress,
+          ImageHandle,
+          NULL
+          );
+        ASSERT_EFI_ERROR(Status);
+      }
+
+      if ((mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioIndex].StackRes[IioStack].PciResourceMem64Limit >
+             mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioIndex].StackRes[IioStack].PciResourceMem64Base) &&
+             (mIioUds->IioUdsPtr->PlatformData.Pci64BitResourceAllocation)) {
+
+        Status = gDS->AddMemorySpace (
+                           EfiGcdMemoryTypeMemoryMappedIo,
+                           mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioIndex].StackRes[IioStack].PciResourceMem64Base ,
+                           (mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioIndex].StackRes[IioStack].PciResourceMem64Limit -
+                            mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioIndex].StackRes[IioStack].PciResourceMem64Base + 1),
+                           0
+                           );
+        ASSERT_EFI_ERROR (Status);
+      }
+    }
+  }
+
+  if (!EFI_ERROR (Status)) {
+    mIoMmuEvent = EfiCreateProtocolNotifyEvent (
+                    &gEdkiiIoMmuProtocolGuid,
+                    TPL_CALLBACK,
+                    IoMmuProtocolCallback,
+                    NULL,
+                    &mIoMmuRegistration
+                    );
+  }
+  mHostBridge = HostBridge;
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Enter the EfiPciHostBridgeBeginEnumeration phase of the PCI(e)
+  numeration process.
+
+  @param This     The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+                  instance.
+
+  @retval EFI_SUCCESS
+  @retval EFI_NOT_READY
+*/
+STATIC EFI_STATUS
+BeginBridgeEnumeration (
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This
+  )
+{
+  PCI_HOST_BRIDGE_INSTANCE *HostBridge;
+  LIST_ENTRY               *List;
+  PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
+  PCI_RESOURCE_TYPE        Index;
+
+  Index = TypeMax;
+  HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
+
+  if (HostBridge->CanRestarted) {
+    //
+    // Reset Root Bridge
+    //
+    List = HostBridge->RootBridges.ForwardLink;
+
+    while (List != &HostBridge->RootBridges) {
+      RootBridge = ROOT_BRIDGE_FROM_LINK (List);
+      for (Index = TypeIo; Index < TypeMax; Index++) {
+        RootBridge->ResAllocNode[Index].Type    = Index;
+        RootBridge->ResAllocNode[Index].Base    = 0;
+        RootBridge->ResAllocNode[Index].Length  = 0;
+        RootBridge->ResAllocNode[Index].Status  = ResNone;
+      } // for
+
+      List = List->ForwardLink;
+    } // while
+
+    HostBridge->ResourceSubmited  = FALSE;
+    HostBridge->CanRestarted      = TRUE;
+  } else {
+    //
+    // Can not restart
+    //
+    return EFI_NOT_READY;
+  } // if
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Enter the EfiPciHostBridgeAllocateResources phase of the
+  PCI(e) numeration process.
+
+  @param[in] This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
+
+  @retval EFI_SUCCESS
+  @retval EFI_NOT_READY
+  @retval EFI_OUT_OF_RESOURCES
+*/
+STATIC EFI_STATUS
+BridgeAllocateResources (
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This
+  )
+{
+  PCI_HOST_BRIDGE_INSTANCE              *HostBridge;
+  PCI_ROOT_BRIDGE_INSTANCE              *RootBridge;
+  PCI_RESOURCE_TYPE                     Index;
+  LIST_ENTRY                            *List;
+  EFI_PHYSICAL_ADDRESS                  BaseAddress;
+  UINT64                                AddrLen;
+  UINTN                                 BitsOfAlignment;
+  UINT64                                Alignment;
+  EFI_STATUS                            Status;
+  EFI_STATUS                            ReturnStatus;
+  PCI_RESOURCE_TYPE                     Index1;
+  PCI_RESOURCE_TYPE                     Index2;
+  BOOLEAN                               ResNodeHandled[TypeMax];
+  UINT64                                MaxAlignment;
+  SOCKET_RESOURCE_ADJUSTMENT_RESULT     RatioAdjustResult;
+  UINT8                                 Socket;
+  UINT8                                 Stack;
+
+  Index = TypeMax;
+  HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
+
+  ReturnStatus = EFI_SUCCESS;
+  if (HostBridge->ResourceSubmited) {
+
+    List = HostBridge->RootBridges.ForwardLink;
+    while (List != &HostBridge->RootBridges) {
+
+      for (Index1 = TypeIo; Index1 < TypeBus; Index1++) {
+        ResNodeHandled[Index1] = FALSE;
+      }
+      RootBridge = ROOT_BRIDGE_FROM_LINK (List);
+      Socket = Stack = (UINT8)-1;
+      PciRootBridge2SocketStack (RootBridge, &Socket, &Stack);
+      for (Index1 = TypeIo; Index1 < TypeBus; Index1++) {
+
+        if (RootBridge->ResAllocNode[Index1].Status == ResNone) {
+
+          ResNodeHandled[Index1] = TRUE;
+
+        } else {
+          //
+          // Allocate the resource node with max alignment at first
+          //
+          MaxAlignment = 0;
+          Index        = TypeMax;
+          for (Index2 = TypeIo; Index2 < TypeBus; Index2++) {
+
+            if (ResNodeHandled[Index2]) {
+              continue;
+            }
+            if (MaxAlignment <= RootBridge->ResAllocNode[Index2].Alignment) {
+              MaxAlignment = RootBridge->ResAllocNode[Index2].Alignment;
+              Index = Index2;
+            }
+          } // for
+
+          if (Index < TypeMax) {
+
+            ResNodeHandled[Index] = TRUE;
+            Alignment = RootBridge->ResAllocNode[Index].Alignment;
+            //
+            // Get the number of '1' in Alignment.
+            //
+            for (BitsOfAlignment = 0; Alignment != 0; BitsOfAlignment++) {
+              Alignment = RShiftU64 (Alignment, 1);
+            }
+
+            AddrLen   = RootBridge->ResAllocNode[Index].Length;
+            Alignment = RootBridge->ResAllocNode[Index].Alignment;
+
+            DEBUG ((DEBUG_INFO, "\n[%d.%d] Resource Type to assign :     %s\n", Socket, Stack, mPciResourceTypeStr[Index]));
+            DEBUG ((DEBUG_INFO, "      Length to allocate:           %lx\n", RootBridge->ResAllocNode[Index].Length));
+            DEBUG ((DEBUG_INFO, "      Alignment:                    %lx\n", Alignment));
+            DEBUG ((DEBUG_INFO, "      Base Address:                 %lx\n", RootBridge->ResAllocNode[Index].Base));
+
+            switch (Index) {
+            case TypeIo:
+              if (RootBridge->Aperture.IoBase < RootBridge->Aperture.IoLimit) {
+                //
+                // It is impossible for 0xFFFF Alignment for IO16
+                //
+                if (BitsOfAlignment >= 16) {
+                  Alignment = 0;
+                }
+                BaseAddress = RootBridge->Aperture.IoBase;
+                //
+                // Have to make sure Alignment is handled seeing we are doing direct address allocation
+                //
+                if ((BaseAddress & ~(Alignment)) != BaseAddress) {
+                  BaseAddress = ((BaseAddress + Alignment) & ~(Alignment));
+                }
+
+                while((BaseAddress + AddrLen) <= RootBridge->Aperture.IoLimit + 1) {
+                  Status = gDS->AllocateIoSpace (EfiGcdAllocateAddress, EfiGcdIoTypeIo, BitsOfAlignment,
+                    AddrLen, &BaseAddress, mDriverImageHandle, NULL );
+
+                  if (!EFI_ERROR (Status)) {
+                    RootBridge->ResAllocNode[Index].Base    = (UINT64) BaseAddress;
+                    RootBridge->ResAllocNode[Index].Status  = ResAllocated;
+                    goto TypeIoFound;
+                  }
+
+                  BaseAddress += (Alignment + 1);
+                } // while
+              } // if
+
+              TypeIoFound:
+              if (RootBridge->ResAllocNode[Index].Status  != ResAllocated) {
+                //
+                // No Room at the Inn for this resources request
+                //
+                ReturnStatus = EFI_OUT_OF_RESOURCES;
+              } // if
+              break;
+
+              case TypeMem32:
+                if (RootBridge->Aperture.Mem32Base < RootBridge->Aperture.Mem32Limit) {
+
+                  BaseAddress = RootBridge->Aperture.Mem32Base;
+                  //
+                  // Have to make sure Alignment is handled seeing we are doing direct address allocation
+                  //
+                  if ((BaseAddress & ~(Alignment)) != BaseAddress) {
+                    BaseAddress = ((BaseAddress + Alignment) & ~(Alignment));
+                  }
+
+                  while ((BaseAddress + AddrLen) <= RootBridge->Aperture.Mem32Limit + 1) {
+                    DEBUG ((DEBUG_INFO, "      Attempting %s allocation at 0x%llX.....",
+                            mPciResourceTypeStr[Index], BaseAddress));
+                    Status = gDS->AllocateMemorySpace (EfiGcdAllocateAddress, EfiGcdMemoryTypeMemoryMappedIo,
+                                                       BitsOfAlignment, AddrLen, &BaseAddress, mDriverImageHandle, NULL);
+                    if (!EFI_ERROR (Status)) {
+                      RootBridge->ResAllocNode[Index].Base    = (UINT64) BaseAddress;
+                      RootBridge->ResAllocNode[Index].Status  = ResAllocated;
+                      DEBUG ((DEBUG_INFO, "Passed\n"));
+                      goto TypeMem32Found;
+                    } // if
+                    DEBUG ((DEBUG_INFO, "Failed\n"));
+                    BaseAddress += (Alignment + 1);
+                  } // while
+                } // if
+
+                TypeMem32Found:
+                if (RootBridge->ResAllocNode[Index].Status  != ResAllocated) {
+                  //
+                  // No Room at the Inn for this resources request
+                  //
+                  ReturnStatus = EFI_OUT_OF_RESOURCES;
+                }
+                break;
+
+              case TypePMem32:
+                StartTypePMem32:
+                if (RootBridge->Aperture.Mem32Base < RootBridge->Aperture.Mem32Limit) {
+                  BaseAddress = RootBridge->Aperture.Mem32Limit + 1;
+                  BaseAddress -= AddrLen;
+
+                  //
+                  // Have to make sure Alignment is handled seeing we are doing direct address allocation
+                  //
+                  if ((BaseAddress & ~(Alignment)) != BaseAddress) {
+                    BaseAddress = ((BaseAddress) & ~(Alignment));
+                  }
+
+                  while (RootBridge->Aperture.Mem32Base <= BaseAddress) {
+
+                    DEBUG ((DEBUG_INFO, "      Attempting %s allocation at 0x%llX.....",
+                            mPciResourceTypeStr[Index], BaseAddress));
+                    Status = gDS->AllocateMemorySpace (EfiGcdAllocateAddress, EfiGcdMemoryTypeMemoryMappedIo,
+                                                       BitsOfAlignment, AddrLen, &BaseAddress, mDriverImageHandle, NULL);
+                    if (!EFI_ERROR (Status)) {
+                      RootBridge->ResAllocNode[Index].Base    = (UINT64) BaseAddress;
+                      RootBridge->ResAllocNode[Index].Status  = ResAllocated;
+                      DEBUG ((DEBUG_INFO, "Passed\n"));
+                      goto TypePMem32Found;
+                    }
+                    DEBUG ((DEBUG_INFO, "Failed\n"));
+                    BaseAddress -= (Alignment + 1);
+                  } // while
+                } // if
+
+                TypePMem32Found:
+                if (RootBridge->ResAllocNode[Index].Status  != ResAllocated) {
+                  //
+                  // No Room at the Inn for this resources request
+                  //
+                  ReturnStatus = EFI_OUT_OF_RESOURCES;
+                }
+                break;
+
+              case TypeMem64:
+              case TypePMem64:
+                if ((RootBridge->Aperture.Mem64Limit > RootBridge->Aperture.Mem64Base) &&
+                    (mIioUds->IioUdsPtr->PlatformData.Pci64BitResourceAllocation)) {
+
+                  if (RootBridge->Aperture.Mem64Limit < AddrLen) {
+                    RootBridge->ResAllocNode[Index].Status = ResNone;
+                    goto TypeMem64Found;
+                  }
+                  BaseAddress = RootBridge->Aperture.Mem64Limit + 1;
+                  BaseAddress -= AddrLen;
+
+                  //
+                  // Have to make sure Alignment is handled seeing we are doing direct address allocation
+                  //
+                  if ((BaseAddress & ~(Alignment)) != BaseAddress) {
+                    BaseAddress = ((BaseAddress) & ~(Alignment));
+                  }
+
+                  while (RootBridge->Aperture.Mem64Base <= BaseAddress) {
+
+                    DEBUG ((DEBUG_INFO, "      Attempting %s allocation at 0x%llX.....",
+                            mPciResourceTypeStr[Index], BaseAddress));
+                    Status = gDS->AllocateMemorySpace (EfiGcdAllocateAddress, EfiGcdMemoryTypeMemoryMappedIo,
+                                                       BitsOfAlignment, AddrLen, &BaseAddress, mDriverImageHandle, NULL);
+                    if (!EFI_ERROR (Status)) {
+                      RootBridge->ResAllocNode[Index].Base    = (UINT64) BaseAddress;
+                      RootBridge->ResAllocNode[Index].Status  = ResAllocated;
+                      DEBUG ((DEBUG_INFO, "Passed\n"));
+                      goto TypeMem64Found;
+                    }
+                    DEBUG ((DEBUG_INFO, "Failed\n"));
+                    BaseAddress -= (Alignment + 1);
+                  } // while
+
+                  TypeMem64Found:
+                  if (RootBridge->ResAllocNode[Index].Status != ResAllocated) {
+                    //
+                    // No Room at the Inn for this resources request
+                    //
+                    ReturnStatus = EFI_OUT_OF_RESOURCES;
+                  }
+                } else {
+                  //
+                  // If 64-bit resourcing is not available, and the requested size is not greater than the Mem32Limit, then try as PMem32
+                  //
+                  if (AddrLen >= RootBridge->Aperture.Mem32Limit + 1) {
+
+                    DEBUG((DEBUG_ERROR, "      64-bit resource length 0x%llX > Mem32Limit (0x%llX). Failed!!\n", AddrLen, RootBridge->Aperture.Mem32Limit + 1));
+                    goto TypeMem64Found; // Let it handle out-of-resources case, try MMIO rebalance
+
+                  } else {
+
+                    DEBUG((DEBUG_ERROR, "      64-bit resourcing not available. Try as PMem32\n"));
+                    goto StartTypePMem32;
+                  }
+                }
+                break;
+
+              default:
+                DEBUG ((EFI_D_ERROR, "[PCI] ERROR: Unhandled resource type (%d)\n", Index));
+                break;
+            } // End switch (Index)
+
+            DEBUG ((DEBUG_INFO, "Resource Type Assigned:   %s\n", mPciResourceTypeStr[Index]));
+            if (RootBridge->ResAllocNode[Index].Status == ResAllocated) {
+              DEBUG ((DEBUG_INFO, "  Base Address Assigned: %lx\n", RootBridge->ResAllocNode[Index].Base));
+              DEBUG ((DEBUG_INFO, "  Length Assigned:       %lx\n", RootBridge->ResAllocNode[Index].Length));
+            } else {
+              DEBUG ((DEBUG_ERROR, "  Resource Allocation failed!  There was no room at the inn\n"));
+            }
+          } else {
+            //
+            // Index >= TypeMax
+            //
+            ASSERT (FALSE);
+          }
+        }
+      }
+      List = List->ForwardLink;
+    }
+
+    if (ReturnStatus == EFI_OUT_OF_RESOURCES) {
+
+      DEBUG ((DEBUG_ERROR, "[PCI] Resource allocation failed, rebalance resource allocation and reboot\n"));
+      AdjustResourceAmongRootBridges (HostBridge, &RatioAdjustResult);
+      if (RatioAdjustResult == SocketResourceRatioChanged) {
+        DEBUG ((DEBUG_WARN, "[PCI] WARNING: Resource allocation failed. Adjusted the resource requests and resetting the system.\n"));
+        gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
+
+      } else {
+
+        DEBUG ((DEBUG_WARN, "[PCI] WARNING: Resource allocation failed, rebalance not possible, continue boot\n"));
+      }
+    }
+
+    //
+    // Set resource to zero for nodes where allocation fails
+    //
+    List = HostBridge->RootBridges.ForwardLink;
+    while (List != &HostBridge->RootBridges) {
+      RootBridge = ROOT_BRIDGE_FROM_LINK (List);
+      for (Index = TypeIo; Index < TypeBus; Index++) {
+        if (RootBridge->ResAllocNode[Index].Status != ResAllocated) {
+          RootBridge->ResAllocNode[Index].Length = 0;
+        }
+      }
+      List = List->ForwardLink;
+    }
+    return ReturnStatus;
+  } else {
+    return EFI_NOT_READY;
+  }
+  //
+  // HostBridge->CanRestarted = FALSE;
+  //
+}
+
+
+/**
+  Enter the EfiPciHostBridgeFreeResources phase of the
+  PCI(e) numeration process.
+
+  @param This     The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+                  instance.
+  @retval EFI_SUCCESS   Things worked out
+  @retval other         Failures as reported by functions leveraged
+*/
+STATIC EFI_STATUS
+BridgeFreeResources (
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This
+  )
+{
+  PCI_HOST_BRIDGE_INSTANCE              *HostBridge;
+  PCI_ROOT_BRIDGE_INSTANCE              *RootBridge;
+  PCI_RESOURCE_TYPE                     Index;
+  LIST_ENTRY                            *List;
+  EFI_PHYSICAL_ADDRESS                  BaseAddress;
+  UINT64                                AddrLen;
+  EFI_STATUS                            Status;
+  EFI_STATUS                            ReturnStatus;
+
+  HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
+  ReturnStatus = EFI_SUCCESS;
+  List = HostBridge->RootBridges.ForwardLink;
+
+  while (List != &HostBridge->RootBridges) {
+    RootBridge = ROOT_BRIDGE_FROM_LINK (List);
+    for (Index = TypeIo; Index < TypeBus; Index++) {
+      if (RootBridge->ResAllocNode[Index].Status == ResAllocated) {
+        AddrLen     = RootBridge->ResAllocNode[Index].Length;
+        BaseAddress = (EFI_PHYSICAL_ADDRESS) RootBridge->ResAllocNode[Index].Base;
+
+        switch (Index) {
+        case TypeIo:
+          Status = gDS->FreeIoSpace (BaseAddress, AddrLen);
+          if (EFI_ERROR (Status)) {
+            ReturnStatus = Status;
+          }
+          break;
+
+        case TypeMem32:
+          Status = gDS->FreeMemorySpace (BaseAddress, AddrLen);
+          if (EFI_ERROR (Status)) {
+            ReturnStatus = Status;
+          }
+          break;
+
+        case TypePMem32:
+          break;
+
+        case TypeMem64:
+          break;
+
+        case TypePMem64:
+          Status = gDS->FreeMemorySpace (BaseAddress, AddrLen);
+          if (EFI_ERROR (Status)) {
+            ReturnStatus = Status;
+          }
+          break;
+
+        default:
+          DEBUG ((DEBUG_ERROR, "[PCI] ERROR: Invalid resource type %d\n", Index));
+          break;
+        }
+
+        RootBridge->ResAllocNode[Index].Type    = Index;
+        RootBridge->ResAllocNode[Index].Base    = 0;
+        RootBridge->ResAllocNode[Index].Length  = 0;
+        RootBridge->ResAllocNode[Index].Status  = ResNone;
+      }
+    }
+
+    List = List->ForwardLink;
+  }
+
+  HostBridge->ResourceSubmited  = FALSE;
+  HostBridge->CanRestarted      = TRUE;
+  return ReturnStatus;
+}
+
+
+/**
+  Enter the EfiPciHostBridgeEndResourceAllocation phase of the
+  PCI(e) numeration process.
+
+  @param This     The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+                  instance.
+  @retval EFI_SUCCESS   Things worked out
+*/
+STATIC EFI_STATUS
+PciHostBridgeEndResourceAllocation (
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This
+  )
+{
+  return EFI_SUCCESS;
+}
+
+
+/**
+
+  Enter a certain phase of the PCI enumeration process.
+
+  @param This   The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
+  @param Phase  The phase during enumeration.
+
+  @retval EFI_SUCCESS            Succeed.
+  @retval EFI_INVALID_PARAMETER  Wrong phase parameter passed in.
+  @retval EFI_NOT_READY          Resources have not been submitted yet.
+
+**/
+EFI_STATUS
+EFIAPI
+NotifyPhase (
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE    Phase
+  )
+{
+  PCI_HOST_BRIDGE_INSTANCE              *HostBridge;
+
+  HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
+
+  switch (Phase) {
+  case EfiPciHostBridgeBeginEnumeration:
+    return BeginBridgeEnumeration (This);
+
+  case EfiPciHostBridgeEndEnumeration:
+    return EFI_SUCCESS;
+
+  case EfiPciHostBridgeBeginBusAllocation:
+    //
+    // No specific action is required here, can perform any chipset specific programing
+    //
+    HostBridge->CanRestarted = FALSE;
+    break;
+
+  case EfiPciHostBridgeEndBusAllocation:
+    //
+    // No specific action is required here, can perform any chipset specific programing
+    //
+    break;
+
+  case EfiPciHostBridgeBeginResourceAllocation:
+    //
+    // No specific action is required here, can perform any chipset specific programing
+    //
+    break;
+
+  case EfiPciHostBridgeAllocateResources:
+    return BridgeAllocateResources (This);
+
+  case EfiPciHostBridgeSetResources:
+    //
+    // HostBridgeInstance->CanRestarted = FALSE;
+    //
+    break;
+
+  case EfiPciHostBridgeFreeResources:
+    return BridgeFreeResources (This);
+
+  case EfiPciHostBridgeEndResourceAllocation:
+    return PciHostBridgeEndResourceAllocation (This);
+
+  default:
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+
+  Return the device handle of the next PCI root bridge that is associated with
+  this Host Bridge.
+
+  @param This              The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
+  @param RootBridgeHandle  Returns the device handle of the next PCI Root Bridge.
+                           On input, it holds the RootBridgeHandle returned by the most
+                           recent call to GetNextRootBridge().The handle for the first
+                           PCI Root Bridge is returned if RootBridgeHandle is NULL on input.
+
+  @retval EFI_SUCCESS            Succeed.
+  @retval EFI_NOT_FOUND          Next PCI root bridge not found.
+  @retval EFI_INVALID_PARAMETER  Wrong parameter passed in.
+
+**/
+EFI_STATUS
+EFIAPI
+GetNextRootBridge (
+  IN     EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+  IN OUT EFI_HANDLE                                       *RootBridgeHandle
+  )
+{
+  BOOLEAN                   NoRootBridge;
+  LIST_ENTRY                *List;
+  PCI_HOST_BRIDGE_INSTANCE  *HostBridge;
+  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;
+
+  NoRootBridge = TRUE;
+  HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
+  List = HostBridge->RootBridges.ForwardLink;
+
+  while (List != &HostBridge->RootBridges) {
+    NoRootBridge = FALSE;
+    RootBridge = ROOT_BRIDGE_FROM_LINK (List);
+    if (*RootBridgeHandle == NULL) {
+      //
+      // Return the first Root Bridge Handle of the Host Bridge
+      //
+      *RootBridgeHandle = RootBridge->Handle;
+      return EFI_SUCCESS;
+    } else {
+      if (*RootBridgeHandle == RootBridge->Handle) {
+        //
+        // Get next if have
+        //
+        List = List->ForwardLink;
+        if (List != &HostBridge->RootBridges) {
+          RootBridge = ROOT_BRIDGE_FROM_LINK (List);
+          *RootBridgeHandle   = RootBridge->Handle;
+          return EFI_SUCCESS;
+        } else {
+          return EFI_NOT_FOUND;
+        }
+      }
+    }
+
+    List = List->ForwardLink;
+    //
+    // end while
+    //
+  }
+
+  if (NoRootBridge) {
+    return EFI_NOT_FOUND;
+  } else {
+    return EFI_INVALID_PARAMETER;
+  }
+}
+
+/**
+
+  Returns the attributes of a PCI Root Bridge.
+
+  @param This              The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
+  @param RootBridgeHandle  The device handle of the PCI Root Bridge
+                           that the caller is interested in.
+  @param Attributes        The pointer to attributes of the PCI Root Bridge.
+
+  @retval EFI_SUCCESS            Succeed.
+  @retval EFI_INVALID_PARAMETER  Attributes parameter passed in is NULL or
+                                 RootBridgeHandle is not an EFI_HANDLE
+                                 that was returned on a previous call to
+                                 GetNextRootBridge().
+
+**/
+EFI_STATUS
+EFIAPI
+GetAttributes (
+  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+  IN  EFI_HANDLE                                       RootBridgeHandle,
+  OUT UINT64                                           *Attributes
+  )
+{
+  LIST_ENTRY                *Link;
+  PCI_HOST_BRIDGE_INSTANCE  *HostBridge;
+  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;
+
+  if (Attributes == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
+  for (Link = GetFirstNode (&HostBridge->RootBridges)
+      ; !IsNull (&HostBridge->RootBridges, Link)
+      ; Link = GetNextNode (&HostBridge->RootBridges, Link)
+      ) {
+    RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
+    if (RootBridgeHandle == RootBridge->Handle) {
+      *Attributes = RootBridge->AllocationAttributes;
+      return EFI_SUCCESS;
+    }
+  }
+
+  return EFI_INVALID_PARAMETER;
+}
+
+/**
+
+  This is the request from the PCI enumerator to set up
+  the specified PCI Root Bridge for bus enumeration process.
+
+  @param This              The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
+  @param RootBridgeHandle  The PCI Root Bridge to be set up.
+  @param Configuration     Pointer to the pointer to the PCI bus resource descriptor.
+
+  @retval EFI_SUCCESS            Succeed.
+  @retval EFI_OUT_OF_RESOURCES   Not enough pool to be allocated.
+  @retval EFI_INVALID_PARAMETER  RootBridgeHandle is not a valid handle.
+
+**/
+EFI_STATUS
+EFIAPI
+StartBusEnumeration (
+  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+  IN  EFI_HANDLE                                       RootBridgeHandle,
+  OUT VOID                                             **Configuration
+  )
+{
+  LIST_ENTRY                *List;
+  PCI_HOST_BRIDGE_INSTANCE  *HostBridge;
+  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;
+  VOID                      *Buffer;
+  UINT8                     *Temp;
+  EFI_STATUS                Status;
+  UINTN                     BusStart;
+  UINTN                     BusEnd;
+  UINT64                    BusReserve;
+
+  HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
+  List = HostBridge->RootBridges.ForwardLink;
+
+  while (List != &HostBridge->RootBridges) {
+
+    RootBridge = ROOT_BRIDGE_FROM_LINK (List);
+    if (RootBridgeHandle == RootBridge->Handle) {
+      //
+      // Set up the Root Bridge for Bus Enumeration
+      //
+      BusStart  = RootBridge->Aperture.BusBase;
+      BusEnd    = RootBridge->Aperture.BusLimit;
+      BusReserve = RootBridge->Aperture.BusReserve;
+      //
+      // Program the Hardware(if needed) if error return EFI_DEVICE_ERROR
+      //
+      Status = gBS->AllocatePool (
+                      EfiBootServicesData,
+                      sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR),
+                      &Buffer
+                      );
+      if (EFI_ERROR (Status)) {
+        return EFI_OUT_OF_RESOURCES;
+      }
+
+      Temp  = (UINT8 *) Buffer;
+
+      ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->Desc                  = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+      ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->Len                   = 0x2B;
+      ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->ResType               = ACPI_ADDRESS_SPACE_TYPE_BUS;
+      ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->GenFlag               = 0;
+      ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->SpecificFlag          = 0;
+      ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->AddrSpaceGranularity  = 0;
+      ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->AddrRangeMin          = BusStart;
+      ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->AddrRangeMax          = BusReserve;
+      ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->AddrTranslationOffset = 0;
+      ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->AddrLen               = BusEnd - BusStart + 1;
+
+      Temp = Temp + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+      ((EFI_ACPI_END_TAG_DESCRIPTOR *) Temp)->Desc = ACPI_END_TAG_DESCRIPTOR;
+      ((EFI_ACPI_END_TAG_DESCRIPTOR *) Temp)->Checksum = 0x0;
+
+      *Configuration = Buffer;
+      return EFI_SUCCESS;
+    }
+
+    List = List->ForwardLink;
+  }
+
+  return EFI_INVALID_PARAMETER;
+}
+
+/**
+
+  This function programs the PCI Root Bridge hardware so that
+  it decodes the specified PCI bus range.
+
+  @param This              The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
+  @param RootBridgeHandle  The PCI Root Bridge whose bus range is to be programmed.
+  @param Configuration     The pointer to the PCI bus resource descriptor.
+
+  @retval EFI_SUCCESS            Succeed.
+  @retval EFI_INVALID_PARAMETER  Wrong parameters passed in.
+
+**/
+EFI_STATUS
+EFIAPI
+SetBusNumbers (
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+  IN EFI_HANDLE                                       RootBridgeHandle,
+  IN VOID                                             *Configuration
+  )
+{
+  LIST_ENTRY                *List;
+  PCI_HOST_BRIDGE_INSTANCE  *HostBridge;
+  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;
+  UINT8                     *Ptr;
+  UINTN                     BusStart;
+  UINTN                     BusEnd;
+  UINTN                     BusLen;
+
+  if (Configuration == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Ptr = Configuration;
+
+  //
+  // Check the Configuration is valid
+  //
+  if (*Ptr != ACPI_ADDRESS_SPACE_DESCRIPTOR) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Ptr)->ResType != ACPI_ADDRESS_SPACE_TYPE_BUS) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Ptr += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+  if (*Ptr != ACPI_END_TAG_DESCRIPTOR) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
+  List = HostBridge->RootBridges.ForwardLink;
+  Ptr = Configuration;
+
+  while (List != &HostBridge->RootBridges) {
+
+    RootBridge = ROOT_BRIDGE_FROM_LINK (List);
+    if (RootBridgeHandle == RootBridge->Handle) {
+      BusStart  = (UINTN) ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Ptr)->AddrRangeMin;
+      BusLen    = (UINTN) ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Ptr)->AddrLen;
+      BusEnd    = BusStart + BusLen - 1;
+
+      if (BusStart > BusEnd) {
+        return EFI_INVALID_PARAMETER;
+      }
+
+      if ((BusStart < RootBridge->Aperture.BusBase) || (BusEnd > RootBridge->Aperture.BusLimit)) {
+        return EFI_INVALID_PARAMETER;
+      }
+      //
+      // Update the Bus Range
+      //
+      RootBridge->ResAllocNode[TypeBus].Base    = BusStart;
+      RootBridge->ResAllocNode[TypeBus].Length  = BusLen + RootBridge->Aperture.BusReserve;
+      RootBridge->ResAllocNode[TypeBus].Status  = ResAllocated;
+      RootBridge->BusScanCount++;
+      if (RootBridge->BusScanCount > 0) {
+        //
+        // Only care about the 2nd PCI bus scanning
+        //
+        RootBridge->BusNumberAssigned = TRUE;
+      }
+
+      return EFI_SUCCESS;
+    }
+
+    List = List->ForwardLink;
+  }
+
+  return EFI_INVALID_PARAMETER;
+}
+
+
+/**
+
+  Submits the I/O and memory resource requirements for the specified PCI Root Bridge.
+
+  @param This              The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
+  @param RootBridgeHandle  The PCI Root Bridge whose I/O and memory resource requirements.
+                           are being submitted.
+  @param Configuration     The pointer to the PCI I/O and PCI memory resource descriptor.
+
+  @retval EFI_SUCCESS            Succeed.
+  @retval EFI_INVALID_PARAMETER  Wrong parameters passed in.
+**/
+EFI_STATUS
+EFIAPI
+SubmitResources (
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+  IN EFI_HANDLE                                       RootBridgeHandle,
+  IN VOID                                             *Configuration
+  )
+{
+  LIST_ENTRY                        *List;
+  PCI_HOST_BRIDGE_INSTANCE          *HostBridge;
+  PCI_ROOT_BRIDGE_INSTANCE          *RootBridge;
+  UINT8                             *Temp;
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *ptr;
+  UINT64                            AddrLen;
+  UINT64                            Alignment;
+  UINT64                            Value;
+
+  //
+  // Check the input parameter: Configuration
+  //
+  if (Configuration == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
+  List = HostBridge->RootBridges.ForwardLink;
+
+  Temp = (UINT8 *) Configuration;
+  while (List != &HostBridge->RootBridges) {
+
+    RootBridge = ROOT_BRIDGE_FROM_LINK (List);
+    if (RootBridgeHandle == RootBridge->Handle) {
+      //
+      // Check the resource descriptors.
+      // If the Configuration includes one or more invalid resource descriptors, all the resource
+      // descriptors are ignored and the function returns EFI_INVALID_PARAMETER.
+      //
+      for (; *Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR; Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR)) {
+
+        ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;
+        //DEBUG ((DEBUG_ERROR, " ptr->ResType:%x", ptr->ResType));
+        //DEBUG ((DEBUG_ERROR, " ptr->AddrLen:0x%llX AddrRangeMin:0x%llX AddrRangeMax:0x%llX\n",ptr->AddrLen,ptr->AddrRangeMin,ptr->AddrRangeMax));
+        //
+        // A zero-length resource request indicates the PCI root bridge doesn't require
+        // any resources. Skip the check and proceed to the next descriptor.
+        //
+        if (ptr->AddrLen == 0) {
+          continue;
+        }
+
+        switch (ptr->ResType) {
+          case ACPI_ADDRESS_SPACE_TYPE_MEM:
+            if (ptr->AddrSpaceGranularity != 32 && ptr->AddrSpaceGranularity != 64) {
+
+              DEBUG ((DEBUG_ERROR, "[PCI] ERROR: Inavlid granularity %d for resource type %d\n",
+                      ptr->AddrSpaceGranularity, ptr->ResType));
+              return EFI_INVALID_PARAMETER;
+            }
+            if (ptr->AddrSpaceGranularity == 32 && ptr->AddrLen > 0xffffffff) {
+
+              DEBUG ((DEBUG_ERROR, "[PCI] ERROR: Inavlid granularity %d for resource type %d of size 0x%llX\n",
+                      ptr->AddrSpaceGranularity, ptr->ResType, ptr->AddrLen));
+              return EFI_INVALID_PARAMETER;
+            }
+            //
+            // If the PCI root bridge does not support separate windows for nonprefetchable and
+            // prefetchable memory, then the PCI bus driver needs to include requests for
+            // prefetchable memory in the nonprefetchable memory pool.
+            //
+            if ((RootBridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0 &&
+                ((ptr->SpecificFlag & (BIT2 | BIT1)) != 0)) {
+              return EFI_INVALID_PARAMETER;
+            }
+          case ACPI_ADDRESS_SPACE_TYPE_IO:
+            //
+            // Check alignment, it should be of the form 2^n-1
+            //
+            Value = Power2MaxMemory (ptr->AddrRangeMax + 1);
+            if (Value != (ptr->AddrRangeMax + 1)) {
+              CpuDeadLoop();
+              return EFI_INVALID_PARAMETER;
+            }
+            break;
+          case ACPI_ADDRESS_SPACE_TYPE_BUS:
+          default:
+            return EFI_INVALID_PARAMETER;
+        }
+      }
+      if (*Temp != ACPI_END_TAG_DESCRIPTOR) {
+        return EFI_INVALID_PARAMETER;
+      }
+
+      Temp = (UINT8 *) Configuration;
+      for (; *Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR; Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR)) {
+        ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;
+
+        //
+        // If a PCI root bridge does not require any resources, a zero-length resource
+        // request must be explicitly submitted.
+        //
+        if (ptr->AddrLen == 0) {
+          HostBridge->ResourceSubmited = TRUE;
+          continue;
+        }
+
+        switch (ptr->ResType) {
+        case ACPI_ADDRESS_SPACE_TYPE_MEM:
+          AddrLen   = (UINT64) ptr->AddrLen;
+          Alignment = (UINT64) ptr->AddrRangeMax;
+          if (ptr->AddrSpaceGranularity == 32) {
+            if (ptr->SpecificFlag == 0x06) {
+              //
+              // Apply from GCD
+              //
+              RootBridge->ResAllocNode[TypePMem32].Status = ResSubmitted;
+            } else {
+              RootBridge->ResAllocNode[TypeMem32].Length    = AddrLen;
+              RootBridge->ResAllocNode[TypeMem32].Alignment = Alignment;
+              RootBridge->ResAllocNode[TypeMem32].Status    = ResRequested;
+              HostBridge->ResourceSubmited                  = TRUE;
+            }
+          }
+
+          if (ptr->AddrSpaceGranularity == 64) {
+            if (ptr->SpecificFlag == 0x06) {
+              RootBridge->ResAllocNode[TypePMem64].Status = ResSubmitted;
+            } else {
+              RootBridge->ResAllocNode[TypeMem64].Length    = AddrLen;
+              RootBridge->ResAllocNode[TypeMem64].Alignment = Alignment;
+              RootBridge->ResAllocNode[TypeMem64].Status    = ResSubmitted;
+              HostBridge->ResourceSubmited                  = TRUE;
+            }
+          }
+          break;
+
+        case ACPI_ADDRESS_SPACE_TYPE_IO:
+          AddrLen   = (UINT64) ptr->AddrLen;
+          Alignment = (UINT64) ptr->AddrRangeMax;
+          RootBridge->ResAllocNode[TypeIo].Length     = AddrLen;
+          RootBridge->ResAllocNode[TypeIo].Alignment  = Alignment;
+          RootBridge->ResAllocNode[TypeIo].Status     = ResRequested;
+          HostBridge->ResourceSubmited                = TRUE;
+          break;
+
+        default:
+          break;
+        }
+      }
+
+      return EFI_SUCCESS;
+    }
+    List = List->ForwardLink;
+  }
+
+  return EFI_INVALID_PARAMETER;
+}
+
+/**
+
+  This function returns the proposed resource settings for the specified
+  PCI Root Bridge.
+
+  @param This              The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
+  @param RootBridgeHandle  The PCI Root Bridge handle.
+  @param Configuration     The pointer to the pointer to the PCI I/O
+                           and memory resource descriptor.
+
+  @retval EFI_SUCCESS            Succeed.
+  @retval EFI_OUT_OF_RESOURCES   Not enough pool to be allocated.
+  @retval EFI_INVALID_PARAMETER  RootBridgeHandle is not a valid handle.
+
+**/
+EFI_STATUS
+EFIAPI
+GetProposedResources (
+  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+  IN  EFI_HANDLE                                       RootBridgeHandle,
+  OUT VOID                                             **Configuration
+  )
+{
+  LIST_ENTRY                        *List;
+  PCI_HOST_BRIDGE_INSTANCE          *HostBridge;
+  PCI_ROOT_BRIDGE_INSTANCE          *RootBridge;
+  UINTN                             Index;
+  UINTN                             Number;
+  VOID                              *Buffer;
+  UINT8                             *Temp;
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *ptr;
+  EFI_STATUS                        Status;
+  UINT64                            ResStatus;
+
+  Buffer  = NULL;
+  Number  = 0;
+  //
+  // Get the Host Bridge Instance from the resource allocation protocol
+  //
+  HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
+  List = HostBridge->RootBridges.ForwardLink;
+
+  //
+  // Enumerate the root bridges in this Host bridge
+  //
+  while (List != &HostBridge->RootBridges) {
+
+    RootBridge = ROOT_BRIDGE_FROM_LINK (List);
+    if (RootBridgeHandle == RootBridge->Handle) {
+      for (Index = 0; Index < TypeBus; Index++) {
+        if (RootBridge->ResAllocNode[Index].Status != ResNone) {
+          Number++;
+        }
+      }
+
+      Status = gBS->AllocatePool (
+                      EfiBootServicesData,
+                      Number * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR),
+                      &Buffer
+                      );
+
+      if (EFI_ERROR (Status)) {
+        return EFI_OUT_OF_RESOURCES;
+      }
+
+      ZeroMem (Buffer, sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * Number + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
+
+      Temp = Buffer;
+      for (Index = 0; Index < TypeBus; Index++) {
+        if (RootBridge->ResAllocNode[Index].Status != ResNone) {
+          ptr       = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;
+          ResStatus = RootBridge->ResAllocNode[Index].Status;
+
+          switch (Index) {
+
+          case TypeIo:
+            //
+            // Io
+            //
+            ptr->Desc                   = 0x8A;
+            ptr->Len                    = 0x2B;
+            ptr->ResType                = 1;
+            ptr->GenFlag                = 0;
+            ptr->SpecificFlag           = 0;
+            ptr->AddrRangeMin           = RootBridge->ResAllocNode[Index].Base;
+            ptr->AddrRangeMax           = 0;
+            ptr->AddrTranslationOffset  = (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS;
+            ptr->AddrLen                = RootBridge->ResAllocNode[Index].Length;
+            break;
+
+          case TypeMem32:
+            //
+            // Memory 32
+            //
+            ptr->Desc                   = 0x8A;
+            ptr->Len                    = 0x2B;
+            ptr->ResType                = 0;
+            ptr->GenFlag                = 0;
+            ptr->SpecificFlag           = 0;
+            ptr->AddrSpaceGranularity   = 32;
+            ptr->AddrRangeMin           = RootBridge->ResAllocNode[Index].Base;
+            ptr->AddrRangeMax           = 0;
+            ptr->AddrTranslationOffset  = (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS;
+            ptr->AddrLen                = RootBridge->ResAllocNode[Index].Length;
+            break;
+
+          case TypePMem32:
+            //
+            // Prefetch memory 32
+            //
+            ptr->Desc                   = 0x8A;
+            ptr->Len                    = 0x2B;
+            ptr->ResType                = 0;
+            ptr->GenFlag                = 0;
+            ptr->SpecificFlag           = 6;
+            ptr->AddrSpaceGranularity   = 32;
+            ptr->AddrRangeMin           = 0;
+            ptr->AddrRangeMax           = 0;
+            ptr->AddrTranslationOffset  = EFI_RESOURCE_NONEXISTENT;
+            ptr->AddrLen                = 0;
+            break;
+
+          case TypeMem64:
+            //
+            // Memory 64
+            //
+            ptr->Desc                   = 0x8A;
+            ptr->Len                    = 0x2B;
+            ptr->ResType                = 0;
+            ptr->GenFlag                = 0;
+            ptr->SpecificFlag           = 0;
+            ptr->AddrSpaceGranularity   = 64;
+            ptr->AddrRangeMin           = RootBridge->ResAllocNode[Index].Base;
+            ptr->AddrRangeMax           = 0;
+            ptr->AddrTranslationOffset  = (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS;
+            ptr->AddrLen                = RootBridge->ResAllocNode[Index].Length;
+            break;
+
+          case TypePMem64:
+            //
+            // Prefetch memory 64
+            //
+            ptr->Desc                   = 0x8A;
+            ptr->Len                    = 0x2B;
+            ptr->ResType                = 0;
+            ptr->GenFlag                = 0;
+            ptr->SpecificFlag           = 6;
+            ptr->AddrSpaceGranularity   = 64;
+            ptr->AddrRangeMin           = 0;
+            ptr->AddrRangeMax           = 0;
+            ptr->AddrTranslationOffset  = EFI_RESOURCE_NONEXISTENT;
+            ptr->AddrLen                = 0;
+            break;
+            default:
+              DEBUG ((EFI_D_INFO, "default case.\n"));  //Auto added. Please review.
+              break;
+          }
+
+          Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+        }
+      }
+
+      ((EFI_ACPI_END_TAG_DESCRIPTOR *) Temp)->Desc      = 0x79;
+      ((EFI_ACPI_END_TAG_DESCRIPTOR *) Temp)->Checksum  = 0x0;
+
+      *Configuration = Buffer;
+
+      return EFI_SUCCESS;
+    }
+
+    List = List->ForwardLink;
+  }
+
+  return EFI_INVALID_PARAMETER;
+}
+
+/**
+
+  This function is called for all the PCI controllers that the PCI
+  bus driver finds. Can be used to Preprogram the controller.
+
+  @param This              The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
+  @param RootBridgeHandle  The PCI Root Bridge handle.
+  @param PciAddress        Address of the controller on the PCI bus.
+  @param Phase             The Phase during resource allocation.
+
+  @retval EFI_SUCCESS            Succeed.
+  @retval EFI_INVALID_PARAMETER  RootBridgeHandle is not a valid handle.
+
+**/
+EFI_STATUS
+EFIAPI
+PreprocessController (
+  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL          *This,
+  IN  EFI_HANDLE                                                RootBridgeHandle,
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS               PciAddress,
+  IN  EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE              Phase
+  )
+{
+  BOOLEAN                   RootBridgeFound;
+  LIST_ENTRY                *List;
+  PCI_HOST_BRIDGE_INSTANCE  *HostBridge;
+  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;
+
+  if (RootBridgeHandle == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  RootBridgeFound     = FALSE;
+  HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
+  List = HostBridge->RootBridges.ForwardLink;
+
+  while (List != &HostBridge->RootBridges) {
+
+    RootBridge = ROOT_BRIDGE_FROM_LINK (List);
+    if (RootBridgeHandle == RootBridge->Handle) {
+      RootBridgeFound = TRUE;
+      break;
+    }
+    //
+    // Get next if have
+    //
+    List = List->ForwardLink;
+  }
+
+  if (RootBridgeFound == FALSE) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+
+  Calculate maximum memory length that can be fit to a mtrr.
+
+  @param MemoryLength  -  Input memory length.
+
+  @retval Returned Maximum length.
+
+**/
+UINT64
+Power2MaxMemory (
+  IN UINT64                     MemoryLength
+  )
+{
+  UINT64  Result;
+
+  if (RShiftU64 (MemoryLength, 32)) {
+    Result = LShiftU64 ((UINT64) GetPowerOfTwo64 ((UINT32) RShiftU64 (MemoryLength, 32)), 32);
+  } else {
+    Result = (UINT64) GetPowerOfTwo64 ((UINT32) MemoryLength);
+  }
+
+  return Result;
+}
+
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciHostBridge.h b/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciHostBridge.h
new file mode 100644
index 0000000000..4c1b757952
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciHostBridge.h
@@ -0,0 +1,300 @@
+/** @file
+
+  @copyright
+  Copyright 1999 - 2021 Intel Corporation. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PCI_HOST_BRIDGE_H_
+#define _PCI_HOST_BRIDGE_H_
+
+
+#include <PiDxe.h>
+#include <IndustryStandard/Acpi.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PciHostBridgeLib.h>
+#include <Protocol/PciHostBridgeResourceAllocation.h>
+#include <Protocol/IoMmu.h>
+
+#include "PciRootBridge.h"
+
+#define PCI_HOST_BRIDGE_SIGNATURE SIGNATURE_32 ('p', 'h', 'b', 'g')
+typedef struct {
+  UINTN                                             Signature;
+  EFI_HANDLE                                        Handle;
+  UINTN                                             RootBridgeCount;
+  LIST_ENTRY                                        RootBridges;
+  BOOLEAN                                           ResourceSubmited;
+  BOOLEAN                                           CanRestarted;
+  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  ResAlloc;
+} PCI_HOST_BRIDGE_INSTANCE;
+
+#define PCI_HOST_BRIDGE_FROM_THIS(a) CR (a, PCI_HOST_BRIDGE_INSTANCE, ResAlloc, PCI_HOST_BRIDGE_SIGNATURE)
+
+//
+// Driver Entry Point
+//
+/**
+
+  Entry point of this driver.
+
+  @param ImageHandle  -  Image handle of this driver.
+  @param SystemTable  -  Pointer to standard EFI system table.
+
+  @retval EFI_SUCCESS       -  Succeed.
+  @retval EFI_DEVICE_ERROR  -  Fail to install PCI_ROOT_BRIDGE_IO protocol.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializePciHostBridge (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  );
+
+//
+//  HostBridge Resource Allocation interface
+//
+/**
+
+  Enter a certain phase of the PCI enumeration process.
+
+  @param This   The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
+  @param Phase  The phase during enumeration.
+
+  @retval EFI_SUCCESS            Succeed.
+  @retval EFI_INVALID_PARAMETER  Wrong phase parameter passed in.
+  @retval EFI_NOT_READY          Resources have not been submitted yet.
+
+**/
+EFI_STATUS
+EFIAPI
+NotifyPhase (
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL   *This,
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE      Phase
+  );
+
+/**
+
+  Return the device handle of the next PCI root bridge that is associated with
+  this Host Bridge.
+
+  @param This              The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
+  @param RootBridgeHandle  Returns the device handle of the next PCI Root Bridge.
+                           On input, it holds the RootBridgeHandle returned by the most
+                           recent call to GetNextRootBridge().The handle for the first
+                           PCI Root Bridge is returned if RootBridgeHandle is NULL on input.
+
+  @retval EFI_SUCCESS            Succeed.
+  @retval EFI_NOT_FOUND          Next PCI root bridge not found.
+  @retval EFI_INVALID_PARAMETER  Wrong parameter passed in.
+
+**/
+EFI_STATUS
+EFIAPI
+GetNextRootBridge (
+  IN     EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+  IN OUT EFI_HANDLE                                       *RootBridgeHandle
+  );
+
+/**
+
+  Returns the attributes of a PCI Root Bridge.
+
+  @param This              -  The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance
+  @param RootBridgeHandle  -  The device handle of the PCI Root Bridge
+                              that the caller is interested in
+  @param Attributes        -  The pointer to attributes of the PCI Root Bridge
+
+  @retval EFI_SUCCESS            -  Succeed.
+  @retval EFI_INVALID_PARAMETER  -  Attributes parameter passed in is NULL or
+                            @retval RootBridgeHandle is not an EFI_HANDLE
+                            @retval that was returned on a previous call to
+                            @retval GetNextRootBridge().
+
+**/
+EFI_STATUS
+EFIAPI
+GetAttributes (
+  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+  IN  EFI_HANDLE                                       RootBridgeHandle,
+  OUT UINT64                                           *Attributes
+  );
+
+/**
+
+  This is the request from the PCI enumerator to set up
+  the specified PCI Root Bridge for bus enumeration process.
+
+  @param This              -  The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
+  @param RootBridgeHandle  -  The PCI Root Bridge to be set up.
+  @param Configuration     -  Pointer to the pointer to the PCI bus resource descriptor.
+
+  @retval EFI_SUCCESS            -  Succeed.
+  @retval EFI_OUT_OF_RESOURCES   -  Not enough pool to be allocated.
+  @retval EFI_INVALID_PARAMETER  -  RootBridgeHandle is not a valid handle.
+
+**/
+EFI_STATUS
+EFIAPI
+StartBusEnumeration (
+  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+  IN  EFI_HANDLE                                       RootBridgeHandle,
+  OUT VOID                                             **Configuration
+  );
+
+/**
+
+  This function programs the PCI Root Bridge hardware so that
+  it decodes the specified PCI bus range.
+
+  @param This              -  The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
+  @param RootBridgeHandle  -  The PCI Root Bridge whose bus range is to be programmed.
+  @param Configuration     -  The pointer to the PCI bus resource descriptor.
+
+  @retval EFI_SUCCESS            -  Succeed.
+  @retval EFI_INVALID_PARAMETER  -  Wrong parameters passed in.
+
+**/
+EFI_STATUS
+EFIAPI
+SetBusNumbers (
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+  IN EFI_HANDLE                                       RootBridgeHandle,
+  IN VOID                                             *Configuration
+  );
+
+/**
+
+  Submits the I/O and memory resource requirements for the specified PCI Root Bridge.
+
+  @param This              -  The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance
+  @param RootBridgeHandle  -  The PCI Root Bridge whose I/O and memory resource requirements
+                              are being submitted
+  @param Configuration     -  The pointer to the PCI I/O and PCI memory resource descriptor
+
+  @retval EFI_SUCCESS            -  Succeed.
+  @retval EFI_INVALID_PARAMETER  -  Wrong parameters passed in.
+
+**/
+EFI_STATUS
+EFIAPI
+SubmitResources (
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+  IN EFI_HANDLE                                       RootBridgeHandle,
+  IN VOID                                             *Configuration
+  );
+
+/**
+
+  This function returns the proposed resource settings for the specified
+  PCI Root Bridge.
+
+  @param This              -  The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
+  @param RootBridgeHandle  -  The PCI Root Bridge handle.
+  @param Configuration     -  The pointer to the pointer to the PCI I/O
+                              and memory resource descriptor.
+
+  @retval EFI_SUCCESS            -  Succeed.
+  @retval EFI_OUT_OF_RESOURCES   -  Not enough pool to be allocated.
+  @retval EFI_INVALID_PARAMETER  -  RootBridgeHandle is not a valid handle.
+
+**/
+EFI_STATUS
+EFIAPI
+GetProposedResources (
+  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+  IN  EFI_HANDLE                                       RootBridgeHandle,
+  OUT VOID                                             **Configuration
+  );
+
+/**
+
+  This function is called for all the PCI controllers that the PCI
+  bus driver finds. Can be used to Preprogram the controller.
+
+  @param This              -  The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
+  @param RootBridgeHandle  -  The PCI Root Bridge handle.
+  @param PciAddress        -  Address of the controller on the PCI bus.
+  @param Phase             -  The Phase during resource allocation.
+
+  @retval EFI_SUCCESS            -  Succeed.
+  @retval EFI_INVALID_PARAMETER  -  RootBridgeHandle is not a valid handle.
+
+**/
+EFI_STATUS
+EFIAPI
+PreprocessController (
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL          *This,
+  IN EFI_HANDLE                                                RootBridgeHandle,
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS               PciAddress,
+  IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE              Phase
+  );
+
+//
+// Host Bridge Silicon specific hooks
+//
+/**
+
+  Returns the Allocation attributes for the BNB Root Bridge.
+
+  @param RootBridgeIndex  -  The root bridge number. 0 based.
+
+  @retval EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM | EFI_PCI_HOST_BRIDGE_MEM64_DECODE
+
+**/
+UINT64
+GetAllocAttributes (
+  IN  UINTN        RootBridgeIndex
+  )
+;
+
+/**
+
+  Returns memory apertures for the BNB Root Bridge.
+
+  @param PciRootBridgeIo  -  Pointer to Efi Pci root bridge Io protocol interface instance.
+  @param Mem32Base        -  Pointer to 32 bit memory base. This is the lowest 32 bit memory address
+                             that is decoded by the Host Bridge.
+  @param Mem32Limit       -  Pointer to 32 bit memory limit.This is the highest 32 bit memory address
+                             that is decoded by the Host Bridge. The size of the 32 bit window is
+                             (Mem32Limit - Mem32base + 1).
+  @param Mem64Base        -  Pointer to 64 bit memory base. This is the lowest 64 bit memory address
+                             that is decoded by the Host Bridge.
+  @param Mem64Limit       -  Pointer to 64 bit memory limit.This is the highest 64 bit memory address
+                             that is decoded by the Host Bridge. The size of the 64 bit window is
+                             (Mem64Limit - Mem64base + 1). Set Mem64Limit < Mem64Base if the Host bridge
+                             does not support 64 bit memory addresses.
+
+  @retval EFI_SUCCESS  -  Success.
+
+**/
+EFI_STATUS
+GetHostBridgeMemApertures (
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL               *PciRootBridgeIo,
+  OUT UINT32                                        *Mem32Base,
+  OUT UINT32                                        *Mem32Limit,
+  OUT UINT64                                        *Mem64Base,
+  OUT UINT64                                        *Mem64Limit
+  );
+
+/**
+
+  Calculate maximum memory length that can be fit to a mtrr.
+
+  @param MemoryLength  -  Input memory length.
+
+  @retval Returned Maximum length.
+
+**/
+UINT64
+Power2MaxMemory (
+  IN UINT64         MemoryLength
+  );
+
+extern EDKII_IOMMU_PROTOCOL        *mIoMmu;
+
+#endif // _PCI_HOST_BRIDGE_H_
+
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciHostBridge.inf b/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciHostBridge.inf
new file mode 100644
index 0000000000..faea9726f7
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciHostBridge.inf
@@ -0,0 +1,69 @@
+## @file
+#
+# @copyright
+# Copyright 2009 - 2021 Intel Corporation. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PciHostBridge
+  FILE_GUID                      = D58EBCE1-AF26-488d-BE66-C164417F8C13
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = InitializePciHostBridge
+
+[Sources]
+  PciHostBridge.h
+  PciRootBridge.h
+  PciHostBridge.c
+  PciRootBridgeIo.c
+  PciHostBridgeSupport.c
+  PciHostResource.h
+  PciRebalance.c
+  PciRebalanceIo.c
+  PciRebalanceMmio32.c
+  PciRebalanceMmio64.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  WhitleySiliconPkg/WhitleySiliconPkg.dec
+  WhitleySiliconPkg/SiliconPkg.dec
+  WhitleySiliconPkg/CpRcPkg.dec
+  WhitleySiliconPkg/Cpu/CpuRcPkg.dec
+  WhitleyOpenBoardPkg/PlatformPkg.dec
+
+[LibraryClasses]
+  UefiDriverEntryPoint
+  UefiBootServicesTableLib
+  DebugLib
+  DxeServicesTableLib
+  DevicePathLib
+  BaseMemoryLib
+  BaseLib
+  UefiLib
+  TimerLib
+  SetupLib
+
+[Protocols]
+  gEfiCpuIo2ProtocolGuid                          ## CONSUMES
+  gEfiDevicePathProtocolGuid                      ## BY_START
+  gEfiPciRootBridgeIoProtocolGuid                 ## BY_START
+  gEfiPciHostBridgeResourceAllocationProtocolGuid ## BY_START
+  gEdkiiIoMmuProtocolGuid                         ## SOMETIMES_CONSUMES
+  gEfiIioUdsProtocolGuid
+  gDynamicSiLibraryProtocolGuid                   ## CONSUMES
+
+[Guids]
+  gEfiSocketPciResourceDataGuid
+
+[FixedPcd]
+  gEfiCpRcPkgTokenSpaceGuid.PcdMaxCpuSocketCount
+  gEfiCpRcPkgTokenSpaceGuid.PcdMaxCpuCoreCount
+
+[Depex]
+  gEfiCpuIo2ProtocolGuid AND
+  gEfiIioUdsProtocolGuid AND
+  gDynamicSiLibraryProtocolGuid
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciHostBridgeSupport.c b/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciHostBridgeSupport.c
new file mode 100644
index 0000000000..fe3f274f1f
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciHostBridgeSupport.c
@@ -0,0 +1,127 @@
+/** @file
+  Do platform initialization for PCI bridge.
+
+  @copyright
+  Copyright 1999 - 2021 Intel Corporation. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "PciHostBridge.h"
+
+//
+// The default latency for controllers
+//
+#define DEFAULT_PCI_LATENCY 0x20
+
+
+EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *mPciRootBridgeIo;
+
+/**
+
+  This function is called for all the PCI controllers that the PCI
+  bus driver finds. Can be used to Preprogram the controller.
+
+  @param This             -- The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance
+  @param RootBridgeHandle -- The PCI Root Bridge handle
+  @param PciBusAddress    -- Address of the controller on the PCI bus
+  @param Phase            -- The Phase during resource allocation
+
+  @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+ChipsetPreprocessController (
+  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL          *This,
+  IN  EFI_HANDLE                                                RootBridgeHandle,
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS               PciAddress,
+  IN  EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE              Phase
+  )
+{
+
+  EFI_STATUS  Status;
+  UINT8       Latency;
+  UINT8       CacheLineSize;
+
+  if (mPciRootBridgeIo == NULL) {
+    //
+    // Get root bridge in the system.
+    //
+    Status = gBS->HandleProtocol (RootBridgeHandle, &gEfiPciRootBridgeIoProtocolGuid, &mPciRootBridgeIo);
+    ASSERT_EFI_ERROR (Status);
+  }
+
+  if (Phase == EfiPciBeforeResourceCollection) {
+    //
+    // Program the latency register, CLS register
+    //
+    PciAddress.Register = PCI_LATENCY_TIMER_OFFSET;
+    mPciRootBridgeIo->Pci.Read (
+                            mPciRootBridgeIo,
+                            EfiPciWidthUint8,
+                            *((UINT64 *) &PciAddress),
+                            1,
+                            &Latency
+                            );
+
+    //
+    // PCI-x cards come up with a default latency of 0x40. Don't touch them.
+    //
+    if (Latency == 0) {
+      Latency = DEFAULT_PCI_LATENCY;
+      mPciRootBridgeIo->Pci.Write (
+                              mPciRootBridgeIo,
+                              EfiPciWidthUint8,
+                              *((UINT64 *) &PciAddress),
+                              1,
+                              &Latency
+                              );
+    }
+    //
+    // Program Cache Line Size as 64bytes
+    // 16 of DWORDs = 64bytes (0x10)
+    //
+    PciAddress.Register = PCI_CACHELINE_SIZE_OFFSET;
+    CacheLineSize       = 0x10;
+    mPciRootBridgeIo->Pci.Write (
+                            mPciRootBridgeIo,
+                            EfiPciWidthUint8,
+                            *((UINT64 *) &PciAddress),
+                            1,
+                            &CacheLineSize
+                            );
+
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+
+  Returns the Allocation attributes for the BNB Root Bridge.
+
+  @param RootBridgeIndex  -  The root bridge number. 0 based.
+
+  @retval EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM | EFI_PCI_HOST_BRIDGE_MEM64_DECODE
+
+**/
+UINT64
+GetAllocAttributes (
+  IN  UINTN        RootBridgeIndex
+  )
+{
+  //
+  // Cannot have more than one Root bridge
+  //
+  //ASSERT (RootBridgeIndex == 0);
+
+  //
+  // PCI Root Bridge does not support separate windows for Non-prefetchable
+  // and Prefetchable memory. A PCI bus driver needs to include requests for
+  // Prefetchable memory in the Non-prefetchable memory pool.
+  // Further TNB does not support 64 bit memory apertures for PCI. BNB
+  // can only have system memory above 4 GB,
+  //
+
+    return EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM | EFI_PCI_HOST_BRIDGE_MEM64_DECODE;
+}
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciHostResource.h b/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciHostResource.h
new file mode 100644
index 0000000000..dd95e9773f
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciHostResource.h
@@ -0,0 +1,62 @@
+/** @file
+
+  @copyright
+  Copyright 1999 - 2021 Intel Corporation. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PCI_HOST_RESOURCE_H_
+#define _PCI_HOST_RESOURCE_H_
+
+#include <PiDxe.h>
+#include <UncoreCommonIncludes.h>
+
+#define EFI_RESOURCE_NONEXISTENT  0xFFFFFFFFFFFFFFFF
+#define EFI_RESOURCE_LESS         0xFFFFFFFFFFFFFFFE
+
+typedef struct {
+  UINTN   BusBase;
+  UINTN   BusLimit;
+  UINTN   BusReserve;
+
+  UINT32  Mem32Base;
+  UINT32  Mem32Limit;
+
+  UINT64  Mem64Base;
+  UINT64  Mem64Limit;
+
+  UINTN   IoBase;
+  UINTN   IoLimit;
+} PCI_ROOT_BRIDGE_RESOURCE_APERTURE;
+
+typedef enum {
+  TypeIo    = 0,
+  TypeMem32,
+  TypePMem32,
+  TypeMem64,
+  TypePMem64,
+  TypeBus,
+  TypeMax
+} PCI_RESOURCE_TYPE;
+
+typedef enum {
+  ResNone,
+  ResSubmitted,
+  ResRequested,
+  ResAllocated,
+  ResStatusMax
+} RES_STATUS;
+
+typedef struct {
+  PCI_RESOURCE_TYPE Type;
+  //
+  // Base is a host address
+  //
+  UINT64            Base;
+  UINT64            Length;
+  UINT64            Alignment;
+  RES_STATUS        Status;
+} PCI_RES_NODE;
+
+#endif // _PCI_HOST_RESOURCE_H_
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciRebalance.c b/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciRebalance.c
new file mode 100644
index 0000000000..b32f0bf835
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciRebalance.c
@@ -0,0 +1,1356 @@
+/** @file
+
+  @copyright
+  Copyright 1999 - 2021 Intel Corporation. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Guid/SocketPciResourceData.h>
+#include <Guid/SocketIioVariable.h>
+#include "PciHostBridge.h"
+#include "PciRootBridge.h"
+#include <CpuAndRevisionDefines.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Protocol/IioUds.h>
+
+#include "PciRebalance.h"
+
+
+/******************************************************************************
+ * Local definitions.
+ ******************************************************************************/
+extern CHAR16                           *mAcpiAddressSpaceTypeStr[];
+extern CHAR16                           *mPciResourceTypeStr[];
+
+extern EFI_IIO_UDS_PROTOCOL              *mIioUds;
+
+/******************************************************************************
+ * Variables.
+ ******************************************************************************/
+/**
+ * The table below is a cache with pointers to protocol instances created at
+ * Host Bridge initialization. It also provides mapping of protocol instance
+ * to the PCI stack.
+ */
+PCI_ROOT_BRIDGE_INSTANCE *mPciRootBridgeTable[MAX_SOCKET][MAX_LOGIC_IIO_STACK] = {0};
+PCI_ROOT_BRIDGE_INSTANCE *mPciRootBridgeTableReserved[MAX_SOCKET][IIO_RESERVED_1] = {0};
+
+
+/******************************************************************************
+ * Functions.
+ ******************************************************************************/
+
+/**
+ Find socket and stack index for given PCI Root Bridge protocol pointer.
+
+ @param[out] PciResConfigPtr - Buffer for the resource configuration variable.
+
+ @retval EFI_SUCCESS            The function completed successfully.
+ @retval EFI_NOT_FOUND          The variable was not found.
+ @retval EFI_DEVICE_ERROR       The variable could not be retrieved due to a hardware error.
+ @retval EFI_SECURITY_VIOLATION The variable could not be retrieved due to an authentication failure.
+**/
+EFI_STATUS
+PciRootBridge2SocketStack (
+  IN     PCI_ROOT_BRIDGE_INSTANCE *RootBridgePtr,
+     OUT UINT8                    *SocketPtr,
+     OUT UINT8                    *StackPtr
+  )
+{
+  UINT8  Socket;
+  UINT8  Stack;
+
+  if (RootBridgePtr != NULL) {
+
+    for (Socket = 0; Socket < NELEMENTS(mPciRootBridgeTable); Socket++) {
+
+      for (Stack = 0; Stack < NELEMENTS(mPciRootBridgeTable[Socket]); Stack++) {
+
+        if (mPciRootBridgeTable[Socket][Stack] == RootBridgePtr) {
+          if (SocketPtr != NULL) {
+            *SocketPtr = Socket;
+          }
+          if (StackPtr != NULL) {
+            *StackPtr = Stack;
+          }
+          return EFI_SUCCESS;
+        }
+      }
+    }
+  }
+  return EFI_NOT_FOUND;
+}
+
+/**
+  Determine the last stack for a given socket
+
+  @param  Socket the socket for which the last socket is desired
+
+  @return the number of the last socket
+*/
+UINT8
+LastStackOfSocket (
+  UINT8 Socket
+  )
+{
+  UINT8   LastStack;
+  BOOLEAN FoundEnabledStack;
+  UINT8   Stack;
+
+  ASSERT (Socket < ARRAY_SIZE(mIioUds->IioUdsPtr->PlatformData.IIO_resource));
+  ASSERT (mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].Valid);
+
+  FoundEnabledStack = FALSE;
+  LastStack = 0;
+
+  for (Stack = 0; Stack < MAX_IIO_STACK; Stack++) {
+    if (mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap & (1 << Stack)) {
+      LastStack = Stack;
+      FoundEnabledStack = TRUE;
+    }
+  }
+
+  ASSERT (FoundEnabledStack);
+  return LastStack;
+}
+
+
+/**
+  Determine the last stack for a given socket with resources
+
+  @param SocketResources   - CPU_RESOURCE structure pointer that stores all resources need per stack
+  @param Socket            - Index of the Socket
+  @param ResourceType      - Type of resource that requires alignment
+  @param LastStack         - Pointer that will store the value of the last stack with resources allocated to it
+  @param ResourceSize      - Pointer that will store the sum of the requested resource type
+
+  @return The last stack with resources allocated to it and the
+          total amount of resoures requested of the type
+          requested.
+*/
+VOID
+LastStackWithResources (
+  IN CPU_RESOURCE       *SocketResources,
+  IN UINT8              Socket,
+  IN PCI_RESOURCE_TYPE  ResourceType,
+  OUT UINT8             *LastStack,
+  OUT UINT64            *ResourceSize
+  )
+{
+  UINT8   Stack;
+
+  *LastStack    = 0;
+  *ResourceSize = 0;
+
+  for (Stack = 0; Stack < MAX_IIO_STACK; Stack++) {
+    if (!(mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap & (1 << Stack))) {
+      continue;
+    }
+
+    switch (ResourceType) {
+      case TypeIo:
+        if (SocketResources->StackRes[Stack].NumIoPortsDesired != 0) {
+          *ResourceSize += SocketResources->StackRes[Stack].NumIoPortsDesired + 1;
+          *LastStack = Stack;
+        }
+        break;
+      case TypeMem32:
+        if (SocketResources->StackRes[Stack].MmiolLength != 0) {
+          *ResourceSize += SocketResources->StackRes[Stack].MmiolLength + 1;
+          *LastStack = Stack;
+        }
+        break;
+      case TypeMem64:
+        if (SocketResources->StackRes[Stack].MmiohLength != 0) {
+          *ResourceSize += SocketResources->StackRes[Stack].MmiohLength + 1;
+          *LastStack = Stack;
+        }
+        break;
+      default:
+        break;
+    }
+  }
+}
+
+
+/**
+  Visit all stacks in this socket and recalculate the resource ranges per stack based on resource
+  needs from PCI/PCIe device/functions.
+
+  @param SocketResources   -  CPU_RESOURCE structure pointer that stores all resources need per stack
+  @param Socket            -  Index of the Socket
+  @param ResourceType      -  type of resource that requires alignment
+
+  @retval EFI_SUCCESS            -  Succeed.
+  @retval EFI_OUT_OF_RESOURCES   -  Not enough resources to be adjusted within the socket.
+**/
+EFI_STATUS
+AdjustResources (
+  CPU_RESOURCE *SocketResources,
+  UINT8         Socket,
+  UINT8         ResourceType
+  )
+{
+  UINT8       Stack;
+  UINT64      NewLength;
+  CONST UINT8 LastStack = LastStackOfSocket (Socket);
+  UINT64      PreviousLimit;
+  BOOLEAN     FirstStack = TRUE;
+
+  switch (ResourceType) {
+    case TypeIo:
+      // Return if IoResourceNeeds is not zero which indicates a socket adjustment is needed
+      if(SocketResources->IoResourceNeeds != 0){
+          return EFI_OUT_OF_RESOURCES;
+      }
+
+      for (Stack = 0; Stack < MAX_IIO_STACK; Stack++) {
+
+        if (!(mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap & (1 << Stack))){
+          continue;
+        }
+        //
+        // For the first enabled stack, use the base I/O address for the socket, otherwise
+        // calculate the new base based off the last enabled stack
+        //
+        if (FirstStack) {
+          // stackPresentBitmap doesn't cover if a valid stack was disable due to resource adjustments.
+          // Start with valid resources for current socket
+          SocketResources->StackRes[Stack].IoBase = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].PciResourceIoBase;
+          FirstStack = FALSE;
+        } else {
+          // Check to see if the previous stack is disabled by checking for equal base and limit
+          if (SocketResources->StackRes[Stack-1].IoBase == SocketResources->StackRes[Stack-1].IoLimit) {
+            if (PreviousLimit % 2 == 1) {
+              PreviousLimit += 1;
+            }
+            SocketResources->StackRes[Stack].IoBase = (UINT16) PreviousLimit;
+          } else {
+            SocketResources->StackRes[Stack].IoBase = (UINT16) PreviousLimit + 1;
+          }
+        }
+
+        NewLength = SocketResources->StackRes[Stack].NumIoPortsDesired;
+
+        //
+        //assign the left space to the last IIO stack. Reserved for across socket resource adjustment.
+        //make adjustments if NewLength is zero
+        //
+        if (Stack == LastStack) {
+          if (NewLength != 0) {
+            if (SocketResources->IoResourcesLeft != 0) {
+              NewLength += SocketResources->IoResourcesLeft + 1;
+            }
+          } else {
+            NewLength = SocketResources->IoResourcesLeft;
+          }
+        }
+
+        SocketResources->StackRes[Stack].NeedIoUpdate = TRUE;
+        SocketResources->StackRes[Stack].IoLimit = (UINT16)(SocketResources->StackRes[Stack].IoBase + NewLength);
+        PreviousLimit = SocketResources->StackRes[Stack].IoLimit;
+        DEBUG((DEBUG_INFO, "SocketResources[%x].StackRes[%x].IoBase =%x   newLength = %x\n",Socket,Stack,SocketResources->StackRes[Stack].IoBase,NewLength));
+        DEBUG((DEBUG_INFO, "SocketResources[%x].StackRes[%x].IoLimit =%x\n",Socket,Stack,SocketResources->StackRes[Stack].IoLimit));
+      }
+      break;
+
+    case TypeMem32:
+      //
+      // Return if MmiolResourceNeeds is not zero which indicates a socket adjustment is needed
+      //
+        if (SocketResources->MmiolResourceNeeds != 0) {
+          return EFI_OUT_OF_RESOURCES;
+        }
+        //
+        // Visit all Stacks in this Socket and recalculate the New Mem32 Ranges per Stack
+        //
+        for (Stack = 0; Stack < MAX_IIO_STACK; Stack++){
+
+          if (!(mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap & (1 << Stack))) {
+            continue;
+          }
+          //
+          // For the first enabled stack, use the base low mmio address for the socket, otherwize
+          // calculate the new base based off the last enabled stack
+          //
+          if (FirstStack) {
+            // stackPresentBitmap doesn't cover if a valid stack was disable due to resource adjustments.
+            // Start with valid resources for current socket
+            SocketResources->StackRes[Stack].MmiolBase = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].Mmio32Base;
+            FirstStack = FALSE;
+          } else {
+            // Check to see if the previous stack is disabled by checking for equal base and limit
+            if (SocketResources->StackRes[Stack-1].MmiolBase == SocketResources->StackRes[Stack-1].MmiolLimit) {
+              if (PreviousLimit % 2 == 1) {
+                PreviousLimit += 1;
+              }
+              SocketResources->StackRes[Stack].MmiolBase = (UINT32) PreviousLimit;
+            } else {
+              SocketResources->StackRes[Stack].MmiolBase = (UINT32) PreviousLimit + 1;
+            }
+          }
+          //
+          // Verify if this Stack is the one that requires an update and calculate the new Limit
+          // otherwise assign the new limit based on the Chunk and Extra Chunk calculation and assign the Newlength
+          //
+          NewLength =  SocketResources->StackRes[Stack].MmiolLength;
+          //
+          //assign the left space to the last IIO stack. Reserved for across socket resource adjustment.
+          //make adjustments if NewLength is zero
+          //
+          if (Stack == LastStack) {
+            if (NewLength != 0) {
+              if (SocketResources->MmiolResourcesLeft){
+                NewLength += SocketResources->MmiolResourcesLeft + 1;
+              }
+            } else {
+              NewLength = SocketResources->MmiolResourcesLeft;
+            }
+          }
+
+          SocketResources->StackRes[Stack].MmiolUpdate = 1;
+          SocketResources->StackRes[Stack].MmiolLimit =  (UINT32)(SocketResources->StackRes[Stack].MmiolBase + NewLength);
+          PreviousLimit = SocketResources->StackRes[Stack].MmiolLimit;
+          DEBUG((DEBUG_INFO, "SocketResources[%x].StackRes[%x].MmiolBase =%x   newLength = %x\n",Socket,Stack,SocketResources->StackRes[Stack].MmiolBase,NewLength));
+          DEBUG((DEBUG_INFO, "SocketResources[%x].StackRes[%x].MmiolLimit =%x\n",Socket,Stack,SocketResources->StackRes[Stack].MmiolLimit));
+        }
+      break;
+
+    case TypeMem64:
+      // Return if MmiohResourceNeeds is not zero which indicates a socket adjustment is needed
+      if (SocketResources->MmiohResourceNeeds != 0){
+        return EFI_OUT_OF_RESOURCES;
+      }
+      //
+      // Visit all Stacks in this Socket and recalculate the New Mem64 Ranges per Stack
+      //
+      for (Stack = 0; Stack < MAX_IIO_STACK; Stack++) {
+
+        if(!(mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap & (1 << Stack))){
+          continue;
+        }
+        //
+        // For the first enabled stack, use the base high mmio address for the socket, otherwise
+        // calculate the new base based off the last enabled stack
+        //
+        if (FirstStack) {
+          // stackPresentBitmap doesn't cover if a valid stack was disable due to resource adjustments.
+          // Start with valid resources for current socket
+          SocketResources->StackRes[Stack].MmiohBase = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].Mmio64Base;
+          FirstStack = FALSE;
+        } else {
+           // Check to see if the previous stack is disabled by checking for equal base and limit
+          if (SocketResources->StackRes[Stack-1].MmiohBase == SocketResources->StackRes[Stack-1].MmiohLimit) {
+            if (PreviousLimit % 2 == 1) {
+              PreviousLimit += 1;
+            }
+            SocketResources->StackRes[Stack].MmiohBase = PreviousLimit;
+          } else {
+            SocketResources->StackRes[Stack].MmiohBase = PreviousLimit + 1;
+          }
+        }
+
+        //
+        // Verify if this Stack is the one that requires an update and calculate the new Limit
+        // otherwise assign the new limit based on the Chunk and Extra Chunk calculation and assign the Newlength
+        //
+
+        NewLength =  SocketResources->StackRes[Stack].MmiohLength;
+
+        //
+        //assign the left space to the last IIO stack. Reserved for across socket resource adjustment.
+        //make adjustments if NewLength is zero
+        //
+        if (Stack == LastStack) {
+          if (NewLength != 0) {
+            if (SocketResources->MmiohResourcesLeft) {
+              NewLength += SocketResources->MmiohResourcesLeft + 1;
+            }
+          } else {
+              NewLength = SocketResources->MmiohResourcesLeft;
+          }
+        }
+
+        SocketResources->StackRes[Stack].MmiohUpdate = 1;
+        SocketResources->StackRes[Stack].MmiohLimit =  (SocketResources->StackRes[Stack].MmiohBase + NewLength);
+        PreviousLimit = SocketResources->StackRes[Stack].MmiohLimit;
+        DEBUG((DEBUG_INFO, "SocketResources[%x].StackRes[%x].MmiohBase =%lx   newLength = %lx\n",Socket,Stack,SocketResources->StackRes[Stack].MmiohBase,NewLength));
+        DEBUG((DEBUG_INFO, "SocketResources[%x].StackRes[%x].MmiohLimit =%lx\n",Socket,Stack,SocketResources->StackRes[Stack].MmiohLimit));
+
+      } // for Stack
+      break;
+    default:
+        DEBUG((DEBUG_ERROR, "[PCI] ERROR: Resource Type Unknown = %x\n", ResourceType));
+      break;
+  }// switch
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Adjust resource ratio assignment among sockets to fit the resource needs from PCI devices.
+
+  @param SocketResources   -  CPU_RESOURCE structure pointer that stores all resources need per socket
+  @param ResourceType      -  type of resource that requires alignment
+  @param ValidSockets       -  Number of Valid Sockets, need it to calculate how resources need to be splitted
+
+  @retval EFI_SUCCESS            -  Succeed.
+  @retval EFI_OUT_OF_RESOURCES   -  Not enough resources to be adjusted within the socket.
+**/
+EFI_STATUS
+AdjustSocketResources (
+  CPU_RESOURCE *SocketResources,
+  UINT8         ResourceType,
+  UINT8         ValidSockets
+  )
+{
+  EFI_STATUS    Status;
+
+  switch(ResourceType){
+    case TypeIo:
+      Status = AdjustSocketIo (SocketResources, ResourceType, ValidSockets);
+      break;
+    case TypeMem32:
+      Status = AdjustSocketMmioL (SocketResources, ResourceType, ValidSockets);
+      break;
+    case TypeMem64:
+      Status = AdjustSocketMmioH (SocketResources, ResourceType, ValidSockets);
+      break;
+    default:
+      DEBUG((DEBUG_ERROR, "ERROR: Resource Type Unknown = %x\n",ResourceType));
+      Status = EFI_INVALID_PARAMETER;
+      break;
+  } // switch
+
+  return Status;
+}
+
+
+/**
+  Calculate current system resource map with retrieved NVRAM variable to see if stored settings were applied
+
+  @param[in] SocketPciResourceData - Pointer to stored CPU resource map
+
+  @retval TRUE   - SYSTEM_PCI_BASE_LIMITS has been rejected and was not applied or not initialized
+  @retval FALSE  - SYSTEM_PCI_BASE_LIMITS has been applied and still has relevant data
+**/
+BOOLEAN
+IsResourceMapRejected (
+  SYSTEM_PCI_BASE_LIMITS *SocketPciResourceData
+  )
+{
+  UINT8                  Socket;
+  UINT8                  Stack;
+  BOOLEAN                Rejected = FALSE;
+  PCI_BASE_LIMITS        *StackLimits;
+  PCI_BASE_LIMITS        *UboxStackLimits;
+  PCI_BASE_LIMITS        *SocketLimits;
+  STACK_RES              *IioUdsUboxStackLimits;
+  STACK_RES              *IioUdsStackLimits;
+  IIO_RESOURCE_INSTANCE  *IioUdsSocketLimits;
+
+  if (SocketPciResourceData == NULL) {
+    return TRUE;
+  }
+  for (Socket = 0; Socket < MAX_SOCKET; Socket++) {
+
+    if (mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].Valid) {
+
+      IioUdsSocketLimits = &mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket];
+      SocketLimits = &SocketPciResourceData->Socket[Socket].SocketLimits;
+      IioUdsUboxStackLimits = &mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[UBOX_STACK];
+      UboxStackLimits = &SocketPciResourceData->Socket[Socket].StackLimits[UBOX_STACK];
+
+      for (Stack = 0; Stack < MAX_IIO_STACK; Stack++) {
+
+        if (mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap & (1 << Stack)) {
+
+          IioUdsStackLimits = &mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack];
+          StackLimits = &SocketPciResourceData->Socket[Socket].StackLimits[Stack];
+          //
+          // Per stack
+          //
+          if (Socket == 0 && Stack == 0) {
+            // First base starts at zero, mIioUds struct reserves 4K of Io for legacy purposes
+            if (StackLimits->Io.Base != 0) {
+              Rejected = TRUE;
+            }
+          } else {
+            if (IioUdsStackLimits->PciResourceIoBase != StackLimits->Io.Base && StackLimits->Io.Base != 0) {
+              Rejected = TRUE;
+            }
+          }
+          if (IioUdsStackLimits->PciResourceIoLimit != StackLimits->Io.Limit && StackLimits->Io.Limit != 0) {
+            Rejected = TRUE;
+          }
+          PCIDEBUG ("[%d.%d] Current I/O: 0x%04X..0x%04X\n", Socket, Stack,
+                    IioUdsStackLimits->PciResourceIoBase, IioUdsStackLimits->PciResourceIoLimit);
+          PCIDEBUG ("[%d.%d]   Saved I/O: 0x%04X..0x%04X %a\n", Socket, Stack,
+                   StackLimits->Io.Base, StackLimits->Io.Limit, Rejected ? "rejected" : "");
+
+          if (IioUdsStackLimits->Mmio32Base != StackLimits->LowMmio.Base && StackLimits->LowMmio.Base != 0) {
+            Rejected = TRUE;
+          }
+          if (IioUdsStackLimits->Mmio32Limit != StackLimits->LowMmio.Limit && StackLimits->LowMmio.Limit != 0) {
+            Rejected = TRUE;
+          }
+          PCIDEBUG ("[%d.%d] Current MMIOL: 0x%08X..0x%08X\n", Socket, Stack,
+                    IioUdsStackLimits->Mmio32Base, IioUdsStackLimits->Mmio32Limit);
+          PCIDEBUG ("[%d.%d]   Saved MMIOL: 0x%08X..0x%08X %a\n", Socket, Stack,
+                    StackLimits->LowMmio.Base, StackLimits->LowMmio.Limit, Rejected ? "rejected" : "");
+
+          if (IioUdsStackLimits->Mmio64Base != StackLimits->HighMmio.Base && StackLimits->HighMmio.Base != 0) {
+            Rejected = TRUE;
+          }
+          if (IioUdsStackLimits->Mmio64Limit != StackLimits->HighMmio.Limit && StackLimits->HighMmio.Limit != 0) {
+            Rejected = TRUE;
+          }
+          PCIDEBUG ("[%d.%d] Current MMIOH: 0x%012llX..0x%012llX\n", Socket, Stack,
+                    IioUdsStackLimits->Mmio64Base, IioUdsStackLimits->Mmio64Limit);
+          PCIDEBUG ("[%d.%d]   Saved MMIOH: 0x%012llX..0x%012llX %a\n", Socket, Stack,
+                    StackLimits->HighMmio.Base, StackLimits->HighMmio.Limit, Rejected ? "rejected" : "");
+        }
+      }
+      //
+      // Per socket
+      //
+      if (IioUdsSocketLimits->PciResourceIoBase != SocketLimits->Io.Base && SocketLimits->Io.Base != 0) {
+        Rejected = TRUE;
+      }
+      if (IioUdsSocketLimits->PciResourceIoLimit != SocketLimits->Io.Limit && SocketLimits->Io.Limit != 0) {
+        Rejected = TRUE;
+      }
+      PCIDEBUG("[%d] Current I/O: 0x%04X..0x%04X\n", Socket,
+               IioUdsSocketLimits->PciResourceIoBase, IioUdsSocketLimits->PciResourceIoLimit);
+      PCIDEBUG("[%d]   Saved I/O: 0x%04X..0x%04X %a\n", Socket,
+               SocketLimits->Io.Base, SocketLimits->Io.Limit, Rejected ? "rejected" : "");
+
+      if (IioUdsSocketLimits->Mmio32Base != SocketLimits->LowMmio.Base && SocketLimits->LowMmio.Base != 0) {
+        Rejected = TRUE;
+      }
+      if (IioUdsSocketLimits->Mmio32Limit != SocketLimits->LowMmio.Limit && SocketLimits->LowMmio.Limit != 0) {
+        Rejected = TRUE;
+      }
+      PCIDEBUG ("[%d] Current MMIOL: 0x%08X..0x%08X\n", Socket,
+               IioUdsSocketLimits->Mmio32Base, IioUdsSocketLimits->Mmio32Limit);
+      PCIDEBUG ("[%d]   Saved MMIOL: 0x%08X..0x%08X %a\n", Socket,
+                SocketLimits->LowMmio.Base, SocketLimits->LowMmio.Limit, Rejected ? "rejected" : "");
+
+      if (IioUdsSocketLimits->Mmio64Base != SocketLimits->HighMmio.Base && SocketLimits->HighMmio.Base != 0) {
+        Rejected = TRUE;
+      }
+      if (IioUdsSocketLimits->Mmio64Limit != SocketLimits->HighMmio.Limit && SocketLimits->HighMmio.Limit != 0) {
+        Rejected = TRUE;
+      }
+      PCIDEBUG ("[%d] Current MMIOH: 0x%012llX..0x%012llX\n", Socket,
+               IioUdsSocketLimits->Mmio64Base, IioUdsSocketLimits->Mmio64Limit);
+      PCIDEBUG ("[%d]   Saved MMIOH: 0x%012llX..0x%012llX %a\n", Socket,
+                SocketLimits->HighMmio.Base, SocketLimits->HighMmio.Limit, Rejected ? "rejected" : "");
+
+      if (IioUdsUboxStackLimits->Mmio64Base != UboxStackLimits->HighMmio.Base && UboxStackLimits->HighMmio.Base != 0) {
+        Rejected = TRUE;
+      }
+      if (IioUdsUboxStackLimits->Mmio64Limit != UboxStackLimits->HighMmio.Limit && UboxStackLimits->HighMmio.Limit != 0) {
+        Rejected = TRUE;
+      }
+      PCIDEBUG ("[%d] Current UBOX: 0x%08X..0x%08X\n", Socket,
+                IioUdsUboxStackLimits->Mmio64Base, IioUdsUboxStackLimits->Mmio64Limit);
+      PCIDEBUG ("[%d]   Saved UBOX: 0x%08X..0x%08X %a\n", Socket,
+                UboxStackLimits->HighMmio.Base, UboxStackLimits->HighMmio.Limit, Rejected ? "rejected" : "");
+    }
+  }
+  DEBUG ((DEBUG_INFO, "[PCI] Resource rebalance rejected ? %a\n", Rejected ? "TRUE" : "FALSE"));
+  return Rejected;
+}
+
+
+/**
+ Read SYSTEM_PCI_RESOURCE_CONFIGURATION_DATA_NAME variable from flash and verify its content.
+
+ If the variable does not exist, or is not valid for current system configuration
+ the buffer at *PciResConfigPtr is just cleared.
+
+ @param[out] PciResConfigPtr - Buffer for the resource configuration variable.
+
+ @retval EFI_SUCCESS            The function completed successfully.
+ @retval EFI_NOT_FOUND          The variable was not found.
+ @retval EFI_DEVICE_ERROR       The variable could not be retrieved due to a hardware error.
+ @retval EFI_SECURITY_VIOLATION The variable could not be retrieved due to an authentication failure.
+**/
+EFI_STATUS
+PciHostReadResourceConfig (
+  OUT SYSTEM_PCI_BASE_LIMITS *PciResConfigPtr
+  )
+{
+  UINTN                       VarSize;
+  EFI_STATUS                  Status;
+  UINT8                       Socket;
+
+  VarSize = sizeof(*PciResConfigPtr);
+  Status = gRT->GetVariable (SYSTEM_PCI_RESOURCE_CONFIGURATION_DATA_NAME, &gEfiSocketPciResourceDataGuid,
+                             NULL, &VarSize, PciResConfigPtr);
+  if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {
+    goto ErrExit;
+  }
+  if (Status == EFI_BUFFER_TOO_SMALL || VarSize != sizeof(*PciResConfigPtr)) {
+
+    PCIDEBUG ("Got variable '%s' of unexpected size %d (expect %d) - overwrite\n",
+              SYSTEM_PCI_RESOURCE_CONFIGURATION_DATA_NAME, VarSize, sizeof(*PciResConfigPtr));
+    Status = EFI_NOT_FOUND;
+    goto ErrExit;
+  }
+  //
+  // If any of the below checks fails clear the buffer and return EFI_NOT_FOUND.
+  //
+  Status = EFI_NOT_FOUND;
+  if (PciResConfigPtr->MmioHBase != mIioUds->IioUdsPtr->PlatformData.PlatGlobalMmio64Base ||
+      PciResConfigPtr->MmioHLimit != mIioUds->IioUdsPtr->PlatformData.PlatGlobalMmio64Limit) {
+
+    PCIDEBUG ("%s: Memory map changed (MMIOH %012llX..%012llX != %012llX..%012llX) - overwrite\n",
+              SYSTEM_PCI_RESOURCE_CONFIGURATION_DATA_NAME,
+              PciResConfigPtr->MmioHBase, PciResConfigPtr->MmioHLimit,
+              mIioUds->IioUdsPtr->PlatformData.PlatGlobalMmio64Base,
+              mIioUds->IioUdsPtr->PlatformData.PlatGlobalMmio64Limit);
+    goto ErrExit;
+  }
+  if (PciResConfigPtr->MmioLBase != mIioUds->IioUdsPtr->PlatformData.PlatGlobalMmio32Base ||
+      PciResConfigPtr->MmioLLimit != mIioUds->IioUdsPtr->PlatformData.PlatGlobalMmio32Limit) {
+
+    PCIDEBUG ("%s: Memory map changed (MMIOL %08X..%08X != %08X..%08X) - overwrite\n",
+              SYSTEM_PCI_RESOURCE_CONFIGURATION_DATA_NAME,
+              PciResConfigPtr->MmioLBase, PciResConfigPtr->MmioLLimit,
+              mIioUds->IioUdsPtr->PlatformData.PlatGlobalMmio32Base,
+              mIioUds->IioUdsPtr->PlatformData.PlatGlobalMmio32Limit);
+    goto ErrExit;
+  }
+  if (PciResConfigPtr->IoBase != mIioUds->IioUdsPtr->PlatformData.PlatGlobalIoBase ||
+      PciResConfigPtr->IoLimit != mIioUds->IioUdsPtr->PlatformData.PlatGlobalIoLimit) {
+
+    PCIDEBUG ("%s: Memory map changed (I/O %04X..%04X != %04X..%04X) - overwrite\n",
+              SYSTEM_PCI_RESOURCE_CONFIGURATION_DATA_NAME,
+              PciResConfigPtr->IoBase, PciResConfigPtr->IoLimit,
+              mIioUds->IioUdsPtr->PlatformData.PlatGlobalIoBase,
+              mIioUds->IioUdsPtr->PlatformData.PlatGlobalIoLimit);
+    goto ErrExit;
+  }
+  for (Socket = 0; Socket < NELEMENTS (PciResConfigPtr->Socket); Socket++) {
+
+    if (PciResConfigPtr->StackPresentBitmap[Socket] !=
+                                              mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap) {
+
+      PCIDEBUG ("%s: Stack bitmap mismach (%04X != %04X) in socket %d - overwrite\n",
+                SYSTEM_PCI_RESOURCE_CONFIGURATION_DATA_NAME, PciResConfigPtr->StackPresentBitmap[Socket],
+                mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap, Socket);
+      goto ErrExit;
+    }
+  }
+  return EFI_SUCCESS;
+
+ ErrExit:
+  ZeroMem (PciResConfigPtr, sizeof(*PciResConfigPtr));
+  return Status;
+} // PciHostReadResourceConfig()
+
+
+/**
+  Adjust resource ratio assignment among CPU sockets to fit the resource needs from PCI devices.
+  Update Setup variable if there are changes from the existing ratio requests for this boot.
+
+  @param[in]  HostBridgeInstance    -  The Host Bridge Instance where the resource adjustment happens.
+  @param[out] Result                -  Output parameter. Indicates whether changes have been made.
+**/
+VOID
+AdjustResourceAmongRootBridges (
+  IN  PCI_HOST_BRIDGE_INSTANCE          *HostBridgeInstance,
+  OUT SOCKET_RESOURCE_ADJUSTMENT_RESULT *Result
+  )
+{
+  PCI_ROOT_BRIDGE_INSTANCE               *RootBridgeInstance;
+  LIST_ENTRY                             *List;
+  CPU_RESOURCE                           SocketResources[MAX_SOCKET];
+  UINT64                                 SocketIoLength;
+  UINT64                                 SocketMem32Length;
+  UINT64                                 SocketMem64Length;
+  UINT64                                 SocketIoBase;
+  UINT64                                 SocketMem32Base;
+  UINT64                                 SocketMem64Base;
+  UINT64                                 RsvLenAtBegin;
+  UINT64                                 RsvLenAtEnd;
+  UINT64                                 StackLength;
+  UINT64                                 NewLength;
+  UINT64                                 Alignment;
+  UINT64                                 Remainder;
+  UINT8                                  Socket;
+  UINT8                                  ValidSockets;
+  BOOLEAN                                ChangedType[TypeMax];
+  BOOLEAN                                ChangedTypeOOR[TypeMax]; // Change type for out of resources
+  UINT8                                  TypeIndex;
+  UINT8                                  ChangedBitMap;
+  EFI_STATUS                             Status;
+  SYSTEM_PCI_BASE_LIMITS                 SocketPciResourceData;
+  UINT8                                  Stack;
+  UINT8                                  LastStack;
+  UINT16                                 IoGranularity;
+  UINT32                                 MmiolGranularity;
+  UINT64                                 MmiohGranularity;
+  BOOLEAN                                OutOfResources;
+  UINT32                                 UboxMmioSize;
+  BOOLEAN                                IsVirtualRootBridge;
+  PCI_BASE_LIMITS                        *CurStackLimits;
+  PCI_BASE_LIMITS                        *UboxStackLimits;
+  PCI_BASE_LIMITS                        *CurSocketLimits;
+  UINT32                                 PlatGlobalMmiolBase;
+  UINT32                                 VtdBarSize;
+
+  *Result = SocketResourceRatioNotChanged;
+  SetMem (ChangedType, TypeMax, FALSE);
+  SetMem (ChangedTypeOOR, TypeMax, FALSE);
+  ChangedBitMap = 0;
+  OutOfResources = FALSE;
+  IsVirtualRootBridge = FALSE;
+
+  IoGranularity = mIioUds->IioUdsPtr->PlatformData.IoGranularity;
+  MmiolGranularity = mIioUds->IioUdsPtr->PlatformData.MmiolGranularity;
+  MmiohGranularity = (UINT64) mIioUds->IioUdsPtr->PlatformData.MmiohGranularity.lo;
+  MmiohGranularity |= ((UINT64)mIioUds->IioUdsPtr->PlatformData.MmiohGranularity.hi) << 32;
+  ZeroMem (&SocketResources[0], sizeof(SocketResources));
+  //
+  // Read the system resource cfg from NVRAM. If the variable does not exist, or is
+  // not valid for current system configuration the buffer SocketPciResourceData
+  // is just cleared.
+  //
+  Status = PciHostReadResourceConfig (&SocketPciResourceData);
+  if (EFI_ERROR (Status)) {
+
+    if (Status != EFI_NOT_FOUND) {
+
+      ASSERT_EFI_ERROR (Status);
+      return;
+    }
+    //
+    // Variable is not initialized yet, go with empty structure.
+    //
+  } else if (IsResourceMapRejected (&SocketPciResourceData)) {
+    //
+    // If variable is already initialized, but rejected by KTI do not reboot to avoid loop.
+    //
+    return;
+  }
+
+  UboxMmioSize = mIioUds->IioUdsPtr->PlatformData.UboxMmioSize;
+  PlatGlobalMmiolBase = mIioUds->IioUdsPtr->PlatformData.PlatGlobalMmio32Base;
+  ValidSockets = 0;
+  for (List = HostBridgeInstance->RootBridges.ForwardLink, Socket = 0; Socket < MAX_SOCKET; Socket ++) {
+
+    if (!mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].Valid) {
+      continue;
+    }
+    ValidSockets++;
+    //
+    // Calculate the length of resources available per socket
+    //
+    if (mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].PciResourceIoBase >=
+        mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].PciResourceIoLimit) {
+      SocketIoBase = 0;
+      SocketIoLength = 0;
+    } else {
+      SocketIoBase = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].PciResourceIoBase;
+      SocketIoLength = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].PciResourceIoLimit -
+                       mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].PciResourceIoBase;
+    }
+    if (mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].Mmio32Base >=
+                                                   mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].Mmio32Limit) {
+      SocketMem32Base = 0;
+      SocketMem32Length = 0;
+    } else {
+      SocketMem32Base = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].Mmio32Base;
+      SocketMem32Length = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].Mmio32Limit  -
+                                                      mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].Mmio32Base;
+      // Reserve 8M for ubox mmio
+      SocketMem32Length = SocketMem32Length - UboxMmioSize;
+    }
+
+    if (mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].Mmio64Base >=
+                                                   mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].Mmio64Limit) {
+      SocketMem64Base = 0;
+      SocketMem64Length = 0;
+    } else{
+      SocketMem64Base = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].Mmio64Base;
+      SocketMem64Length = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].Mmio64Limit -
+                                                      mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].Mmio64Base;
+    }
+
+    // Get all the resources that are in this socket
+    SocketResources[Socket].IoResourcesLeft = (UINT16)SocketIoLength;
+    SocketResources[Socket].MmiolResourcesLeft = (UINT32)SocketMem32Length;
+    SocketResources[Socket].MmiohResourcesLeft = (UINT64)SocketMem64Length;
+
+    LastStack = LastStackOfSocket (Socket);
+
+    for (Stack = 0; Stack < MAX_IIO_STACK; Stack++) {
+      if (!(mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap & (1 << Stack))) {
+        continue;
+      }
+      RootBridgeInstance = ROOT_BRIDGE_FROM_LINK (List);
+      //
+      // Check IO Resource
+      //
+      Alignment = RootBridgeInstance->ResAllocNode[TypeIo].Alignment + 1;
+      NewLength = RootBridgeInstance->ResAllocNode[TypeIo].Length;
+
+      if (IsVirtualRootBridge) {
+        NewLength += NewLength;
+      }
+      // IoTrap allocates 256 byte range from GCD for common pool usage
+      // For device to fit move to the next available alignment
+      if ((Socket == 0) && (Stack == 0)) {
+        NewLength += Alignment;
+      }
+
+      if (NewLength != 0) {
+        //
+        // At least 2KB align per KTI requirement. Add the length requested with given alignment.
+        // If the sum is not 2KB aligned add on the remainder that would make it align.
+        // Bump up to 4KB for root bridge requirements
+        // Have to make sure Alignment is handled for direct address allocation
+        //
+        Remainder = SocketIoBase & (Alignment - 1);
+        if (Remainder != 0) {
+          NewLength += Alignment - Remainder;
+        }
+        if (NewLength % (IoGranularity * 2)) {
+          Remainder = (IoGranularity * 2) - (NewLength % (IoGranularity * 2));
+          NewLength += Remainder;
+        }
+        //
+        // Store length as length - 1 for handling
+        //
+        NewLength -= 1;
+
+        // Zero StackLength if its disable or negative
+        if (mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].PciResourceIoBase >=
+            mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].PciResourceIoLimit) {
+          StackLength = 0;
+        } else {
+          StackLength = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].PciResourceIoLimit -
+                        mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].PciResourceIoBase;
+        }
+        SocketResources[Socket].StackRes[Stack].NumIoPortsDesired = (UINT16)NewLength;
+        // Check if new length can fit in the socket or stack
+        if (SocketResources[Socket].IoResourcesLeft > (UINT16)NewLength) {
+            SocketResources[Socket].IoResourcesLeft -=  (UINT16)NewLength + 1;
+        } else if (SocketResources[Socket].IoResourcesLeft == (UINT16)NewLength) {
+            SocketResources[Socket].IoResourcesLeft -=  (UINT16)NewLength;
+        } else {
+          // If there are resources left consume them
+          if (SocketResources[Socket].IoResourcesLeft != 0) {
+            NewLength = NewLength - SocketResources[Socket].IoResourcesLeft - 1;
+            SocketResources[Socket].IoResourcesLeft =  0;
+          }
+
+          SocketResources[Socket].IoResourceNeeds += (UINT16)NewLength + 1;
+          OutOfResources = TRUE;
+          ChangedTypeOOR[TypeIo] = TRUE;
+        }
+        SocketResources[Socket].StackRes[Stack].IoAlignment = Alignment;
+        if (NewLength > StackLength) {
+          SocketResources[Socket].StackRes[Stack].NeedIoUpdate = TRUE;
+
+          //IoResourcesLeft is UINT16 type, not 2's-complement value.
+          if (SocketResources[Socket].IoResourcesLeft > SocketIoLength) {
+            DEBUG ((DEBUG_ERROR, "[PCI] Out of Resources for Socket = %x  Stack = %x Type = %x\n",
+                   Socket, Stack, TypeIo));
+            SocketResources[Socket].IoResourcesLeft = 0;
+          }
+          ChangedType[TypeIo] = TRUE;
+        }
+        SocketIoBase += SocketResources[Socket].StackRes[Stack].NumIoPortsDesired + 1;
+        DEBUG ((DEBUG_INFO, "SocketResources[%x].IoResourceLeft = %x\n",
+               Socket, SocketResources[Socket].IoResourcesLeft));
+        DEBUG ((DEBUG_INFO, "SocketResources[%x].StackRes[%x].IoAlignment = %x\n",
+               Socket, Stack, SocketResources[Socket].StackRes[Stack].IoAlignment));
+      } else {
+        SocketResources[Socket].StackRes[Stack].NumIoPortsDesired = 0;
+      }
+      //
+      // Check Mmem32 resource. This Host bridge does not support separated MEM / PMEM requests,
+      // so only count MEM requests here.
+      //
+      Alignment = RootBridgeInstance->ResAllocNode[TypeMem32].Alignment + 1;
+      NewLength = RootBridgeInstance->ResAllocNode[TypeMem32].Length;
+      //
+      // Account for reserved regions at begin and end of the stack MMIO32 region.
+      //
+      RsvLenAtBegin = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].PciResourceMem32Base -
+                                      mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].Mmio32Base;
+
+      RsvLenAtEnd = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].Mmio32Limit -
+                           mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].PciResourceMem32Limit;
+      NewLength += RsvLenAtBegin + RsvLenAtEnd;
+      if (Alignment < RsvLenAtBegin) {
+        Alignment = RsvLenAtBegin;
+      }
+      if (Alignment < RsvLenAtEnd) {
+        Alignment = RsvLenAtEnd;
+      }
+      //
+      // Always account for VT-d reserved resource ranges.
+      // TODO: Remove when VTd BAR is included in RsvLenAtEnd.
+      //
+      if (mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].VtdBarAddress != 0) {
+
+        VtdBarSize = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].PciResourceMem32Limit -
+                     mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].VtdBarAddress + 1;
+        NewLength += VtdBarSize;
+        if (Alignment < VtdBarSize) {
+          Alignment = VtdBarSize;
+        }
+      }
+
+      if (IsVirtualRootBridge) {
+        NewLength += NewLength;
+      }
+      // PCH Allocates reserved MMIO for Sx SMI handler use
+      // For device to fit move to the next available alignment
+      if ((Socket == 0) && (Stack == 0)) {
+        NewLength += Alignment;
+      }
+
+      if (NewLength != 0) {
+        //
+        // At least 4MB align per KTI requirement. Add the length requested with given alignment.
+        // If the sum is not 4MB aligned add on the remainder that would make it align.
+        // Have to make sure Alignment is handled for direct address allocation
+        //
+        Remainder = SocketMem32Base & (Alignment - 1);
+        if (Remainder != 0) {
+          NewLength += Alignment - Remainder;
+        }
+        if (NewLength % MmiolGranularity) {
+
+          Remainder = MmiolGranularity - (NewLength % MmiolGranularity);
+          NewLength += Remainder;
+        }
+
+        if (Stack == LastStack) {
+          //
+          // Ubox address must be 8MB aligned for the base address on most processors; skip check
+          // if uboxMmioSize is 0 (avoid divide by zero exception).
+          // At this point the requested resource has already been calculated to be satisfied.
+          // Add granularity padding if necessary to satisfy Ubox requirement.
+          //
+          if (UboxMmioSize != 0 && (SocketMem32Base + NewLength) % UboxMmioSize) {
+            Remainder = UboxMmioSize - (NewLength % UboxMmioSize);
+            NewLength += Remainder;
+          }
+        }
+        //
+        // Store length as length - 1 for handling
+        //
+        NewLength -= 1;
+
+        // Zero StackLength if its disable or negative
+        if (mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].Mmio32Base >=
+                                   mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].Mmio32Limit) {
+          StackLength = 0;
+        } else {
+          StackLength = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].Mmio32Limit -
+                                      mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].Mmio32Base;
+        }
+        SocketResources[Socket].StackRes[Stack].MmiolLength = (UINT32)NewLength;
+
+        // Check if new length can fit in the socket or stack
+        if (SocketResources[Socket].MmiolResourcesLeft > (UINT32)NewLength) {
+            SocketResources[Socket].MmiolResourcesLeft -=  (UINT32)NewLength + 1;
+        } else if (SocketResources[Socket].MmiolResourcesLeft == (UINT32)NewLength) {
+            SocketResources[Socket].MmiolResourcesLeft -=  (UINT32)NewLength;
+        } else {
+            // If there are resources left consume them
+            if (SocketResources[Socket].MmiolResourcesLeft) {
+                NewLength = NewLength - SocketResources[Socket].MmiolResourcesLeft - 1;
+                SocketResources[Socket].MmiolResourcesLeft =  0;
+            }
+
+            SocketResources[Socket].MmiolResourceNeeds += (UINT32)NewLength + 1;
+            OutOfResources = TRUE;
+            ChangedTypeOOR[TypeMem32] = TRUE;
+        }
+        SocketResources[Socket].StackRes[Stack].MmiolAlignment = Alignment;
+
+        if (NewLength > StackLength) {
+          SocketResources[Socket].StackRes[Stack].MmiolUpdate = 1;
+
+          //MmiolResourcesLeft is UINT32 type, not 2's-complement value.
+          if (SocketResources[Socket].MmiolResourcesLeft > SocketMem32Length) {
+            DEBUG ((DEBUG_ERROR, "Out of Resources for Socket = %x  Stack = %x Type = %x\n",
+                   Socket, Stack, TypeMem32));
+            SocketResources[Socket].MmiolResourcesLeft = 0;
+          }
+          ChangedType[TypeMem32] = TRUE;
+        }
+        SocketMem32Base += SocketResources[Socket].StackRes[Stack].MmiolLength + 1;
+        DEBUG ((DEBUG_INFO, "SocketResources[%x].MmiolResourceLeft = %x\n",
+               Socket, SocketResources[Socket].MmiolResourcesLeft));
+        DEBUG ((DEBUG_INFO, "SocketResources[%x].StackRes[%x].MmiolAlignment = %x\n",
+               Socket, Stack, SocketResources[Socket].StackRes[Stack].MmiolAlignment));
+      } else {
+        SocketResources[Socket].StackRes[Stack].MmiolLength = 0;
+      }
+      //
+      // Check Mem64 resource. This Host bridge does not support separated MEM / PMEM requests, so only count MEM requests here.
+      //
+      Alignment = RootBridgeInstance->ResAllocNode[TypeMem64].Alignment + 1;
+      NewLength = RootBridgeInstance->ResAllocNode[TypeMem64].Length;
+      //
+      // Account for reserved regions at begin and end of the stack MMIO32 region.
+      //
+      RsvLenAtBegin = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].PciResourceMem64Base -
+                                      mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].Mmio64Base;
+
+      RsvLenAtEnd = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].Mmio64Limit -
+                           mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].PciResourceMem64Limit;
+      NewLength += RsvLenAtBegin + RsvLenAtEnd;
+      if (Alignment < RsvLenAtBegin) {
+        Alignment = RsvLenAtBegin;
+      }
+      if (Alignment < RsvLenAtEnd) {
+        Alignment = RsvLenAtEnd;
+      }
+      if (IsVirtualRootBridge) {
+        NewLength += NewLength;
+      }
+
+      if (NewLength != 0) {
+        //
+        // At least 1GB align per KTI requirement. Add the length requested with given alignment.
+        // If the sum is not 1GB aligned add on the remainder that would make it align.
+        // Have to make sure Alignment is handled for direct address allocation
+        //
+        Remainder = SocketMem64Base & (Alignment - 1);
+        if (Remainder != 0) {
+          NewLength += Alignment - Remainder;
+        }
+        if (NewLength % MmiohGranularity) {
+          Remainder = MmiohGranularity - (NewLength % MmiohGranularity);
+          NewLength += Remainder;
+        }
+        //
+        // Store length as length - 1 for handling
+        //
+        NewLength -= 1;
+
+        // Zero StackLength if it's disable or negative
+        if (mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].Mmio64Base >=
+                                   mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].Mmio64Limit) {
+          StackLength = 0;
+        } else {
+          StackLength = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].Mmio64Limit -
+                                      mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].Mmio64Base;
+        }
+        SocketResources[Socket].StackRes[Stack].MmiohLength = NewLength;
+
+        // Check if new length can fit in the socket or stack
+        if (SocketResources[Socket].MmiohResourcesLeft > NewLength) {
+          SocketResources[Socket].MmiohResourcesLeft -=  NewLength + 1;
+        } else if (SocketResources[Socket].MmiohResourcesLeft == NewLength) {
+          SocketResources[Socket].MmiohResourcesLeft -=  NewLength;
+        } else {
+          // If there are resources left consume them
+          if (SocketResources[Socket].MmiohResourcesLeft != 0) {
+            NewLength = NewLength - SocketResources[Socket].MmiohResourcesLeft - 1;
+            SocketResources[Socket].MmiohResourcesLeft =  0;
+          }
+
+          SocketResources[Socket].MmiohResourceNeeds += NewLength + 1;
+          OutOfResources = TRUE;
+          ChangedTypeOOR[TypeMem64] = TRUE;
+        }
+        SocketResources[Socket].StackRes[Stack].MmiohAlignment = Alignment;
+
+        if (NewLength > StackLength) {
+          SocketResources[Socket].StackRes[Stack].MmiohUpdate = 1;
+
+          //MmiohResourcesLeft is UINT64 type, not 2's-complement value.
+          if (SocketResources[Socket].MmiohResourcesLeft > SocketMem64Length) {
+            DEBUG ((DEBUG_ERROR, "Out of Resources for Socket = %x  Stack = %x Type = %x\n",
+                   Socket, Stack, TypeMem64));
+            SocketResources[Socket].MmiohResourcesLeft = 0;
+          }
+          ChangedType[TypeMem64] = TRUE;
+        }
+        SocketMem64Base += SocketResources[Socket].StackRes[Stack].MmiohLength + 1;
+        DEBUG ((DEBUG_INFO, "SocketResources[%x].MmiohResourceLeft = %lx\n",
+               Socket, SocketResources[Socket].MmiohResourcesLeft));
+        DEBUG ((DEBUG_INFO, "SocketResources[%x].StackRes[%x].MmiohAlignment = %lx\n",
+               Socket, Stack, SocketResources[Socket].StackRes[Stack].MmiohAlignment));
+      } else {
+        SocketResources[Socket].StackRes[Stack].MmiohLength = 0;
+      }
+
+      List = List->ForwardLink;
+
+    } // for Stack
+
+    // Check and update all resource types in socket that needs adjustment
+    for (TypeIndex = 0; TypeIndex < TypeMax; TypeIndex++) {
+
+      if (ChangedType[TypeIndex]) {
+
+        DEBUG ((DEBUG_INFO, "[%d] Adjust stack %s resources...\n", Socket, mPciResourceTypeStr[TypeIndex]));
+        Status = AdjustResources (&SocketResources[Socket], Socket, TypeIndex);
+        ChangedType[TypeIndex] = FALSE;
+        if (Status == EFI_SUCCESS) {
+          ChangedBitMap |= (1 << TypeIndex);
+        } else {
+          ChangedBitMap &= ~(1 << TypeIndex);
+        }
+      }
+    }
+    //
+    // Account for Ubox resources to accurately calculate new alignments for the next socket
+    //
+    SocketMem32Base += UboxMmioSize;
+  } // for Socket ..
+
+  ASSERT (List == &HostBridgeInstance->RootBridges);
+
+  //
+  // If a socket is out of resources, try to adjusting sockets for more room.
+  //
+  if (OutOfResources && (MAX_SOCKET > 1) && (ValidSockets > 1)) {
+
+    for (TypeIndex = 0; TypeIndex < TypeMax; TypeIndex++) {
+
+      if (ChangedTypeOOR[TypeIndex]) {
+
+        DEBUG ((DEBUG_INFO, "Adjust socket %s resources...\n", mPciResourceTypeStr[TypeIndex]));
+        Status = AdjustSocketResources (SocketResources, TypeIndex, ValidSockets);
+        if (Status == EFI_SUCCESS) {
+          ChangedBitMap |= (1 << TypeIndex);
+        } else {
+          ChangedBitMap &= ~(1 << TypeIndex);
+        }
+      }
+    }
+  } else if (OutOfResources && ChangedTypeOOR[TypeMem64]){
+    //
+    // Allow mmioh to be adjusted to access max available physical address range.
+    //
+    Status = AdjustSocketResources (SocketResources, TypeMem64, ValidSockets);
+    if (Status == EFI_SUCCESS) {
+      ChangedBitMap |= (1 << TypeIndex);
+    } else {
+      ChangedBitMap &= ~(1 << TypeIndex);
+    }
+  }
+
+  // Update changed resource type.
+  // OemGetResourceMapUpdate() will only update changed resource type so it is alright if data is zero.
+  if (ChangedBitMap != 0) {
+
+    for (Socket = 0; Socket < MAX_SOCKET; Socket++) {
+
+      SocketPciResourceData.StackPresentBitmap[Socket] = mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap;
+      for (Stack = 0; Stack < MAX_IIO_STACK; Stack++) {
+        if (!(mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap & (1 << Stack))) {
+          continue;
+        }
+        CurStackLimits = &SocketPciResourceData.Socket[Socket].StackLimits[Stack];
+
+        //
+        // Disable stacks that have no resources and are assigned none.
+        // Reaching this far means the stack is valid and should be disabled if base equals limit and
+        // length is zero.
+        // Assigned address will be none zero at this point because CSTACK takes the first 4K in legacy
+        // IO space.
+        //
+        if ((SocketResources[Socket].StackRes[Stack].NeedIoUpdate) &&
+            (SocketResources[Socket].StackRes[Stack].IoLimit -
+             SocketResources[Socket].StackRes[Stack].IoBase == 0)) {
+          SocketResources[Socket].StackRes[Stack].IoBase = (UINT16)(-1);
+          SocketResources[Socket].StackRes[Stack].IoLimit = 0;
+        }
+
+        if ((SocketResources[Socket].StackRes[Stack].MmiolUpdate) &&
+            (SocketResources[Socket].StackRes[Stack].MmiolLimit -
+             SocketResources[Socket].StackRes[Stack].MmiolBase == 0)) {
+          SocketResources[Socket].StackRes[Stack].MmiolBase = (UINT32)(-1);
+          SocketResources[Socket].StackRes[Stack].MmiolLimit = 0;
+        }
+
+        if ((SocketResources[Socket].StackRes[Stack].MmiohUpdate) &&
+            (SocketResources[Socket].StackRes[Stack].MmiohLimit -
+             SocketResources[Socket].StackRes[Stack].MmiohBase == 0)) {
+          SocketResources[Socket].StackRes[Stack].MmiohBase = (UINT64)(-1);
+          SocketResources[Socket].StackRes[Stack].MmiohLimit = 0;
+        }
+
+        // Zero base if 4K because mIioUds struct reserves 4K of Io for legacy purposes
+        // Remove if mIioUds first base starts at zero
+        if (SocketResources[Socket].StackRes[Stack].IoBase == 0x1000){
+          SocketResources[Socket].StackRes[Stack].IoBase = 0;
+        }
+
+        if (SocketResources[Socket].StackRes[Stack].NeedIoUpdate) {
+          CurStackLimits->Io.Base = SocketResources[Socket].StackRes[Stack].IoBase;
+          CurStackLimits->Io.Limit = SocketResources[Socket].StackRes[Stack].IoLimit;
+        }
+
+        if (SocketResources[Socket].StackRes[Stack].MmiolUpdate) {
+          if ((Socket == 0) && (Stack == 0)) {
+            CurStackLimits->LowMmio.Base = PlatGlobalMmiolBase;
+          } else {
+            CurStackLimits->LowMmio.Base = SocketResources[Socket].StackRes[Stack].MmiolBase;
+          }
+          CurStackLimits->LowMmio.Limit = SocketResources[Socket].StackRes[Stack].MmiolLimit;
+        }
+
+        if (SocketResources[Socket].StackRes[Stack].MmiohUpdate) {
+          CurStackLimits->HighMmio.Base = SocketResources[Socket].StackRes[Stack].MmiohBase;
+          CurStackLimits->HighMmio.Limit = SocketResources[Socket].StackRes[Stack].MmiohLimit;
+        }
+
+        DEBUG((DEBUG_INFO, "\nSocketResources[%x].StackRes[%x].IoBase =%x\n",Socket,Stack,SocketResources[Socket].StackRes[Stack].IoBase));
+        DEBUG((DEBUG_INFO, "SocketResources[%x].StackRes[%x].IoLimit =%x\n",Socket,Stack,SocketResources[Socket].StackRes[Stack].IoLimit));
+        DEBUG((DEBUG_INFO, "SocketResources[%x].StackRes[%x].MmiolBase =%x\n",Socket,Stack,SocketResources[Socket].StackRes[Stack].MmiolBase));
+        DEBUG((DEBUG_INFO, "SocketResources[%x].StackRes[%x].MmiolLimit =%x\n",Socket,Stack,SocketResources[Socket].StackRes[Stack].MmiolLimit));
+        DEBUG((DEBUG_INFO, "SocketResources[%x].StackRes[%x].MmiohBase =%lx\n",Socket,Stack,SocketResources[Socket].StackRes[Stack].MmiohBase));
+        DEBUG((DEBUG_INFO, "SocketResources[%x].StackRes[%x].MmiohLimit =%lx\n",Socket,Stack,SocketResources[Socket].StackRes[Stack].MmiohLimit));
+      } // for Stack
+
+      // Initialize to disabled
+      SocketResources[Socket].IoBase = (UINT16)(-1);
+      SocketResources[Socket].IoLimit = 0;
+      SocketResources[Socket].MmiolBase = (UINT32)(-1);
+      SocketResources[Socket].MmiolLimit = 0;
+      SocketResources[Socket].MmiohBase = (UINT64)(-1);
+      SocketResources[Socket].MmiohLimit = 0;
+
+      // Search backwards to find the beginning valid stack
+      for (Stack = MAX_IIO_STACK - 1; Stack < MAX_IIO_STACK ; Stack--) {
+        CurSocketLimits = &SocketPciResourceData.Socket[Socket].SocketLimits;
+
+        if (!(mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap & (1 << Stack))) {
+          continue;
+        }
+
+        if (SocketResources[Socket].StackRes[Stack].IoBase != (UINT16)(-1)) {
+          SocketResources[Socket].IoBase = SocketResources[Socket].StackRes[Stack].IoBase;
+        }
+
+        if (SocketResources[Socket].StackRes[Stack].MmiolBase != (UINT32)(-1)) {
+          SocketResources[Socket].MmiolBase = SocketResources[Socket].StackRes[Stack].MmiolBase;
+        }
+
+        if (SocketResources[Socket].StackRes[Stack].MmiohBase != (UINT64)(-1)) {
+          SocketResources[Socket].MmiohBase = SocketResources[Socket].StackRes[Stack].MmiohBase;
+        }
+      } // for Stack
+
+      // Search to find the last valid limit
+      for (Stack = 0; Stack < MAX_IIO_STACK; Stack++) {
+        if (!(mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap & (1 << Stack))) {
+          continue;
+        }
+
+        if (SocketResources[Socket].StackRes[Stack].IoLimit != 0) {
+          SocketResources[Socket].IoLimit = SocketResources[Socket].StackRes[Stack].IoLimit;
+        }
+
+        if (SocketResources[Socket].StackRes[Stack].MmiolLimit) {
+          SocketResources[Socket].MmiolLimit = SocketResources[Socket].StackRes[Stack].MmiolLimit;
+        }
+
+        if (SocketResources[Socket].StackRes[Stack].MmiohLimit) {
+          SocketResources[Socket].MmiohLimit = SocketResources[Socket].StackRes[Stack].MmiohLimit;
+        }
+      } // for Stack
+
+      // Update socket level resource range
+      if (SocketResources[Socket].StackRes[0].NeedIoUpdate) {
+        CurSocketLimits->Io.Base = SocketResources[Socket].IoBase;
+        CurSocketLimits->Io.Limit = SocketResources[Socket].IoLimit;
+      }
+
+      if (SocketResources[Socket].StackRes[0].MmiolUpdate) {
+        //
+        // Apply stolen 8M for ubox mmio per socket
+        //
+        if (UboxMmioSize != 0) {
+          UboxStackLimits = &SocketPciResourceData.Socket[Socket].StackLimits[UBOX_STACK];
+
+          UboxStackLimits->LowMmio.Base = SocketResources[Socket].MmiolLimit + 1;
+          SocketResources[Socket].MmiolLimit = (UINT32)UboxStackLimits->LowMmio.Base + UboxMmioSize - 1;
+          UboxStackLimits->LowMmio.Limit = SocketResources[Socket].MmiolLimit;
+        }
+        CurSocketLimits->LowMmio.Base = SocketResources[Socket].MmiolBase;
+        CurSocketLimits->LowMmio.Limit = SocketResources[Socket].MmiolLimit;
+      }
+
+      if (SocketResources[Socket].StackRes[0].MmiohUpdate) {
+        CurSocketLimits->HighMmio.Base  = SocketResources[Socket].MmiohBase;
+        CurSocketLimits->HighMmio.Limit = SocketResources[Socket].MmiohLimit;
+      }
+
+      DEBUG((DEBUG_INFO, "\nSocketResources[%x].UboxBase =%x\n",Socket,UboxStackLimits->LowMmio.Base));
+      DEBUG((DEBUG_INFO, "SocketResources[%x].UboxLimit =%x\n",Socket,UboxStackLimits->LowMmio.Limit));
+      DEBUG((DEBUG_INFO, "\nSocketResources[%x].IoBase =%x\n",Socket,SocketResources[Socket].IoBase));
+      DEBUG((DEBUG_INFO, "SocketResources[%x].IoLimit =%x\n",Socket,SocketResources[Socket].IoLimit));
+      DEBUG((DEBUG_INFO, "SocketResources[%x].MmiolBase =%x\n",Socket,SocketResources[Socket].MmiolBase));
+      DEBUG((DEBUG_INFO, "SocketResources[%x].MmiolLimit =%x\n",Socket,SocketResources[Socket].MmiolLimit));
+      DEBUG((DEBUG_INFO, "SocketResources[%x].MmiohBase =%lx\n",Socket,SocketResources[Socket].MmiohBase));
+      DEBUG((DEBUG_INFO, "SocketResources[%x].MmiohLimit =%lx\n",Socket,SocketResources[Socket].MmiohLimit));
+    } // for Socket
+    SocketPciResourceData.MmioHBase = mIioUds->IioUdsPtr->PlatformData.PlatGlobalMmio64Base;
+    SocketPciResourceData.MmioHLimit = mIioUds->IioUdsPtr->PlatformData.PlatGlobalMmio64Limit;
+    SocketPciResourceData.MmioLBase = mIioUds->IioUdsPtr->PlatformData.PlatGlobalMmio32Base;
+    SocketPciResourceData.MmioLLimit = mIioUds->IioUdsPtr->PlatformData.PlatGlobalMmio32Limit;
+    SocketPciResourceData.IoBase = mIioUds->IioUdsPtr->PlatformData.PlatGlobalIoBase;
+    SocketPciResourceData.IoLimit = mIioUds->IioUdsPtr->PlatformData.PlatGlobalIoLimit;
+
+    PCIDEBUG("Writing resource rebalance request '%s':\n", SYSTEM_PCI_RESOURCE_CONFIGURATION_DATA_NAME);
+    PCIDEBUG("System I/O  : %04X..%04X\n", SocketPciResourceData.IoBase, SocketPciResourceData.IoLimit);
+    PCIDEBUG("System MMIOL: %08X..%08X\n", SocketPciResourceData.MmioLBase, SocketPciResourceData.MmioLLimit);
+    PCIDEBUG("System MMIOH: %012llX..%012llX\n", SocketPciResourceData.MmioHBase, SocketPciResourceData.MmioHLimit);
+    for (Socket = 0; Socket < NELEMENTS (SocketPciResourceData.Socket); Socket++) {
+
+      PCIDEBUG("[%d] StackPresent: 0x%04X\n", Socket, SocketPciResourceData.StackPresentBitmap[Socket]);
+      PCIDEBUG("[%d] I/O  : %04X..%04X\n", Socket,
+               SocketPciResourceData.Socket[Socket].SocketLimits.Io.Base,
+               SocketPciResourceData.Socket[Socket].SocketLimits.Io.Limit);
+      PCIDEBUG("[%d] MMIOL: %08X..%08X\n", Socket,
+               SocketPciResourceData.Socket[Socket].SocketLimits.LowMmio.Base,
+               SocketPciResourceData.Socket[Socket].SocketLimits.LowMmio.Limit);
+      PCIDEBUG("[%d] MMIOH: %012llX..%012llX\n", Socket,
+               SocketPciResourceData.Socket[Socket].SocketLimits.HighMmio.Base,
+               SocketPciResourceData.Socket[Socket].SocketLimits.HighMmio.Limit);
+      for (Stack = 0; Stack <  NELEMENTS (SocketPciResourceData.Socket[Socket].StackLimits); Stack++) {
+
+        PCIDEBUG("[%d.%d] I/O  : %04X..%04X\n", Socket, Stack,
+                 SocketPciResourceData.Socket[Socket].StackLimits[Stack].Io.Base,
+                 SocketPciResourceData.Socket[Socket].StackLimits[Stack].Io.Limit);
+        PCIDEBUG("[%d.%d] MMIOL: %08X..%08X\n", Socket, Stack,
+                 SocketPciResourceData.Socket[Socket].StackLimits[Stack].LowMmio.Base,
+                 SocketPciResourceData.Socket[Socket].StackLimits[Stack].LowMmio.Limit);
+        PCIDEBUG("[%d.%d] MMIOH: %012llX..%012llX\n", Socket, Stack,
+                 SocketPciResourceData.Socket[Socket].StackLimits[Stack].HighMmio.Base,
+                 SocketPciResourceData.Socket[Socket].StackLimits[Stack].HighMmio.Limit);
+      }
+    }
+
+    *Result = SocketResourceRatioChanged;
+    Status = gRT->SetVariable(
+              SYSTEM_PCI_RESOURCE_CONFIGURATION_DATA_NAME,
+              &gEfiSocketPciResourceDataGuid,
+              EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+              sizeof(SocketPciResourceData),
+              &SocketPciResourceData
+            );
+    ASSERT_EFI_ERROR(Status);
+  }
+
+  return;
+}
+
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciRebalance.h b/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciRebalance.h
new file mode 100644
index 0000000000..85a9192c12
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciRebalance.h
@@ -0,0 +1,158 @@
+/** @file
+
+  @copyright
+  Copyright 2019 - 2021 Intel Corporation. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PCIREBALANCE_H_
+#define _PCIREBALANCE_H_
+
+/******************************************************************************
+ * Definitions.
+ ******************************************************************************/
+/**
+  Uncomment the PCIDEBUG macro to enable tracing the library activity in a test build.
+ **/
+#define PCIDEBUG(...) // { DEBUG((DEBUG_INFO, "[PCI] " __VA_ARGS__)); }
+
+typedef enum {
+  SocketResourceRatioChanged,
+  SocketResourceRatioNotChanged,
+  SocketResourceAdjustMax
+} SOCKET_RESOURCE_ADJUSTMENT_RESULT;
+
+typedef struct {
+  UINT16        IoBase;       // IO base of each stack
+  UINT16        IoLimit;      // IO limit for each stack
+  UINT16        NumIoPortsDesired;
+  UINT64        IoAlignment;
+  BOOLEAN       NeedIoUpdate; // Resource allocation required.
+  UINT32        MmiolBase;    // Mmiol base of each stack
+  UINT32        MmiolLimit;   // Mmiol limit of each stack
+  UINT32        MmiolLength;
+  UINT64        MmiolAlignment;
+  UINT8         MmiolUpdate;  // Resource allocation required.
+  UINT64        MmiohBase;    // Mmioh base of each stack
+  UINT64        MmiohLimit;   // Mmioh limit of each stack
+  UINT64        MmiohLength;
+  UINT64        MmiohAlignment;
+  UINT8         MmiohUpdate;  // Resource allocation required.
+} STACK_RESOURCE;
+
+typedef struct{
+  UINT16      IoBase;              // Io base of each socket
+  UINT16      IoLimit;             // Io limit for each socket
+  UINT16      IoResourcesLeft;     // Io resources left over in socket
+  UINT16      IoResourceNeeds;     // Io resources lacking in socket
+  UINT32      MmiolBase;           // Mmiol base of each socket
+  UINT32      MmiolLimit;          // Mmiol limit of each socket
+  UINT32      MmiolResourcesLeft;  // Mmiol resources left over in socket
+  UINT32      MmiolResourceNeeds;  // Mmiol resources lacking in socket
+  UINT64      MmiohBase;           // Mmioh base of each socket
+  UINT64      MmiohLimit;          // Mmioh limit of each socket
+  UINT64      MmiohResourcesLeft;  // Mmioh resources left over in socket
+  UINT64      MmiohResourceNeeds;  // Mmioh resources lacking in socket
+  STACK_RESOURCE  StackRes[MAX_LOGIC_IIO_STACK];
+} CPU_RESOURCE;
+
+
+/******************************************************************************
+ * Function prototypes.
+ ******************************************************************************/
+extern PCI_ROOT_BRIDGE_INSTANCE *mPciRootBridgeTable[MAX_SOCKET][MAX_LOGIC_IIO_STACK];
+extern PCI_ROOT_BRIDGE_INSTANCE *mPciRootBridgeTableReserved[MAX_SOCKET][IIO_RESERVED_1];
+
+
+/******************************************************************************
+ * Function prototypes.
+ ******************************************************************************/
+
+/**
+  Adjust resource ratio assignment among CPU sockets to fit the resource needs from PCI devices.
+  Update Setup variable if there are changes from the existing ratio requests for this boot.
+
+  @param HostBridgeInstance    -  The Host Bridge Instance where the resource adjustment happens.
+  @param Result                -  Output parameter. Indicates whether changes have been made.
+**/
+VOID
+AdjustResourceAmongRootBridges (
+  IN  PCI_HOST_BRIDGE_INSTANCE          *HostBridgeInstance,
+  OUT SOCKET_RESOURCE_ADJUSTMENT_RESULT *Result
+  );
+
+EFI_STATUS
+AdjustSocketIo (
+  IN OUT CPU_RESOURCE *SocketResources,
+  IN     UINT8         ResourceType,
+  IN     UINT8         ValidSockets
+  );
+
+EFI_STATUS
+AdjustSocketMmioH (
+  IN OUT CPU_RESOURCE *SocketResources,
+  IN     UINT8         ResourceType,
+  IN     UINT8         ValidSockets
+  );
+
+EFI_STATUS
+AdjustSocketMmioL (
+  IN OUT CPU_RESOURCE *SocketResources,
+  IN     UINT8         ResourceType,
+  IN     UINT8         ValidSockets
+  );
+
+/**
+  Determine the last stack for a given socket
+
+  @param  Socket the socket for which the last socket is desired
+
+  @return The number of the last stack is returned.
+*/
+UINT8
+LastStackOfSocket (
+  IN UINT8 Socket
+  );
+
+/**
+  Determine the last stack for a given socket with resources
+
+  @param SocketResources   - CPU_RESOURCE structure pointer that stores all resources need per stack
+  @param Socket            - Index of the Socket
+  @param ResourceType      - Type of resource that requires alignment
+  @param LastStack         - Pointer that will store the value of the last stack with resources allocated to it
+  @param ResourceSize      - Pointer that will store the sum of the requested resource type
+
+  @return The last stack with resources allocated to it and the
+          total amount of resoures requested of the type
+          requested.
+*/
+VOID
+LastStackWithResources (
+  IN     CPU_RESOURCE      *SocketResources,
+  IN     UINT8              Socket,
+  IN     PCI_RESOURCE_TYPE  ResourceType,
+     OUT UINT8             *LastStack,
+     OUT UINT64            *ResourceSize
+  );
+
+/**
+ Find socket and stack index for given PCI Root Bridge protocol pointer.
+
+ @param[out] PciResConfigPtr - Buffer for the resource configuration variable.
+
+ @retval EFI_SUCCESS            The function completed successfully.
+ @retval EFI_NOT_FOUND          The variable was not found.
+ @retval EFI_DEVICE_ERROR       The variable could not be retrieved due to a hardware error.
+ @retval EFI_SECURITY_VIOLATION The variable could not be retrieved due to an authentication failure.
+**/
+EFI_STATUS
+PciRootBridge2SocketStack (
+  IN     PCI_ROOT_BRIDGE_INSTANCE *RootBridgePtr,
+     OUT UINT8                    *SocketPtr,
+     OUT UINT8                    *StackPtr
+  );
+
+#endif // _PCIREBALANCE_H_
+
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciRebalanceIo.c b/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciRebalanceIo.c
new file mode 100644
index 0000000000..cc0fd2b562
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciRebalanceIo.c
@@ -0,0 +1,218 @@
+/** @file
+
+  @copyright
+  Copyright 1999 - 2021 Intel Corporation. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Guid/SocketPciResourceData.h>
+#include <Guid/SocketIioVariable.h>
+#include <Protocol/IioUds.h>
+
+#include "PciHostBridge.h"
+#include "PciRootBridge.h"
+#include "PciRebalance.h"
+
+
+extern EFI_IIO_UDS_PROTOCOL *mIioUds;
+
+/**
+  Return TRUE if the specified socket/stack combination exists,
+  otherwise return FALSE
+
+  @param Socket - the socket to be checked
+  @param Stack - the stack of the socket to be checked
+
+  @retval TRUE - the socket/stack combination exists
+  @retval FALSE - the socket/stack combination does not exist
+*/
+STATIC BOOLEAN
+IsStackPresent (
+  UINT8 Socket,
+  UINT8 Stack
+  )
+{
+  BOOLEAN Result;
+  UINT64 Mask;
+
+  ASSERT (Socket < ARRAY_SIZE (mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo));  // simple overrun check
+  if (Socket >= ARRAY_SIZE (mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo)) {
+    Result = FALSE;
+    goto err_exit;
+  }
+
+  //
+  // if the StackPresentBitmap is a single byte, then we can track 8 stacks,
+  // the sizeof will tell us how many bytes we have, we scale by 8 to
+  // determine the maximum number of stacks we can track.  Stacks larger
+  // than this are not present essentially by definition, but could also
+  // be a sign that we need a wider type to store the information; hence we
+  // assert
+  //
+  ASSERT (Stack < 8 * sizeof(mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[0].stackPresentBitmap));
+  if (Stack >= 8 * sizeof(mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[0].stackPresentBitmap)) {
+    Result = FALSE;
+    goto err_exit;
+  }
+
+  Mask = 1;
+  Mask <<= Stack;
+  Result = (Mask & mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap) != 0;
+
+err_exit:
+  return Result;
+}
+
+
+/**
+  Adjust resource assignment among sockets to fit the IO
+  resources from the PCI() devices in the system
+
+  @param SocketResources   -  CPU_RESOURCE structure pointer that stores all resources need per socket
+  @param ResourceType      -  type of resource that requires alignment
+  @param ValidSockets       -  Number of Valid Sockets, need it
+                            to calculate how resources need to
+                            be split
+
+  @retval EFI_SUCCESS            -  Succeed.
+  @retval EFI_OUT_OF_RESOURCES   -  Not enough resources to be adjusted within the socket.
+**/
+EFI_STATUS
+AdjustSocketIo (
+  CPU_RESOURCE *SocketResources,
+  UINT8         ResourceType,
+  UINT8         ValidSockets
+)
+{
+  UINT64 Base;                                    ///< Next base I/O port number to use
+  UINT64 Limit;                                   ///< Most recent limit for I/O port numbers
+  CONST UINT64 MaxLimit = ((UINT64)1 << 16) - 1;  ///< Maximum value for limit; used to ensure we don't overflow
+  CPU_RESOURCE *CurSocketResources;               ///< Pointer to the CPU_RESOURE structure for the CPU we
+                                                  ///< are examining
+  STACK_RESOURCE *CurStackResources;              ///< Pointer to the STACK_RESOURCE structure for the CPU/Stack
+                                                  ///< we are examining
+  UINT16 NumFreePorts;                            ///< Number of i/o ports allocated to sockets that are not used
+  UINT8 LastStack;                                ///< Last enabled stack of the last enabled socket
+  CONST UINT8 LastSocketIndex = ValidSockets - 1; ///< Index of the last socket
+  UINT64 TotalResourceSize;
+  UINT64 ResourceSize;
+  UINT8 Socket;                                   ///< Loop variable used to iterate over the sockets
+  UINT8 Stack;                                    ///< Loop variable used to iterate over the stacks of a given socket
+
+  NumFreePorts = 0;
+  for (Socket = 0; Socket < ValidSockets; Socket++)  {
+    CurSocketResources = &SocketResources[Socket];
+    if (CurSocketResources->IoResourceNeeds == 0 && CurSocketResources->IoResourcesLeft != 0) {
+      ASSERT (NumFreePorts < NumFreePorts + CurSocketResources->IoResourcesLeft + 1); // check for overflow
+      NumFreePorts += CurSocketResources->IoResourcesLeft + 1;
+      CurSocketResources->IoResourcesLeft = 0;
+    }
+  }
+
+  for (Socket = 0; Socket < ValidSockets; Socket++) {
+    CurSocketResources = &SocketResources[Socket];
+    if (CurSocketResources->IoResourceNeeds != 0 && NumFreePorts >= CurSocketResources->IoResourceNeeds) {
+      ASSERT (NumFreePorts > NumFreePorts - CurSocketResources->IoResourceNeeds); // check for underflow
+      NumFreePorts -= CurSocketResources->IoResourceNeeds;
+      CurSocketResources->IoResourceNeeds = 0;
+    }
+  }
+
+  LastStack = LastStackOfSocket (LastSocketIndex);
+
+  if (NumFreePorts > 0) {
+    CurStackResources = &SocketResources[LastSocketIndex].StackRes[LastStack];
+    if (CurStackResources->NumIoPortsDesired != 0) {
+      CurStackResources->NumIoPortsDesired += NumFreePorts;
+    } else {
+      CurStackResources->NumIoPortsDesired += NumFreePorts - 1;
+    }
+  }
+
+  //
+  // Verify all resource requested can fit into the systems address range.
+  //
+  TotalResourceSize = 0;
+  for (Socket = 0; Socket < ValidSockets; Socket ++) {
+    LastStackWithResources (&SocketResources[Socket], Socket, ResourceType, &LastStack, &ResourceSize);
+    TotalResourceSize += ResourceSize;
+  }
+  DEBUG ((DEBUG_INFO, "Total Request IO Range = %xh\n", TotalResourceSize));
+  DEBUG ((DEBUG_INFO, "Total System IO Range  = %xh\n", MaxLimit));
+  if (TotalResourceSize > MaxLimit) {
+    //
+    // Not enough system resources to support the request.
+    // Remove all request to update NVRAM variable for this resource type.
+    //
+    for (Socket = 0; Socket < ValidSockets; Socket ++) {
+      for (Stack = 0; Stack < MAX_IIO_STACK; Stack ++) {
+        if (!(mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap & (1 << Stack))) {
+          continue;
+        }
+        SocketResources[Socket].StackRes[Stack].NeedIoUpdate = 0;
+      }
+    }
+    DEBUG ((DEBUG_ERROR, "ERROR: Out of adjustable IO resources. Can't adjust across sockets\n"));
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  DEBUG((DEBUG_ERROR, "Assigning new socket i/o range...\n"));
+
+  Base = mIioUds->IioUdsPtr->PlatformData.IIO_resource[0].PciResourceIoBase;
+  Limit = Base;   // assume no resources are allocated
+  for (Socket = 0, CurSocketResources = SocketResources; Socket < ValidSockets; Socket++, CurSocketResources++) {
+    DEBUG ((DEBUG_INFO, "socket = %d, Base = %x, Limit =%x, MaxLimit = %x\n", Socket, Base, Limit, MaxLimit));
+    ASSERT (Base < MaxLimit);
+    CurSocketResources->IoBase = (UINT16)Base;
+    DEBUG ((DEBUG_INFO, "set socket io base to %x\n", Base));
+
+    for (Stack = 0, CurStackResources = CurSocketResources->StackRes;
+         Stack < MAX_IIO_STACK;
+         Stack++, CurStackResources++) {
+      if (!IsStackPresent (Socket, Stack)) {
+        DEBUG ((DEBUG_INFO, "  Stack %d not present, setting base/limit to 0xffff/0\n", Stack));
+        CurStackResources->IoBase = 0xffff;
+        CurStackResources->IoLimit = 0;
+        continue;
+      }
+
+      if (CurStackResources->NumIoPortsDesired == 0) {
+        DEBUG ((DEBUG_INFO, "  Stack %d doesn't need i/o resources, setting base/limit to 0xffff/0\n", Stack));
+        CurStackResources->IoBase = 0xffff;
+        CurStackResources->IoLimit = 0;
+        CurStackResources->NeedIoUpdate = TRUE;
+        continue;
+      }
+
+      DEBUG((DEBUG_INFO, "  Stack %d setting i/o base to %x, ports desired was %x\n",
+        Stack, Base, CurStackResources->NumIoPortsDesired));
+      ASSERT (Base < MaxLimit);
+      CurStackResources->IoBase = (UINT16)Base;
+      Limit = Base + CurStackResources->NumIoPortsDesired;
+      DEBUG ((DEBUG_INFO, "    limit set to %x (var and stack)\n", Limit));
+      ASSERT (Base <= Limit);
+      ASSERT (Limit <= MaxLimit);
+      CurStackResources->IoLimit = (UINT16)Limit;
+      CurStackResources->NeedIoUpdate = TRUE;
+      Base = Limit + 1;
+      DEBUG ((DEBUG_INFO, "    Base variable updated to %x\n", Base));
+    }
+    ASSERT (Limit <= MaxLimit);
+    DEBUG ((DEBUG_INFO, "  Socket %d limit set to %x\n", Socket, Limit));
+    CurSocketResources->IoLimit = (UINT16)Limit;
+  }
+
+  DEBUG ((DEBUG_INFO, "Dumping new I/O requests\n"));
+  for (Socket = 0, CurSocketResources = SocketResources; Socket < ValidSockets; Socket++, CurSocketResources++) {
+    DEBUG((DEBUG_INFO, "socket %d %x/%x\n", Socket, CurSocketResources->IoBase, CurSocketResources->IoLimit));
+    for (Stack = 0, CurStackResources = CurSocketResources->StackRes;
+         Stack < MAX_IIO_STACK;
+         Stack++, CurStackResources++) {
+      DEBUG ((DEBUG_INFO, "%d/%d: %x/%x\n", Socket, Stack, CurStackResources->IoBase, CurStackResources->IoLimit));
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciRebalanceMmio32.c b/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciRebalanceMmio32.c
new file mode 100644
index 0000000000..41975dee6f
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciRebalanceMmio32.c
@@ -0,0 +1,163 @@
+/** @file
+
+  @copyright
+  Copyright 1999 - 2021 Intel Corporation. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Guid/SocketPciResourceData.h>
+#include <Guid/SocketIioVariable.h>
+#include <Protocol/IioUds.h>
+
+#include "PciHostBridge.h"
+#include "PciRootBridge.h"
+#include "PciRebalance.h"
+
+extern EFI_IIO_UDS_PROTOCOL *mIioUds;
+
+
+/**
+  Adjust resource assignments among sockets to fit the low
+  MMIO resources (32-bit addresses) from the PCI(e) devices in the system
+
+  @param[in,out] SocketResources - CPU_RESOURCE structure pointer that stores all resources need per socket
+  @param[in]     ResourceType    - Type of resource that requires alignment
+  @param[in]     ValidSockets    - Number of Valid Sockets, need it to calculate how resources need to be splitted
+
+  @retval EFI_SUCCESS            -  Succeed.
+  @retval EFI_OUT_OF_RESOURCES   -  Not enough resources to be adjusted within the socket.
+ */
+EFI_STATUS
+AdjustSocketMmioL (
+  IN OUT CPU_RESOURCE *SocketResources,
+  IN     UINT8         ResourceType,
+  IN     UINT8         ValidSockets
+  )
+{
+  CONST UINT8 LastSocket = ValidSockets - 1;
+  UINT8       Socket;
+  UINT8       Stack;
+  UINT8       LastStack;
+  UINT64      Take;
+  UINT32      UboxMmioSize;
+  UINT64      ResourceSize;
+  UINT64      TotalResourceSize;
+  UINT32      TempMmioBase;
+  UINT32      TempMmioLimit;
+
+  Take = 0;
+  UboxMmioSize = mIioUds->IioUdsPtr->PlatformData.UboxMmioSize;
+  //
+  // Get first and last MMIOL address
+  //
+  TempMmioBase  = mIioUds->IioUdsPtr->PlatformData.PlatGlobalMmio32Base;
+  TempMmioLimit = mIioUds->IioUdsPtr->PlatformData.PlatGlobalMmio32Limit;
+  //
+  // Find all the extra space left
+  //
+  for (Socket = 0; Socket < ValidSockets; Socket++) {
+    if ((SocketResources[Socket].MmiolResourceNeeds == 0) && (SocketResources[Socket].MmiolResourcesLeft != 0)) {
+
+      Take += SocketResources[Socket].MmiolResourcesLeft + 1;
+      SocketResources[Socket].MmiolResourcesLeft = 0;
+    }
+  }
+  //
+  // Give space to sockets that needs more space favoring first come first served
+  //
+  for (Socket = 0; Socket < ValidSockets; Socket++) {
+    if ((SocketResources[Socket].MmiolResourceNeeds != 0) && (Take >= SocketResources[Socket].MmiolResourceNeeds)) {
+
+      Take -= SocketResources[Socket].MmiolResourceNeeds;
+      DEBUG((DEBUG_ERROR, "SocketResources[%x].MmiolResourceNeeds = %x\n", Socket, SocketResources[Socket].MmiolResourceNeeds));
+      SocketResources[Socket].MmiolResourceNeeds = 0;
+    }
+  }
+  //
+  // Give away leftover resources
+  //
+  LastStack = LastStackOfSocket (LastSocket);
+  if (Take != 0) {
+    if (SocketResources[LastSocket].StackRes[LastStack].MmiolLength != 0) {
+      SocketResources[LastSocket].StackRes[LastStack].MmiolLength += (UINT32)Take;
+    } else{
+      SocketResources[LastSocket].StackRes[LastStack].MmiolLength += ((UINT32)Take - 1);
+    }
+  }
+  //
+  // Verify all resource requested can fit into the systems address range.
+  //
+  TotalResourceSize = 0;
+  for (Socket = 0; Socket < ValidSockets; Socket++) {
+    LastStackWithResources (&SocketResources[Socket], Socket, ResourceType, &LastStack, &ResourceSize);
+    TotalResourceSize += ResourceSize + UboxMmioSize;
+  }
+  DEBUG ((DEBUG_INFO, "Total Request MMIOL Range = %08Xh\n", TotalResourceSize));
+  DEBUG ((DEBUG_INFO, "Total System MMIOL Range  = %08Xh\n", (TempMmioLimit - TempMmioBase + 1)));
+  if (TotalResourceSize > (TempMmioLimit - TempMmioBase + 1)) {
+    //
+    // Not enough system resources to support the request.
+    // Remove all request to update NVRAM variable for this resource type.
+    //
+    for (Socket = 0; Socket < ValidSockets; Socket ++) {
+      for (Stack = 0; Stack < MAX_IIO_STACK; Stack ++) {
+        if (!(mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap & (1 << Stack))) {
+          continue;
+        }
+        SocketResources[Socket].StackRes[Stack].MmiolUpdate = 0;
+      }
+    }
+    DEBUG ((DEBUG_ERROR, "[PCI] ERROR: Out of adjustable MMIOL resources. Can't adjust across sockets\n"));
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  DEBUG ((DEBUG_ERROR, "Assigning new socket MMIOL range...\n"));
+  for (Socket = 0, TempMmioLimit = TempMmioBase - 1; Socket < ValidSockets; Socket ++) {
+
+    SocketResources[Socket].MmiolBase = TempMmioLimit + 1;
+    //
+    // Update the stacks base and limit values.
+    //
+    for (Stack = 0; Stack < MAX_IIO_STACK; Stack++) {
+
+      if (!(mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap & (1 << Stack))) {
+
+        SocketResources[Socket].StackRes[Stack].MmiolBase = 0;
+        SocketResources[Socket].StackRes[Stack].MmiolLimit = 0;
+
+      } else {
+
+        SocketResources[Socket].StackRes[Stack].MmiolBase = TempMmioLimit + 1;
+        if (SocketResources[Socket].StackRes[Stack].MmiolLength != 0) {
+          //
+          // MmiolLength is actually length-1, so we should move TempMmioLimit by MmiolLength+1,
+          // but only when it is >0, i.e. only for stack that has resources.
+          //
+          TempMmioLimit += SocketResources[Socket].StackRes[Stack].MmiolLength + 1;
+          SocketResources[Socket].StackRes[Stack].MmiolLimit = TempMmioLimit;
+
+        } else {
+
+          SocketResources[Socket].StackRes[Stack].MmiolLimit = SocketResources[Socket].StackRes[Stack].MmiolBase;
+        }
+        SocketResources[Socket].StackRes[Stack].MmiolUpdate = 1;
+      }
+      DEBUG ((DEBUG_ERROR, "SocketResources[%x].StackRes[%x].MmiolBase  = %X  newLength = %x\n", Socket, Stack,
+              SocketResources[Socket].StackRes[Stack].MmiolBase, SocketResources[Socket].StackRes[Stack].MmiolLength));
+      DEBUG ((DEBUG_ERROR, "SocketResources[%x].StackRes[%x].MmiolLimit = %X\n", Socket, Stack,
+              SocketResources[Socket].StackRes[Stack].MmiolLimit));
+      DEBUG ((DEBUG_ERROR, "SocketResources[%x].StackRes[%x].MmiolUpdate= %d\n", Socket, Stack,
+              SocketResources[Socket].StackRes[Stack].MmiolUpdate));
+    } // for (Stack...)
+    //
+    // In the socket resources there can be UBOX, unfortunatelly not exposed in stackPresentBitmap
+    // so it has to be handled with such uguly hacks.
+    //
+    TempMmioLimit += UboxMmioSize;
+    SocketResources[Socket].MmiolLimit = TempMmioLimit;
+  } // for (Socket...)
+
+  return EFI_SUCCESS;
+}
+
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciRebalanceMmio64.c b/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciRebalanceMmio64.c
new file mode 100644
index 0000000000..0101904285
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciRebalanceMmio64.c
@@ -0,0 +1,204 @@
+/** @file
+
+  @copyright
+  Copyright 1999 - 2021 Intel Corporation. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Guid/SocketPciResourceData.h>
+#include <Guid/SocketIioVariable.h>
+#include <Protocol/IioUds.h>
+
+#include "PciHostBridge.h"
+#include "PciRootBridge.h"
+#include "PciRebalance.h"
+
+
+extern EFI_IIO_UDS_PROTOCOL *mIioUds;
+
+
+/**
+  Adjust resource assignments among sockets to fit the high
+  MMIO resources (64-bit addresses, typically above 4GB) from
+  the PCI(e) devices in the system
+
+  @param[in,out] SocketResources - CPU_RESOURCE structure pointer that stores all resources need per socket
+  @param[in]     ResourceType    - Type of resource that requires alignment
+  @param[in]     ValidSockets    - Number of Valid Sockets, need it to calculate how resources need to be splitted
+
+  @retval EFI_SUCCESS            -  Succeed.
+  @retval EFI_OUT_OF_RESOURCES   -  Not enough resources to be adjusted within the socket.
+ */
+EFI_STATUS
+AdjustSocketMmioH (
+  IN OUT CPU_RESOURCE *SocketResources,
+  IN     UINT8         ResourceType,
+  IN     UINT8         ValidSockets
+  )
+{
+  CONST UINT8 LastSocket = ValidSockets - 1;
+  UINT8       Socket;
+  UINT8       Stack;
+  UINT8       LastStack;
+  UINT64      Take;
+  UINT32      UboxMmioSize;
+  UINT64      UnAllocatedMmioh;
+  UINT64      MaxMmioh;
+  UINT64      ResourceSize;
+  UINT64      TotalResourceSize;
+  UINT64      TempMmioBase;
+  UINT64      TempMmioLimit;
+
+  Take = 0;
+  UboxMmioSize = mIioUds->IioUdsPtr->PlatformData.UboxMmioSize;
+  UnAllocatedMmioh = 0;
+  //
+  // Get first and last IO base address
+  //
+  TempMmioBase  = mIioUds->IioUdsPtr->PlatformData.PlatGlobalMmio64Base;
+  TempMmioLimit = mIioUds->IioUdsPtr->PlatformData.PlatGlobalMmio64Limit;
+
+  // Find all the extra space left
+  for (Socket = 0; Socket < ValidSockets; Socket ++) {
+    if ((SocketResources[Socket].MmiohResourceNeeds == 0) && (SocketResources[Socket].MmiohResourcesLeft != 0)) {
+
+      Take += SocketResources[Socket].MmiohResourcesLeft + 1;
+      SocketResources[Socket].MmiohResourcesLeft = 0;
+    }
+  }
+
+  MaxMmioh = (UINT64) mIioUds->IioUdsPtr->PlatformData.MmiohGranularity.lo;
+  MaxMmioh |= ((UINT64) mIioUds->IioUdsPtr->PlatformData.MmiohGranularity.hi) << 32;
+  //
+  // Maximum chunk accessible in the system based on the given granularity
+  //
+  if (UboxMmioSize == 0) {
+    MaxMmioh = MaxMmioh * 32; //for 14nm
+  } else {
+    MaxMmioh = ((UINT64) 1 << mIioUds->IioUdsPtr->PlatformData.MaxAddressBits);
+  }
+
+  //
+  // Find out how much MMIOH has not been allocated
+  //
+  if (MaxMmioh > (TempMmioLimit - TempMmioBase)) {
+    UnAllocatedMmioh = MaxMmioh - (TempMmioLimit - TempMmioBase) - 1;
+  } else {
+    //
+    // Extra MMIOH is not enough to close the gap for a successful adjustment.
+    // Use all extra MMIOH in case if only a small amount is needed for adjustment or
+    // the granularity was reduced due to MMIOH base.
+    // (14nm only) or remove if map is rejected for this case to start over with correct values.
+    // (10nm only) does not have this problem and doesn't need the code below because the limit is removed and we can use max address lines.
+    //
+    Take += MaxMmioh;
+  }
+
+  // Give space to sockets that needs more space favoring first come first served
+  for (Socket = 0; Socket < ValidSockets; Socket ++) {
+    if ((SocketResources[Socket].MmiohResourceNeeds != 0) && (Take >= SocketResources[Socket].MmiohResourceNeeds)) {
+      //
+      // The socket requesting additional resources can be granted by using the already
+      // allocated range given to the whole system originally.
+      //
+      Take -= SocketResources[Socket].MmiohResourceNeeds;
+      DEBUG ((DEBUG_ERROR, "SocketResources[%x].MmiohResourceNeeds = %llX\n",Socket, SocketResources[Socket].MmiohResourceNeeds));
+      SocketResources[Socket].MmiohResourceNeeds = 0;
+    } else if ((SocketResources[Socket].MmiohResourceNeeds != 0) &&
+               (Take < SocketResources[Socket].MmiohResourceNeeds) &&
+               ((UnAllocatedMmioh + Take) >= SocketResources[Socket].MmiohResourceNeeds)) {
+      //
+      // Apply unallocated Mmioh to the socket that requires more to satisfy its request
+      // that's outside the allocated range given to the whole system originally.
+      //
+      SocketResources[Socket].MmiohResourceNeeds -= Take;
+      UnAllocatedMmioh -= SocketResources[Socket].MmiohResourceNeeds;
+      DEBUG ((DEBUG_INFO, "SocketResources[%x].MmiohResourceNeeds = %llX\n", Socket, SocketResources[Socket].MmiohResourceNeeds));
+      DEBUG ((DEBUG_INFO, "Unallocated MMIOH left = %llX\n", UnAllocatedMmioh));
+      SocketResources[Socket].MmiohResourceNeeds = 0;
+    }
+  }
+  //
+  // Give away leftover resources
+  //
+  LastStack = LastStackOfSocket (LastSocket);
+  if (Take != 0) {
+    if (SocketResources[LastSocket].StackRes[LastStack].MmiohLength != 0) {
+      SocketResources[LastSocket].StackRes[LastStack].MmiohLength += Take;
+    } else{
+      SocketResources[LastSocket].StackRes[LastStack].MmiohLength += (Take - 1);
+    }
+  }
+  //
+  // Verify all resource requested can fit into the systems address range.
+  //
+  TotalResourceSize = 0;
+  for (Socket = 0; Socket < ValidSockets; Socket++) {
+    LastStackWithResources (&SocketResources[Socket], Socket, ResourceType, &LastStack, &ResourceSize);
+    TotalResourceSize += ResourceSize;
+  }
+  DEBUG ((DEBUG_INFO, "MaxMmioh                 = %016llXh\n", MaxMmioh));
+  DEBUG ((DEBUG_INFO, "Total Request MMIOH Range= %016llXh\n", TotalResourceSize));
+  DEBUG ((DEBUG_INFO, "Total System MMIOH Range = %016llXh\n", (MaxMmioh - TempMmioBase)));
+  if (TotalResourceSize > MaxMmioh) {
+    //
+    // Not enough system resources to support the request.
+    // Remove all request to update NVRAM variable for this resource type.
+    //
+    for (Socket = 0; Socket < ValidSockets; Socket ++) {
+      for (Stack = 0; Stack < MAX_IIO_STACK; Stack ++) {
+        if (!(mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap & (1 << Stack))) {
+          continue;
+        }
+        SocketResources[Socket].StackRes[Stack].MmiohUpdate = 0;
+      }
+    }
+    DEBUG ((DEBUG_ERROR, "[PCI] ERROR: Out of adjustable MMIOH resources. Can't adjust across sockets\n"));
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  DEBUG ((DEBUG_ERROR, "Assigning new socket MMIOH range...\n"));
+  for (Socket = 0, TempMmioLimit = TempMmioBase - 1; Socket < ValidSockets; Socket++) {
+
+    SocketResources[Socket].MmiohBase = TempMmioLimit + 1;
+    //
+    // Update the stacks base and limit values.
+    //
+    for (Stack = 0; Stack < MAX_IIO_STACK; Stack++) {
+
+      if (!(mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap & (1 << Stack))) {
+
+       SocketResources[Socket].StackRes[Stack].MmiohBase = 0;
+       SocketResources[Socket].StackRes[Stack].MmiohLimit = 0;
+
+      } else {
+
+        SocketResources[Socket].StackRes[Stack].MmiohBase = TempMmioLimit + 1;
+        if (SocketResources[Socket].StackRes[Stack].MmiohLength != 0) {
+          //
+          // MmiohLength is actually length-1, so we should move TempMmioLimit by MmiohLength+1,
+          // but only when it is >0, i.e. only for stack that has resources.
+          //
+          TempMmioLimit += SocketResources[Socket].StackRes[Stack].MmiohLength + 1;
+          SocketResources[Socket].StackRes[Stack].MmiohLimit = TempMmioLimit;
+
+        } else {
+
+          SocketResources[Socket].StackRes[Stack].MmiohLimit = SocketResources[Socket].StackRes[Stack].MmiohBase;
+        }
+        SocketResources[Socket].StackRes[Stack].MmiohUpdate = 1;
+      }
+      DEBUG ((DEBUG_ERROR, "SocketResources[%x].StackRes[%x].MmiohBase  = %llX   newLength = %llX\n", Socket, Stack,
+              SocketResources[Socket].StackRes[Stack].MmiohBase, SocketResources[Socket].StackRes[Stack].MmiohLength));
+      DEBUG ((DEBUG_ERROR, "SocketResources[%x].StackRes[%x].MmiohLimit = %llX\n", Socket, Stack,
+              SocketResources[Socket].StackRes[Stack].MmiohLimit));
+      DEBUG ((DEBUG_ERROR, "SocketResources[%x].StackRes[%x].MmiohUpdate= %d\n", Socket, Stack,
+              SocketResources[Socket].StackRes[Stack].MmiohUpdate));
+    } // for (Stack...)
+
+    SocketResources[Socket].MmiohLimit = TempMmioLimit;
+  } // for (Socket...)
+  return EFI_SUCCESS;
+}
+
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciRootBridge.h b/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciRootBridge.h
new file mode 100644
index 0000000000..54faf82e98
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciRootBridge.h
@@ -0,0 +1,573 @@
+/** @file
+
+  @copyright
+  Copyright 1999 - 2021 Intel Corporation. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PCI_ROOT_BRIDGE_H_
+#define _PCI_ROOT_BRIDGE_H_
+
+#include <PiDxe.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Pci.h>
+
+//
+// Driver Consumed Protocol Prototypes
+//
+#include <Protocol/CpuIo2.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/UefiLib.h>
+#include <Library/TimerLib.h>
+#include "PciHostResource.h"
+
+
+//
+// Define resource status constant
+//
+typedef struct {
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation;
+  UINTN                                     NumberOfBytes;
+  UINTN                                     NumberOfPages;
+  EFI_PHYSICAL_ADDRESS                      HostAddress;
+  EFI_PHYSICAL_ADDRESS                      MappedHostAddress;
+} MAP_INFO;
+
+typedef struct {
+  ACPI_HID_DEVICE_PATH      AcpiDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL  EndDevicePath;
+} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH;
+
+#define PCI_ROOT_BRIDGE_SIGNATURE SIGNATURE_32 ('e', '2', 'p', 'b')
+
+typedef struct {
+  UINT32                            Signature;
+  LIST_ENTRY                        Link;
+  EFI_HANDLE                        Handle;
+  UINT64                            AllocationAttributes;
+  UINT64                            Attributes;
+  UINT64                            Supports;
+  PCI_RES_NODE                      ResAllocNode[TypeMax];
+  PCI_ROOT_BRIDGE_RESOURCE_APERTURE Aperture;
+  EFI_LOCK                          PciLock;
+  UINTN                             PciAddress;
+  UINTN                             PciData;
+  UINT32                            HecBase;
+  UINT32                            HecLen;
+  UINTN                             BusScanCount;
+  BOOLEAN                           BusNumberAssigned;
+  BOOLEAN                           DmaAbove4G;
+  VOID                              *ConfigBuffer;
+  EFI_DEVICE_PATH_PROTOCOL          *DevicePath;
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL   RootBridgeIo;
+} PCI_ROOT_BRIDGE_INSTANCE;
+
+#define ROOT_BRIDGE_FROM_THIS(a) CR (a, PCI_ROOT_BRIDGE_INSTANCE, RootBridgeIo, PCI_ROOT_BRIDGE_SIGNATURE)
+
+#define ROOT_BRIDGE_FROM_LINK(a) CR (a, PCI_ROOT_BRIDGE_INSTANCE, Link, PCI_ROOT_BRIDGE_SIGNATURE)
+
+/**
+  Construct the Pci Root Bridge Io protocol.
+
+  @param[out] Protocol         - Protocol to initialize.
+  @param[in]  HostBridgeHandle - Handle to the HostBridge.
+  @param[in]  ResAperture      - Resource apperture of the root bridge.
+  @param[in]  SegmentNumber    - PCI segment of this root bridge
+  @param[in]  AllocAttributes  - Attribute of resouce allocated.
+
+  @retval EFI_SUCCESS  -  Success.
+  @retval Others       -  Fail.
+**/
+EFI_STATUS
+SimpleIioRootBridgeConstructor (
+     OUT EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL   *Protocol,
+  IN     EFI_HANDLE                         HostBridgeHandle,
+  IN     PCI_ROOT_BRIDGE_RESOURCE_APERTURE *ResAperture,
+  IN     UINT16                             SegmentNumber,
+  IN     UINT64                             AllocAttributes
+  );
+
+//
+// Protocol Member Function Prototypes
+//
+/**
+
+  Poll an address in memory mapped space until an exit condition is met
+  or a timeout occurs.
+
+  @param This     -  Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
+  @param Width    -  Width of the memory operation.
+  @param Address  -  The base address of the memory operation.
+  @param Mask     -  Mask used for polling criteria.
+  @param Value    -  Comparison value used for polling exit criteria.
+  @param Delay    -  Number of 100ns units to poll.
+  @param Result   -  Pointer to the last value read from memory location.
+
+  @retval EFI_SUCCESS            -  Success.
+  @retval EFI_INVALID_PARAMETER  -  Invalid parameter found.
+  @retval EFI_TIMEOUT            -  Delay expired before a match occurred.
+  @retval EFI_OUT_OF_RESOURCES   -  Fail due to lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPollMem (
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN  UINT64                                 Address,
+  IN  UINT64                                 Mask,
+  IN  UINT64                                 Value,
+  IN  UINT64                                 Delay,
+  OUT UINT64                                 *Result
+  )
+;
+
+/**
+
+  Poll an address in I/O space until an exit condition is met
+  or a timeout occurs.
+
+  @param This     -  Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
+  @param Width    -  Width of I/O operation.
+  @param Address  -  The base address of the I/O operation.
+  @param Mask     -  Mask used for polling criteria.
+  @param Value    -  Comparison value used for polling exit criteria.
+  @param Delay    -  Number of 100ns units to poll.
+  @param Result   -  Pointer to the last value read from memory location.
+
+  @retval EFI_SUCCESS            -  Success.
+  @retval EFI_INVALID_PARAMETER  -  Invalid parameter found.
+  @retval EFI_TIMEOUT            -  Delay expired before a match occurred.
+  @retval EFI_OUT_OF_RESOURCES   -  Fail due to lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPollIo (
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN  UINT64                                 Address,
+  IN  UINT64                                 Mask,
+  IN  UINT64                                 Value,
+  IN  UINT64                                 Delay,
+  OUT UINT64                                 *Result
+  )
+;
+
+/**
+
+  Allow read from memory mapped I/O space.
+
+  @param This     -  Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
+  @param Width    -  The width of memory operation.
+  @param Address  -  Base address of the memory operation.
+  @param Count    -  Number of memory opeartion to perform.
+  @param Buffer   -  The destination buffer to store data.
+
+  @retval EFI_SUCCESS            -  Success.
+  @retval EFI_INVALID_PARAMETER  -  Invalid parameter found.
+  @retval EFI_OUT_OF_RESOURCES   -  Fail due to lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoMemRead (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT64                                 Address,
+  IN     UINTN                                  Count,
+  IN OUT VOID                                   *Buffer
+  )
+;
+
+/**
+
+  Allow write to memory mapped I/O space.
+
+  @param This     -  Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
+  @param Width    -  The width of memory operation.
+  @param Address  -  Base address of the memory operation.
+  @param Count    -  Number of memory opeartion to perform.
+  @param Buffer   -  The source buffer to write data from.
+
+  @retval EFI_SUCCESS            -  Success.
+  @retval EFI_INVALID_PARAMETER  -  Invalid parameter found.
+  @retval EFI_OUT_OF_RESOURCES   -  Fail due to lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoMemWrite (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT64                                 Address,
+  IN     UINTN                                  Count,
+  IN OUT VOID                                   *Buffer
+  )
+;
+
+/**
+
+  Enable a PCI driver to read PCI controller registers in the
+  PCI root bridge I/O space.
+
+  @param This         -  A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+  @param Width        -  Signifies the width of the memory operation.
+  @param UserAddress  -  The base address of the I/O operation.
+  @param Count        -  The number of I/O operations to perform.
+  @param UserBuffer   -  The destination buffer to store the results.
+
+  @retval EFI_SUCCESS            -  The data was read from the PCI root bridge.
+  @retval EFI_INVALID_PARAMETER  -  Invalid parameters found.
+  @retval EFI_OUT_OF_RESOURCES   -  The request could not be completed due to a lack of
+                            @retval resources.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoIoRead (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT64                                 UserAddress,
+  IN     UINTN                                  Count,
+  IN OUT VOID                                   *UserBuffer
+  )
+;
+
+/**
+
+  Enable a PCI driver to write to PCI controller registers in the
+  PCI root bridge I/O space.
+
+  @param This         -  A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+  @param Width        -  Signifies the width of the memory operation.
+  @param UserAddress  -  The base address of the I/O operation.
+  @param Count        -  The number of I/O operations to perform.
+  @param UserBuffer   -  The source buffer to write data from.
+
+  @retval EFI_SUCCESS            -  The data was written to the PCI root bridge.
+  @retval EFI_INVALID_PARAMETER  -  Invalid parameters found.
+  @retval EFI_OUT_OF_RESOURCES   -  The request could not be completed due to a lack of
+                            @retval resources.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoIoWrite (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT64                                 UserAddress,
+  IN     UINTN                                  Count,
+  IN OUT VOID                                   *UserBuffer
+  )
+;
+
+/**
+
+  Copy one region of PCI root bridge memory space to be copied to
+  another region of PCI root bridge memory space.
+
+  @param This         -  A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
+  @param Width        -  Signifies the width of the memory operation.
+  @param DestAddress  -  Destination address of the memory operation.
+  @param SrcAddress   -  Source address of the memory operation.
+  @param Count        -  Number of memory operations to perform.
+
+  @retval EFI_SUCCESS            -  The data was copied successfully.
+  @retval EFI_INVALID_PARAMETER  -  Invalid parameters found.
+  @retval EFI_OUT_OF_RESOURCES   -  The request could not be completed due to a lack of
+                            @retval resources.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoCopyMem (
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL          *This,
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH    Width,
+  IN UINT64                                   DestAddress,
+  IN UINT64                                   SrcAddress,
+  IN UINTN                                    Count
+  )
+;
+
+/**
+
+  Allows read from PCI configuration space.
+
+  @param This     -  A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+  @param Width    -  Signifies the width of the memory operation.
+  @param Address  -  The address within the PCI configuration space
+                     for the PCI controller.
+  @param Count    -  The number of PCI configuration operations
+                     to perform.
+  @param Buffer   -  The destination buffer to store the results.
+
+  @retval EFI_SUCCESS            -  The data was read from the PCI root bridge.
+  @retval EFI_INVALID_PARAMETER  -  Invalid parameters found.
+  @retval EFI_OUT_OF_RESOURCES   -  The request could not be completed due to a lack of
+                            @retval resources.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPciRead (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT64                                 Address,
+  IN     UINTN                                  Count,
+  IN OUT VOID                                   *Buffer
+  )
+;
+
+/**
+
+  Allows write to PCI configuration space.
+
+  @param This     -  A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+  @param Width    -  Signifies the width of the memory operation.
+  @param Address  -  The address within the PCI configuration space
+                     for the PCI controller.
+  @param Count    -  The number of PCI configuration operations
+                     to perform.
+  @param Buffer   -  The source buffer to get the results.
+
+  @retval EFI_SUCCESS            -  The data was written to the PCI root bridge.
+  @retval EFI_INVALID_PARAMETER  -  Invalid parameters found.
+  @retval EFI_OUT_OF_RESOURCES   -  The request could not be completed due to a lack of
+                            @retval resources.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPciWrite (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT64                                 Address,
+  IN     UINTN                                  Count,
+  IN OUT VOID                                   *Buffer
+  )
+;
+
+/**
+  Provides the PCI controller-specific address needed to access
+  system memory for DMA.
+
+  @param This           A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param Operation      Indicate if the bus master is going to read or write
+                        to system memory.
+  @param HostAddress    The system memory address to map on the PCI controller.
+  @param NumberOfBytes  On input the number of bytes to map.
+                        On output the number of bytes that were mapped.
+  @param DeviceAddress  The resulting map address for the bus master PCI
+                        controller to use to access the system memory's HostAddress.
+  @param Mapping        The value to pass to Unmap() when the bus master DMA
+                        operation is complete.
+
+  @retval EFI_SUCCESS            Success.
+  @retval EFI_INVALID_PARAMETER  Invalid parameters found.
+  @retval EFI_UNSUPPORTED        The HostAddress cannot be mapped as a common buffer.
+  @retval EFI_DEVICE_ERROR       The System hardware could not map the requested address.
+  @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to lack of resources.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoMap (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL            *This,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION  Operation,
+  IN     VOID                                       *HostAddress,
+  IN OUT UINTN                                      *NumberOfBytes,
+  OUT    EFI_PHYSICAL_ADDRESS                       *DeviceAddress,
+  OUT    VOID                                       **Mapping
+  )
+;
+
+/**
+  Completes the Map() operation and releases any corresponding resources.
+
+  The Unmap() function completes the Map() operation and releases any
+  corresponding resources.
+  If the operation was an EfiPciOperationBusMasterWrite or
+  EfiPciOperationBusMasterWrite64, the data is committed to the target system
+  memory.
+  Any resources used for the mapping are freed.
+
+  @param[in] This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param[in] Mapping   The mapping value returned from Map().
+
+  @retval EFI_SUCCESS            The range was unmapped.
+  @retval EFI_INVALID_PARAMETER  Mapping is not a value that was returned by Map().
+  @retval EFI_DEVICE_ERROR       The data was not committed to the target system memory.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoUnmap (
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
+  IN  VOID                             *Mapping
+  )
+;
+
+/**
+  Allocates pages that are suitable for an EfiPciOperationBusMasterCommonBuffer
+  or EfiPciOperationBusMasterCommonBuffer64 mapping.
+
+  @param This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param Type        This parameter is not used and must be ignored.
+  @param MemoryType  The type of memory to allocate, EfiBootServicesData or
+                     EfiRuntimeServicesData.
+  @param Pages       The number of pages to allocate.
+  @param HostAddress A pointer to store the base system memory address of the
+                     allocated range.
+  @param Attributes  The requested bit mask of attributes for the allocated
+                     range. Only the attributes
+                     EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE,
+                     EFI_PCI_ATTRIBUTE_MEMORY_CACHED, and
+                     EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE may be used with this
+                     function.
+
+  @retval EFI_SUCCESS            The requested memory pages were allocated.
+  @retval EFI_INVALID_PARAMETER  MemoryType is invalid.
+  @retval EFI_INVALID_PARAMETER  HostAddress is NULL.
+  @retval EFI_UNSUPPORTED        Attributes is unsupported. The only legal
+                                 attribute bits are MEMORY_WRITE_COMBINE,
+                                 MEMORY_CACHED, and DUAL_ADDRESS_CYCLE.
+  @retval EFI_OUT_OF_RESOURCES   The memory pages could not be allocated.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoAllocateBuffer (
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
+  IN  EFI_ALLOCATE_TYPE                Type,
+  IN  EFI_MEMORY_TYPE                  MemoryType,
+  IN  UINTN                            Pages,
+  OUT VOID                             **HostAddress,
+  IN  UINT64                           Attributes
+  )
+;
+
+/**
+
+  Free memory allocated in AllocateBuffer.
+
+  @param This         -  Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+                         instance.
+  @param Pages        -  Number of pages to free.
+  @param HostAddress  -  The base system memory address of the
+                         allocated range.
+
+  @retval EFI_SUCCESS            -  Requested memory pages were freed.
+  @retval EFI_INVALID_PARAMETER  -  Invalid parameter found.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoFreeBuffer (
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
+  IN  UINTN                            Pages,
+  OUT VOID                             *HostAddress
+  )
+;
+
+/**
+
+  Flushes all PCI posted write transactions from a PCI host
+  bridge to system memory.
+
+  @param This  - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
+
+  @retval EFI_SUCCESS       -  PCI posted write transactions were flushed
+                       @retval from PCI host bridge to system memory.
+  @retval EFI_DEVICE_ERROR  -  Fail due to hardware error.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoFlush (
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This
+  )
+;
+
+/**
+  Gets the attributes that a PCI root bridge supports setting with
+  SetAttributes(), and the attributes that a PCI root bridge is currently
+  using.
+
+  The GetAttributes() function returns the mask of attributes that this PCI
+  root bridge supports and the mask of attributes that the PCI root bridge is
+  currently using.
+
+  @param This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param Supported   A pointer to the mask of attributes that this PCI root
+                     bridge supports setting with SetAttributes().
+  @param Attributes  A pointer to the mask of attributes that this PCI root
+                     bridge is currently using.
+
+  @retval  EFI_SUCCESS           If Supports is not NULL, then the attributes
+                                 that the PCI root bridge supports is returned
+                                 in Supports. If Attributes is not NULL, then
+                                 the attributes that the PCI root bridge is
+                                 currently using is returned in Attributes.
+  @retval  EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoGetAttributes (
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
+  OUT UINT64                           *Supported,
+  OUT UINT64                           *Attributes
+  )
+;
+
+/**
+
+  Sets the attributes for a resource range on a PCI root bridge.
+
+  @param This            -  Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
+  @param Attributes      -  The mask of attributes to set.
+  @param ResourceBase    -  Pointer to the base address of the resource range
+                            to be modified by the attributes specified by Attributes.
+  @param ResourceLength  -  Pointer to the length of the resource range to be modified.
+
+  @retval EFI_SUCCESS            -  Success.
+  @retval EFI_INVALID_PARAMETER  -  Invalid parameter found.
+  @retval EFI_OUT_OF_RESOURCES   -  Not enough resources to set the attributes upon.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoSetAttributes (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
+  IN     UINT64                           Attributes,
+  IN OUT UINT64                           *ResourceBase,
+  IN OUT UINT64                           *ResourceLength
+  )
+;
+
+/**
+
+  Retrieves the current resource settings of this PCI root bridge
+  in the form of a set of ACPI resource descriptor.
+
+  @param This       -  Pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
+  @param Resources  -  Pointer to the resource descriptor that
+                       describe the current configuration of this PCI root
+                       bridge.
+
+  @retval EFI_SUCCESS      -  Success.
+  @retval EFI_UNSUPPORTED  -  Current configuration of the PCI root bridge
+                      @retval could not be retrieved.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoConfiguration (
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
+  OUT VOID                             **Resources
+  )
+;
+
+extern EFI_CPU_IO2_PROTOCOL         *mCpuIo;
+#endif
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciRootBridgeIo.c b/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciRootBridgeIo.c
new file mode 100644
index 0000000000..ed5fb7e4a3
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciHostBridge/PciRootBridgeIo.c
@@ -0,0 +1,1664 @@
+/** @file
+  IIO PCI Root Bridge Io Protocol code. Generic enough to work for all IIOs.
+  Does not support configuration accesses to the extended PCI Express registers yet.
+
+  @copyright
+  Copyright 1999 - 2021 Intel Corporation. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "PciHostBridge.h"
+#include "PciRootBridge.h"
+
+#include <Protocol/IioUds.h>
+#include <Protocol/DynamicSiLibraryProtocol.h>
+
+#include "PciRebalance.h"
+
+extern EFI_IIO_UDS_PROTOCOL *mIioUds;
+
+
+//
+// Pci Root Bridge Io Module Variables
+//
+EFI_CPU_IO2_PROTOCOL               *mCpuIo;
+STATIC DYNAMIC_SI_LIBARY_PROTOCOL  *mDynamicSiLibraryProtocol;
+
+/**
+  Construct the Pci Root Bridge Io protocol.
+
+  @param[out] Protocol         - Protocol to initialize.
+  @param[in]  HostBridgeHandle - Handle to the HostBridge.
+  @param[in]  ResAperture      - Resource apperture of the root bridge.
+  @param[in]  SegmentNumber    - PCI segment of this root bridge
+  @param[in]  AllocAttributes  - Attribute of resouce allocated.
+
+  @retval EFI_SUCCESS  -  Success.
+  @retval Others       -  Fail.
+**/
+EFI_STATUS
+SimpleIioRootBridgeConstructor (
+     OUT EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL   *Protocol,
+  IN     EFI_HANDLE                         HostBridgeHandle,
+  IN     PCI_ROOT_BRIDGE_RESOURCE_APERTURE *ResAperture,
+  IN     UINT16                             SegmentNumber,
+  IN     UINT64                             AllocAttributes
+  )
+{
+  EFI_STATUS                Status;
+  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;
+  PCI_RESOURCE_TYPE         Index;
+  UINT32                    HecBase;
+  UINT32                    HecSize;
+
+  RootBridge = ROOT_BRIDGE_FROM_THIS (Protocol);
+
+  //
+  // Initialize the apertures with default values
+  //
+  CopyMem (
+    &RootBridge->Aperture,
+    ResAperture,
+    sizeof (PCI_ROOT_BRIDGE_RESOURCE_APERTURE)
+    );
+
+  for (Index = TypeIo; Index < TypeMax; Index++) {
+    RootBridge->ResAllocNode[Index].Type   = Index;
+    RootBridge->ResAllocNode[Index].Base   = 0;
+    RootBridge->ResAllocNode[Index].Length = 0;
+    RootBridge->ResAllocNode[Index].Status = ResNone;
+  }
+
+  EfiInitializeLock (&RootBridge->PciLock, TPL_HIGH_LEVEL);
+  RootBridge->PciAddress             = 0xCF8;
+  RootBridge->PciData                = 0xCFC;
+
+  RootBridge->AllocationAttributes   = AllocAttributes;
+  RootBridge->Attributes             = 0;
+  RootBridge->Supports = EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO |
+    EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO |
+    EFI_PCI_ATTRIBUTE_ISA_IO_16         |
+    EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16 |
+    EFI_PCI_ATTRIBUTE_VGA_MEMORY |
+    EFI_PCI_ATTRIBUTE_VGA_IO_16;
+
+  //
+  // Don't support BASE above 4GB currently
+  // Position to bit 39:28
+  //
+  HecBase = (UINT32) mIioUds->IioUdsPtr->PlatformData.PciExpressBase;
+  HecSize = (UINT32) mIioUds->IioUdsPtr->PlatformData.PciExpressSize;
+  ASSERT (HecBase != 0);
+
+  RootBridge->HecBase            = HecBase;
+  RootBridge->HecLen             = HecSize;
+
+  RootBridge->BusNumberAssigned  = FALSE;
+  RootBridge->BusScanCount       = 0;
+
+  Protocol->ParentHandle          = HostBridgeHandle;
+
+  Protocol->PollMem               = RootBridgeIoPollMem;
+  Protocol->PollIo                = RootBridgeIoPollIo;
+
+  Protocol->Mem.Read              = RootBridgeIoMemRead;
+  Protocol->Mem.Write             = RootBridgeIoMemWrite;
+
+  Protocol->Io.Read               = RootBridgeIoIoRead;
+  Protocol->Io.Write              = RootBridgeIoIoWrite;
+
+  Protocol->CopyMem               = RootBridgeIoCopyMem;
+
+  Protocol->Pci.Read              = RootBridgeIoPciRead;
+  Protocol->Pci.Write             = RootBridgeIoPciWrite;
+
+  Protocol->Map                   = RootBridgeIoMap;
+  Protocol->Unmap                 = RootBridgeIoUnmap;
+
+  Protocol->AllocateBuffer        = RootBridgeIoAllocateBuffer;
+  Protocol->FreeBuffer            = RootBridgeIoFreeBuffer;
+
+  Protocol->Flush                 = RootBridgeIoFlush;
+
+  Protocol->GetAttributes         = RootBridgeIoGetAttributes;
+  Protocol->SetAttributes         = RootBridgeIoSetAttributes;
+
+  Protocol->Configuration         = RootBridgeIoConfiguration;
+
+  Protocol->SegmentNumber         = SegmentNumber;
+
+  Status = gBS->LocateProtocol (
+                  &gEfiCpuIo2ProtocolGuid,
+                  NULL,
+                  &mCpuIo
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocolGuid, NULL, &mDynamicSiLibraryProtocol);
+  ASSERT_EFI_ERROR (Status);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Return the result of (Multiplicand * Multiplier / Divisor).
+
+  @param Multiplicand A 64-bit unsigned value.
+  @param Multiplier   A 64-bit unsigned value.
+  @param Divisor      A 32-bit unsigned value.
+  @param Remainder    A pointer to a 32-bit unsigned value. This parameter is
+                      optional and may be NULL.
+
+  @return Multiplicand * Multiplier / Divisor.
+**/
+UINT64
+MultThenDivU64x64x32 (
+  IN      UINT64                    Multiplicand,
+  IN      UINT64                    Multiplier,
+  IN      UINT32                    Divisor,
+  OUT     UINT32                    *Remainder  OPTIONAL
+  )
+{
+  UINT64                            Uint64;
+  UINT32                            LocalRemainder;
+  UINT32                            Uint32;
+  if (Multiplicand > DivU64x64Remainder (MAX_UINT64, Multiplier, NULL)) {
+    //
+    // Make sure Multiplicand is the bigger one.
+    //
+    if (Multiplicand < Multiplier) {
+      Uint64       = Multiplicand;
+      Multiplicand = Multiplier;
+      Multiplier   = Uint64;
+    }
+    //
+    // Because Multiplicand * Multiplier overflows,
+    //   Multiplicand * Multiplier / Divisor
+    // = (2 * Multiplicand' + 1) * Multiplier / Divisor
+    // = 2 * (Multiplicand' * Multiplier / Divisor) + Multiplier / Divisor
+    //
+    Uint64 = MultThenDivU64x64x32 (RShiftU64 (Multiplicand, 1), Multiplier, Divisor, &LocalRemainder);
+    Uint64 = LShiftU64 (Uint64, 1);
+    Uint32 = 0;
+    if ((Multiplicand & 0x1) == 1) {
+      Uint64 += DivU64x32Remainder (Multiplier, Divisor, &Uint32);
+    }
+    return Uint64 + DivU64x32Remainder (Uint32 + LShiftU64 (LocalRemainder, 1), Divisor, Remainder);
+  } else {
+    return DivU64x32Remainder (MultU64x64 (Multiplicand, Multiplier), Divisor, Remainder);
+  }
+}
+
+/**
+  Return the elapsed tick count from CurrentTick.
+
+  @param  CurrentTick  On input, the previous tick count.
+                       On output, the current tick count.
+  @param  StartTick    The value the performance counter starts with when it
+                       rolls over.
+  @param  EndTick      The value that the performance counter ends with before
+                       it rolls over.
+
+  @return  The elapsed tick count from CurrentTick.
+**/
+UINT64
+GetElapsedTick (
+  UINT64  *CurrentTick,
+  UINT64  StartTick,
+  UINT64  EndTick
+  )
+{
+  UINT64  PreviousTick;
+
+  PreviousTick = *CurrentTick;
+  *CurrentTick = GetPerformanceCounter();
+  if (StartTick < EndTick) {
+    return *CurrentTick - PreviousTick;
+  } else {
+    return PreviousTick - *CurrentTick;
+  }
+}
+
+/**
+  Polls an address in memory mapped I/O space until an exit condition is met,
+  or a timeout occurs.
+
+  This function provides a standard way to poll a PCI memory location. A PCI
+  memory read operation is performed at the PCI memory address specified by
+  Address for the width specified by Width. The result of this PCI memory read
+  operation is stored in Result. This PCI memory read operation is repeated
+  until either a timeout of Delay 100 ns units has expired, or (Result & Mask)
+  is equal to Value.
+
+  @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param[in]   Width     Signifies the width of the memory operations.
+  @param[in]   Address   The base address of the memory operations. The caller
+                         is responsible for aligning Address if required.
+  @param[in]   Mask      Mask used for the polling criteria. Bytes above Width
+                         in Mask are ignored. The bits in the bytes below Width
+                         which are zero in Mask are ignored when polling the
+                         memory address.
+  @param[in]   Value     The comparison value used for the polling exit
+                         criteria.
+  @param[in]   Delay     The number of 100 ns units to poll. Note that timer
+                         available may be of poorer granularity.
+  @param[out]  Result    Pointer to the last value read from the memory
+                         location.
+
+  @retval EFI_SUCCESS            The last data returned from the access matched
+                                 the poll exit criteria.
+  @retval EFI_INVALID_PARAMETER  Width is invalid.
+  @retval EFI_INVALID_PARAMETER  Result is NULL.
+  @retval EFI_TIMEOUT            Delay expired before a match occurred.
+  @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a
+                                 lack of resources.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPollMem (
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN  UINT64                                 Address,
+  IN  UINT64                                 Mask,
+  IN  UINT64                                 Value,
+  IN  UINT64                                 Delay,
+  OUT UINT64                                 *Result
+  )
+{
+  EFI_STATUS  Status;
+  UINT64      NumberOfTicks;
+  UINT32      Remainder;
+  UINT64      StartTick;
+  UINT64      EndTick;
+  UINT64      CurrentTick;
+  UINT64      ElapsedTick;
+  UINT64      Frequency;
+
+  if (Result == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((UINT32)Width > EfiPciWidthUint64) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // No matter what, always do a single poll.
+  //
+  Status = This->Mem.Read (This, Width, Address, 1, Result);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if ((*Result & Mask) == Value) {
+    return EFI_SUCCESS;
+  }
+
+  if (Delay == 0) {
+    return EFI_SUCCESS;
+
+  } else {
+    //
+    // NumberOfTicks = Frenquency * Delay / EFI_TIMER_PERIOD_SECONDS(1)
+    //
+    Frequency     = GetPerformanceCounterProperties (&StartTick, &EndTick);
+    NumberOfTicks = MultThenDivU64x64x32 (Frequency, Delay, (UINT32)EFI_TIMER_PERIOD_SECONDS(1), &Remainder);
+    if (Remainder >= (UINTN)EFI_TIMER_PERIOD_SECONDS(1) / 2) {
+      NumberOfTicks++;
+    }
+    for ( ElapsedTick = 0, CurrentTick = GetPerformanceCounter()
+        ; ElapsedTick <= NumberOfTicks
+        ; ElapsedTick += GetElapsedTick (&CurrentTick, StartTick, EndTick)
+        ) {
+      Status = This->Mem.Read (This, Width, Address, 1, Result);
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+
+      if ((*Result & Mask) == Value) {
+        return EFI_SUCCESS;
+      }
+    }
+  }
+  return EFI_TIMEOUT;
+}
+
+/**
+  Reads from the I/O space of a PCI Root Bridge. Returns when either the
+  polling exit criteria is satisfied or after a defined duration.
+
+  This function provides a standard way to poll a PCI I/O location. A PCI I/O
+  read operation is performed at the PCI I/O address specified by Address for
+  the width specified by Width.
+  The result of this PCI I/O read operation is stored in Result. This PCI I/O
+  read operation is repeated until either a timeout of Delay 100 ns units has
+  expired, or (Result & Mask) is equal to Value.
+
+  @param[in] This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param[in] Width     Signifies the width of the I/O operations.
+  @param[in] Address   The base address of the I/O operations. The caller is
+                       responsible for aligning Address if required.
+  @param[in] Mask      Mask used for the polling criteria. Bytes above Width in
+                       Mask are ignored. The bits in the bytes below Width
+                       which are zero in Mask are ignored when polling the I/O
+                       address.
+  @param[in] Value     The comparison value used for the polling exit criteria.
+  @param[in] Delay     The number of 100 ns units to poll. Note that timer
+                       available may be of poorer granularity.
+  @param[out] Result   Pointer to the last value read from the memory location.
+
+  @retval EFI_SUCCESS            The last data returned from the access matched
+                                 the poll exit criteria.
+  @retval EFI_INVALID_PARAMETER  Width is invalid.
+  @retval EFI_INVALID_PARAMETER  Result is NULL.
+  @retval EFI_TIMEOUT            Delay expired before a match occurred.
+  @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a
+                                 lack of resources.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPollIo (
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN  UINT64                                 Address,
+  IN  UINT64                                 Mask,
+  IN  UINT64                                 Value,
+  IN  UINT64                                 Delay,
+  OUT UINT64                                 *Result
+  )
+{
+  EFI_STATUS  Status;
+  UINT64      NumberOfTicks;
+  UINT32      Remainder;
+  UINT64      StartTick;
+  UINT64      EndTick;
+  UINT64      CurrentTick;
+  UINT64      ElapsedTick;
+  UINT64      Frequency;
+
+  //
+  // No matter what, always do a single poll.
+  //
+
+  if (Result == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((UINT32)Width > EfiPciWidthUint64) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = This->Io.Read (This, Width, Address, 1, Result);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  if ((*Result & Mask) == Value) {
+    return EFI_SUCCESS;
+  }
+
+  if (Delay == 0) {
+    return EFI_SUCCESS;
+
+  } else {
+    //
+    // NumberOfTicks = Frenquency * Delay / EFI_TIMER_PERIOD_SECONDS(1)
+    //
+    Frequency     = GetPerformanceCounterProperties (&StartTick, &EndTick);
+    NumberOfTicks = MultThenDivU64x64x32 (Frequency, Delay, (UINT32)EFI_TIMER_PERIOD_SECONDS(1), &Remainder);
+    if (Remainder >= (UINTN)EFI_TIMER_PERIOD_SECONDS(1) / 2) {
+      NumberOfTicks++;
+    }
+    for ( ElapsedTick = 0, CurrentTick = GetPerformanceCounter()
+        ; ElapsedTick <= NumberOfTicks
+        ; ElapsedTick += GetElapsedTick (&CurrentTick, StartTick, EndTick)
+        ) {
+      Status = This->Io.Read (This, Width, Address, 1, Result);
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+
+      if ((*Result & Mask) == Value) {
+        return EFI_SUCCESS;
+      }
+    }
+  }
+  return EFI_TIMEOUT;
+}
+
+/**
+  Enables a PCI driver to access PCI controller registers in the PCI root
+  bridge memory space.
+
+  The Mem.Read(), and Mem.Write() functions enable a driver to access PCI
+  controller registers in the PCI root bridge memory space.
+  The memory operations are carried out exactly as requested. The caller is
+  responsible for satisfying any alignment and memory width restrictions that a
+  PCI Root Bridge on a platform might require.
+
+  @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param[in]   Width     Signifies the width of the memory operation.
+  @param[in]   Address   The base address of the memory operation. The caller
+                         is responsible for aligning the Address if required.
+  @param[in]   Count     The number of memory operations to perform. Bytes
+                         moved is Width size * Count, starting at Address.
+  @param[out]  Buffer    For read operations, the destination buffer to store
+                         the results. For write operations, the source buffer
+                         to write data from.
+
+  @retval EFI_SUCCESS            The data was read from or written to the PCI
+                                 root bridge.
+  @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
+  @retval EFI_INVALID_PARAMETER  Buffer is NULL.
+  @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a
+                                 lack of resources.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoMemRead (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT64                                 Address,
+  IN     UINTN                                  Count,
+  OUT    VOID                                   *Buffer
+  )
+{
+  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;
+  if (Buffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Width < 0 ||Width >= EfiPciWidthMaximum  ) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  RootBridge = ROOT_BRIDGE_FROM_THIS (This);
+  //
+  // Check memory access limit
+  //
+  if (RootBridge->Aperture.Mem64Limit > RootBridge->Aperture.Mem64Base) {
+      if (Address > RootBridge->Aperture.Mem64Limit) {
+        return EFI_INVALID_PARAMETER;
+      }
+  } else {
+      if (Address > RootBridge->Aperture.Mem32Limit) {
+        return EFI_INVALID_PARAMETER;
+      }
+  }
+
+  return mCpuIo->Mem.Read (
+                      mCpuIo,
+                      (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
+                      Address,
+                      Count,
+                      Buffer
+                      );
+}
+
+/**
+  Enables a PCI driver to access PCI controller registers in the PCI root
+  bridge memory space.
+
+  The Mem.Read(), and Mem.Write() functions enable a driver to access PCI
+  controller registers in the PCI root bridge memory space.
+  The memory operations are carried out exactly as requested. The caller is
+  responsible for satisfying any alignment and memory width restrictions that a
+  PCI Root Bridge on a platform might require.
+
+  @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param[in]   Width     Signifies the width of the memory operation.
+  @param[in]   Address   The base address of the memory operation. The caller
+                         is responsible for aligning the Address if required.
+  @param[in]   Count     The number of memory operations to perform. Bytes
+                         moved is Width size * Count, starting at Address.
+  @param[in]   Buffer    For read operations, the destination buffer to store
+                         the results. For write operations, the source buffer
+                         to write data from.
+
+  @retval EFI_SUCCESS            The data was read from or written to the PCI
+                                 root bridge.
+  @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
+  @retval EFI_INVALID_PARAMETER  Buffer is NULL.
+  @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a
+                                 lack of resources.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoMemWrite (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT64                                 Address,
+  IN     UINTN                                  Count,
+  IN     VOID                                   *Buffer
+  )
+{
+  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;
+
+  if (Buffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Width < 0 || Width >= EfiPciWidthMaximum ) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  RootBridge = ROOT_BRIDGE_FROM_THIS (This);
+
+  //
+  // Check memory access limit
+  //
+  if (RootBridge->Aperture.Mem64Limit > RootBridge->Aperture.Mem64Base) {
+      if (Address > RootBridge->Aperture.Mem64Limit) {
+        return EFI_INVALID_PARAMETER;
+      }
+  } else {
+      if (Address > RootBridge->Aperture.Mem32Limit) {
+        return EFI_INVALID_PARAMETER;
+      }
+  }
+  return mCpuIo->Mem.Write (
+                      mCpuIo,
+                      (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
+                      Address,
+                      Count,
+                      Buffer
+                      );
+}
+
+/**
+  Enables a PCI driver to access PCI controller registers in the PCI root
+  bridge I/O space.
+
+  @param[in]   This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param[in]   Width       Signifies the width of the memory operations.
+  @param[in]   Address     The base address of the I/O operation. The caller is
+                           responsible for aligning the Address if required.
+  @param[in]   Count       The number of I/O operations to perform. Bytes moved
+                           is Width size * Count, starting at Address.
+  @param[out]  Buffer      For read operations, the destination buffer to store
+                           the results. For write operations, the source buffer
+                           to write data from.
+
+  @retval EFI_SUCCESS              The data was read from or written to the PCI
+                                   root bridge.
+  @retval EFI_INVALID_PARAMETER    Width is invalid for this PCI root bridge.
+  @retval EFI_INVALID_PARAMETER    Buffer is NULL.
+  @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a
+                                   lack of resources.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoIoRead (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT64                                 Address,
+  IN     UINTN                                  Count,
+  OUT    VOID                                   *Buffer
+  )
+{
+  UINTN                     AlignMask;
+  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;
+
+  if (Buffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Width < 0 || Width >= EfiPciWidthMaximum ) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  RootBridge = ROOT_BRIDGE_FROM_THIS (This);
+
+  //
+  // AlignMask = (1 << Width) - 1;
+  //
+  AlignMask = (1 << (Width & 0x03)) - 1;
+
+  //
+  // check Io access limit
+  //
+  if (Address > RootBridge->Aperture.IoLimit) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Address & AlignMask) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return mCpuIo->Io.Read (
+                      mCpuIo,
+                      (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
+                      Address,
+                      Count,
+                      Buffer
+                      );
+
+}
+
+/**
+  Enables a PCI driver to access PCI controller registers in the PCI root
+  bridge I/O space.
+
+  @param[in]   This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param[in]   Width       Signifies the width of the memory operations.
+  @param[in]   Address     The base address of the I/O operation. The caller is
+                           responsible for aligning the Address if required.
+  @param[in]   Count       The number of I/O operations to perform. Bytes moved
+                           is Width size * Count, starting at Address.
+  @param[in]   Buffer      For read operations, the destination buffer to store
+                           the results. For write operations, the source buffer
+                           to write data from.
+
+  @retval EFI_SUCCESS              The data was read from or written to the PCI
+                                   root bridge.
+  @retval EFI_INVALID_PARAMETER    Width is invalid for this PCI root bridge.
+  @retval EFI_INVALID_PARAMETER    Buffer is NULL.
+  @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a
+                                   lack of resources.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoIoWrite (
+  IN       EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL         *This,
+  IN       EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH   Width,
+  IN       UINT64                                  Address,
+  IN       UINTN                                   Count,
+  IN       VOID                                    *Buffer
+  )
+{
+  UINTN                     AlignMask;
+  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;
+
+  if (Buffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Width < 0 || Width >= EfiPciWidthMaximum ) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  RootBridge = ROOT_BRIDGE_FROM_THIS (This);
+
+  //
+  // AlignMask = (1 << Width) - 1;
+  //
+  AlignMask = (1 << (Width & 0x03)) - 1;
+
+  //
+  // Check Io access limit
+  //
+  if (Address > RootBridge->Aperture.IoLimit) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Address & AlignMask) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return mCpuIo->Io.Write (
+                      mCpuIo,
+                      (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
+                      Address,
+                      Count,
+                      Buffer
+                      );
+
+}
+
+/**
+  Enables a PCI driver to copy one region of PCI root bridge memory space to
+  another region of PCI root bridge memory space.
+
+  The CopyMem() function enables a PCI driver to copy one region of PCI root
+  bridge memory space to another region of PCI root bridge memory space. This
+  is especially useful for video scroll operation on a memory mapped video
+  buffer.
+  The memory operations are carried out exactly as requested. The caller is
+  responsible for satisfying any alignment and memory width restrictions that a
+  PCI root bridge on a platform might require.
+
+  @param[in] This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+                         instance.
+  @param[in] Width       Signifies the width of the memory operations.
+  @param[in] DestAddress The destination address of the memory operation. The
+                         caller is responsible for aligning the DestAddress if
+                         required.
+  @param[in] SrcAddress  The source address of the memory operation. The caller
+                         is responsible for aligning the SrcAddress if
+                         required.
+  @param[in] Count       The number of memory operations to perform. Bytes
+                         moved is Width size * Count, starting at DestAddress
+                         and SrcAddress.
+
+  @retval  EFI_SUCCESS             The data was copied from one memory region
+                                   to another memory region.
+  @retval  EFI_INVALID_PARAMETER   Width is invalid for this PCI root bridge.
+  @retval  EFI_OUT_OF_RESOURCES    The request could not be completed due to a
+                                   lack of resources.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoCopyMem (
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL              *This,
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH        Width,
+  IN UINT64                                       DestAddress,
+  IN UINT64                                       SrcAddress,
+  IN UINTN                                        Count
+  )
+{
+  EFI_STATUS  Status;
+  BOOLEAN     Forward;
+  UINTN       Stride;
+  UINTN       Index;
+  UINT64      Result;
+
+  if ((UINT32) Width > EfiPciWidthUint64) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (DestAddress == SrcAddress) {
+    return EFI_SUCCESS;
+  }
+
+  Stride = (UINTN)1 << Width;
+
+  Forward = TRUE;
+  if ((DestAddress > SrcAddress) &&
+      (DestAddress < (SrcAddress + Count * Stride))) {
+    Forward = FALSE;
+    SrcAddress = SrcAddress + (Count - 1) * Stride;
+    DestAddress = DestAddress + (Count - 1) * Stride;
+  }
+
+  for (Index = 0; Index < Count; Index++) {
+    Status = RootBridgeIoMemRead (
+               This,
+               Width,
+               SrcAddress,
+               1,
+               &Result
+               );
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+    Status = RootBridgeIoMemWrite (
+               This,
+               Width,
+               DestAddress,
+               1,
+               &Result
+               );
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+    if (Forward) {
+      SrcAddress += Stride;
+      DestAddress += Stride;
+    } else {
+      SrcAddress -= Stride;
+      DestAddress -= Stride;
+    }
+  }
+  return EFI_SUCCESS;
+}
+
+
+/**
+
+Arguments:
+
+**/
+STATIC
+EFI_STATUS
+RootBridgeIoPciRW (
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN BOOLEAN                                Write,
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN UINT64                                 UserAddress,
+  IN UINTN                                  Count,
+  IN OUT VOID                              *UserBuffer
+  )
+{
+  PCI_CONFIG_ACCESS_CF8             Pci;
+  PCI_CONFIG_ACCESS_CF8             PciAligned;
+  UINT32                            Stride;
+  UINTN                             PciData;
+  UINTN                             PciDataStride;
+  PCI_ROOT_BRIDGE_INSTANCE         *RootBridge;
+
+  if (Width >= EfiPciWidthMaximum) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  RootBridge = ROOT_BRIDGE_FROM_THIS (This);
+
+  ASSERT (((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*)&UserAddress)->ExtendedRegister == 0x00);
+
+  Stride = 1 << Width;
+
+  Pci.Bits.Reg = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &UserAddress)->Register;
+  Pci.Bits.Func = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &UserAddress)->Function;
+  Pci.Bits.Dev = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &UserAddress)->Device;
+  Pci.Bits.Bus = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &UserAddress)->Bus;
+  Pci.Bits.Reserved = 0;
+  Pci.Bits.Enable = 1;
+
+  //
+  // PCI Configure access are all 32-bit aligned, but by accessing the
+  //  CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types
+  //  are possible on PCI.
+  //
+  // To read a byte of PCI configuration space you load 0xcf8 and
+  //  read 0xcfc, 0xcfd, 0xcfe, 0xcff
+  //
+  PciDataStride = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &UserAddress)->Register & 0x03;
+
+  while (Count) {
+    PciAligned = Pci;
+    PciAligned.Bits.Reg &= 0xfc;
+    PciData = RootBridge->PciData + PciDataStride;
+    EfiAcquireLock(&RootBridge->PciLock);
+    This->Io.Write (This, EfiPciWidthUint32, \
+                    RootBridge->PciAddress, 1, &PciAligned);
+    if (Write) {
+      This->Io.Write (This, Width, PciData, 1, UserBuffer);
+    } else {
+      This->Io.Read (This, Width, PciData, 1, UserBuffer);
+    }
+    EfiReleaseLock(&RootBridge->PciLock);
+    UserBuffer = ((UINT8 *)UserBuffer) + Stride;
+    PciDataStride = (PciDataStride + Stride) % 4;
+    Count -= 1;
+
+    //
+    // Only increment the PCI address if Width is not a FIFO.
+    //
+    if (Width >= EfiPciWidthUint8 && Width <= EfiPciWidthUint64) {
+      Pci.Bits.Reg += Stride;
+    }
+  }
+  return EFI_SUCCESS;
+}
+
+/**
+  Allows read from PCI configuration space.
+
+  @param This     A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+  @param Width    Signifies the width of the memory operation.
+  @param Address  The address within the PCI configuration space
+                  for the PCI controller.
+  @param Count    The number of PCI configuration operations
+                  to perform.
+  @param Buffer   The destination buffer to store the results.
+
+  @retval EFI_SUCCESS           The data was read from the PCI root bridge.
+  @retval EFI_INVALID_PARAMETER Invalid parameters found.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPciRead (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL       *This,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+  IN     UINT64                                Address,
+  IN     UINTN                                 Count,
+  IN OUT VOID                                  *Buffer
+  )
+{
+  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;
+  UINT32                    PciBus;
+  UINT32                    PciDev;
+  UINT32                    PciFn;
+  UINT32                    PciExtReg;
+  USRA_ADDRESS              EndPointPciAddress;
+  UINT8                     *pData8 = Buffer;
+  UINT8                     Size;
+
+  Size = 1 << (Width & 0x3);
+
+  if (Buffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Width < 0 || Width >= EfiPciWidthMaximum ) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Read Pci configuration space
+  //
+  RootBridge = ROOT_BRIDGE_FROM_THIS (This);
+
+  if (RootBridge->HecBase == 0) {
+    return RootBridgeIoPciRW (This, FALSE, Width, Address, Count, Buffer);
+  }
+
+  if (!((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->ExtendedRegister) {
+    PciExtReg = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Register;
+  } else {
+    PciExtReg = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->ExtendedRegister & 0x0FFF;
+  }
+
+  PciBus        = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Bus;
+  PciDev        = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Device;
+  PciFn         = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Function;
+
+  USRA_BLOCK_PCIE_ADDRESS (EndPointPciAddress, Width, Count, This->SegmentNumber, PciBus, PciDev, PciFn, PciExtReg);
+  mDynamicSiLibraryProtocol->RegisterRead (&EndPointPciAddress, pData8);
+  return EFI_SUCCESS;
+}
+
+/**
+  Allows write to PCI configuration space.
+
+  @param This     A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+  @param Width    Signifies the width of the memory operation.
+  @param Address  The address within the PCI configuration space
+                  for the PCI controller.
+  @param Count    The number of PCI configuration operations
+                  to perform.
+  @param Buffer   The source buffer to get the results.
+
+  @retval EFI_SUCCESS            The data was written to the PCI root bridge.
+  @retval EFI_INVALID_PARAMETER  Invalid parameters found.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPciWrite (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL       *This,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+  IN     UINT64                                Address,
+  IN     UINTN                                 Count,
+  IN OUT VOID                                  *Buffer
+  )
+{
+  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;
+  UINT32                    PciBus;
+  UINT32                    PciDev;
+  UINT32                    PciFn;
+  UINT32                    PciExtReg;
+  USRA_ADDRESS              EndPointPciAddress;
+  UINT8                     *pData8 = Buffer;
+  UINT8                     Size;
+
+  Size = 1 << (Width & 0x3);
+
+  if (Buffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Width < 0 || Width >= EfiPciWidthMaximum) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Write Pci configuration space
+  //
+  RootBridge = ROOT_BRIDGE_FROM_THIS (This);
+
+  if (RootBridge->HecBase == 0) {
+    return RootBridgeIoPciRW (This, TRUE, Width, Address, Count, Buffer);
+  }
+
+  if (!((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->ExtendedRegister) {
+    PciExtReg = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Register;
+  } else {
+    PciExtReg = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->ExtendedRegister & 0x0FFF;
+  }
+
+  PciBus        = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Bus;
+  PciDev        = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Device;
+  PciFn         = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Function;
+
+  USRA_BLOCK_PCIE_ADDRESS (EndPointPciAddress, Width, Count, This->SegmentNumber, PciBus, PciDev, PciFn, PciExtReg);
+  mDynamicSiLibraryProtocol->RegisterWrite (&EndPointPciAddress, pData8);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Provides the PCI controller-specific address needed to access
+  system memory for DMA.
+
+  @param This           A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param Operation      Indicate if the bus master is going to read or write
+                        to system memory.
+  @param HostAddress    The system memory address to map on the PCI controller.
+  @param NumberOfBytes  On input the number of bytes to map.
+                        On output the number of bytes that were mapped.
+  @param DeviceAddress  The resulting map address for the bus master PCI
+                        controller to use to access the system memory's HostAddress.
+  @param Mapping        The value to pass to Unmap() when the bus master DMA
+                        operation is complete.
+
+  @retval EFI_SUCCESS            Success.
+  @retval EFI_INVALID_PARAMETER  Invalid parameters found.
+  @retval EFI_UNSUPPORTED        The HostAddress cannot be mapped as a common buffer.
+  @retval EFI_DEVICE_ERROR       The System hardware could not map the requested address.
+  @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to lack of resources.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoMap (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL            *This,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION  Operation,
+  IN     VOID                                       *HostAddress,
+  IN OUT UINTN                                      *NumberOfBytes,
+  OUT    EFI_PHYSICAL_ADDRESS                       *DeviceAddress,
+  OUT    VOID                                       **Mapping
+  )
+{
+  EFI_STATUS                                         Status;
+  PCI_ROOT_BRIDGE_INSTANCE                          *RootBridge;
+  EFI_PHYSICAL_ADDRESS                               PhysicalAddress;
+  MAP_INFO                                          *MapInfo;
+
+  if (NumberOfBytes == NULL || Mapping == NULL || DeviceAddress == NULL || HostAddress == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+  //
+  // Initialize the return values to their defaults
+  //
+  *Mapping = NULL;
+
+  //
+  // Make sure that Operation is valid
+  //
+  if ((UINT32) Operation >= EfiPciOperationMaximum) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  RootBridge = ROOT_BRIDGE_FROM_THIS (This);
+
+  if (mIoMmu != NULL) {
+    if (!RootBridge->DmaAbove4G) {
+      //
+      // Clear 64bit support
+      //
+      if (Operation > EfiPciOperationBusMasterCommonBuffer) {
+        Operation = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) (Operation - EfiPciOperationBusMasterRead64);
+      }
+    }
+    Status = mIoMmu->Map (
+                       mIoMmu,
+                       (EDKII_IOMMU_OPERATION) Operation,
+                       HostAddress,
+                       NumberOfBytes,
+                       DeviceAddress,
+                       Mapping
+                       );
+    return Status;
+  }
+  //
+  // Most PCAT like chipsets can not handle performing DMA above 4GB.
+  // If any part of the DMA transfer being mapped is above 4GB, then
+  // map the DMA transfer to a buffer below 4GB.
+  //
+  PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;
+  if ((PhysicalAddress + *NumberOfBytes) > SIZE_4GB) {
+    //
+    // Common Buffer operations can not be remapped.  If the common buffer
+    // if above 4GB, then it is not possible to generate a mapping, so return
+    // an error.
+    //
+    if (Operation == EfiPciOperationBusMasterCommonBuffer || Operation == EfiPciOperationBusMasterCommonBuffer64) {
+      return EFI_INVALID_PARAMETER;
+    }
+    //
+    // Allocate a MAP_INFO structure to remember the mapping when Unmap() is
+    // called later.
+    //
+    MapInfo = AllocatePool (sizeof (MAP_INFO));
+    if (MapInfo == NULL) {
+      *NumberOfBytes = 0;
+      return EFI_OUT_OF_RESOURCES;
+    }
+    //
+    // Return a pointer to the MAP_INFO structure in Mapping
+    //
+    *Mapping = MapInfo;
+
+    //
+    // Initialize the MAP_INFO structure
+    //
+    MapInfo->Operation = Operation;
+    MapInfo->NumberOfBytes = *NumberOfBytes;
+    MapInfo->NumberOfPages = EFI_SIZE_TO_PAGES (*NumberOfBytes);
+    MapInfo->HostAddress = PhysicalAddress;
+    MapInfo->MappedHostAddress = SIZE_4GB - 1;
+
+    //
+    // Allocate a buffer below 4GB to map the transfer to.
+    //
+    Status = gBS->AllocatePages (
+                    AllocateMaxAddress,
+                    EfiBootServicesData,
+                    MapInfo->NumberOfPages,
+                    &MapInfo->MappedHostAddress
+                    );
+    if (EFI_ERROR (Status)) {
+      FreePool (MapInfo);
+      *NumberOfBytes = 0;
+      return Status;
+    }
+    //
+    // If this is a read operation from the Bus Master's point of view,
+    // then copy the contents of the real buffer into the mapped buffer
+    // so the Bus Master can read the contents of the real buffer.
+    //
+    if (Operation == EfiPciOperationBusMasterRead || Operation == EfiPciOperationBusMasterRead64) {
+      CopyMem (
+        (VOID *) (UINTN) MapInfo->MappedHostAddress,
+        (VOID *) (UINTN) MapInfo->HostAddress,
+        MapInfo->NumberOfBytes
+        );
+    }
+    //
+    // The DeviceAddress is the address of the maped buffer below 4GB
+    //
+    *DeviceAddress = MapInfo->MappedHostAddress;
+  } else {
+    //
+    // The transfer is below 4GB, so the DeviceAddress is simply the HostAddress
+    //
+    *DeviceAddress = PhysicalAddress;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Completes the Map() operation and releases any corresponding resources.
+
+  The Unmap() function completes the Map() operation and releases any
+  corresponding resources.
+  If the operation was an EfiPciOperationBusMasterWrite or
+  EfiPciOperationBusMasterWrite64, the data is committed to the target system
+  memory.
+  Any resources used for the mapping are freed.
+
+  @param[in] This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param[in] Mapping   The mapping value returned from Map().
+
+  @retval EFI_SUCCESS            The range was unmapped.
+  @retval EFI_INVALID_PARAMETER  Mapping is not a value that was returned by Map().
+  @retval EFI_DEVICE_ERROR       The data was not committed to the target system memory.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoUnmap (
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
+  IN VOID                             *Mapping
+  )
+{
+  EFI_STATUS                           Status;
+  MAP_INFO                            *MapInfo;
+
+  if (mIoMmu != NULL) {
+    Status = mIoMmu->Unmap (
+                       mIoMmu,
+                       Mapping
+                       );
+    return Status;
+  }
+  //
+  // See if the Map() operation associated with this Unmap() required a mapping buffer.
+  // If a mapping buffer was not required, then this function simply returns EFI_SUCCESS.
+  //
+  if (Mapping != NULL) {
+    //
+    // Get the MAP_INFO structure from Mapping
+    //
+    MapInfo = (MAP_INFO *) Mapping;
+
+    //
+    // If this is a write operation from the Bus Master's point of view,
+    // then copy the contents of the mapped buffer into the real buffer
+    // so the processor can read the contents of the real buffer.
+    //
+    if ((MapInfo->Operation == EfiPciOperationBusMasterWrite) ||
+        (MapInfo->Operation == EfiPciOperationBusMasterWrite64)
+        ) {
+      CopyMem (
+        (VOID *) (UINTN) MapInfo->HostAddress,
+        (VOID *) (UINTN) MapInfo->MappedHostAddress,
+        MapInfo->NumberOfBytes
+        );
+    }
+    //
+    // Free the mapped buffer and the MAP_INFO structure.
+    //
+    gBS->FreePages (MapInfo->MappedHostAddress, MapInfo->NumberOfPages);
+    FreePool (Mapping);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Allocates pages that are suitable for an EfiPciOperationBusMasterCommonBuffer
+  or EfiPciOperationBusMasterCommonBuffer64 mapping.
+
+  @param This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param Type        This parameter is not used and must be ignored.
+  @param MemoryType  The type of memory to allocate, EfiBootServicesData or
+                     EfiRuntimeServicesData.
+  @param Pages       The number of pages to allocate.
+  @param HostAddress A pointer to store the base system memory address of the
+                     allocated range.
+  @param Attributes  The requested bit mask of attributes for the allocated
+                     range. Only the attributes
+                     EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE,
+                     EFI_PCI_ATTRIBUTE_MEMORY_CACHED, and
+                     EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE may be used with this
+                     function.
+
+  @retval EFI_SUCCESS            The requested memory pages were allocated.
+  @retval EFI_INVALID_PARAMETER  MemoryType is invalid.
+  @retval EFI_INVALID_PARAMETER  HostAddress is NULL.
+  @retval EFI_UNSUPPORTED        Attributes is unsupported. The only legal
+                                 attribute bits are MEMORY_WRITE_COMBINE,
+                                 MEMORY_CACHED, and DUAL_ADDRESS_CYCLE.
+  @retval EFI_OUT_OF_RESOURCES   The memory pages could not be allocated.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoAllocateBuffer (
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
+  IN  EFI_ALLOCATE_TYPE                Type,
+  IN  EFI_MEMORY_TYPE                  MemoryType,
+  IN  UINTN                            Pages,
+  OUT VOID                             **HostAddress,
+  IN  UINT64                           Attributes
+  )
+{
+  EFI_STATUS                           Status;
+  EFI_PHYSICAL_ADDRESS                 PhysicalAddress;
+  PCI_ROOT_BRIDGE_INSTANCE            *RootBridge;
+
+  //
+  // Validate Attributes
+  //
+  if ((Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) != 0) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Check for invalid inputs
+  //
+  if (HostAddress == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // The only valid memory types are EfiBootServicesData and
+  // EfiRuntimeServicesData
+  //
+  if (MemoryType != EfiBootServicesData &&
+      MemoryType != EfiRuntimeServicesData) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  RootBridge = ROOT_BRIDGE_FROM_THIS (This);
+
+  if (mIoMmu != NULL) {
+
+    if (!RootBridge->DmaAbove4G) {
+      //
+      // Clear DUAL_ADDRESS_CYCLE
+      //
+      Attributes &= ~((UINT64) EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE);
+    }
+    Status = mIoMmu->AllocateBuffer (
+                       mIoMmu,
+                       Type,
+                       MemoryType,
+                       Pages,
+                       HostAddress,
+                       Attributes
+                       );
+    return Status;
+  }
+
+  //
+  // Limit allocations to memory below 4GB
+  //
+  PhysicalAddress = SIZE_4GB - 1;
+
+  Status = gBS->AllocatePages (
+                  AllocateMaxAddress,
+                  MemoryType,
+                  Pages,
+                  &PhysicalAddress
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  *HostAddress = (VOID *) (UINTN) PhysicalAddress;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Frees memory that was allocated with AllocateBuffer().
+
+  The FreeBuffer() function frees memory that was allocated with
+  AllocateBuffer().
+
+  @param This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param Pages       The number of pages to free.
+  @param HostAddress The base system memory address of the allocated range.
+
+  @retval EFI_SUCCESS            The requested memory pages were freed.
+  @retval EFI_INVALID_PARAMETER  The memory range specified by HostAddress and
+                                 Pages was not allocated with AllocateBuffer().
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoFreeBuffer (
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
+  IN  UINTN                            Pages,
+  OUT VOID                             *HostAddress
+  )
+{
+  EFI_STATUS                Status;
+
+  if (mIoMmu != NULL) {
+    Status = mIoMmu->FreeBuffer (
+                       mIoMmu,
+                       Pages,
+                       HostAddress
+                       );
+    return Status;
+  }
+
+  return gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, Pages);
+}
+
+/**
+  Flushes all PCI posted write transactions from a PCI host bridge to system
+  memory.
+
+  The Flush() function flushes any PCI posted write transactions from a PCI
+  host bridge to system memory. Posted write transactions are generated by PCI
+  bus masters when they perform write transactions to target addresses in
+  system memory.
+  This function does not flush posted write transactions from any PCI bridges.
+  A PCI controller specific action must be taken to guarantee that the posted
+  write transactions have been flushed from the PCI controller and from all the
+  PCI bridges into the PCI host bridge. This is typically done with a PCI read
+  transaction from the PCI controller prior to calling Flush().
+
+  @param This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+
+  @retval EFI_SUCCESS        The PCI posted write transactions were flushed
+                             from the PCI host bridge to system memory.
+  @retval EFI_DEVICE_ERROR   The PCI posted write transactions were not flushed
+                             from the PCI host bridge due to a hardware error.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoFlush (
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL           *This
+  )
+{
+  return EFI_SUCCESS;
+}
+
+/**
+  Gets the attributes that a PCI root bridge supports setting with
+  SetAttributes(), and the attributes that a PCI root bridge is currently
+  using.
+
+  The GetAttributes() function returns the mask of attributes that this PCI
+  root bridge supports and the mask of attributes that the PCI root bridge is
+  currently using.
+
+  @param This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param Supported   A pointer to the mask of attributes that this PCI root
+                     bridge supports setting with SetAttributes().
+  @param Attributes  A pointer to the mask of attributes that this PCI root
+                     bridge is currently using.
+
+  @retval  EFI_SUCCESS           If Supports is not NULL, then the attributes
+                                 that the PCI root bridge supports is returned
+                                 in Supports. If Attributes is not NULL, then
+                                 the attributes that the PCI root bridge is
+                                 currently using is returned in Attributes.
+  @retval  EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoGetAttributes (
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
+  OUT UINT64                           *Supported,
+  OUT UINT64                           *Attributes
+  )
+{
+  PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
+
+  if (Attributes == NULL && Supported == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  RootBridge = ROOT_BRIDGE_FROM_THIS (This);
+  //
+  // Set the return value for Supported and Attributes
+  //
+  if (Supported != NULL) {
+    *Supported  = RootBridge->Supports;
+  }
+
+  if (Attributes != NULL) {
+    *Attributes = RootBridge->Attributes;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Sets attributes for a resource range on a PCI root bridge.
+
+  The SetAttributes() function sets the attributes specified in Attributes for
+  the PCI root bridge on the resource range specified by ResourceBase and
+  ResourceLength. Since the granularity of setting these attributes may vary
+  from resource type to resource type, and from platform to platform, the
+  actual resource range and the one passed in by the caller may differ. As a
+  result, this function may set the attributes specified by Attributes on a
+  larger resource range than the caller requested. The actual range is returned
+  in ResourceBase and ResourceLength. The caller is responsible for verifying
+  that the actual range for which the attributes were set is acceptable.
+
+  @param This            A pointer to the
+                         EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param Attributes      The mask of attributes to set. If the
+                         attribute bit MEMORY_WRITE_COMBINE,
+                         MEMORY_CACHED, or MEMORY_DISABLE is set,
+                         then the resource range is specified by
+                         ResourceBase and ResourceLength. If
+                         MEMORY_WRITE_COMBINE, MEMORY_CACHED, and
+                         MEMORY_DISABLE are not set, then
+                         ResourceBase and ResourceLength are ignored,
+                         and may be NULL.
+  @param ResourceBase    A pointer to the base address of the
+                         resource range to be modified by the
+                         attributes specified by Attributes.
+  @param ResourceLength  A pointer to the length of the resource
+                                   range to be modified by the attributes
+                                   specified by Attributes.
+
+  @retval  EFI_SUCCESS           The current configuration of this PCI root bridge
+                                 was returned in Resources.
+  @retval  EFI_UNSUPPORTED       The current configuration of this PCI root bridge
+                                 could not be retrieved.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoSetAttributes (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
+  IN     UINT64                           Attributes,
+  IN OUT UINT64                           *ResourceBase,
+  IN OUT UINT64                           *ResourceLength
+  )
+{
+  PCI_ROOT_BRIDGE_INSTANCE            *RootBridge;
+
+  RootBridge = ROOT_BRIDGE_FROM_THIS (This);
+
+  if ((Attributes & (~RootBridge->Supports)) != 0) {
+    return EFI_UNSUPPORTED;
+  }
+
+  RootBridge->Attributes = Attributes;
+  return EFI_SUCCESS;
+}
+
+/**
+  Retrieves the current resource settings of this PCI root bridge in the form
+  of a set of ACPI resource descriptors.
+
+  There are only two resource descriptor types from the ACPI Specification that
+  may be used to describe the current resources allocated to a PCI root bridge.
+  These are the QWORD Address Space Descriptor, and the End Tag. The QWORD
+  Address Space Descriptor can describe memory, I/O, and bus number ranges for
+  dynamic or fixed resources. The configuration of a PCI root bridge is described
+  with one or more QWORD Address Space Descriptors followed by an End Tag.
+
+  @param[in]   This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param[out]  Resources   A pointer to the resource descriptors that
+                           describe the current configuration of this PCI root
+                           bridge. The storage for the resource
+                           descriptors is allocated by this function. The
+                           caller must treat the return buffer as read-only
+                           data, and the buffer must not be freed by the
+                           caller.
+
+  @retval  EFI_SUCCESS     The current configuration of this PCI root bridge
+                           was returned in Resources.
+  @retval  EFI_UNSUPPORTED The current configuration of this PCI root bridge
+                           could not be retrieved.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoConfiguration (
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL     *This,
+  OUT VOID                                **Resources
+  )
+{
+  EFI_STATUS                        Status;
+  UINTN                             Idx;
+
+  PCI_ROOT_BRIDGE_INSTANCE          *RootBridge;
+  PCI_RES_NODE                      *ResAllocNode;
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Config;
+
+  //
+  // Get this instance of the Root Bridge.
+  //
+  RootBridge = ROOT_BRIDGE_FROM_THIS (This);
+
+  //
+  // If the pointer is not NULL, it points to a buffer already allocated.
+  //
+  if (RootBridge->ConfigBuffer == NULL) {
+    Status = gBS->AllocatePool (
+                    EfiBootServicesData,
+                    TypeMax * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR),
+                    &RootBridge->ConfigBuffer
+                    );
+    if (EFI_ERROR (Status)) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+  }
+
+  Config = RootBridge->ConfigBuffer;
+
+  ZeroMem (Config, TypeMax * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
+
+  for (Idx = 0; Idx < TypeMax; Idx++) {
+
+    ResAllocNode = &RootBridge->ResAllocNode[Idx];
+
+    if (ResAllocNode->Status != ResAllocated) {
+      continue;
+    }
+
+    switch (ResAllocNode->Type) {
+
+    case TypeIo:
+      Config->Desc          = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+      Config->Len           = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
+      Config->ResType       = ACPI_ADDRESS_SPACE_TYPE_IO;
+      Config->AddrRangeMin  = ResAllocNode->Base;
+      Config->AddrRangeMax  = ResAllocNode->Base + ResAllocNode->Length - 1;
+      Config->AddrLen       = ResAllocNode->Length;
+      break;
+
+    case TypeMem32:
+      Config->Desc                  = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+      Config->Len                   = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
+      Config->ResType               = ACPI_ADDRESS_SPACE_TYPE_MEM;
+      Config->AddrSpaceGranularity  = 32;
+      Config->AddrRangeMin          = ResAllocNode->Base;
+      Config->AddrRangeMax          = ResAllocNode->Base + ResAllocNode->Length - 1;
+      Config->AddrLen               = ResAllocNode->Length;
+      break;
+
+    case TypePMem32:
+      Config->Desc                  = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+      Config->Len                   = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
+      Config->ResType               = ACPI_ADDRESS_SPACE_TYPE_MEM;
+      Config->SpecificFlag          = 6;
+      Config->AddrSpaceGranularity  = 32;
+      Config->AddrRangeMin          = ResAllocNode->Base;
+      Config->AddrRangeMax          = ResAllocNode->Base + ResAllocNode->Length - 1;
+      Config->AddrLen               = ResAllocNode->Length;
+      break;
+
+    case TypeMem64:
+      Config->Desc                  = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+      Config->Len                   = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
+      Config->ResType               = ACPI_ADDRESS_SPACE_TYPE_MEM;
+      Config->SpecificFlag          = 6;
+      Config->AddrSpaceGranularity  = 64;
+      Config->AddrRangeMin          = ResAllocNode->Base;
+      Config->AddrRangeMax          = ResAllocNode->Base + ResAllocNode->Length - 1;
+      Config->AddrLen               = ResAllocNode->Length;
+      break;
+
+    case TypePMem64:
+      Config->Desc                  = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+      Config->Len                   = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
+      Config->ResType               = ACPI_ADDRESS_SPACE_TYPE_MEM;
+      Config->SpecificFlag          = 6;
+      Config->AddrSpaceGranularity  = 64;
+      Config->AddrRangeMin          = ResAllocNode->Base;
+      Config->AddrRangeMax          = ResAllocNode->Base + ResAllocNode->Length - 1;
+      Config->AddrLen               = ResAllocNode->Length;
+      break;
+
+    case TypeBus:
+      Config->Desc          = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+      Config->Len           = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
+      Config->ResType       = ACPI_ADDRESS_SPACE_TYPE_BUS;
+      Config->AddrRangeMin  = ResAllocNode->Base;
+      Config->AddrRangeMax  = ResAllocNode->Base + ResAllocNode->Length - 1;
+      Config->AddrLen       = ResAllocNode->Length;
+      break;
+
+    default:
+      break;
+    }
+
+    Config++;
+  }
+  //
+  // Terminate the entries.
+  //
+  ((EFI_ACPI_END_TAG_DESCRIPTOR *) Config)->Desc      = ACPI_END_TAG_DESCRIPTOR;
+  ((EFI_ACPI_END_TAG_DESCRIPTOR *) Config)->Checksum  = 0x0;
+
+  *Resources = RootBridge->ConfigBuffer;
+  return EFI_SUCCESS;
+}
+
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciPlatform/PciIovPlatformPolicy.c b/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciPlatform/PciIovPlatformPolicy.c
new file mode 100644
index 0000000000..32775fafe7
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciPlatform/PciIovPlatformPolicy.c
@@ -0,0 +1,99 @@
+/** @file
+
+  @copyright
+  Copyright 2014 - 2021 Intel Corporation. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <PiDxe.h>
+#include "PciPlatform.h"
+#include <Guid/SetupVariable.h>
+
+#ifdef EFI_PCI_IOV_SUPPORT
+
+/**
+
+    The GetSystemLowestPageSize() function retrieves the system lowest page size.
+
+    @param This                 - Pointer to the EFI_PCI_IOV_PLATFORM_PROTOCOL instance.
+    @param SystemLowestPageSize - The system lowest page size. (This system supports a
+                                  page size of 2^(n+12) if bit n is set.)
+
+    @retval EFI_SUCCESS           - The function completed successfully.
+    @retval EFI_INVALID_PARAMETER - SystemLowestPageSize is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+GetSystemLowestPageSize (
+  IN  EFI_PCI_IOV_PLATFORM_PROTOCOL           *This,
+  OUT UINT32                                  *SystemLowestPageSize
+)
+{
+  UINT8                                 SystemPageSizeOption;
+
+  CopyMem (&SystemPageSizeOption, (((UINT8*) PcdGetPtr (PcdSetup)) + OFFSET_OF (SYSTEM_CONFIGURATION, SystemPageSize)), sizeof (UINT8));
+
+  if (SystemLowestPageSize != NULL) {
+    //
+    // Convert page size option to page size
+    // Option is n in 2^n
+    // Page size is number of 4KiB pages
+    //
+
+    *SystemLowestPageSize = (UINT32) (1 << SystemPageSizeOption);
+  }
+  return EFI_SUCCESS;
+}
+
+/**
+
+    The GetIovPlatformPolicy() function retrieves the platform policy regarding PCI IOV.
+
+    @param This         - Pointer to the EFI_PCI_IOV_PLATFORM_PROTOCOL instance.
+    @param PciIovPolicy - The platform policy for PCI IOV configuration.
+
+    @retval EFI_SUCCESS           - The function completed successfully.
+    @retval EFI_INVALID_PARAMETER - PciPolicy is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+GetIovPlatformPolicy (
+  IN  EFI_PCI_IOV_PLATFORM_PROTOCOL           *This,
+  OUT EFI_PCI_IOV_PLATFORM_POLICY             *PciIovPolicy
+)
+{
+  UINT8                                 PolicyEnable;
+  UINT8                                 ARIEnable;
+  UINT8                                 SRIOVEnable;
+  UINT8                                 MRIOVEnable;
+
+  PolicyEnable = 0;
+
+  CopyMem (&ARIEnable,   (((UINT8*) PcdGetPtr (PcdSetup)) + OFFSET_OF (SYSTEM_CONFIGURATION, ARIEnable)),   sizeof (UINT8));
+  CopyMem (&SRIOVEnable, (((UINT8*) PcdGetPtr (PcdSetup)) + OFFSET_OF (SYSTEM_CONFIGURATION, SRIOVEnable)), sizeof (UINT8));
+  CopyMem (&MRIOVEnable, (((UINT8*) PcdGetPtr (PcdSetup)) + OFFSET_OF (SYSTEM_CONFIGURATION, MRIOVEnable)), sizeof (UINT8));
+
+  if (ARIEnable == TRUE) {
+    PolicyEnable = PolicyEnable | EFI_PCI_IOV_POLICY_ARI;
+  }
+
+  if (SRIOVEnable == TRUE) {
+    PolicyEnable = PolicyEnable | EFI_PCI_IOV_POLICY_SRIOV;
+  }
+
+  if (MRIOVEnable == TRUE) {
+    PolicyEnable = PolicyEnable | EFI_PCI_IOV_POLICY_MRIOV;
+  }
+
+  if (PciIovPolicy != NULL) {
+    //*PciIovPolicy = EFI_PCI_IOV_POLICY_ARI | EFI_PCI_IOV_POLICY_SRIOV;
+    *PciIovPolicy = PolicyEnable;
+  }
+  return EFI_SUCCESS;
+}
+
+#endif
+
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciPlatform/PciIovPlatformPolicy.h b/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciPlatform/PciIovPlatformPolicy.h
new file mode 100644
index 0000000000..ecd57292e2
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciPlatform/PciIovPlatformPolicy.h
@@ -0,0 +1,53 @@
+/** @file
+  Include file for PciIovPlatformPolicy.c
+
+  @copyright
+  Copyright 2014 - 2021 Intel Corporation. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PCI_IOV_PLATFORM_POLICY_H_
+#define _PCI_IOV_PLATFORM_POLICY_H_
+
+/**
+
+    The GetSystemLowestPageSize() function retrieves the system lowest page size.
+
+    @param This                 - Pointer to the EFI_PCI_IOV_PLATFORM_PROTOCOL instance.
+    @param SystemLowestPageSize - The system lowest page size. (This system supports a
+                                  page size of 2^(n+12) if bit n is set.)
+
+    @retval EFI_SUCCESS           - The function completed successfully.
+    @retval EFI_INVALID_PARAMETER - SystemLowestPageSize is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+GetSystemLowestPageSize (
+  IN  EFI_PCI_IOV_PLATFORM_PROTOCOL           *This,
+  OUT UINT32                                  *SystemLowestPageSize
+)
+;
+
+
+/**
+
+    The GetPlatformPolicy() function retrieves the platform policy regarding PCI IOV.
+
+    @param This         - Pointer to the EFI_PCI_IOV_PLATFORM_PROTOCOL instance.
+    @param PciIovPolicy - The platform policy for PCI IOV configuration.
+
+    @retval EFI_SUCCESS           - The function completed successfully.
+    @retval EFI_INVALID_PARAMETER - PciPolicy is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+GetIovPlatformPolicy (
+  IN  EFI_PCI_IOV_PLATFORM_PROTOCOL           *This,
+  OUT EFI_PCI_IOV_PLATFORM_POLICY             *PciIovPolicy
+)
+;
+
+#endif
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciPlatform/PciPlatform.c b/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciPlatform/PciPlatform.c
new file mode 100644
index 0000000000..8584c0f330
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciPlatform/PciPlatform.c
@@ -0,0 +1,541 @@
+/** @file
+
+  @copyright
+  Copyright 2004 - 2021 Intel Corporation. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <PiDxe.h>
+#include "PciPlatform.h"
+#include <Library/PcdLib.h>
+#include <Library/PlatformOpromPolicyLib.h>
+#include <Protocol/DynamicSiLibraryProtocol.h>
+#include <Protocol/UbaCfgDb.h>
+#ifdef EFI_PCI_IOV_SUPPORT
+#include "PciIovPlatformPolicy.h"
+#endif
+
+#include <Library/UbaPlatLib.h>
+
+PCI_PLATFORM_PRIVATE_DATA mPciPrivateData;
+
+BOOLEAN                   FirstCall = TRUE;
+UINT8                     sSataRaidLoadEfiDriverOption;
+UINT8                     SataRaidLoadEfiDriverOption[PCH_MAX_SATA_CONTROLLERS];
+UINT8                     BootNetworkOption;
+
+STATIC
+BOOLEAN
+InternalPlatformCheckPcieRootPort (
+  IN  UINTN                 Bus,
+  IN  UINT32                PcieSlotOpromBitMap
+)
+{
+  EFI_STATUS                              Status;
+
+  UBA_CONFIG_DATABASE_PROTOCOL            *UbaConfigProtocol = NULL;
+  UINTN                                   DataLength = 0;
+  PLATFORM_OPTION_ROM_UPDATE_DATA         OptionRomUpdateTable;
+
+  Status = gBS->LocateProtocol (
+                  &gUbaConfigDatabaseProtocolGuid,
+                  NULL,
+                  &UbaConfigProtocol
+                  );
+  if (EFI_ERROR(Status)) {
+    DEBUG ((DEBUG_INFO," InternalPlatformCheckPcieRootPort fail!\n"));
+    return TRUE;
+  }
+
+  DataLength  = sizeof (OptionRomUpdateTable);
+  Status = UbaConfigProtocol->GetData (
+                                UbaConfigProtocol,
+                                &gPlatformOptionRomUpdateConfigDataGuid,
+                                &OptionRomUpdateTable,
+                                &DataLength
+                                );
+  if (EFI_ERROR(Status)) {
+    DEBUG ((DEBUG_INFO,"InternalPlatformCheckPcieRootPort fail!\n"));
+    return TRUE;
+  }
+
+  ASSERT (OptionRomUpdateTable.Signature == PLATFORM_OPTION_ROM_UPDATE_SIGNATURE);
+  ASSERT (OptionRomUpdateTable.Version == PLATFORM_OPTION_ROM_UPDATE_VERSION);
+
+  return OptionRomUpdateTable.CallCheckRootPort (Bus, PcieSlotOpromBitMap);
+}
+
+STATIC
+EFI_STATUS
+InternalGetSystemBoardInfo (
+  IN OUT   DXE_SYSTEM_BOARD_INFO       **SystemboardInfoTableBuffer
+  )
+{
+  EFI_STATUS                        Status;
+  UBA_CONFIG_DATABASE_PROTOCOL      *UbaConfigProtocol = NULL;
+  UINTN                             DataLength = 0;
+  SYSTEM_BOARD_INFO_DATA            SystemBoardInfoData;
+
+  Status = gBS->LocateProtocol (
+                  &gUbaConfigDatabaseProtocolGuid,
+                  NULL,
+                  &UbaConfigProtocol
+                  );
+
+  if (EFI_ERROR(Status)) {
+    DEBUG ((EFI_D_ERROR,"  [GetSystemBoardInfo] Locate UbaConfigProtocol fail!\n"));
+    return Status;
+  }
+
+  DataLength = sizeof(SystemBoardInfoData);
+  Status = UbaConfigProtocol->GetData (
+                                UbaConfigProtocol,
+                                &gSystemBoardInfoConfigDataGuid,
+                                &SystemBoardInfoData,
+                                &DataLength
+                                );
+
+  if (EFI_ERROR(Status)) {
+    DEBUG ((EFI_D_ERROR," [GetSystemBoardInfo] Get Data fail!\n"));
+    return Status;
+  }
+
+  ASSERT (SystemBoardInfoData.Signature == SYSTEM_SYSTEM_BOARD_INFO_SIGNATURE);
+  ASSERT (SystemBoardInfoData.Version   == SYSTEM_SYSTEM_BOARD_INFO_VERSION);
+
+  *SystemboardInfoTableBuffer = SystemBoardInfoData.CallUpdate ();
+
+  return Status;
+}
+
+/**
+
+  Set the PciPolicy as EFI_RESERVE_ISA_IO_NO_ALIAS | EFI_RESERVE_VGA_IO_NO_ALIAS.
+
+  @param This       -  The pointer to the Protocol itself.
+  PciPolicy  -  the returned Policy.
+
+  @retval EFI_UNSUPPORTED        -  Function not supported.
+  @retval EFI_INVALID_PARAMETER  -  Invalid PciPolicy value.
+
+**/
+EFI_STATUS
+EFIAPI
+GetPlatformPolicy (
+  IN  CONST EFI_PCI_PLATFORM_PROTOCOL         *This,
+  OUT EFI_PCI_PLATFORM_POLICY           *PciPolicy
+  )
+{
+  if (PciPolicy == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return EFI_UNSUPPORTED;
+}
+
+/**
+
+  Get an indicated image in raw sections.
+
+  @param NameGuid  -  NameGuid of the image to get.
+  @param Buffer    -  Buffer to store the image get.
+  @param Size      -  size of the image get.
+
+  @retval EFI_NOT_FOUND   -  Could not find the image.
+  @retval EFI_LOAD_ERROR  -  Error occurred during image loading.
+  @retval EFI_SUCCESS     -  Image has been successfully loaded.
+
+**/
+EFI_STATUS
+GetRawImage(
+   IN     EFI_GUID                       *NameGuid,
+   IN OUT VOID                           **Buffer,
+   IN OUT UINTN                          *Size
+   ) {
+  EFI_STATUS                    Status;
+  EFI_HANDLE                    *HandleBuffer;
+  UINTN                         HandleCount;
+  UINTN                         Index;
+  EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
+  UINT32                        AuthenticationStatus;
+
+  Status = gBS->LocateHandleBuffer(
+     ByProtocol,
+     &gEfiFirmwareVolume2ProtocolGuid,
+     NULL,
+     &HandleCount,
+     &HandleBuffer
+     );
+  if (EFI_ERROR(Status) || HandleCount == 0) {
+    return EFI_NOT_FOUND;
+  }
+  //
+  // Find desired image in all Fvs
+  //
+  for (Index = 0; Index < HandleCount; Index++) {
+    Status = gBS->HandleProtocol(
+       HandleBuffer[Index],
+       &gEfiFirmwareVolume2ProtocolGuid,
+       &Fv
+       );
+    if (EFI_ERROR(Status)) {
+      return EFI_LOAD_ERROR;
+    }
+    //
+    // Try a raw file
+    //
+    *Buffer = NULL;
+    *Size   = 0;
+    Status = Fv->ReadSection(
+         Fv,
+         NameGuid,
+         EFI_SECTION_RAW,
+         0,
+         Buffer,
+         Size,
+         &AuthenticationStatus
+         );
+    if (!EFI_ERROR(Status)) {
+      DEBUG((EFI_D_INFO, "Read the OROM successfully!\n"));
+      break;
+    }
+  }
+
+  if (Index >= HandleCount) {
+    return EFI_NOT_FOUND;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+
+  Return a PCI ROM image for the onboard device represented by PciHandle.
+
+  @param This       -  Protocol instance pointer.
+  PciHandle  -  PCI device to return the ROM image for.
+  RomImage   -  PCI Rom Image for onboard device.
+  RomSize    -  Size of RomImage in bytes.
+
+  @retval EFI_SUCCESS    -  RomImage is valid.
+  @retval EFI_NOT_FOUND  -  No RomImage.
+
+**/
+EFI_STATUS
+EFIAPI
+GetPciRom (
+  IN  CONST EFI_PCI_PLATFORM_PROTOCOL   *This,
+  IN  EFI_HANDLE                        PciHandle,
+  OUT VOID                              **RomImage,
+  OUT UINTN                             *RomSize
+  )
+{
+  EFI_STATUS                        Status;
+  EFI_PCI_IO_PROTOCOL               *PciIo;
+  UINTN                             Segment;
+  UINTN                             Bus;
+  UINTN                             Device;
+  UINTN                             Function;
+  UINT16                            VendorId;
+  UINT16                            DeviceId;
+  UINT16                            DeviceClass;
+  UINTN                             TableIndex;
+  UINTN                             RomImageNumber;
+  VOID                              *OpRomBase;
+  UINTN                             OpRomSize;
+  EFI_PCI_ROM_HEADER                RomHeader;
+  PCI_DATA_STRUCTURE                *Pcir;
+  OPROM_LOAD_POLICY                 OpromPolicy;
+  BOOLEAN                           SlotOptionRomDisabled;
+  DXE_SYSTEM_BOARD_INFO             *SystemBoardInfo = NULL;
+  UINT32                            Index;
+  DYNAMIC_SI_LIBARY_PROTOCOL        *DynamicSiLibraryProtocol = NULL;
+
+  OpRomBase = NULL;
+  OpRomSize = 0;
+
+  Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocolGuid, NULL, &DynamicSiLibraryProtocol);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    return Status;
+  }
+
+  //
+  // Get System Board Info
+  //
+  Status = InternalGetSystemBoardInfo (&SystemBoardInfo);
+  ASSERT_EFI_ERROR (Status);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "[GetPciRom] Get system board info fail!\n"));
+    return Status;
+  }
+
+  Status = gBS->HandleProtocol (
+                  PciHandle,
+                  &gEfiPciIoProtocolGuid,
+                  (VOID **) &PciIo
+                  );
+  if (EFI_ERROR (Status)) {
+    return EFI_NOT_FOUND;
+  }
+
+  if (FirstCall == TRUE) {
+    Status = GetOptionData (&gEfiSetupVariableGuid, OFFSET_OF(SYSTEM_CONFIGURATION, BootNetwork), &BootNetworkOption, sizeof(BootNetworkOption));
+    if (EFI_ERROR (Status)) {
+      BootNetworkOption = 0;
+    }
+    Status = GetOptionData (&gPchSetupVariableGuid,
+                          OFFSET_OF(PCH_SETUP, SataRaidLoadEfiDriver),
+                          &SataRaidLoadEfiDriverOption,
+                          sizeof(SataRaidLoadEfiDriverOption) * PCH_MAX_SATA_CONTROLLERS);
+    if (EFI_ERROR (Status)) {
+      for (Index = 0; Index < DynamicSiLibraryProtocol->MaxSataControllerNum(); Index++) {
+        SataRaidLoadEfiDriverOption[Index] = 0;
+      }
+    }
+
+    FirstCall = FALSE;
+  }
+
+  PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);
+  PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, PCI_CLASSCODE_OFFSET + 1, 1, &DeviceClass);
+
+  //
+  // Run PXE ROM only if Boot network is enabled
+  //
+  if ((BootNetworkOption == 0) &&
+      (DeviceClass == ((PCI_CLASS_NETWORK << 8) | PCI_CLASS_NETWORK_ETHERNET))
+      ) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Run each PCI-E slot ROM only if PCI-E Slot Oprom is enabled.
+  //
+  if ( Bus != 0 ) {
+    SlotOptionRomDisabled = InternalPlatformCheckPcieRootPort (Bus, PcdGet32(PcdOemSkuPcieSlotOpromBitMap));
+
+    if (SlotOptionRomDisabled) {
+      return EFI_NOT_FOUND;
+    }
+  }
+
+  PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, PCI_VENDOR_ID_OFFSET, 1, &VendorId);
+  PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, PCI_DEVICE_ID_OFFSET, 1, &DeviceId);
+
+  //DEBUG ((EFI_D_INFO, "GetPciRom - VenID:DevID: %04x:%04x\n", (UINTN)VendorId, (UINTN)DeviceId));
+
+  //
+  // Fix MS-HD5770 video adapter can not work:
+  // This device is not a OPROM 3.0 and does not have device id list as well.
+  // It only have 1 device id in OPROM.
+  // Device Id in OpROM is not same with the value in PCI configuration space
+  // it will cause VBIOS fails to start
+  //
+  if ((VendorId == 0x1002) && (DeviceId == 0x68BE)) {
+    DEBUG ((DEBUG_INFO, "MS-HD5770 video adapter\n"));
+    RomHeader.Raw = PciIo->RomImage;
+    if (RomHeader.Raw != NULL) {
+      Pcir = (PCI_DATA_STRUCTURE *)(RomHeader.Raw + RomHeader.Generic->PcirOffset);
+      if ((Pcir->VendorId == 0x1002) && (Pcir->DeviceId == 0x68B8)) {
+        //
+        // Assign same device id in PCI configuration space
+        //
+        Pcir->DeviceId = DeviceId;
+      }
+    } else {
+      DEBUG ((EFI_D_ERROR, "MS-HD5770 video adapter detected but PciIo->RomImage == NULL!\n"));
+    }
+  }
+
+  //Check if user disables the option rom loading for this device.
+  if (!PlatformOpromLoadDevicePolicy(PciIo)) {
+    return EFI_NOT_FOUND;
+  }
+
+   // If setup value requested EFI, we don't load the RAID OROM.
+  if (VendorId == V_SATA_CFG_VENDOR_ID) {
+    for (Index = 0; Index < DynamicSiLibraryProtocol->MaxSataControllerNum(); Index++) {
+      if (Bus == DEFAULT_PCI_BUS_NUMBER_PCH &&
+          Device == DynamicSiLibraryProtocol->SataDevNumber (Index) &&
+          Function == DynamicSiLibraryProtocol->SataFuncNumber (Index) &&
+          SataRaidLoadEfiDriverOption[Index] == 1) {
+        return EFI_NOT_FOUND;
+      }
+    }
+  }
+
+  //
+  // Loop through table of video option rom descriptions
+  //
+  RomImageNumber = 0;
+  for (TableIndex = 0; SystemBoardInfo->PciOptionRomTable[TableIndex].VendorId != 0xffff; TableIndex++) {
+    //
+    // See if the PCI device specified by PciHandle matches at device in mPciOptionRomTable
+    //
+    if (VendorId != SystemBoardInfo->PciOptionRomTable[TableIndex].VendorId ||
+        DeviceId != SystemBoardInfo->PciOptionRomTable[TableIndex].DeviceId ||
+        Device != SystemBoardInfo->PciOptionRomTable[TableIndex].Device ||
+        Function != SystemBoardInfo->PciOptionRomTable[TableIndex].Function
+        ) {
+      continue;
+    }
+
+    //Check if user wants to exclusively run this option rom for the device.
+    OpromPolicy = PlatformOpromLoadTypePolicy(PciHandle, TableIndex);
+    if(OpromPolicy == DONT_LOAD) {
+      continue;
+    }
+
+    Status = GetRawImage (
+              &SystemBoardInfo->PciOptionRomTable[TableIndex].FileName,
+              &OpRomBase,
+              &OpRomSize
+              );
+
+    if (EFI_ERROR (Status)) {
+      continue;
+    } else {
+      RomImageNumber++;
+      if (RomImageNumber == PcdGet8(PcdMaxOptionRomNumber) || OpromPolicy == EXCLUSIVE_LOAD) {
+        break;
+      }
+    }
+  }
+
+  if (RomImageNumber == 0) {
+
+    return EFI_NOT_FOUND;
+
+  } else {
+
+    *RomImage = OpRomBase;
+    *RomSize  = OpRomSize;
+
+    return EFI_SUCCESS;
+  }
+}
+
+/**
+
+  GC_TODO: Add function description
+
+  @param This      - GC_TODO: add argument description
+  @param Function  - GC_TODO: add argument description
+  @param Phase     - GC_TODO: add argument description
+
+  @retval EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
+  @retval EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
+  @retval EFI_UNSUPPORTED - GC_TODO: Add description for return value
+  @retval EFI_SUCCESS - GC_TODO: Add description for return value
+
+**/
+EFI_STATUS
+EFIAPI
+RegisterPciCallback (
+  IN  EFI_PCI_CALLBACK_PROTOCOL               *This,
+  IN  EFI_PCI_CALLBACK_FUNC                   Function,
+  IN  EFI_PCI_ENUMERATION_PHASE               Phase
+  )
+{
+  LIST_ENTRY     *NodeEntry;
+  PCI_CALLBACK_DATA *PciCallbackData;
+
+  if (Function == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ( (Phase &  (EfiPciEnumerationDeviceScanning | EfiPciEnumerationBusNumberAssigned \
+              | EfiPciEnumerationResourceAssigned)) == 0) {
+    return EFI_INVALID_PARAMETER;
+  }
+  //
+  // Check if the node has been added
+  //
+  NodeEntry = GetFirstNode (&mPciPrivateData.PciCallbackList);
+  while (!IsNull (&mPciPrivateData.PciCallbackList, NodeEntry)) {
+    PciCallbackData = PCI_CALLBACK_DATA_FROM_LINK (NodeEntry);
+    if (PciCallbackData->Function == Function) {
+      return EFI_UNSUPPORTED;
+    }
+
+    NodeEntry = GetNextNode (&mPciPrivateData.PciCallbackList, NodeEntry);
+  }
+
+  PciCallbackData = NULL;
+  PciCallbackData = AllocateZeroPool (sizeof (PCI_CALLBACK_DATA));
+  ASSERT (PciCallbackData != NULL);
+
+  if(PciCallbackData != NULL){
+    PciCallbackData->Signature  = PCI_CALLBACK_DATA_SIGNATURE;
+    PciCallbackData->Function   = Function;
+    PciCallbackData->Phase      = Phase;
+    InsertTailList (&mPciPrivateData.PciCallbackList, &PciCallbackData->Link);
+    return EFI_SUCCESS;
+  } else {
+    return EFI_UNSUPPORTED;
+  }
+}
+
+
+/**
+
+  Main Entry point of the Pci Platform Driver.
+
+  @param ImageHandle  -  Handle to the image.
+  @param SystemTable  -  Handle to System Table.
+
+  @retval EFI_STATUS  -  Status of the function calling.
+
+**/
+EFI_STATUS
+EFIAPI
+PciPlatformDriverEntry (
+  IN EFI_HANDLE                         ImageHandle,
+  IN EFI_SYSTEM_TABLE                   *SystemTable
+  )
+{
+  EFI_STATUS  Status;
+  EFI_HOB_GUID_TYPE             *GuidHob;
+
+
+  GuidHob    = GetFirstGuidHob (&gEfiPlatformInfoGuid);
+  ASSERT (GuidHob != NULL);
+  if (GuidHob == NULL) {
+    return EFI_NOT_FOUND;
+  }
+  mPciPrivateData.PlatformInfo = GET_GUID_HOB_DATA(GuidHob);
+
+  //EDK2_TODO Check if clearing mPciPrivateData.PlatformInfo (got above) is intended.
+  ZeroMem (&mPciPrivateData, sizeof (mPciPrivateData));
+  InitializeListHead (&mPciPrivateData.PciCallbackList);
+
+  mPciPrivateData.PciPlatform.PlatformNotify          = PhaseNotify;
+  mPciPrivateData.PciPlatform.PlatformPrepController  = PlatformPrepController;
+  mPciPrivateData.PciPlatform.GetPlatformPolicy       = GetPlatformPolicy;
+  mPciPrivateData.PciPlatform.GetPciRom               = GetPciRom;
+  mPciPrivateData.PciCallback.RegisterPciCallback     = RegisterPciCallback;
+#ifdef EFI_PCI_IOV_SUPPORT
+  mPciPrivateData.PciIovPlatform.GetSystemLowestPageSize = GetSystemLowestPageSize;
+  mPciPrivateData.PciIovPlatform.GetPlatformPolicy       = GetIovPlatformPolicy;
+#endif
+
+  //
+  // Install on a new handle
+  //
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &mPciPrivateData.PciPlatformHandle,
+                  &gEfiPciPlatformProtocolGuid,
+                  &mPciPrivateData.PciPlatform,
+                  &gEfiPciCallbackProtocolGuid,
+                  &mPciPrivateData.PciCallback,
+#ifdef EFI_PCI_IOV_SUPPORT
+                  &gEfiPciIovPlatformProtocolGuid,
+                  &mPciPrivateData.PciIovPlatform,
+#endif
+                  NULL
+                  );
+
+  return Status;
+}
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciPlatform/PciPlatform.h b/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciPlatform/PciPlatform.h
new file mode 100644
index 0000000000..45d9c38b16
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciPlatform/PciPlatform.h
@@ -0,0 +1,209 @@
+/** @file
+  This is PCI platform initialization code.
+
+  @copyright
+  Copyright 2004 - 2021 Intel Corporation. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PCI_PLATFORM_MODULE_H_
+#define _PCI_PLATFORM_MODULE_H_
+
+#include <PiDxe.h>
+#include <Register/PchRegsEva.h>
+#include <PchAccess.h>
+#include <Platform.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/S3PciLib.h>
+#include <Library/PciLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/HobLib.h>
+#include <Library/SetupLib.h>
+#include <Protocol/Runtime.h>
+#include <Protocol/CpuIo2.h>
+#include <Protocol/PciCallback.h>
+#include <Protocol/PciPlatform.h>
+#include <Protocol/PciIovPlatform.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <SystemBoard.h>
+#include <Guid/SetupVariable.h>
+#include <Guid/SocketVariable.h>
+#include <Guid/PlatformInfo.h>
+#include <IndustryStandard/Pci.h>
+
+
+#ifndef NELEMENTS
+#define NELEMENTS(Array) (sizeof(Array)/sizeof((Array)[0]))
+#endif
+//
+// Global variables for Option ROMs
+//
+
+#define INVALID                     0xBD
+
+#define PCI_CALLBACK_DATA_SIGNATURE SIGNATURE_32 ('P', 'c', 'i', 'c')
+
+typedef struct {
+  UINT32                    Signature;
+  LIST_ENTRY                Link;
+  EFI_PCI_CALLBACK_FUNC     Function;
+  EFI_PCI_ENUMERATION_PHASE Phase;
+} PCI_CALLBACK_DATA;
+
+typedef struct {
+  EFI_HANDLE                      PciPlatformHandle;
+  EFI_HANDLE                      RootBridgeHandle;
+  EFI_PCI_PLATFORM_PROTOCOL       PciPlatform;
+  EFI_PCI_CALLBACK_PROTOCOL       PciCallback;
+#ifdef EFI_PCI_IOV_SUPPORT
+  EFI_PCI_IOV_PLATFORM_PROTOCOL   PciIovPlatform;
+#endif
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo[MAX_SOCKET][MAX_IIO_STACK];
+  EFI_CPU_IO2_PROTOCOL            *CpuIo;
+  EFI_LIST_ENTRY                  PciCallbackList;
+  EFI_PCI_CALLBACK_CONTEXT        Context;
+  EFI_PCI_ENUMERATION_PHASE       PciEnumerationPhase;
+  EFI_PLATFORM_INFO               *PlatformInfo;
+  UINT8                           BusAssignedTime;
+} PCI_PLATFORM_PRIVATE_DATA;
+
+#define PCI_CALLBACK_DATA_FROM_LINK(_node) \
+  CR ( \
+    _node, \
+    PCI_CALLBACK_DATA, \
+    Link, \
+    PCI_CALLBACK_DATA_SIGNATURE \
+    )
+
+extern PCI_PLATFORM_PRIVATE_DATA  mPciPrivateData;
+extern EFI_GUID  gPchSataEfiLoadProtocolGuid;
+
+/**
+
+  Perform initialization by the phase indicated.
+
+  @param This          -  Pointer to the EFI_PCI_PLATFORM_PROTOCOL instance.
+  @param HostBridge    -  The associated PCI Host bridge handle.
+  @param Phase         -  The phase of the PCI controller enumeration.
+  @param ChipsetPhase  -  Defines the execution phase of the PCI chipset driver.
+
+  @retval EFI_SUCCESS  -  Must return with success.
+
+**/
+EFI_STATUS
+EFIAPI
+PhaseNotify (
+  IN EFI_PCI_PLATFORM_PROTOCOL                        *This,
+  IN EFI_HANDLE                                       HostBridge,
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE    Phase,
+  IN EFI_PCI_CHIPSET_EXECUTION_PHASE                  ChipsetPhase
+  )
+;
+
+/**
+
+  The PlatformPrepController() function can be used to notify the platform driver so that
+  it can perform platform-specific actions. No specific actions are required.
+  Several notification points are defined at this time. More synchronization points may be
+  added as required in the future. The PCI bus driver calls the platform driver twice for
+  every PCI controller-once before the PCI Host Bridge Resource Allocation Protocol driver
+  is notified, and once after the PCI Host Bridge Resource Allocation Protocol driver has
+  been notified.
+  This member function may not perform any error checking on the input parameters. It also
+  does not return any error codes. If this member function detects any error condition, it
+  needs to handle those errors on its own because there is no way to surface any errors to
+  the caller.
+
+  @param This          -  Pointer to the EFI_PCI_PLATFORM_PROTOCOL instance.
+  @param HostBridge    -  The associated PCI Host bridge handle.
+  @param RootBridge    -  The associated PCI root bridge handle.
+  @param PciAddress    -  The address of the PCI device on the PCI bus.
+  @param Phase         -  The phase of the PCI controller enumeration.
+  @param ChipsetPhase  -  Defines the execution phase of the PCI chipset driver.
+
+  @retval EFI_SUCCESS  -  The function completed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformPrepController (
+  IN  EFI_PCI_PLATFORM_PROTOCOL                      *This,
+  IN  EFI_HANDLE                                     HostBridge,
+  IN  EFI_HANDLE                                     RootBridge,
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS    PciAddress,
+  IN  EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE   Phase,
+  IN  EFI_PCI_CHIPSET_EXECUTION_PHASE                ChipsetPhase
+  )
+;
+
+/**
+
+  Set the PciPolicy as EFI_RESERVE_ISA_IO_NO_ALIAS | EFI_RESERVE_VGA_IO_NO_ALIAS.
+
+  @param This       -  The pointer to the Protocol itself.
+  PciPolicy  -  the returned Policy.
+
+  @retval EFI_UNSUPPORTED        -  Function not supported.
+  @retval EFI_INVALID_PARAMETER  -  Invalid PciPolicy value.
+
+**/
+EFI_STATUS
+EFIAPI
+GetPlatformPolicy (
+  IN  CONST EFI_PCI_PLATFORM_PROTOCOL            *This,
+  OUT EFI_PCI_PLATFORM_POLICY              *PciPolicy
+  )
+;
+
+/**
+
+  Return a PCI ROM image for the onboard device represented by PciHandle.
+
+  @param This       -  Protocol instance pointer.
+  PciHandle  -  PCI device to return the ROM image for.
+  RomImage   -  PCI Rom Image for onboard device.
+  RomSize    -  Size of RomImage in bytes.
+
+  @retval EFI_SUCCESS    -  RomImage is valid.
+  @retval EFI_NOT_FOUND  -  No RomImage.
+
+**/
+EFI_STATUS
+EFIAPI
+GetPciRom (
+  IN   CONST EFI_PCI_PLATFORM_PROTOCOL      *This,
+  IN   EFI_HANDLE                           PciHandle,
+  OUT  VOID                                 **RomImage,
+  OUT  UINTN                                *RomSize
+  )
+;
+
+/**
+
+  Register a callback during PCI bus enumeration
+
+  @param This       -  Protocol instance pointer.
+  @param Function   -  Callback function pointer.
+  @param Phase      -  PCI enumeration phase.
+
+  @retval EFI_SUCCESS           - Function has registed successfully
+  @retval EFI_UNSUPPORTED       - The function has been regisered
+  @retval EFI_InVALID_PARAMETER - The parameter is incorrect
+
+**/
+EFI_STATUS
+EFIAPI
+RegisterPciCallback (
+  IN  EFI_PCI_CALLBACK_PROTOCOL               *This,
+  IN  EFI_PCI_CALLBACK_FUNC                   Function,
+  IN  EFI_PCI_ENUMERATION_PHASE               Phase
+  )
+;
+
+#endif
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciPlatform/PciPlatform.inf b/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciPlatform/PciPlatform.inf
new file mode 100644
index 0000000000..4121ea8982
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciPlatform/PciPlatform.inf
@@ -0,0 +1,87 @@
+## @file
+#
+# @copyright
+# Copyright 2006 - 2021 Intel Corporation. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+  INF_VERSION                   = 0x00010005
+  BASE_NAME                     = PciPlatform
+  FILE_GUID                     = E2441B64-7EF4-41fe-B3A3-8CAA7F8D3017
+  MODULE_TYPE                   = DXE_DRIVER
+  VERSION_STRING                = 1.0
+  ENTRY_POINT                   = PciPlatformDriverEntry
+
+[Sources]
+  PciPlatform.c
+  PciPlatform.h
+  PciPlatformHooks.c
+  PciPlatformHooks.h
+  PciIovPlatformPolicy.c
+  PciIovPlatformPolicy.h
+  PciSupportLib.c
+  PciSupportLib.h
+
+[Packages]
+  MdePkg/MdePkg.dec
+  WhitleySiliconPkg/WhitleySiliconPkg.dec
+  WhitleySiliconPkg/SiliconPkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  WhitleySiliconPkg/CpRcPkg.dec
+  WhitleySiliconPkg/Cpu/CpuRcPkg.dec
+  WhitleyOpenBoardPkg/PlatformPkg.dec
+
+[LibraryClasses]
+  UefiDriverEntryPoint
+  IoLib
+  BaseMemoryLib
+  DebugLib
+  UefiRuntimeServicesTableLib
+  UefiBootServicesTableLib
+  HobLib
+  S3PciLib
+  SetupLib
+  PcdLib
+  PlatformOpromPolicyLib
+
+[Protocols]
+  gEfiPciCallbackProtocolGuid
+  gEfiCpuIo2ProtocolGuid
+  gEfiFirmwareVolume2ProtocolGuid
+  gEfiPciIoProtocolGuid
+  gEfiPciPlatformProtocolGuid
+  gEfiIioUdsProtocolGuid
+  gEfiPciRootBridgeIoProtocolGuid
+  gEfiPciIovPlatformProtocolGuid
+  gEfiIioSystemProtocolGuid
+  gEfiPciHostBridgeResourceAllocationProtocolGuid
+  gUbaConfigDatabaseProtocolGuid
+  gDynamicSiLibraryProtocolGuid                            ## CONSUMES
+
+[Guids]
+  gEfiPlatformInfoGuid
+  gEfiSetupVariableGuid
+  gPchSetupVariableGuid
+  gSystemBoardInfoConfigDataGuid
+
+[Pcd]
+  gPlatformTokenSpaceGuid.PcdOemSkuPcieSlotOpromBitMap
+  gPlatformTokenSpaceGuid.PcdMaxOptionRomNumber
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSrIovSystemPageSize
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSrIovSupport
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAriSupport
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMrIovSupport
+  gStructPcdTokenSpaceGuid.PcdSetup
+
+[FixedPcd]
+  gEfiCpRcPkgTokenSpaceGuid.PcdMaxNestedLevel
+  gEfiCpRcPkgTokenSpaceGuid.PcdMaxCpuSocketCount
+  gEfiCpRcPkgTokenSpaceGuid.PcdMaxCpuCoreCount
+
+[Depex]
+  gSystemBoardInfoConfigDataGuid AND
+  gEfiPciHostBridgeResourceAllocationProtocolGuid AND
+  gUbaConfigDatabaseProtocolGuid AND
+  gDynamicSiLibraryProtocolGuid
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciPlatform/PciPlatformHooks.c b/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciPlatform/PciPlatformHooks.c
new file mode 100644
index 0000000000..89154cb6e1
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciPlatform/PciPlatformHooks.c
@@ -0,0 +1,939 @@
+/** @file
+
+  @copyright
+  Copyright 2004 - 2021 Intel Corporation. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <PchLimits.h>
+#include <PiDxe.h>
+#include <Protocol/IioUds.h>
+#include <PciPlatform.h>
+#include <PciPlatformHooks.h>
+#include <PciSupportLib.h>
+#include <IoApic.h>
+#include <Library/S3BootScriptLib.h>
+#include <Library/IoLib.h>
+#include <Protocol/DynamicSiLibraryProtocol.h>
+#include "../PciHostBridge/PciRootBridge.h"
+#include "../PciHostBridge/PciHostBridge.h"
+
+
+/******************************************************************************
+ * Local definitions.
+ ******************************************************************************/
+/**
+  Uncomment the PCIDEBUG macro to enable tracing the library activity in a test build.
+ **/
+#define PCIDEBUG(...) // { DEBUG((DEBUG_INFO, "[PCI] " __VA_ARGS__)); }
+
+
+/******************************************************************************
+ * Variables.
+ ******************************************************************************/
+SYSTEM_CONFIGURATION  mSystemConfiguration;
+EFI_IIO_UDS_PROTOCOL *mIioUds = NULL;
+
+
+/******************************************************************************
+ * Functions.
+ ******************************************************************************/
+VOID
+ChipsetCallback (
+  IN  EFI_HANDLE                                    RootBridgeHandle,
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS   PciAddress,
+  IN  EFI_PCI_ENUMERATION_PHASE                     Phase,
+  IN  EFI_PCI_CALLBACK_CONTEXT                      *ContextPtr
+  )
+{
+  EFI_LIST_ENTRY    *NodePtr;
+  PCI_CALLBACK_DATA *CallbackDataPtr;
+
+  //
+  // Check if the node has been added
+  //
+  for (NodePtr = GetFirstNode (&mPciPrivateData.PciCallbackList);
+       !IsNull (&mPciPrivateData.PciCallbackList, NodePtr);
+       NodePtr = GetNextNode (&mPciPrivateData.PciCallbackList, NodePtr)) {
+    CallbackDataPtr = PCI_CALLBACK_DATA_FROM_LINK (NodePtr);
+    if (CallbackDataPtr->Phase & Phase) {
+      (CallbackDataPtr->Function) (RootBridgeHandle, PciAddress, Phase, ContextPtr);
+    }
+  }
+}
+
+/**
+
+    GC_TODO: add routine description
+
+    @param StartBus - GC_TODO: add arg description
+
+    @retval EFI_SUCCESS - GC_TODO: add retval description
+
+**/
+EFI_STATUS
+PciTreeTraverse (
+  IN  UINT8       Socket,
+  IN  UINT8       Stack,
+  IN  UINT8       StartBus
+  )
+{
+  UINT64                          PciAddress;
+  UINT8                           Device;
+  UINT8                           Func;
+  UINT8                           SecondaryBus;
+  BOOLEAN                         MultiFunc;
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+
+  if (Socket >= NELEMENTS (mPciPrivateData.PciRootBridgeIo) ||
+      Stack >= NELEMENTS (mPciPrivateData.PciRootBridgeIo[Socket]) ||
+      mPciPrivateData.PciRootBridgeIo[Socket][Stack] == NULL) {
+    ASSERT (FALSE);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  PciRootBridgeIo = mPciPrivateData.PciRootBridgeIo[Socket][Stack];
+
+  for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
+    MultiFunc = FALSE;
+    for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
+      if (IsPciDevicePresent (
+            PciRootBridgeIo,
+            &mPciPrivateData.Context.PciHeader,
+            StartBus,
+            Device,
+            Func
+            )) {
+        if ((Func == 0) && IS_PCI_MULTI_FUNC(&mPciPrivateData.Context.PciHeader)) {
+          MultiFunc = TRUE;
+        }
+        PciAddress = EFI_PCI_ADDRESS (StartBus, Device, Func, 0);
+        mPciPrivateData.Context.PciRootBridgeIo = PciRootBridgeIo;
+        ChipsetCallback (
+          mPciPrivateData.RootBridgeHandle,
+          *(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &PciAddress,
+          mPciPrivateData.PciEnumerationPhase,
+          &(mPciPrivateData.Context)
+          );
+        if (IS_PCI_BRIDGE (&(mPciPrivateData.Context.PciHeader))) {
+          PciAddress = EFI_PCI_ADDRESS (StartBus, Device, Func, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET);
+          PciRootBridgeIo->Pci.Read (
+                                PciRootBridgeIo,
+                                EfiPciWidthUint8,
+                                *(UINT64 *) &PciAddress,
+                                1,
+                                &SecondaryBus
+                                );
+          if ((SecondaryBus > 0) && (SecondaryBus < 0xFF)) {
+            //
+            // Recursive call for next bus in this stack
+            //
+            PciTreeTraverse (Socket, Stack, SecondaryBus);
+          }
+        }
+      }
+
+      if (!MultiFunc) {
+        //
+        // Skip sub functions, this is not a multi function device
+        //
+        Func = PCI_MAX_FUNC;
+      }
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+
+  Program Io Apic Id
+
+  @param IoApicAddress and IoApicId
+
+  @retval None
+
+**/
+VOID
+ProgramIoApicId (
+  IN UINT32                            IoApicAddress,
+  IN UINT8                             IoApicId
+  )
+{
+
+  UINT32  Data;
+
+  mPciPrivateData.CpuIo->Mem.Read (
+                              mPciPrivateData.CpuIo,
+                              EfiCpuIoWidthUint32,
+                              IoApicAddress + EFI_IO_APIC_INDEX_OFFSET,
+                              1,
+                              &Data
+                              );
+
+  //
+  // IOAPIC is not there
+  //
+  if (Data == (UINT32) -1) {
+    return ;
+  }
+  //
+  // Set up IO APIC ID and enable FSB delivery
+  // Use CPU IO protocol since the IO APIC ranges
+  // are not included in PCI apertures
+  //
+  Data = EFI_IO_APIC_ID_REGISTER;
+  mPciPrivateData.CpuIo->Mem.Write (
+                              mPciPrivateData.CpuIo,
+                              EfiCpuIoWidthUint32,
+                              IoApicAddress + EFI_IO_APIC_INDEX_OFFSET,
+                              1,
+                              &Data
+                              );
+
+  Data = IoApicId << EFI_IO_APIC_ID_BITSHIFT;
+  mPciPrivateData.CpuIo->Mem.Write (
+                              mPciPrivateData.CpuIo,
+                              EfiCpuIoWidthUint32,
+                              IoApicAddress + EFI_IO_APIC_DATA_OFFSET,
+                              1,
+                              &Data
+                              );
+
+  Data = EFI_IO_APIC_BOOT_CONFIG_REGISTER;
+  mPciPrivateData.CpuIo->Mem.Write (
+                              mPciPrivateData.CpuIo,
+                              EfiCpuIoWidthUint32,
+                              IoApicAddress + EFI_IO_APIC_INDEX_OFFSET,
+                              1,
+                              &Data
+                              );
+
+  Data = EFI_IO_APIC_FSB_INT_DELIVERY;
+  mPciPrivateData.CpuIo->Mem.Write (
+                              mPciPrivateData.CpuIo,
+                              EfiCpuIoWidthUint32,
+                              IoApicAddress + EFI_IO_APIC_DATA_OFFSET,
+                              1,
+                              &Data
+                              );
+}
+
+#ifdef EFI_PCI_IOV_SUPPORT
+/**
+
+  Initialize the Pci Iov Platform Data.
+
+  @param ImageHandle  -  Handle to the image.
+  @param SystemTable  -  Handle to System Table.
+
+  @retval EFI_STATUS  -  Status of the function calling.
+
+**/
+EFI_STATUS
+EFIAPI
+PciPlatformInitPciIovData (
+  VOID
+  )
+{
+  EFI_STATUS                            Status;
+  EFI_PCI_IOV_PLATFORM_POLICY           PciIovPolicy;
+  UINT32                                SystemPageSize;
+  EFI_PCI_IOV_PLATFORM_PROTOCOL         *gPciIovPlatformProtocol;
+
+  Status = gBS->LocateProtocol (
+             &gEfiPciIovPlatformProtocolGuid,
+             NULL,
+             &gPciIovPlatformProtocol
+             );
+  if (!EFI_ERROR (Status)) {
+    Status = gPciIovPlatformProtocol->GetSystemLowestPageSize (
+                                           gPciIovPlatformProtocol,
+                                           &SystemPageSize
+                                           );
+    if (!EFI_ERROR (Status)) {
+      Status = PcdSet32S (PcdSrIovSystemPageSize, SystemPageSize);
+      ASSERT_EFI_ERROR (Status);
+      if (EFI_ERROR(Status)) {
+        return Status;
+      }
+    } else {
+      return Status;
+    }
+    Status = gPciIovPlatformProtocol->GetPlatformPolicy (
+                                           gPciIovPlatformProtocol,
+                                           &PciIovPolicy
+                                           );
+    if (!EFI_ERROR (Status)) {
+      if (PciIovPolicy & EFI_PCI_IOV_POLICY_ARI) {
+        Status = PcdSetBoolS (PcdAriSupport, TRUE);
+        ASSERT_EFI_ERROR (Status);
+        if (EFI_ERROR(Status)) {
+          return Status;
+        }
+      } else {
+        Status = PcdSetBoolS (PcdAriSupport, FALSE);
+        ASSERT_EFI_ERROR (Status);
+        if (EFI_ERROR(Status)) {
+          return Status;
+        }
+      }
+      if (PciIovPolicy & EFI_PCI_IOV_POLICY_SRIOV) {
+        Status = PcdSetBoolS (PcdSrIovSupport, TRUE);
+        ASSERT_EFI_ERROR (Status);
+        if (EFI_ERROR(Status)) {
+          return Status;
+        }
+      } else {
+        Status = PcdSetBoolS (PcdSrIovSupport, FALSE);
+        ASSERT_EFI_ERROR (Status);
+        if (EFI_ERROR(Status)) {
+          return Status;
+        }
+      }
+      if (PciIovPolicy & EFI_PCI_IOV_POLICY_MRIOV) {
+        Status = PcdSetBoolS (PcdMrIovSupport, TRUE);
+        ASSERT_EFI_ERROR (Status);
+        if (EFI_ERROR(Status)) {
+          return Status;
+        }
+      } else {
+        Status = PcdSetBoolS (PcdMrIovSupport, FALSE);
+        ASSERT_EFI_ERROR (Status);
+        if (EFI_ERROR(Status)) {
+          return Status;
+        }
+      }
+    } else {
+      return Status;
+    }
+    DEBUG ((
+          EFI_D_INFO,
+          " Initialized SR-IOV Platform Data: PCIIovPolicy = 0x%x; SystemPageSize = 0x%x;\n",
+          PciIovPolicy, SystemPageSize
+          ));
+  } else {
+    DEBUG ((
+          EFI_D_INFO,
+          " Using default values for SystemPageSize;\n"
+          ));
+  }
+  return Status;
+}
+#endif
+
+/**
+
+  Platform Pci Express init.
+
+  @param HostBridgeInstance  -  Pointer to Host Bridge private data
+                                does not support 64 bit memory addresses.
+
+  @retval EFI_SUCCESS  -  Success.
+
+**/
+EFI_STATUS
+PciPlatformEarlyInit (
+  VOID
+  )
+{
+  EFI_STATUS                        Status;
+
+  Status = EFI_SUCCESS;
+
+#ifdef EFI_PCI_IOV_SUPPORT
+  Status = PciPlatformInitPciIovData();  // Update IOV PCD values
+#endif
+  return Status;
+}
+
+/**
+
+  Attempts to set the XHCI controller's PCI CMD.MSE and CMD.BME bits to enable OS kernel debugging over XHCI.
+
+**/
+VOID
+AttemptToSetXhciMse (
+  )
+
+{
+  UINT32                            XhciBar;
+  UINT16                            Command;
+  DYNAMIC_SI_LIBARY_PROTOCOL        *DynamicSiLibraryProtocol = NULL;
+  EFI_STATUS                        Status;
+
+  Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocolGuid, NULL, &DynamicSiLibraryProtocol);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    return;
+  }
+
+  //
+  // Step 1. Make sure the XHCI BAR is initialized.
+  //         Check if lower 32 bits of 64-bit BAR are configured.
+  //
+  XhciBar = MmioRead32 (DynamicSiLibraryProtocol->MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_XHCI, PCI_FUNCTION_NUMBER_PCH_XHCI) + R_XHCI_CFG_BAR0) & ~(0xF);
+  if (XhciBar == 0xFFFFFFF0) {
+    return;
+  }
+  if ((XhciBar & 0xFFFF0000) == 0) {
+    //
+    // If lower 32 bits are not configured, check upper 32 bits.
+    //
+    XhciBar = MmioRead32 (DynamicSiLibraryProtocol->MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_XHCI, PCI_FUNCTION_NUMBER_PCH_XHCI) + R_XHCI_CFG_BAR0 + 4);
+    if (XhciBar == 0) {
+      return;
+    }
+  }
+
+  //
+  // Step 2. If XHCI's MSE (Memory Space Enable) or BME (Bus Master Enable) bits are cleared, set them.
+  //
+  Command = MmioRead16 (DynamicSiLibraryProtocol->MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_XHCI, PCI_FUNCTION_NUMBER_PCH_XHCI) + PCI_COMMAND_OFFSET);
+  if ((Command & (EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER)) != (EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER)) {
+    MmioOr16 (DynamicSiLibraryProtocol->MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_XHCI, PCI_FUNCTION_NUMBER_PCH_XHCI) + PCI_COMMAND_OFFSET, (EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER));
+  }
+}
+
+
+/**
+
+  Init pci device registers after the device resources have been allocated, so
+  that devices behind a bus could be accessed.
+
+  @param HostBridgeInstance  -  PCI_HOST_BRIDGE_INSTANCE.
+
+  @retval EFI_SUCCESS  -  Function has completed successfully.
+
+**/
+EFI_STATUS
+PciPlatformPostInit (
+  VOID
+  )
+{
+  DYNAMIC_SI_LIBARY_PROTOCOL        *DynamicSiLibraryProtocol = NULL;
+  EFI_STATUS                        Status;
+
+  //
+  // Program all the IOAPIC in system
+  //
+
+  Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocolGuid, NULL, &DynamicSiLibraryProtocol);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    return Status;
+  }
+
+  UINT8 Socket, Stack, IoApicId, ApicIndex = 0;
+  CPU_CSR_ACCESS_VAR   *CpuCsrAccessVarPtr = NULL;
+  Stack = 0;
+  IoApicId = 0;
+  CpuCsrAccessVarPtr = DynamicSiLibraryProtocol->GetSysCpuCsrAccessVar ();
+  DEBUG ((DEBUG_INFO, "PciPlatformPostInit: setting up IOAPIC for PCH\n"));
+  ProgramIoApicId (mIioUds->IioUdsPtr->PlatformData.IIO_resource[0].StackRes[0].IoApicBase, PCH_IOAPIC_ID);
+  for (Socket = 0; Socket < MAX_SOCKET; Socket++) {
+    if (!(CpuCsrAccessVarPtr->socketPresentBitMap & (1 << Socket))) {
+      continue;
+    }
+
+    for (Stack = 0; Stack < MAX_IIO_STACK; Stack++, ApicIndex++) {
+      if (!(mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap & (1 << Stack))) {
+        continue;
+      }
+      switch (ApicIndex) {
+      case 0:
+        IoApicId = PC00_IOAPIC_ID;
+        break;
+      case 1:
+        IoApicId = PC01_IOAPIC_ID;
+        break;
+      case 2:
+        IoApicId = PC02_IOAPIC_ID;
+        break;
+      case 3:
+        IoApicId = PC03_IOAPIC_ID;
+        break;
+      case 4:
+        IoApicId = PC04_IOAPIC_ID;
+        break;
+      case 5:
+        IoApicId = PC05_IOAPIC_ID;
+        break;
+      case 6:
+        IoApicId = PC06_IOAPIC_ID;
+        break;
+      case 7:
+        IoApicId = PC07_IOAPIC_ID;
+        break;
+      case 8:
+        IoApicId = PC08_IOAPIC_ID;
+        break;
+      case 9:
+        IoApicId = PC09_IOAPIC_ID;
+        break;
+      case 10:
+        IoApicId = PC10_IOAPIC_ID;
+        break;
+      case 11:
+        IoApicId = PC11_IOAPIC_ID;
+        break;
+      case 12:
+        IoApicId = PC12_IOAPIC_ID;
+        break;
+      case 13:
+        IoApicId = PC13_IOAPIC_ID;
+        break;
+      case 14:
+        IoApicId = PC14_IOAPIC_ID;
+        break;
+      case 15:
+        IoApicId = PC15_IOAPIC_ID;
+        break;
+      case 16:
+        IoApicId = PC16_IOAPIC_ID;
+        break;
+      case 17:
+        IoApicId = PC17_IOAPIC_ID;
+        break;
+      case 18:
+        IoApicId = PC18_IOAPIC_ID;
+        break;
+      case 19:
+        IoApicId = PC19_IOAPIC_ID;
+        break;
+      case 20:
+        IoApicId = PC20_IOAPIC_ID;
+        break;
+      case 21:
+        IoApicId = PC21_IOAPIC_ID;
+        break;
+      case 22:
+        IoApicId = PC22_IOAPIC_ID;
+        break;
+      case 23:
+        IoApicId = PC23_IOAPIC_ID;
+        break;
+      case 24:
+        IoApicId = PC24_IOAPIC_ID;
+        break;
+      case 25:
+        IoApicId = PC25_IOAPIC_ID;
+        break;
+      case 26:
+        IoApicId = PC26_IOAPIC_ID;
+        break;
+      case 27:
+        IoApicId = PC27_IOAPIC_ID;
+        break;
+      case 28:
+        IoApicId = PC28_IOAPIC_ID;
+        break;
+      case 29:
+        IoApicId = PC29_IOAPIC_ID;
+        break;
+      case 30:
+        IoApicId = PC30_IOAPIC_ID;
+        break;
+      case 31:
+        IoApicId = PC31_IOAPIC_ID;
+        break;
+      case 32:
+        IoApicId = PC32_IOAPIC_ID;
+        break;
+      case 33:
+        IoApicId = PC33_IOAPIC_ID;
+        break;
+      case 34:
+        IoApicId = PC34_IOAPIC_ID;
+        break;
+      case 35:
+        IoApicId = PC35_IOAPIC_ID;
+        break;
+      case 36:
+        IoApicId = PC36_IOAPIC_ID;
+        break;
+      case 37:
+        IoApicId = PC37_IOAPIC_ID;
+        break;
+      case 38:
+        IoApicId = PC38_IOAPIC_ID;
+        break;
+      case 39:
+        IoApicId = PC39_IOAPIC_ID;
+        break;
+      case 40:
+        IoApicId = PC40_IOAPIC_ID;
+        break;
+      case 41:
+        IoApicId = PC41_IOAPIC_ID;
+        break;
+      case 42:
+        IoApicId = PC42_IOAPIC_ID;
+        break;
+      case 43:
+        IoApicId = PC43_IOAPIC_ID;
+        break;
+      case 44:
+        IoApicId = PC44_IOAPIC_ID;
+        break;
+      case 45:
+        IoApicId = PC45_IOAPIC_ID;
+        break;
+      case 46:
+        IoApicId = PC46_IOAPIC_ID;
+        break;
+      case 47:
+        IoApicId = PC47_IOAPIC_ID;
+        break;
+      default:
+        break;
+      }
+      if ((Socket == 0) && (Stack == 0)) {
+        ProgramIoApicId ((mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].IoApicBase + 0x1000), IoApicId);
+      } else {
+        ProgramIoApicId (mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].IoApicBase, IoApicId);
+      }
+    }
+  }
+
+  AttemptToSetXhciMse ();
+
+  return EFI_SUCCESS;
+}
+
+/**
+
+  The PlatformPrepController() function can be used to notify the platform driver so that
+  it can perform platform-specific actions. No specific actions are required.
+  Several notification points are defined at this time. More synchronization points may be
+  added as required in the future. The PCI bus driver calls the platform driver twice for
+  every PCI controller-once before the PCI Host Bridge Resource Allocation Protocol driver
+  is notified, and once after the PCI Host Bridge Resource Allocation Protocol driver has
+  been notified.
+  This member function may not perform any error checking on the input parameters. It also
+  does not return any error codes. If this member function detects any error condition, it
+  needs to handle those errors on its own because there is no way to surface any errors to
+  the caller.
+
+  @param This          -  Pointer to the EFI_PCI_PLATFORM_PROTOCOL instance.
+  @param HostBridge    -  The associated PCI Host bridge handle.
+  @param RootBridge    -  The associated PCI root bridge handle.
+  @param PciAddress    -  The address of the PCI device on the PCI bus.
+  @param Phase         -  The phase of the PCI controller enumeration.
+  @param ChipsetPhase  -  Defines the execution phase of the PCI chipset driver.
+
+  @retval EFI_SUCCESS     -  The function completed successfully.
+  @retval EFI_UNSUPPORTED -  Not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformPrepController (
+  IN  EFI_PCI_PLATFORM_PROTOCOL                      *This,
+  IN  EFI_HANDLE                                     HostBridge,
+  IN  EFI_HANDLE                                     RootBridge,
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS    PciAddress,
+  IN  EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE   Phase,
+  IN  EFI_PCI_CHIPSET_EXECUTION_PHASE                ChipsetPhase
+  )
+{
+  EFI_STATUS                       Status = EFI_SUCCESS;
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *RootBridgeIo;
+  PCI_TYPE00                       Pci0;
+  UINT64                           Address;
+  UINT8                            SecBus;
+  UINT8                            Device;
+  UINT8                            Func;
+  UINT64                           DummyData = 0xFFFFFFFF;
+  UINT32                           DidVid;
+  DYNAMIC_SI_LIBARY_PROTOCOL       *DynamicSiLibraryProtocol = NULL;
+
+  if (mPciPrivateData.RootBridgeHandle == NULL) {
+    mPciPrivateData.RootBridgeHandle = RootBridge;
+  }
+
+  Status = gBS->HandleProtocol (
+                    mPciPrivateData.RootBridgeHandle,
+                    &gEfiPciRootBridgeIoProtocolGuid,
+                    (VOID **) &RootBridgeIo
+                    );
+  ASSERT_EFI_ERROR (Status);
+
+  Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocolGuid, NULL, &DynamicSiLibraryProtocol);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    return Status;
+  }
+
+// Workaround for PCI devices under Pilot IV, this video controller can only be exposed if write 0xFFFFFFFF to it and read back
+  if (Phase == EfiPciBeforeChildBusEnumeration && ChipsetPhase == ChipsetExit ) {
+
+// Read the entire config header
+    Address = EFI_PCI_ADDRESS (PciAddress.Bus, PciAddress.Device, PciAddress.Function, 0);
+    Status = RootBridgeIo->Pci.Read (
+                                RootBridgeIo,
+                                EfiPciWidthUint32,
+                                Address,
+                                sizeof (PCI_TYPE00) / sizeof (UINT32),
+                                &Pci0
+                                );
+
+    if (!EFI_ERROR (Status) && IS_PCI_BRIDGE(&Pci0)) {
+
+      // Read the secondary bus number
+      Address = EFI_PCI_ADDRESS (PciAddress.Bus, PciAddress.Device, PciAddress.Function, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET);
+      Status = RootBridgeIo->Pci.Read (
+                                RootBridgeIo,
+                                EfiPciWidthUint8,
+                                Address,
+                                1,
+                                &SecBus
+                                );
+
+      if (!EFI_ERROR (Status)) {
+
+        //
+        // For this bridge with existing secondary bus apply PCI Intel WAs
+        //
+        DidVid = ((Pci0.Hdr).DeviceId << 16) | (Pci0.Hdr).VendorId;
+        DynamicSiLibraryProtocol->IioPciHookBeforeEnumeration ((UINT8)RootBridgeIo->SegmentNumber, PciAddress.Bus, PciAddress.Device, PciAddress.Function, DidVid);
+
+        for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
+          for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
+            Address = EFI_PCI_ADDRESS (SecBus, Device, Func, 0);
+            Status = RootBridgeIo->Pci.Read (
+                                      RootBridgeIo,
+                                      EfiPciWidthUint32,
+                                      Address,
+                                      1,
+                                      &Pci0
+                                      );
+
+            if ( !EFI_ERROR (Status) && (Pci0.Hdr).VendorId == 0xffff) {
+
+              Status = RootBridgeIo->Pci.Write(
+                                        RootBridgeIo,
+                                        EfiPciWidthUint32,
+                                        Address,
+                                        1,
+                                        &DummyData
+                                        );
+              PCIDEBUG ("%a: For B(0x%x)-D(0x%x)-F(0x%x),Pci.Write() returns with %r\n",
+                        __FUNCTION__, SecBus, Device, Func, Status);
+
+              if (EFI_ERROR (Status)) {
+                //
+                // If error, go to next function
+                //
+                continue;
+              } else {
+                Func = PCI_MAX_FUNC;    // skip the remaining function
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+
+  Perform initialization by the phase indicated.
+
+  @param This          -  Pointer to the EFI_PCI_PLATFORM_PROTOCOL instance.
+  @param HostBridge    -  The associated PCI Host bridge handle.
+  @param Phase         -  The phase of the PCI controller enumeration.
+  @param ChipsetPhase  -  Defines the execution phase of the PCI chipset driver.
+
+  @retval EFI_SUCCESS  -  Must return with success.
+
+**/
+EFI_STATUS
+EFIAPI
+PhaseNotify (
+  IN  EFI_PCI_PLATFORM_PROTOCOL                      *This,
+  IN  EFI_HANDLE                                     HostBridge,
+  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE  Phase,
+  IN  EFI_PCI_CHIPSET_EXECUTION_PHASE                ChipsetPhase
+  )
+{
+  EFI_STATUS                                        Status = EFI_SUCCESS;
+  UINT16                                            StackBit;
+  UINT8                                             Socket;
+  UINT8                                             Stack;
+  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *HostResAllocPtr;
+  PCI_HOST_BRIDGE_INSTANCE                          *HostBridgePtr;
+  PCI_ROOT_BRIDGE_INSTANCE                          *RootBridgePtr;
+  LIST_ENTRY                                        *NodePtr;
+  CPU_CSR_ACCESS_VAR                                *CpuCsrAccessVarPtr;
+  DYNAMIC_SI_LIBARY_PROTOCOL                        *DynamicSiLibraryProtocol = NULL;
+
+  static CHAR8 *NotifyPhase2Name[] = {"EfiPciHostBridgeBeginEnumeration",
+                                      "EfiPciHostBridgeBeginBusAllocation",
+                                      "EfiPciHostBridgeEndBusAllocation",
+                                      "EfiPciHostBridgeBeginResourceAllocation",
+                                      "EfiPciHostBridgeAllocateResources",
+                                      "EfiPciHostBridgeSetResources",
+                                      "EfiPciHostBridgeFreeResources",
+                                      "EfiPciHostBridgeEndResourceAllocation",
+                                      "EfiPciHostBridgeEndEnumeration"};
+
+  if (Phase < NELEMENTS (NotifyPhase2Name)) {
+    DEBUG ((DEBUG_INFO, "[PCI] %a phase notified (execution %d)\n", NotifyPhase2Name[Phase], ChipsetPhase));
+  } else {
+    DEBUG ((DEBUG_ERROR, "[PCI] ERROR: Unknown phase %d notified (execution %d)\n", Phase, ChipsetPhase));
+  }
+
+  Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocolGuid, NULL, &DynamicSiLibraryProtocol);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    return Status;
+  }
+
+  CpuCsrAccessVarPtr = DynamicSiLibraryProtocol->GetSysCpuCsrAccessVar ();
+
+  if (ChipsetPhase == ChipsetEntry) {
+    return EFI_SUCCESS;
+  }
+  //
+  // If for multiple Host bridges, need special consideration
+  //
+  switch (Phase) {
+
+  case EfiPciHostBridgeBeginEnumeration:
+    //
+    // Pre-initialization before PCI bus enumeration
+    // No bus number and no PCI resource
+    // Locate the IIO Protocol Interface
+    //
+    Status = gBS->LocateProtocol (
+                    &gEfiIioUdsProtocolGuid,
+                    NULL,
+                    &mIioUds
+                    );
+    ASSERT_EFI_ERROR (Status);
+
+    Status = gBS->LocateProtocol (
+                    &gEfiCpuIo2ProtocolGuid,
+                    NULL,
+                    &mPciPrivateData.CpuIo
+                    );
+    ASSERT_EFI_ERROR (Status);
+
+    mPciPrivateData.Context.CpuIo = mPciPrivateData.CpuIo;
+    DEBUG ((DEBUG_INFO, "[PCI] Platform Pre-Initialization (Before bus scanning)\n"));
+    //
+    // Locate gEfiPciRootBridgeIoProtocolGuid instance created for each IIO stack.
+    // They were created by host bridge driver and linked to the
+    // gEfiPciHostBridgeResourceAllocationProtocolGuid protocol.
+    //
+    Status = gBS->LocateProtocol (
+                    &gEfiPciHostBridgeResourceAllocationProtocolGuid,
+                    NULL,
+                    &HostResAllocPtr
+                    );
+    ASSERT_EFI_ERROR (Status);
+
+    HostBridgePtr = CR (HostResAllocPtr, PCI_HOST_BRIDGE_INSTANCE, ResAlloc, PCI_HOST_BRIDGE_SIGNATURE);
+    for (NodePtr = GetFirstNode (&HostBridgePtr->RootBridges);
+         !IsNull (&HostBridgePtr->RootBridges, NodePtr);
+         NodePtr = GetNextNode (&HostBridgePtr->RootBridges, NodePtr)) {
+      RootBridgePtr = CR (NodePtr, PCI_ROOT_BRIDGE_INSTANCE, Link, PCI_ROOT_BRIDGE_SIGNATURE);
+      for (Socket = 0; Socket < NELEMENTS (mPciPrivateData.PciRootBridgeIo); Socket++) {
+        if (!mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].Valid) {
+          continue;
+        }
+        for (StackBit = 1, Stack = 0;
+             Stack < NELEMENTS (mPciPrivateData.PciRootBridgeIo[Socket]);
+             StackBit <<= 1, Stack++) {
+          if ((CpuCsrAccessVarPtr->stackPresentBitmap[Socket] & StackBit) &&
+              CpuCsrAccessVarPtr->StackBus[Socket][Stack] == RootBridgePtr->Aperture.BusBase) {
+            //
+            // This is the stack handled by this instance of root bridge IO protocol. Store it for future use.
+            //
+            mPciPrivateData.PciRootBridgeIo[Socket][Stack] = &RootBridgePtr->RootBridgeIo;
+            Socket = NELEMENTS (mPciPrivateData.PciRootBridgeIo);
+            break;
+          }
+        }
+      }
+    }
+    PciPlatformEarlyInit ();
+    break;
+
+  case EfiPciHostBridgeEndBusAllocation:
+    //
+    // There are two rounds PCI bus scanning
+    // First round will initilize the PCI hotplug device
+    // Second round will be the final one
+    //
+    if (mPciPrivateData.BusAssignedTime == 0) {
+      mPciPrivateData.PciEnumerationPhase = EfiPciEnumerationDeviceScanning;
+      for (Socket = 0; Socket < NELEMENTS (mPciPrivateData.PciRootBridgeIo); Socket++) {
+        if (!mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].Valid) {
+          continue;
+        }
+        for (Stack = 0; Stack < NELEMENTS (mPciPrivateData.PciRootBridgeIo[Socket]); Stack ++) {
+          if (mPciPrivateData.PciRootBridgeIo[Socket][Stack] == NULL) {
+            continue;
+          }
+          PciTreeTraverse (Socket, Stack, CpuCsrAccessVarPtr->StackBus[Socket][Stack]);
+        }
+      }
+      mPciPrivateData.BusAssignedTime++;
+      DEBUG ((DEBUG_INFO, "[PCI] Platform bus assigned\n"));
+    }
+    break;
+
+  case EfiPciHostBridgeBeginResourceAllocation:
+    //
+    // PCI bus number has been assigned, but resource is still empty
+    //
+    DEBUG ((DEBUG_INFO, "[PCI] Platform Mid-Initialization (After bus number assignment)\n"));
+    mPciPrivateData.PciEnumerationPhase = EfiPciEnumerationBusNumberAssigned;
+    for (Socket = 0; Socket < NELEMENTS (mPciPrivateData.PciRootBridgeIo); Socket++) {
+      if (!mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].Valid) {
+        continue;
+      }
+      for (Stack = 0; Stack < NELEMENTS (mPciPrivateData.PciRootBridgeIo[Socket]); Stack ++) {
+        if (mPciPrivateData.PciRootBridgeIo[Socket][Stack] == NULL) {
+          continue;
+        }
+        PciTreeTraverse (Socket, Stack, CpuCsrAccessVarPtr->StackBus[Socket][Stack]);
+      }
+    }
+    //PciPlatformMidInit ();
+    break;
+
+  case EfiPciHostBridgeEndResourceAllocation:
+    //
+    // Resource enumeration is done.
+    // Both bus number and resource have been assigned
+    // Do any post initialization.
+    //
+    DEBUG ((DEBUG_INFO, "[PCI] Platform Post-Initialization (After resource alloction)\n"));
+    mPciPrivateData.PciEnumerationPhase = EfiPciEnumerationResourceAssigned;
+    for (Socket = 0; Socket < NELEMENTS (mPciPrivateData.PciRootBridgeIo); Socket++) {
+      if (!mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].Valid) {
+        continue;
+      }
+      for (Stack = 0; Stack < NELEMENTS (mPciPrivateData.PciRootBridgeIo[Socket]); Stack ++) {
+        if (mPciPrivateData.PciRootBridgeIo[Socket][Stack] == NULL) {
+          continue;
+        }
+        PciTreeTraverse (Socket, Stack, CpuCsrAccessVarPtr->StackBus[Socket][Stack]);
+      }
+    }
+    PciPlatformPostInit ();
+    break;
+
+  default:
+    return EFI_UNSUPPORTED;
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciPlatform/PciPlatformHooks.h b/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciPlatform/PciPlatformHooks.h
new file mode 100644
index 0000000000..b52b5de16e
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciPlatform/PciPlatformHooks.h
@@ -0,0 +1,31 @@
+/** @file
+  This code supports a the private implementation
+  of the Legacy BIOS Platform protocol
+
+  @copyright
+  Copyright 2004 - 2021 Intel Corporation. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PCI_PLATFORM_HOOKS_H_
+#define _PCI_PLATFORM_HOOKS_H_
+
+#include <Library/IoLib.h>
+
+VOID
+ChipsetCallback (
+  IN  EFI_HANDLE                                    RootBridgeHandle,
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS   PciAddress,
+  IN  EFI_PCI_ENUMERATION_PHASE                     Phase,
+  EFI_PCI_CALLBACK_CONTEXT                          *Context
+  );
+
+EFI_STATUS
+PciTreeTraverse (
+  IN  UINT8                                        Socket,
+  IN  UINT8                                        Stack,
+  IN  UINT8                                        StartBus
+  );
+
+#endif
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciPlatform/PciSupportLib.c b/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciPlatform/PciSupportLib.c
new file mode 100644
index 0000000000..7b5d45711d
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciPlatform/PciSupportLib.c
@@ -0,0 +1,108 @@
+/** @file
+  Support PCI chipset initialization.
+
+  @copyright
+  Copyright 1999 - 2021 Intel Corporation. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "PiDxe.h"
+#include <Base.h>
+#include <Guid/SocketIioVariable.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include "IndustryStandard/Pci.h"
+#include "PciSupportLib.h"
+
+PCIE_STACK  mPcieStack;
+
+
+/**
+
+  This routine is used to check whether the pci device is present
+
+  @retval None
+
+**/
+BOOLEAN
+IsPciDevicePresent (
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,
+  OUT PCI_TYPE00                      *Pci,
+  UINT8                               Bus,
+  UINT8                               Device,
+  UINT8                               Func
+  )
+// TODO:    PciRootBridgeIo - add argument and description to function comment
+// TODO:    Pci - add argument and description to function comment
+// TODO:    Bus - add argument and description to function comment
+// TODO:    Device - add argument and description to function comment
+// TODO:    Func - add argument and description to function comment
+// TODO:    EFI_SUCCESS - add return value to function comment
+// TODO:    EFI_NOT_FOUND - add return value to function comment
+{
+  UINT64      Address;
+  UINT32      Dummy;
+  EFI_STATUS  Status;
+
+  Dummy = 0xFFFFFFFF;
+  //
+  // Create PCI address map in terms of Bus, Device and Func
+  //
+  Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);
+
+  //
+  // Read the Vendor Id register
+  //
+  Status = PciRootBridgeIo->Pci.Read (
+                                  PciRootBridgeIo,
+                                  EfiPciWidthUint32,
+                                  Address,
+                                  1,
+                                  Pci
+                                  );
+  if ((Pci->Hdr).VendorId == 0xFFFF) {
+    //
+    // The PCIe card could have been assigned a temporary bus number earlier in
+    // the boot flow. Performing a write cycle can be used to cause the PCIe
+    // card to latch the new bus number. Try to writing the Vendor Id register,
+    // then recheck if the card is present.
+    //
+    Status = PciRootBridgeIo->Pci.Write(
+                                    PciRootBridgeIo,
+                                    EfiPciWidthUint32,
+                                    Address,
+                                    1,
+                                    &Dummy
+                                    );
+
+    //
+    // Retry the previous read after the PCI write cycle.
+    //
+    Status = PciRootBridgeIo->Pci.Read (
+                                    PciRootBridgeIo,
+                                    EfiPciWidthUint32,
+                                    Address,
+                                    1,
+                                    Pci
+                                    );
+  }
+
+  if (!EFI_ERROR (Status) && (Pci->Hdr).VendorId != 0xFFFF) {
+    //
+    // Read the entire config header for the device
+    //
+    Status = PciRootBridgeIo->Pci.Read (
+                                    PciRootBridgeIo,
+                                    EfiPciWidthUint32,
+                                    Address,
+                                    sizeof (PCI_TYPE00) / sizeof (UINT32),
+                                    Pci
+                                    );
+
+    return TRUE;
+  }
+
+  return FALSE;
+}
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciPlatform/PciSupportLib.h b/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciPlatform/PciSupportLib.h
new file mode 100644
index 0000000000..e173125c97
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Features/Pci/Dxe/PciPlatform/PciSupportLib.h
@@ -0,0 +1,46 @@
+/** @file
+  Support PCI chipset initialization.
+
+  @copyright
+  Copyright 1999 - 2021 Intel Corporation. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef  _EFI_PCI_SUPPORT_H_
+#define  _EFI_PCI_SUPPORT_H_
+
+#include <Protocol/PciRootBridgeIo.h>
+
+#include <Guid/SetupVariable.h>
+
+typedef struct {
+  UINT8  PcieCapPtr;
+  UINT8  Function;
+  UINT8  Device;
+  UINT8  Bus;
+  UINT16 PcieLnkCap;
+  UINT16 PcieDevCap;
+  //Added to Support AtomicOp Request-->Start
+  UINT16 PcieDevCap2;
+  //Added to Support AtomicOp Request-->End
+} PCIE_CAP_INFO;
+
+typedef struct {
+  INTN            Top;
+  PCIE_CAP_INFO   PcieCapInfo[FixedPcdGet32(PcdMaxNestedLevel)];
+} PCIE_STACK;
+
+extern  PCIE_STACK  mPcieStack;
+
+BOOLEAN
+IsPciDevicePresent (
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,
+  OUT PCI_TYPE00                      *Pci,
+  UINT8                               Bus,
+  UINT8                               Device,
+  UINT8                               Func
+  );
+
+
+#endif
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Features/Variable/PlatformVariable/Pei/PlatformVariableInitPei.c b/Platform/Intel/WhitleyOpenBoardPkg/Features/Variable/PlatformVariable/Pei/PlatformVariableInitPei.c
new file mode 100644
index 0000000000..003787a163
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Features/Variable/PlatformVariable/Pei/PlatformVariableInitPei.c
@@ -0,0 +1,274 @@
+/** @file
+  Platform variable initialization PEIM.
+
+  This PEIM determines whether to load variable defaults. Ordinarily, the
+  decision is based on the boot mode, but an OEM hook is provided to override
+  that. The appropriate HOBs and PCDs are created to signal DXE code to update
+  the variable default values.
+
+  @copyright
+  Copyright 2012 - 2021 Intel Corporation. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "PlatformVariableInitPei.h"
+#include <Guid/PlatformVariableCommon.h>
+#include <Uefi/UefiInternalFormRepresentation.h>
+
+UINT16 BoardId = BOARD_ID_DEFAULT;
+
+EFI_PEI_PPI_DESCRIPTOR  mPpiListPlatformVariableInit = {
+  (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+  &gPlatformVariableInitPpiGuid,
+  NULL
+};
+
+/**
+Apply platform variable defaults.
+
+Create HOBs and set PCDs to prompt the (re-)loading of variable defaults.
+Each step is attempted regardless of whether the previous steps succeeded.
+If multiple errors occur, only the last error code is returned.
+
+@param[in]  Events            Bitmap of events that occurred.
+@param[in]  DefaultId         Default store ID, STANDARD or MANUFACTURING.
+
+@retval EFI_SUCCESS           All steps completed successfully.
+@retval EFI_OUT_OF_RESOURCES  One of the HOBs could not be created.
+@retval EFI_NOT_FOUND         The default data could not be found in FFS.
+**/
+
+EFI_STATUS
+ApplyPlatformVariableDefaults(
+  IN UINT8  Events,
+  IN UINT16 DefaultId
+  )
+{
+  VOID        *Hob;
+  EFI_STATUS  Status;
+  EFI_STATUS  ReturnStatus;
+
+  DEBUG((DEBUG_INFO, "Applying platform variable defaults:\n"));
+  DEBUG((DEBUG_INFO, "  Events    = 0x%02x\n", Events));
+  DEBUG((DEBUG_INFO, "  DefaultId = 0x%04x\n", DefaultId));
+
+  //
+  // Assume success up front. This will be overwritten if errors occur.
+  //
+  ReturnStatus = EFI_SUCCESS;
+
+  //
+  // Send the bitmap of events to the platform variable DXE driver.
+  //
+  Hob = BuildGuidDataHob(&gPlatformVariableHobGuid, &Events, sizeof(Events));
+  if (Hob == NULL) {
+    DEBUG((DEBUG_ERROR, "Create platform var event HOB: %r!\n", EFI_OUT_OF_RESOURCES));
+    ReturnStatus = EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // Locate variable default data in FFS and send it to the core variable DXE
+  // driver to write.
+  //
+  Status = CreateDefaultVariableHob(DefaultId, BoardId);
+  if (EFI_ERROR(Status)) {
+    DEBUG((DEBUG_ERROR, "create default var HOB: %r!\n", Status));
+    ReturnStatus = Status;
+  }
+
+  //
+  // Set the PCD SKU ID.
+  //
+  LibPcdSetSku(BoardId);
+
+  //
+  // Set the PCD default store ID.
+  //
+  Status = PcdSet16S(PcdSetNvStoreDefaultId, DefaultId);
+  if (EFI_ERROR(Status)) {
+    DEBUG((DEBUG_ERROR, "setNVstore default ID PCD: %r!\n", Status));
+    ReturnStatus = Status;
+  }
+
+  return ReturnStatus;
+}
+
+/**
+Perform the default variable initializations after variable service is ready.
+
+@param[in]  PeiServices       General purpose services available to every PEIM.
+@param[in]  NotifyDescriptor  Pointer to Notify PPI descriptor.
+@param[in]  Interface         Pointer to PPI.
+
+@retval EFI_SUCCESS   Default setting is initialized into variable.
+@retval Other values  Can't find the matched default setting.
+**/
+EFI_STATUS
+EFIAPI
+PlatformVariablePeiInit(
+  IN EFI_PEI_SERVICES           **PeiServices,
+  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,
+  IN VOID                       *Interface
+)
+{
+  EFI_STATUS                      Status;
+  UINT8                           *SystemConfiguration;
+  EFI_GUID                        *SystemConfigurationGuid;
+  UINTN                           DataSize;
+  EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariableServices;
+  UINT8                           Events;
+  UINT16                          DefaultId;
+  BOOLEAN                         ApplyDefaults;
+
+  SystemConfigurationGuid = PcdGetPtr(PcdSetupVariableGuid);
+  Events = 0;
+  DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
+
+  if (PlatformVariableHookForHobGeneration(Interface, &Events, &DefaultId)) {
+    //
+    // Use events bitmap and default ID returned by PlatformVariableHook.
+    //
+    ApplyDefaults = TRUE;
+  }
+  else {
+    //
+    // If the setup variable does not exist (yet), defaults should be applied.
+    //
+    VariableServices = (EFI_PEI_READ_ONLY_VARIABLE2_PPI *)Interface;
+    SystemConfiguration = NULL;
+    DataSize = 0;
+    Status = VariableServices->GetVariable(
+      VariableServices,
+      PLATFORM_SETUP_VARIABLE_NAME,
+      SystemConfigurationGuid,
+      NULL,
+      &DataSize,
+      SystemConfiguration
+    );
+    //
+    // Setup variable is not found. So, set the default setting.
+    //
+    if (Status == EFI_NOT_FOUND) {
+      Events = NULL_VARIABLE_EVENT;
+      DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
+      ApplyDefaults = TRUE;
+    }
+    else {
+      ApplyDefaults = FALSE;
+    }
+  }
+
+
+  if (ApplyDefaults) {
+    Status = ApplyPlatformVariableDefaults(Events, DefaultId);
+  }
+  else {
+    //
+    // Normal case boot flow
+    //
+    Events = 0; // no events occurred
+    BuildGuidDataHob (&gPlatformVariableHobGuid, &Events, sizeof (UINT8));
+
+    //
+    // Patch RP variable value with PC variable in the begining of PEI
+    //
+    Status = CreateRPVariableHob (EFI_HII_DEFAULT_CLASS_STANDARD, BoardId);
+  }
+
+  PeiServicesInstallPpi (&mPpiListPlatformVariableInit);
+  return Status;
+}
+
+
+/**
+Variable Init BootMode CallBack
+Prepare Knob values based on boot mode
+Execute after discovering BootMode
+
+@param[in]  PeiServices       General purpose services available to every PEIM.
+@param[in]  NotifyDescriptor  Pointer to Notify PPI descriptor.
+@param[in]  Interface         Pointer to PPI.
+
+@retval EFI_SUCCESS   Knob Values.
+@retval Other values
+**/
+EFI_STATUS
+EFIAPI
+VariableInitBootModeCallBack(
+  IN EFI_PEI_SERVICES           **PeiServices,
+  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,
+  IN VOID                       *Interface
+) {
+  EFI_BOOT_MODE                   BootMode;
+  BOOLEAN                         ApplyDefaults;
+  UINT8                           Events;
+  UINT16                          DefaultId;
+  EFI_STATUS                      Status;
+
+  Events = 0;
+  DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
+  ApplyDefaults = FALSE;
+
+  //
+  // Certain boot modes require defaults to be (re-)applied.
+  //
+  Status = PeiServicesGetBootMode(&BootMode);
+  ASSERT_EFI_ERROR(Status);
+  if (EFI_ERROR(Status)) {
+    BootMode = BOOT_WITH_DEFAULT_SETTINGS;
+  }
+  if (BootMode == BOOT_WITH_MFG_MODE_SETTINGS) {
+    Events = MFG_MODE_EVENT;
+    DefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
+    ApplyDefaults = TRUE;
+  }
+  else if (BootMode == BOOT_IN_RECOVERY_MODE) {
+    Events = RECOVERY_MODE_EVENT;
+    DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
+    ApplyDefaults = TRUE;
+  }
+  else if (BootMode == BOOT_WITH_DEFAULT_SETTINGS) {
+    Events = CMOS_CLEAR_EVENT;
+    DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
+    ApplyDefaults = TRUE;
+  }
+  if (ApplyDefaults) {
+    Status = ApplyPlatformVariableDefaults(Events, DefaultId);
+  }
+  return Status;
+}
+
+EFI_PEI_NOTIFY_DESCRIPTOR mVariableNotifyList[] = {
+  {
+    (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK),
+    &gEfiPeiReadOnlyVariable2PpiGuid,
+    PlatformVariablePeiInit
+  },
+  {
+    (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+    &gUpdateBootModePpiGuid,
+    VariableInitBootModeCallBack
+  }
+};
+
+EFI_STATUS
+EFIAPI
+PlatformVariableInitPeiEntry (
+  IN EFI_PEI_FILE_HANDLE            FileHandle,
+  IN CONST EFI_PEI_SERVICES          **PeiServices
+  )
+/*++
+
+--*/
+{
+  EFI_STATUS                    Status;
+
+  PlatformVariableHookForEntry();
+
+  // Register notify to set default variable once variable service is ready.
+  //
+  Status = PeiServicesNotifyPpi(&mVariableNotifyList[0]);
+
+  return Status;
+}
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Features/Variable/PlatformVariable/Pei/PlatformVariableInitPei.h b/Platform/Intel/WhitleyOpenBoardPkg/Features/Variable/PlatformVariable/Pei/PlatformVariableInitPei.h
new file mode 100644
index 0000000000..f4701426ff
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Features/Variable/PlatformVariable/Pei/PlatformVariableInitPei.h
@@ -0,0 +1,41 @@
+/** @file
+  Platform variable initialization PEIM.
+
+  This PEIM determines whether to load variable defaults. Ordinarily, the
+  decision is based on the boot mode, but an OEM hook is provided to override
+  that. The appropriate HOBs and PCDs are created to signal DXE code to update
+  the variable default values.
+
+  @copyright
+  Copyright 2012 - 2021 Intel Corporation. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PLATFORM_VARIABLE_INIT_PEI_H_
+#define _PLATFORM_VARIABLE_INIT_PEI_H_
+
+#include <PiPei.h>
+
+#include <Library/MultiPlatSupportLib.h>
+
+#include <Ppi/ReadOnlyVariable2.h>
+#include <Ppi/FirmwareVolumeInfo.h>
+#include <Ppi/CpuIo.h>
+
+#include <Library/PcdLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/IoLib.h>
+#include <Library/PlatformVariableHookLib.h>
+#include <Library/PlatformSetupVariableSyncLib.h>
+
+//
+// We only have one ID for all the platforms.
+//
+#define BOARD_ID_DEFAULT  0
+
+#endif  // #ifndef _PLATFORM_VARIABLE_INIT_PEI_H_
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Features/Variable/PlatformVariable/Pei/PlatformVariableInitPei.inf b/Platform/Intel/WhitleyOpenBoardPkg/Features/Variable/PlatformVariable/Pei/PlatformVariableInitPei.inf
new file mode 100644
index 0000000000..02d216206e
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Features/Variable/PlatformVariable/Pei/PlatformVariableInitPei.inf
@@ -0,0 +1,58 @@
+## @file
+# Platform variable initialization PEIM.
+#
+# This PEIM determines whether to load variable defaults. Ordinarily, the
+# decision is based on the boot mode, but an OEM hook is provided to override
+# that. The appropriate HOBs and PCDs are created to signal DXE code to update
+# the variable default values.
+#
+# @copyright
+# Copyright 2012 - 2021 Intel Corporation. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PlatformVariableInitPei
+  FILE_GUID                      = B88303F6-2E0E-41cc-8510-F5892BF1D9D9
+  MODULE_TYPE                    = PEIM
+  ENTRY_POINT                    = PlatformVariableInitPeiEntry
+
+[Sources]
+  PlatformVariableInitPei.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  SecurityPkg/SecurityPkg.dec
+  WhitleySiliconPkg/WhitleySiliconPkg.dec
+  WhitleySiliconPkg/SiliconPkg.dec
+  WhitleyOpenBoardPkg/PlatformPkg.dec
+
+[LibraryClasses]
+  PeiServicesLib
+  PeimEntryPoint
+  DebugLib
+  HobLib
+  IoLib
+  PciLib
+  PcdLib
+  MultiPlatSupportLib
+  PlatformVariableHookLib
+  PlatformSetupVariableSyncLib
+
+[Pcd]
+  gPlatformTokenSpaceGuid.PcdSetupVariableGuid          ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSetNvStoreDefaultId ## PRODUCES
+
+[Guids]
+  gPlatformVariableHobGuid                              ## PRODUCES           ## HOB
+
+[Ppis]
+  gPlatformVariableInitPpiGuid                          ## PRODUCES
+  gEfiPeiReadOnlyVariable2PpiGuid                       ## SOMETIMES_CONSUMES ## NOTIFY
+  gUpdateBootModePpiGuid                                ## CONSUMES
+
+[Depex]
+  TRUE
-- 
2.27.0.windows.1


  parent reply	other threads:[~2021-07-13  0:42 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-13  0:41 [edk2-platforms] [PATCH V1 00/17] Add IceLake-SP and CooperLake Support to MinPlatform Nate DeSimone
2021-07-13  0:41 ` [edk2-platforms] [PATCH V1 01/17] WhitleySiliconPkg: Add DEC and DSC files Nate DeSimone
2021-07-13  0:41 ` [edk2-platforms] [PATCH V1 02/17] WhitleySiliconPkg: Add Includes and Libraries Nate DeSimone
2021-07-13  0:41 ` [edk2-platforms] [PATCH V1 03/17] WhitleySiliconPkg: Add Cpu Includes Nate DeSimone
2021-07-13  0:41 ` [edk2-platforms] [PATCH V1 04/17] WhitleySiliconPkg: Add Me Includes Nate DeSimone
2021-07-13  0:41 ` [edk2-platforms] [PATCH V1 05/17] WhitleySiliconPkg: Add PCH Register Includes Nate DeSimone
2021-07-13  0:41 ` [edk2-platforms] [PATCH V1 06/17] WhitleySiliconPkg: Add PCH Includes Nate DeSimone
2021-07-13  0:41 ` [edk2-platforms] [PATCH V1 07/17] WhitleySiliconPkg: Add PCH Libraries Nate DeSimone
2021-07-13  0:41 ` [edk2-platforms] [PATCH V1 08/17] WhitleySiliconPkg: Add Security Includes Nate DeSimone
2021-07-13  0:41 ` [edk2-platforms] [PATCH V1 09/17] WhitleySiliconPkg: Add SiliconPolicyInit Nate DeSimone
2021-07-13  0:41 ` [edk2-platforms] [PATCH V1 10/17] WhitleyOpenBoardPkg: Add Includes and Libraries Nate DeSimone
2021-07-13  0:41 ` [edk2-platforms] [PATCH V1 11/17] WhitleyOpenBoardPkg: Add Platform Modules Nate DeSimone
2021-07-13  0:41 ` Nate DeSimone [this message]
2021-07-13  0:41 ` [edk2-platforms] [PATCH V1 13/17] WhitleyOpenBoardPkg: Add UBA Modules Nate DeSimone
2021-07-13  0:41 ` [edk2-platforms] [PATCH V1 14/17] WhitleyOpenBoardPkg: Add build scripts and package metadata Nate DeSimone
2021-07-13  0:41 ` [edk2-platforms] [PATCH V1 15/17] Platform/Intel: Add WhitleyOpenBoardPkg to build_bios.py Nate DeSimone
2021-07-13  0:41 ` [edk2-platforms] [PATCH V1 16/17] Readme.md: Add WhitleyOpenBoardPkg Nate DeSimone
2021-07-13  0:41 ` [edk2-platforms] [PATCH V1 17/17] Maintainers.txt: Add WhitleyOpenBoardPkg and WhitleySiliconPkg Nate DeSimone
2021-07-13  1:35 ` [edk2-platforms] [PATCH V1 00/17] Add IceLake-SP and CooperLake Support to MinPlatform Oram, Isaac W
2021-07-14  2:03 ` Michael D Kinney

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210713004131.1782-13-nathaniel.l.desimone@intel.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox