[edk2-devel] [edk2-platforms] [PATCH V1 09/18] PurleyOpenBoardPkg: Add modules

Nate DeSimone nathaniel.l.desimone at intel.com
Tue May 11 09:48:17 UTC 2021


Cc: Chasel Chiu <chasel.chiu at intel.com>
Cc: Mike Kinney <michael.d.kinney at intel.com>
Cc: Isaac Oram <isaac.w.oram at intel.com>
Cc: Mohamed Abbas <mohamed.abbas at intel.com>
Cc: Michael Kubacki <michael.kubacki at microsoft.com>
Cc: Zachary Bobroff <zacharyb at ami.com>
Cc: Harikrishna Doppalapudi <harikrishnad at ami.com>
Signed-off-by: Nate DeSimone <nathaniel.l.desimone at intel.com>
---
 .../DxePlatformBootManagerLib/BdsPlatform.c   | 1354 +++++++++++++++++
 .../DxePlatformBootManagerLib/BdsPlatform.h   |  184 +++
 .../DxePlatformBootManagerLib.inf             |   96 ++
 .../DxePlatformBootManagerLib/MemoryTest.c    |   85 ++
 .../PlatformBootOption.c                      |  559 +++++++
 .../Pci/PciPlatform/IoApic.h                  |   22 +
 .../Pci/PciPlatform/PciIovPlatformPolicy.c    |   96 ++
 .../Pci/PciPlatform/PciIovPlatformPolicy.h    |   51 +
 .../Pci/PciPlatform/PciPlatform.c             |  183 +++
 .../Pci/PciPlatform/PciPlatform.h             |  201 +++
 .../Pci/PciPlatform/PciPlatform.inf           |   70 +
 .../Pci/PciPlatform/PciPlatformHooks.c        |  527 +++++++
 .../Pci/PciPlatform/PciPlatformHooks.h        |   24 +
 .../Pci/PciPlatform/PciSupportLib.c           |  103 ++
 .../Pci/PciPlatform/PciSupportLib.h           |   44 +
 .../Policy/IioUdsDataDxe/IioUdsDataDxe.c      |   86 ++
 .../Policy/IioUdsDataDxe/IioUdsDataDxe.h      |   81 +
 .../Policy/IioUdsDataDxe/IioUdsDataDxe.inf    |   36 +
 .../PlatformCpuPolicy/PlatformCpuPolicy.c     |  654 ++++++++
 .../PlatformCpuPolicy/PlatformCpuPolicy.inf   |   80 +
 .../Policy/S3NvramSave/S3NvramSave.c          |  256 ++++
 .../Policy/S3NvramSave/S3NvramSave.h          |   31 +
 .../Policy/S3NvramSave/S3NvramSave.inf        |   59 +
 .../Policy/SystemBoard/SystemBoardCommon.c    |  625 ++++++++
 .../Policy/SystemBoard/SystemBoardPei.c       |  255 ++++
 .../Policy/SystemBoard/SystemBoardPei.h       |  182 +++
 .../Policy/SystemBoard/SystemBoardPei.inf     |   76 +
 27 files changed, 6020 insertions(+)
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/BdsPlatform.c
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/BdsPlatform.h
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/DxePlatformBootManagerLib.inf
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/MemoryTest.c
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/PlatformBootOption.c
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Pci/PciPlatform/IoApic.h
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Pci/PciPlatform/PciIovPlatformPolicy.c
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Pci/PciPlatform/PciIovPlatformPolicy.h
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Pci/PciPlatform/PciPlatform.c
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Pci/PciPlatform/PciPlatform.h
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Pci/PciPlatform/PciPlatform.inf
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Pci/PciPlatform/PciPlatformHooks.c
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Pci/PciPlatform/PciPlatformHooks.h
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Pci/PciPlatform/PciSupportLib.c
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Pci/PciPlatform/PciSupportLib.h
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Policy/IioUdsDataDxe/IioUdsDataDxe.c
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Policy/IioUdsDataDxe/IioUdsDataDxe.h
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Policy/IioUdsDataDxe/IioUdsDataDxe.inf
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Policy/PlatformCpuPolicy/PlatformCpuPolicy.c
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Policy/PlatformCpuPolicy/PlatformCpuPolicy.inf
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Policy/S3NvramSave/S3NvramSave.c
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Policy/S3NvramSave/S3NvramSave.h
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Policy/S3NvramSave/S3NvramSave.inf
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Policy/SystemBoard/SystemBoardCommon.c
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Policy/SystemBoard/SystemBoardPei.c
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Policy/SystemBoard/SystemBoardPei.h
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Policy/SystemBoard/SystemBoardPei.inf

diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/BdsPlatform.c b/Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/BdsPlatform.c
new file mode 100644
index 0000000000..b3b8ceba6f
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/BdsPlatform.c
@@ -0,0 +1,1354 @@
+/** @file
+  This file include all platform action which can be customized by IBV/OEM.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "BdsPlatform.h"
+#include <Guid/EventGroup.h>
+#include <Protocol/DxeSmmReadyToLock.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/PciRootBridgeIo.h>
+
+#include <Protocol/BlockIo.h>
+#include <Protocol/PciIo.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
+#include <Guid/EventGroup.h>
+
+#include <Library/Tcg2PhysicalPresenceLib.h>
+
+#include <Library/HobLib.h>
+#include <Protocol/UsbIo.h>
+
+#include <Library/UefiBootManagerLib.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_BOOT_MODE                 gBootMode;
+
+BOOLEAN                      gPPRequireUIConfirm;
+
+extern UINTN                                      mBootMenuOptionNumber;
+
+GLOBAL_REMOVE_IF_UNREFERENCED USB_CLASS_FORMAT_DEVICE_PATH gUsbClassKeyboardDevicePath = {
+  {
+    {
+      MESSAGING_DEVICE_PATH,
+      MSG_USB_CLASS_DP,
+      {
+        (UINT8) (sizeof (USB_CLASS_DEVICE_PATH)),
+        (UINT8) ((sizeof (USB_CLASS_DEVICE_PATH)) >> 8)
+      }
+    },
+    0xffff,           // VendorId
+    0xffff,           // ProductId
+    CLASS_HID,        // DeviceClass
+    SUBCLASS_BOOT,    // DeviceSubClass
+    PROTOCOL_KEYBOARD // DeviceProtocol
+  },
+  gEndEntire
+};
+
+//
+// Internal shell mode
+//
+GLOBAL_REMOVE_IF_UNREFERENCED UINT32         mShellModeColumn;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT32         mShellModeRow;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT32         mShellHorizontalResolution;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT32         mShellVerticalResolution;
+//
+// BDS Platform Functions
+//
+
+BOOLEAN
+IsMorBitSet (
+  VOID
+  )
+{
+  UINTN                     MorControl;
+  EFI_STATUS                Status;
+  UINTN                     DataSize;
+
+  //
+  // Check if the MOR bit is set.
+  //
+  DataSize = sizeof (MorControl);
+  Status = gRT->GetVariable (
+                  MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,
+                  &gEfiMemoryOverwriteControlDataGuid,
+                  NULL,
+                  &DataSize,
+                  &MorControl
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_INFO, " PlatformBootMangerLib: gEfiMemoryOverwriteControlDataGuid doesn't exist!!***\n"));
+    MorControl = 0;
+  } else {
+    DEBUG ((DEBUG_INFO, " PlatformBootMangerLib: Get the gEfiMemoryOverwriteControlDataGuid = %x!!***\n", MorControl));
+  }
+
+  return (BOOLEAN) (MorControl & 0x01);
+}
+
+VOID
+DumpDevicePath (
+  IN CHAR16           *Name,
+  IN EFI_DEVICE_PATH  *DevicePath
+  )
+{
+  CHAR16 *Str;
+
+  Str = ConvertDevicePathToText(DevicePath, TRUE, TRUE);
+  DEBUG ((DEBUG_INFO, "%s: %s\n", Name, Str));
+  if (Str != NULL) {
+    FreePool (Str);
+  }
+}
+
+/**
+  An empty function to pass error checking of CreateEventEx ().
+
+  This empty function ensures that EVT_NOTIFY_SIGNAL_ALL is error
+  checked correctly since it is now mapped into CreateEventEx() in UEFI 2.0.
+
+  @param  Event                 Event whose notification function is being invoked.
+  @param  Context               The pointer to the notification function's context,
+                                which is implementation-dependent.
+**/
+VOID
+EFIAPI
+InternalBdsEmptyCallbackFuntion (
+  IN EFI_EVENT                Event,
+  IN VOID                     *Context
+  )
+{
+  return;
+}
+
+VOID
+ExitPmAuth (
+  VOID
+  )
+{
+  EFI_HANDLE                 Handle;
+  EFI_STATUS                 Status;
+  EFI_EVENT                  EndOfDxeEvent;
+
+  DEBUG((DEBUG_INFO,"ExitPmAuth ()- Start\n"));
+  //
+  // Prepare S3 information, this MUST be done before ExitPmAuth/EndOfDxe
+  //
+  //
+  // Since PI1.2.1, we need signal EndOfDxe as ExitPmAuth
+  //
+  Status = gBS->CreateEventEx (
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_CALLBACK,
+                  InternalBdsEmptyCallbackFuntion,
+                  NULL,
+                  &gEfiEndOfDxeEventGroupGuid,
+                  &EndOfDxeEvent
+                  );
+  ASSERT_EFI_ERROR (Status);
+  gBS->SignalEvent (EndOfDxeEvent);
+  gBS->CloseEvent (EndOfDxeEvent);
+  DEBUG((DEBUG_INFO,"All EndOfDxe callbacks have returned successfully\n"));
+
+  //
+  // NOTE: We need install DxeSmmReadyToLock directly here because many boot script is added via ExitPmAuth/EndOfDxe callback.
+  // If we install them at same callback, these boot script will be rejected because BootScript Driver runs first to lock them done.
+  // So we seperate them to be 2 different events, ExitPmAuth is last chance to let platform add boot script. DxeSmmReadyToLock will
+  // make boot script save driver lock down the interface.
+  //
+  Handle = NULL;
+  Status = gBS->InstallProtocolInterface (
+                  &Handle,
+                  &gEfiDxeSmmReadyToLockProtocolGuid,
+                  EFI_NATIVE_INTERFACE,
+                  NULL
+                  );
+  ASSERT_EFI_ERROR (Status);
+  DEBUG((DEBUG_INFO,"ExitPmAuth ()- End\n"));
+}
+
+VOID
+ConnectRootBridge (
+  BOOLEAN Recursive
+  )
+{
+  UINTN                            RootBridgeHandleCount;
+  EFI_HANDLE                       *RootBridgeHandleBuffer;
+  UINTN                            RootBridgeIndex;
+
+  RootBridgeHandleCount = 0;
+  gBS->LocateHandleBuffer (
+         ByProtocol,
+         &gEfiPciRootBridgeIoProtocolGuid,
+         NULL,
+         &RootBridgeHandleCount,
+         &RootBridgeHandleBuffer
+         );
+  for (RootBridgeIndex = 0; RootBridgeIndex < RootBridgeHandleCount; RootBridgeIndex++) {
+    gBS->ConnectController (RootBridgeHandleBuffer[RootBridgeIndex], NULL, NULL, Recursive);
+  }
+}
+
+
+/**
+  Return whether the device is trusted console.
+
+  @param Device  The device to be tested.
+
+  @retval TRUE   The device can be trusted.
+  @retval FALSE  The device cannot be trusted.
+**/
+BOOLEAN
+IsTrustedConsole (
+  IN CONSOLE_TYPE              ConsoleType,
+  IN EFI_DEVICE_PATH_PROTOCOL  *Device
+  )
+{
+  VOID                      *TrustedConsoleDevicepath;
+  EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL  *Instance;
+  UINTN                     Size;
+  EFI_DEVICE_PATH_PROTOCOL  *ConsoleDevice;
+
+  if (Device == NULL) {
+    return FALSE;
+  }
+
+  ConsoleDevice = DuplicateDevicePath(Device);
+
+  TrustedConsoleDevicepath = NULL;
+
+  switch (ConsoleType) {
+  case ConIn:
+    TrustedConsoleDevicepath = PcdGetPtr (PcdTrustedConsoleInputDevicePath);
+    break;
+  case ConOut:
+    //
+    // Check GOP and remove last node
+    //
+    TempDevicePath = ConsoleDevice;
+    while (!IsDevicePathEndType (TempDevicePath)) {
+      if (DevicePathType (TempDevicePath) == ACPI_DEVICE_PATH &&
+          DevicePathSubType (TempDevicePath) == ACPI_ADR_DP) {
+        SetDevicePathEndNode (TempDevicePath);
+        break;
+      }
+      TempDevicePath = NextDevicePathNode (TempDevicePath);
+    }
+
+    TrustedConsoleDevicepath = PcdGetPtr (PcdTrustedConsoleOutputDevicePath);
+    break;
+  default:
+    ASSERT(FALSE);
+    break;
+  }
+
+  TempDevicePath = TrustedConsoleDevicepath;
+  do {
+    Instance = GetNextDevicePathInstance (&TempDevicePath, &Size);
+    if (Instance == NULL) {
+      break;
+    }
+
+    if (CompareMem (ConsoleDevice, Instance, Size - END_DEVICE_PATH_LENGTH) == 0) {
+      FreePool (Instance);
+      FreePool (ConsoleDevice);
+      return TRUE;
+    }
+
+    FreePool (Instance);
+  } while (TempDevicePath != NULL);
+
+  FreePool (ConsoleDevice);
+
+  return FALSE;
+}
+
+BOOLEAN
+IsUsbShortForm (
+  IN EFI_DEVICE_PATH_PROTOCOL  *DevicePath
+  )
+{
+  if ((DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) &&
+      ((DevicePathSubType (DevicePath) == MSG_USB_CLASS_DP) || (DevicePathSubType (DevicePath) == MSG_USB_WWID_DP)) ) {
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+/**
+  Connect the USB short form device path.
+
+  @param DevicePath   USB short form device path
+
+  @retval EFI_SUCCESS           Successfully connected the USB device
+  @retval EFI_NOT_FOUND         Cannot connect the USB device
+  @retval EFI_INVALID_PARAMETER The device path is invalid.
+**/
+EFI_STATUS
+ConnectUsbShortFormDevicePath (
+  IN EFI_DEVICE_PATH_PROTOCOL   *DevicePath
+  )
+{
+  EFI_STATUS                            Status;
+  EFI_HANDLE                            *Handles;
+  UINTN                                 HandleCount;
+  UINTN                                 Index;
+  EFI_PCI_IO_PROTOCOL                   *PciIo;
+  UINT8                                 Class[3];
+  BOOLEAN                               AtLeastOneConnected;
+
+  //
+  // Check the passed in parameters
+  //
+  if (DevicePath == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (!IsUsbShortForm (DevicePath)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Find the usb host controller firstly, then connect with the remaining device path
+  //
+  AtLeastOneConnected = FALSE;
+  Status = gBS->LocateHandleBuffer (
+                  ByProtocol,
+                  &gEfiPciIoProtocolGuid,
+                  NULL,
+                  &HandleCount,
+                  &Handles
+                  );
+  for (Index = 0; Index < HandleCount; Index++) {
+    Status = gBS->HandleProtocol (
+                    Handles[Index],
+                    &gEfiPciIoProtocolGuid,
+                    (VOID **) &PciIo
+                    );
+    if (!EFI_ERROR (Status)) {
+      //
+      // Check whether the Pci device is the wanted usb host controller
+      //
+      Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x09, 3, &Class);
+      if (!EFI_ERROR (Status) &&
+          ((PCI_CLASS_SERIAL == Class[2]) && (PCI_CLASS_SERIAL_USB == Class[1]))
+         ) {
+        Status = gBS->ConnectController (
+                        Handles[Index],
+                        NULL,
+                        DevicePath,
+                        FALSE
+                        );
+        if (!EFI_ERROR(Status)) {
+          AtLeastOneConnected = TRUE;
+        }
+      }
+    }
+  }
+
+  return AtLeastOneConnected ? EFI_SUCCESS : EFI_NOT_FOUND;
+}
+
+/**
+  Update the ConIn variable with USB Keyboard device path,if its not already exists in ConIn
+**/
+VOID
+EnumUsbKeyboard (
+  VOID
+  )
+{
+  DEBUG ((DEBUG_INFO, "[EnumUsbKeyboard]\n"));
+  EfiBootManagerUpdateConsoleVariable (ConIn, (EFI_DEVICE_PATH_PROTOCOL *) &gUsbClassKeyboardDevicePath, NULL);
+  
+  //
+  // Append Usb Keyboard short form DevicePath into "ConInDev"
+  //
+  EfiBootManagerUpdateConsoleVariable (ConInDev, (EFI_DEVICE_PATH_PROTOCOL *) &gUsbClassKeyboardDevicePath, NULL);
+}
+
+BOOLEAN
+IsVgaHandle (
+  IN EFI_HANDLE Handle
+  )
+{
+  EFI_PCI_IO_PROTOCOL *PciIo;
+  PCI_TYPE00          Pci;
+  EFI_STATUS          Status;
+
+  Status = gBS->HandleProtocol (
+                  Handle,
+                  &gEfiPciIoProtocolGuid,
+                  (VOID **)&PciIo
+                  );
+  if (!EFI_ERROR (Status)) {
+    Status = PciIo->Pci.Read (
+                          PciIo,
+                          EfiPciIoWidthUint32,
+                          0,
+                          sizeof (Pci) / sizeof (UINT32),
+                          &Pci
+                          );
+    if (!EFI_ERROR (Status)) {
+      if (IS_PCI_VGA (&Pci) || IS_PCI_OLD_VGA (&Pci)) {
+        return TRUE;
+      }
+    }
+  }
+  return FALSE;
+}
+
+EFI_HANDLE
+IsVideoController (
+  IN EFI_DEVICE_PATH_PROTOCOL  *DevicePath
+  )
+{
+  EFI_DEVICE_PATH_PROTOCOL  *DupDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;
+  EFI_STATUS                Status;
+  EFI_HANDLE                DeviceHandle;
+
+  DupDevicePath = DuplicateDevicePath (DevicePath);
+  ASSERT (DupDevicePath != NULL);
+  if (DupDevicePath == NULL) {
+    return NULL;
+  }
+
+  TempDevicePath = DupDevicePath;
+  Status = gBS->LocateDevicePath (
+                  &gEfiDevicePathProtocolGuid,
+                  &TempDevicePath,
+                  &DeviceHandle
+                  );
+  FreePool (DupDevicePath);
+  if (EFI_ERROR (Status)) {
+    return NULL;
+  }
+
+  if (IsVgaHandle (DeviceHandle)) {
+    return DeviceHandle;
+  } else {
+    return NULL;
+  }
+}
+
+BOOLEAN
+IsGopDevicePath (
+  IN EFI_DEVICE_PATH_PROTOCOL  *DevicePath
+  )
+{
+  while (!IsDevicePathEndType (DevicePath)) {
+    if (DevicePathType (DevicePath) == ACPI_DEVICE_PATH &&
+        DevicePathSubType (DevicePath) == ACPI_ADR_DP) {
+      return TRUE;
+    }
+    DevicePath = NextDevicePathNode (DevicePath);
+  }
+  return FALSE;
+}
+
+/**
+  Remove all GOP device path instance from DevicePath and add the Gop to the DevicePath.
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+UpdateGopDevicePath (
+  EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+  EFI_DEVICE_PATH_PROTOCOL *Gop
+  )
+{
+  UINTN                    Size;
+  UINTN                    GopSize;
+  EFI_DEVICE_PATH_PROTOCOL *Temp;
+  EFI_DEVICE_PATH_PROTOCOL *Return;
+  EFI_DEVICE_PATH_PROTOCOL *Instance;
+  BOOLEAN                  Exist;
+
+  Exist = FALSE;
+  Return = NULL;
+  GopSize = GetDevicePathSize (Gop);
+  do {
+    Instance = GetNextDevicePathInstance (&DevicePath, &Size);
+    if (Instance == NULL) {
+      break;
+    }
+    if (!IsGopDevicePath (Instance) ||
+        (Size == GopSize && CompareMem (Instance, Gop, GopSize) == 0)
+       ) {
+      if (Size == GopSize && CompareMem (Instance, Gop, GopSize) == 0) {
+        Exist = TRUE;
+      }
+      Temp = Return;
+      Return = AppendDevicePathInstance (Return, Instance);
+      if (Temp != NULL) {
+        FreePool (Temp);
+      }
+    }
+    FreePool (Instance);
+  } while (DevicePath != NULL);
+
+  if (!Exist) {
+    Temp = Return;
+    Return = AppendDevicePathInstance (Return, Gop);
+    if (Temp != NULL) {
+      FreePool (Temp);
+    }
+  }
+  return Return;
+}
+
+/**
+  Get Graphics Controller Handle.
+
+  @retval GraphicsController    Successfully located
+  @retval NULL                  Failed to locate
+**/
+EFI_HANDLE
+EFIAPI
+GetGraphicsController (
+  IN BOOLEAN    NeedTrustedConsole
+  )
+{
+  EFI_STATUS                Status;
+  UINTN                     Index;
+  EFI_HANDLE                *PciHandles;
+  UINTN                     PciHandlesSize;
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
+
+  Status = gBS->LocateHandleBuffer (
+                  ByProtocol,
+                  &gEfiPciIoProtocolGuid,
+                  NULL,
+                  &PciHandlesSize,
+                  &PciHandles
+                  );
+  if (EFI_ERROR (Status)) {
+    return NULL;
+  }
+
+  for (Index = 0; Index < PciHandlesSize; Index++) {
+    Status = gBS->HandleProtocol (
+                    PciHandles[Index],
+                    &gEfiDevicePathProtocolGuid,
+                    (VOID **) &DevicePath
+                    );
+    if (EFI_ERROR(Status)) {
+      continue;
+    }
+    if (!IsVgaHandle (PciHandles[Index])) {
+      continue;
+    }
+    if ((NeedTrustedConsole && IsTrustedConsole (ConOut, DevicePath)) ||
+        ((!NeedTrustedConsole) && (!IsTrustedConsole (ConOut, DevicePath)))) {
+      return PciHandles[Index];
+    }
+  }
+
+  return NULL;
+}
+
+VOID
+UpdateGraphicConOut (
+  IN BOOLEAN    NeedTrustedConsole
+  )
+{
+  EFI_HANDLE                          GraphicsControllerHandle;
+  EFI_DEVICE_PATH_PROTOCOL            *GopDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL            *ConOutDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL            *UpdatedConOutDevicePath;
+
+  //
+  // Update ConOut variable
+  //
+  GraphicsControllerHandle = GetGraphicsController (NeedTrustedConsole);
+  if (GraphicsControllerHandle != NULL) {
+    //
+    // Connect the GOP driver
+    //
+    gBS->ConnectController (GraphicsControllerHandle, NULL, NULL, TRUE);
+
+    //
+    // Get the GOP device path
+    // NOTE: We may get a device path that contains Controller node in it.
+    //
+    GopDevicePath = EfiBootManagerGetGopDevicePath (GraphicsControllerHandle);
+    if (GopDevicePath != NULL) {
+      GetEfiGlobalVariable2 (L"ConOut", (VOID **)&ConOutDevicePath, NULL);
+      UpdatedConOutDevicePath = UpdateGopDevicePath (ConOutDevicePath, GopDevicePath);
+      if (ConOutDevicePath != NULL) {
+        FreePool (ConOutDevicePath);
+      }
+      FreePool (GopDevicePath);
+      gRT->SetVariable (
+                      L"ConOut",
+                      &gEfiGlobalVariableGuid,
+                      EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+                      GetDevicePathSize (UpdatedConOutDevicePath),
+                      UpdatedConOutDevicePath
+                      );
+    }
+  }
+}
+
+VOID
+AddConsoleVariable (
+  IN CONSOLE_TYPE              ConsoleType,
+  IN EFI_DEVICE_PATH           *ConsoleDevicePath
+  )
+{
+  EFI_DEVICE_PATH           *TempDevicePath;
+  EFI_DEVICE_PATH           *Instance;
+  UINTN                     Size;
+  EFI_HANDLE                GraphicsControllerHandle;
+  EFI_DEVICE_PATH           *GopDevicePath;
+
+  TempDevicePath = ConsoleDevicePath;
+  do {
+    Instance = GetNextDevicePathInstance (&TempDevicePath, &Size);
+    if (Instance == NULL) {
+      break;
+    }
+    
+    switch (ConsoleType) {
+    case ConIn:
+      if (IsUsbShortForm (Instance)) {
+        //
+        // Append Usb Keyboard short form DevicePath into "ConInDev"
+        //
+        EfiBootManagerUpdateConsoleVariable (ConInDev, Instance, NULL);
+      }
+      EfiBootManagerUpdateConsoleVariable (ConsoleType, Instance, NULL);
+      break;
+    case ConOut:
+      GraphicsControllerHandle = IsVideoController (Instance);
+      if (GraphicsControllerHandle == NULL) {
+        EfiBootManagerUpdateConsoleVariable (ConsoleType, Instance, NULL);
+      } else {
+        //
+        // Connect the GOP driver
+        //
+        gBS->ConnectController (GraphicsControllerHandle, NULL, NULL, TRUE);
+        //
+        // Get the GOP device path
+        // NOTE: We may get a device path that contains Controller node in it.
+        //
+        GopDevicePath = EfiBootManagerGetGopDevicePath (GraphicsControllerHandle);
+        if (GopDevicePath != NULL) {
+          EfiBootManagerUpdateConsoleVariable (ConsoleType, GopDevicePath, NULL);
+        }
+      }
+      break;
+    default:
+      ASSERT(FALSE);
+      break;
+    }
+
+    FreePool (Instance);
+  } while (TempDevicePath != NULL);
+}
+
+/**
+  The function connects the trusted consoles.
+**/
+VOID
+ConnectTrustedConsole (
+  VOID
+  )
+{
+  EFI_DEVICE_PATH_PROTOCOL     *Consoles;
+  EFI_DEVICE_PATH_PROTOCOL     *TempDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL     *Instance;
+  EFI_DEVICE_PATH_PROTOCOL     *Next;
+  UINTN                        Size;
+  UINTN                        Index;
+  EFI_HANDLE                   Handle;
+  EFI_STATUS                   Status;
+  CHAR16                       *ConsoleVar[] = {L"ConIn", L"ConOut"};
+  VOID                         *TrustedConsoleDevicepath;
+
+  TrustedConsoleDevicepath = PcdGetPtr (PcdTrustedConsoleInputDevicePath);
+  DumpDevicePath (L"TrustedConsoleIn", TrustedConsoleDevicepath);
+  TrustedConsoleDevicepath = PcdGetPtr (PcdTrustedConsoleOutputDevicePath);
+  DumpDevicePath (L"TrustedConsoleOut", TrustedConsoleDevicepath);
+
+  for (Index = 0; Index < sizeof (ConsoleVar) / sizeof (ConsoleVar[0]); Index++) {
+
+    GetEfiGlobalVariable2 (ConsoleVar[Index], (VOID **)&Consoles, NULL);
+
+    TempDevicePath = Consoles;
+    do {
+      Instance = GetNextDevicePathInstance (&TempDevicePath, &Size);
+      if (Instance == NULL) {
+        break;
+      }
+      if (IsTrustedConsole (Index, Instance)) {
+        if (IsUsbShortForm (Instance)) {
+          ConnectUsbShortFormDevicePath (Instance);
+        } else {
+          for (Next = Instance; !IsDevicePathEnd (Next); Next = NextDevicePathNode (Next)) {
+            if (DevicePathType (Next) == ACPI_DEVICE_PATH && DevicePathSubType (Next) == ACPI_ADR_DP) {
+              break;
+            } else if (DevicePathType (Next) == HARDWARE_DEVICE_PATH &&
+                       DevicePathSubType (Next) == HW_CONTROLLER_DP &&
+                       DevicePathType (NextDevicePathNode (Next)) == ACPI_DEVICE_PATH &&
+                       DevicePathSubType (NextDevicePathNode (Next)) == ACPI_ADR_DP
+                       ) {
+              break;
+            }
+          }
+          if (!IsDevicePathEnd (Next)) {
+            SetDevicePathEndNode (Next);
+            Status = EfiBootManagerConnectDevicePath (Instance, &Handle);
+            if (!EFI_ERROR (Status)) {
+              gBS->ConnectController (Handle, NULL, NULL, TRUE);
+            }
+          } else {
+            EfiBootManagerConnectDevicePath (Instance, NULL);
+          }
+        }
+      }
+      FreePool (Instance);
+    } while (TempDevicePath != NULL);
+
+    if (Consoles != NULL) {
+      FreePool (Consoles);
+    }
+  }
+}
+
+/**
+  The function connects the trusted Storages.
+**/
+VOID
+ConnectTrustedStorage (
+  VOID
+  )
+{
+  VOID                      *TrustedStorageDevicepath;
+  EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL  *Instance;
+  UINTN                     Size;
+  EFI_DEVICE_PATH_PROTOCOL  *TempStorageDevicePath;
+  EFI_STATUS                Status;
+  EFI_HANDLE                DeviceHandle;
+
+  TrustedStorageDevicepath = PcdGetPtr (PcdTrustedStorageDevicePath);
+  DumpDevicePath (L"TrustedStorage", TrustedStorageDevicepath);
+
+  TempDevicePath = TrustedStorageDevicepath;
+  do {
+    Instance = GetNextDevicePathInstance (&TempDevicePath, &Size);
+    if (Instance == NULL) {
+      break;
+    }
+
+    EfiBootManagerConnectDevicePath (Instance, NULL);
+
+    TempStorageDevicePath = Instance;
+
+    Status = gBS->LocateDevicePath (
+                    &gEfiDevicePathProtocolGuid,
+                    &TempStorageDevicePath,
+                    &DeviceHandle
+                    );
+    if (!EFI_ERROR (Status)) {
+      gBS->ConnectController (DeviceHandle, NULL, NULL, FALSE);
+    }
+
+    FreePool (Instance);
+  } while (TempDevicePath != NULL);
+}
+
+/**
+  The function connects the trusted consoles and then call the PP processing library interface.
+**/
+VOID
+ProcessTcgPp (
+  VOID
+  )
+{
+  gPPRequireUIConfirm |= Tcg2PhysicalPresenceLibNeedUserConfirm();
+
+  if (gPPRequireUIConfirm) {
+    ConnectTrustedConsole ();
+  }
+
+  Tcg2PhysicalPresenceLibProcessRequest (NULL);
+}
+
+/**
+  The function connects the trusted storage to perform TPerReset.
+**/
+VOID
+ProcessTcgMor (
+  VOID
+  )
+{
+  if (IsMorBitSet ()) {
+    ConnectTrustedConsole();
+    ConnectTrustedStorage();
+  }
+}
+
+/**
+  Check if current BootCurrent variable is internal shell boot option.
+
+  @retval  TRUE         BootCurrent is internal shell.
+  @retval  FALSE        BootCurrent is not internal shell.
+**/
+BOOLEAN
+BootCurrentIsInternalShell (
+  VOID
+  )
+{
+  UINTN                         VarSize;
+  UINT16                        BootCurrent;
+  CHAR16                        BootOptionName[16];
+  UINT8                         *BootOption;
+  UINT8                         *Ptr;
+  BOOLEAN                       Result;
+  EFI_STATUS                    Status;
+  EFI_DEVICE_PATH_PROTOCOL      *TempDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL      *LastDeviceNode;
+  EFI_GUID                      *GuidPoint;
+
+  BootOption = NULL;
+  Result     = FALSE;
+
+  //
+  // Get BootCurrent variable
+  //
+  VarSize = sizeof (UINT16);
+  Status = gRT->GetVariable (
+                  L"BootCurrent",
+                  &gEfiGlobalVariableGuid,
+                  NULL,
+                  &VarSize,
+                  &BootCurrent
+                  );
+  if (EFI_ERROR (Status)) {
+    return FALSE;
+  }
+
+  //
+  // Create boot option Bootxxxx from BootCurrent
+  //
+  UnicodeSPrint (BootOptionName, sizeof(BootOptionName), L"Boot%04X", BootCurrent);
+
+  GetEfiGlobalVariable2 (BootOptionName, (VOID **) &BootOption, &VarSize);
+  if (BootOption == NULL || VarSize == 0) {
+    return FALSE;
+  }
+
+  Ptr = BootOption;
+  Ptr += sizeof (UINT32);
+  Ptr += sizeof (UINT16);
+  Ptr += StrSize ((CHAR16 *) Ptr);
+  TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;
+  LastDeviceNode = TempDevicePath;
+  while (!IsDevicePathEnd (TempDevicePath)) {
+    LastDeviceNode = TempDevicePath;
+    TempDevicePath = NextDevicePathNode (TempDevicePath);
+  }
+  GuidPoint = EfiGetNameGuidFromFwVolDevicePathNode (
+                (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) LastDeviceNode
+                );
+  if ((GuidPoint != NULL) &&
+      ((CompareGuid (GuidPoint, &gUefiShellFileGuid)))
+    ) {
+    //
+    // if this option is internal shell, return TRUE
+    //
+    Result = TRUE;
+  }
+
+  if (BootOption != NULL) {
+    FreePool (BootOption);
+    BootOption = NULL;
+  }
+
+  return Result;
+}
+
+/**
+  This function will change video resolution and text mode
+  for internl shell when internal shell is launched.
+
+  @param   None.
+
+  @retval  EFI_SUCCESS  Mode is changed successfully.
+  @retval  Others       Mode failed to changed.
+**/
+EFI_STATUS
+EFIAPI
+ChangeModeForInternalShell (
+  VOID
+  )
+{
+  EFI_GRAPHICS_OUTPUT_PROTOCOL          *GraphicsOutput;
+  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL       *SimpleTextOut;
+  UINTN                                 SizeOfInfo;
+  EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *Info;
+  UINT32                                MaxGopMode;
+  UINT32                                MaxTextMode;
+  UINT32                                ModeNumber;
+  UINTN                                 HandleCount;
+  EFI_HANDLE                            *HandleBuffer;
+  EFI_STATUS                            Status;
+  UINTN                                 Index;
+  UINTN                                 CurrentColumn;
+  UINTN                                 CurrentRow;
+
+  Status = gBS->HandleProtocol (
+                  gST->ConsoleOutHandle,
+                  &gEfiGraphicsOutputProtocolGuid,
+                  (VOID**)&GraphicsOutput
+                  );
+  if (EFI_ERROR (Status)) {
+    GraphicsOutput = NULL;
+  }
+
+  Status = gBS->HandleProtocol (
+                  gST->ConsoleOutHandle,
+                  &gEfiSimpleTextOutProtocolGuid,
+                  (VOID**)&SimpleTextOut
+                  );
+  if (EFI_ERROR (Status)) {
+    SimpleTextOut = NULL;
+  }
+
+  if ((GraphicsOutput == NULL) || (SimpleTextOut == NULL)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  MaxGopMode  = GraphicsOutput->Mode->MaxMode;
+  MaxTextMode = SimpleTextOut->Mode->MaxMode;
+
+  //
+  // 1. If current video resolution is same with new video resolution,
+  //    video resolution need not be changed.
+  //    1.1. If current text mode is same with new text mode, text mode need not be change.
+  //    1.2. If current text mode is different with new text mode, text mode need be change to new text mode.
+  // 2. If current video resolution is different with new video resolution, we need restart whole console drivers.
+  //
+  for (ModeNumber = 0; ModeNumber < MaxGopMode; ModeNumber++) {
+    Status = GraphicsOutput->QueryMode (
+                       GraphicsOutput,
+                       ModeNumber,
+                       &SizeOfInfo,
+                       &Info
+                       );
+    if (!EFI_ERROR (Status)) {
+      if ((Info->HorizontalResolution == mShellHorizontalResolution) &&
+          (Info->VerticalResolution == mShellVerticalResolution)) {
+        if ((GraphicsOutput->Mode->Info->HorizontalResolution == mShellHorizontalResolution) &&
+            (GraphicsOutput->Mode->Info->VerticalResolution == mShellVerticalResolution)) {
+          //
+          // If current video resolution is same with new resolution,
+          // then check if current text mode is same with new text mode.
+          //
+          Status = SimpleTextOut->QueryMode (SimpleTextOut, SimpleTextOut->Mode->Mode, &CurrentColumn, &CurrentRow);
+          ASSERT_EFI_ERROR (Status);
+          if (CurrentColumn == mShellModeColumn && CurrentRow == mShellModeRow) {
+            //
+            // Current text mode is same with new text mode, text mode need not be change.
+            //
+            FreePool (Info);
+            return EFI_SUCCESS;
+          } else {
+            //
+            // Current text mode is different with new text mode, text mode need be change to new text mode.
+            //
+            for (Index = 0; Index < MaxTextMode; Index++) {
+              Status = SimpleTextOut->QueryMode (SimpleTextOut, Index, &CurrentColumn, &CurrentRow);
+              if (!EFI_ERROR(Status)) {
+                if ((CurrentColumn == mShellModeColumn) && (CurrentRow == mShellModeRow)) {
+                  //
+                  // New text mode is supported, set it.
+                  //
+                  Status = SimpleTextOut->SetMode (SimpleTextOut, Index);
+                  ASSERT_EFI_ERROR (Status);
+                  //
+                  // Update text mode PCD.
+                  //
+                  Status = PcdSet32S (PcdConOutColumn, mShellModeColumn);
+                  ASSERT_EFI_ERROR (Status);
+
+                  Status = PcdSet32S (PcdConOutRow, mShellModeRow);
+                  ASSERT_EFI_ERROR (Status);
+
+                  FreePool (Info);
+                  return EFI_SUCCESS;
+                }
+              }
+            }
+            if (Index == MaxTextMode) {
+              //
+              // If new text mode is not supported, return error.
+              //
+              FreePool (Info);
+              return EFI_UNSUPPORTED;
+            }
+          }
+        } else {
+          FreePool (Info);
+          //
+          // If current video resolution is not same with the new one, set new video resolution.
+          // In this case, the driver which produces simple text out need be restarted.
+          //
+          Status = GraphicsOutput->SetMode (GraphicsOutput, ModeNumber);
+          if (!EFI_ERROR (Status)) {
+            //
+            // Set PCD to restart GraphicsConsole and Consplitter to change video resolution
+            // and produce new text mode based on new resolution.
+            //
+            Status = PcdSet32S (PcdVideoHorizontalResolution, mShellHorizontalResolution);
+            ASSERT_EFI_ERROR (Status);
+
+            Status = PcdSet32S (PcdVideoVerticalResolution, mShellVerticalResolution);
+            ASSERT_EFI_ERROR (Status);
+
+            Status = PcdSet32S (PcdConOutColumn, mShellModeColumn);
+            ASSERT_EFI_ERROR (Status);
+
+            Status = PcdSet32S (PcdConOutRow, mShellModeRow);
+            ASSERT_EFI_ERROR (Status);
+
+            Status = gBS->LocateHandleBuffer (
+                             ByProtocol,
+                             &gEfiSimpleTextOutProtocolGuid,
+                             NULL,
+                             &HandleCount,
+                             &HandleBuffer
+                             );
+            if (!EFI_ERROR (Status)) {
+              for (Index = 0; Index < HandleCount; Index++) {
+                gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);
+              }
+              for (Index = 0; Index < HandleCount; Index++) {
+                gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
+              }
+              if (HandleBuffer != NULL) {
+                FreePool (HandleBuffer);
+              }
+              break;
+            }
+          }
+        }
+      }
+      FreePool (Info);
+    }
+  }
+
+  if (ModeNumber == MaxGopMode) {
+    //
+    // If the new resolution is not supported, return error.
+    //
+    return EFI_UNSUPPORTED;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  ReadyToBoot callback to set video and text mode for internal shell boot.
+  That will not connect USB controller while CSM and FastBoot are disabled, we need to connect them
+  before booting to Shell for showing USB devices in Shell.
+
+  When FastBoot is enabled and Windows Console is the chosen Console behavior, input devices will not be connected
+  by default. Hence, when booting to EFI shell, connecting input consoles are required.
+
+  @param  Event   Pointer to this event
+  @param  Context Event hanlder private data
+
+  @retval None.
+**/
+VOID
+EFIAPI
+OnReadyToBootCallBack (
+  IN  EFI_EVENT                 Event,
+  IN  VOID                      *Context
+  )
+{
+  DEBUG ((EFI_D_INFO, "OnReadyToBootCallBack\n"));
+
+  if (BootCurrentIsInternalShell ()) {
+
+    ChangeModeForInternalShell ();
+    EfiBootManagerConnectAllDefaultConsoles();
+    gDS->Dispatch ();
+  }
+}
+
+/**
+  Platform Bds init. Incude the platform firmware vendor, revision
+  and so crc check.
+**/
+VOID
+EFIAPI
+PlatformBootManagerBeforeConsole (
+  VOID
+  )
+{
+  EFI_STATUS                          Status;
+  EFI_DEVICE_PATH_PROTOCOL            *VarConOut;
+  EFI_DEVICE_PATH_PROTOCOL            *VarConIn;
+  EFI_EVENT                           Event;
+
+  DEBUG ((EFI_D_INFO, "PlatformBootManagerBeforeConsole\n"));
+
+  Status = EFI_SUCCESS;
+
+  //
+  // Get user defined text mode for internal shell only once.
+  //
+  mShellHorizontalResolution = PcdGet32 (PcdSetupVideoHorizontalResolution);
+  mShellVerticalResolution   = PcdGet32 (PcdSetupVideoVerticalResolution);
+  mShellModeColumn           = PcdGet32 (PcdSetupConOutColumn);
+  mShellModeRow              = PcdGet32 (PcdSetupConOutRow);
+
+  if (PcdGetBool (PcdUpdateConsoleInBds) == TRUE) {
+    //
+    // Create event to set proper video resolution and text mode for internal shell.
+    //
+    Status = EfiCreateEventReadyToBootEx (
+               TPL_CALLBACK,
+               OnReadyToBootCallBack,
+               NULL,
+               &Event
+               );
+    ASSERT_EFI_ERROR (Status);
+
+    //
+    // Connect Root Bridge to make PCI BAR resource allocated and all PciIo created
+    //
+    ConnectRootBridge (FALSE);
+
+    //
+    // Fill ConIn/ConOut in Full Configuration boot mode
+    //
+    DEBUG ((DEBUG_INFO, "PlatformBootManagerInit - %x\n", gBootMode));
+
+    if (gBootMode == BOOT_WITH_FULL_CONFIGURATION ||
+        gBootMode == BOOT_WITH_DEFAULT_SETTINGS ||
+        gBootMode == BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS ||
+        gBootMode == BOOT_IN_RECOVERY_MODE) {
+
+      GetEfiGlobalVariable2 (L"ConOut", (VOID **)&VarConOut, NULL);   if (VarConOut != NULL) { FreePool (VarConOut); }
+      GetEfiGlobalVariable2 (L"ConIn", (VOID **)&VarConIn, NULL);    if (VarConIn  != NULL) { FreePool (VarConIn);  }
+
+      //
+      // Only fill ConIn/ConOut when ConIn/ConOut is empty because we may drop to Full Configuration boot mode in non-first boot
+      //
+      if (VarConOut == NULL || VarConIn == NULL) {
+        if (PcdGetSize (PcdTrustedConsoleOutputDevicePath) >= sizeof(EFI_DEVICE_PATH_PROTOCOL)) {
+          AddConsoleVariable (ConOut, PcdGetPtr (PcdTrustedConsoleOutputDevicePath));
+        }
+        if (PcdGetSize (PcdTrustedConsoleInputDevicePath) >= sizeof(EFI_DEVICE_PATH_PROTOCOL)) {
+          AddConsoleVariable (ConIn, PcdGetPtr (PcdTrustedConsoleInputDevicePath));
+        }
+      }
+    }
+
+    EnumUsbKeyboard ();
+    //
+    // For trusted console it must be handled here.
+    //
+    UpdateGraphicConOut (TRUE);
+
+    //
+    // Dynamically register hot key: F2/F7/Enter
+    //
+    RegisterDefaultBootOption ();
+    RegisterStaticHotkey ();
+  }
+  
+  PERF_START_EX(NULL,"EventRec", NULL, AsmReadTsc(), 0x7010);
+  if (PcdGetBool (PcdTpm2Enable)) {
+    ProcessTcgPp ();
+    ProcessTcgMor ();
+  }
+  PERF_END_EX(NULL,"EventRec", NULL, AsmReadTsc(), 0x7011);
+
+  //
+  // We should make all UEFI memory and GCD information populated before ExitPmAuth.
+  // SMM may consume these information.
+  //
+  MemoryTest((EXTENDMEM_COVERAGE_LEVEL) PcdGet32 (PcdPlatformMemoryCheckLevel));
+
+  PERF_START_EX(NULL,"EventRec", NULL, AsmReadTsc(), 0x7020);
+  ExitPmAuth ();
+  PERF_END_EX(NULL,"EventRec", NULL, AsmReadTsc(), 0x7021);
+
+  //
+  // Dispatch the deferred 3rd party images.
+  //
+  EfiBootManagerDispatchDeferredImages ();
+
+  //
+  // For non-trusted console it must be handled here.
+  //
+  if (PcdGetBool (PcdUpdateConsoleInBds) == TRUE) {
+    UpdateGraphicConOut (FALSE);
+  }
+}
+
+
+/**
+  Connect with predeined platform connect sequence,
+  the OEM/IBV can customize with their own connect sequence.
+
+  @param[in] BootMode          Boot mode of this boot.
+**/
+VOID
+ConnectSequence (
+  IN EFI_BOOT_MODE         BootMode
+  )
+{
+  EfiBootManagerConnectAll ();
+}
+
+/**
+  The function is to consider the boot order which is not in our expectation.
+  In the case that we need to re-sort the boot option.
+
+  @retval  TRUE         Need to sort Boot Option.
+  @retval  FALSE        Don't need to sort Boot Option.
+**/
+BOOLEAN
+IsNeedSortBootOption (
+  VOID
+  )
+{
+  EFI_BOOT_MANAGER_LOAD_OPTION  *BootOptions;
+  UINTN                         BootOptionCount;
+
+  BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);
+
+  //
+  // If setup is the first priority in boot option, we need to sort boot option.
+  //
+  if ((BootOptionCount > 1) &&
+      (((StrnCmp (BootOptions->Description, L"Enter Setup", StrLen (L"Enter Setup"))) == 0) ||
+       ((StrnCmp (BootOptions->Description, L"BootManagerMenuApp", StrLen (L"BootManagerMenuApp"))) == 0))) {
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+/**
+  The function will excute with as the platform policy, current policy
+  is driven by boot mode. IBV/OEM can customize this code for their specific
+  policy action.
+
+  @param DriverOptionList - The header of the driver option link list
+  @param BootOptionList   - The header of the boot option link list
+  @param ProcessCapsules  - A pointer to ProcessCapsules()
+  @param BaseMemoryTest   - A pointer to BaseMemoryTest()
+**/
+VOID
+EFIAPI
+PlatformBootManagerAfterConsole (
+  VOID
+  )
+{
+  EFI_BOOT_MODE                 LocalBootMode;
+
+  DEBUG ((EFI_D_INFO, "PlatformBootManagerAfterConsole\n"));
+
+  //
+  // Get current Boot Mode
+  //
+  LocalBootMode = gBootMode;
+  DEBUG ((DEBUG_INFO, "Current local bootmode - %x\n", LocalBootMode));
+
+  //
+  // Go the different platform policy with different boot mode
+  // Notes: this part code can be change with the table policy
+  //
+  switch (LocalBootMode) {
+
+  case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES:
+  case BOOT_WITH_MINIMAL_CONFIGURATION:
+  case BOOT_ON_S4_RESUME:
+    //
+    // Perform some platform specific connect sequence
+    //
+    if (PcdGetBool (PcdFastBoot) == FALSE) {
+      PERF_START_EX(NULL,"EventRec", NULL, AsmReadTsc(), 0x7050);
+      ConnectSequence (LocalBootMode);
+      PERF_END_EX(NULL,"EventRec", NULL, AsmReadTsc(), 0x7051);
+    }
+
+    break;
+
+  case BOOT_WITH_FULL_CONFIGURATION:
+  case BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS:
+  case BOOT_WITH_DEFAULT_SETTINGS:
+  default:
+    //
+    // Perform some platform specific connect sequence
+    //
+    ConnectSequence (LocalBootMode);
+
+    //
+    // Only in Full Configuration boot mode we do the enumeration of boot device
+    //
+    //
+    // Dispatch all but Storage Oprom explicitly, because we assume Int13Thunk driver is there.
+    //
+    EfiBootManagerRefreshAllBootOption ();
+
+    if (IsNeedSortBootOption()) {
+      EfiBootManagerSortLoadOptionVariable (LoadOptionTypeBoot, CompareBootOption);
+    }
+    //
+    // PXE boot option may appear after boot option enumeration
+    //
+
+    break;
+  }
+
+  if (PcdGetBool (PcdFastBoot) == FALSE) {
+    Print (L"Press F7 for BootMenu!\n");
+
+    EfiBootManagerRefreshAllBootOption ();
+    EfiBootManagerSortLoadOptionVariable (LoadOptionTypeBoot, CompareBootOption);
+  }
+}
+
+/**
+  The function is called when no boot option could be launched,
+  including platform recovery options and options pointing to applications
+  built into firmware volumes.
+
+  If this function returns, BDS attempts to enter an infinite loop.
+**/
+VOID
+EFIAPI
+PlatformBootManagerUnableToBoot (
+  VOID
+  )
+{
+  EFI_STATUS                   Status;
+  EFI_BOOT_MANAGER_LOAD_OPTION BootDeviceList;
+  CHAR16                       OptionName[sizeof ("Boot####")];
+
+  if (mBootMenuOptionNumber == LoadOptionNumberUnassigned) {
+    return;
+  }
+  UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", mBootMenuOptionNumber);
+  Status = EfiBootManagerVariableToLoadOption (OptionName, &BootDeviceList);
+  if (EFI_ERROR (Status)) {
+    return;
+  }
+  for (;;) {
+    EfiBootManagerBoot (&BootDeviceList);
+  }
+}
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/BdsPlatform.h b/Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/BdsPlatform.h
new file mode 100644
index 0000000000..360a00d7d7
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/BdsPlatform.h
@@ -0,0 +1,184 @@
+/** @file
+  Header file for BDS Platform specific code
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _BDS_PLATFORM_H
+#define _BDS_PLATFORM_H
+
+#include <PiDxe.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/SimpleNetwork.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/LoadFile.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/CpuIo2.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/DiskInfo.h>
+#include <Protocol/GraphicsOutput.h>
+#include <Protocol/UgaDraw.h>
+#include <Protocol/GenericMemoryTest.h>
+#include <Protocol/DevicePathToText.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/SimpleFileSystem.h>
+
+#include <Guid/CapsuleVendor.h>
+#include <Guid/MemoryTypeInformation.h>
+#include <Guid/GlobalVariable.h>
+#include <Guid/MemoryOverwriteControl.h>
+#include <Guid/FileInfo.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PlatformBootManagerLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/UefiLib.h>
+#include <Library/HobLib.h>
+#include <Library/DxeServicesLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/PrintLib.h>
+#include <Library/HiiLib.h>
+#include <Library/CapsuleLib.h>
+#include <Library/PerformanceLib.h>
+
+#include <IndustryStandard/Pci30.h>
+#include <IndustryStandard/PciCodeId.h>
+
+///
+/// ConnectType
+///
+#define CONSOLE_OUT 0x00000001
+#define STD_ERROR   0x00000002
+#define CONSOLE_IN  0x00000004
+#define CONSOLE_ALL (CONSOLE_OUT | CONSOLE_IN | STD_ERROR)
+
+extern EFI_GUID                  gUefiShellFileGuid;
+extern EFI_BOOT_MODE             gBootMode;
+
+#define gPciRootBridge \
+  { \
+    { \
+      ACPI_DEVICE_PATH, \
+      ACPI_DP, \
+      { \
+        (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)), \
+        (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) \
+      }, \
+    }, \
+    EISA_PNP_ID (0x0A03), \
+    0 \
+  }
+
+#define gEndEntire \
+  { \
+    END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, { END_DEVICE_PATH_LENGTH, 0 } \
+  }
+
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
+  UINTN                     ConnectType;
+} BDS_CONSOLE_CONNECT_ENTRY;
+
+//
+// Platform Root Bridge
+//
+typedef struct {
+  ACPI_HID_DEVICE_PATH      PciRootBridge;
+  EFI_DEVICE_PATH_PROTOCOL  End;
+} PLATFORM_ROOT_BRIDGE_DEVICE_PATH;
+
+//
+// Below is the platform console device path
+//
+typedef struct {
+  ACPI_HID_DEVICE_PATH      PciRootBridge;
+  PCI_DEVICE_PATH           IsaBridge;
+  ACPI_HID_DEVICE_PATH      Keyboard;
+  EFI_DEVICE_PATH_PROTOCOL  End;
+} PLATFORM_KEYBOARD_DEVICE_PATH;
+
+typedef struct {
+  ACPI_HID_DEVICE_PATH      PciRootBridge;
+  PCI_DEVICE_PATH           PciDevice;
+  EFI_DEVICE_PATH_PROTOCOL  End;
+} PLATFORM_ONBOARD_CONTROLLER_DEVICE_PATH;
+
+typedef struct {
+  ACPI_HID_DEVICE_PATH      PciRootBridge;
+  PCI_DEVICE_PATH           Pci0Device;
+  EFI_DEVICE_PATH_PROTOCOL  End;
+} PLATFORM_PEG_ROOT_CONTROLLER_DEVICE_PATH;
+
+typedef struct {
+  ACPI_HID_DEVICE_PATH      PciRootBridge;
+  PCI_DEVICE_PATH           PciBridge;
+  PCI_DEVICE_PATH           PciDevice;
+  EFI_DEVICE_PATH_PROTOCOL  End;
+} PLATFORM_PCI_CONTROLLER_DEVICE_PATH;
+
+//
+// Below is the boot option device path
+//
+
+#define CLASS_HID           3
+#define SUBCLASS_BOOT       1
+#define PROTOCOL_KEYBOARD   1
+
+typedef struct {
+  USB_CLASS_DEVICE_PATH           UsbClass;
+  EFI_DEVICE_PATH_PROTOCOL        End;
+} USB_CLASS_FORMAT_DEVICE_PATH;
+
+extern USB_CLASS_FORMAT_DEVICE_PATH              gUsbClassKeyboardDevicePath;
+
+//
+// Platform BDS Functions
+//
+
+
+/**
+  Perform the memory test base on the memory test intensive level,
+  and update the memory resource.
+
+  @param  Level         The memory test intensive level.
+
+  @retval EFI_STATUS    Success test all the system memory and update
+                        the memory resource
+
+**/
+EFI_STATUS
+MemoryTest (
+  IN EXTENDMEM_COVERAGE_LEVEL Level
+  );
+
+VOID
+ConnectSequence (
+  IN EFI_BOOT_MODE                      BootMode
+  );
+
+
+INTN
+EFIAPI
+CompareBootOption (
+  CONST VOID  *Left,
+  CONST VOID  *Right
+  );
+
+
+VOID
+RegisterStaticHotkey (
+  VOID
+  );
+VOID
+RegisterDefaultBootOption (
+  VOID
+  );
+
+#endif
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/DxePlatformBootManagerLib.inf b/Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/DxePlatformBootManagerLib.inf
new file mode 100644
index 0000000000..5790743565
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/DxePlatformBootManagerLib.inf
@@ -0,0 +1,96 @@
+## @file
+# Component name for module DxePlatformBootManagerLib
+#
+# Copyright (c) 2017 - 2021, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010017
+  BASE_NAME                      = DxePlatformBootManagerLib
+  FILE_GUID                      = A6BC385D-59E5-4B77-87D7-200ABAA83C15
+  VERSION_STRING                 = 1.0
+  MODULE_TYPE                    = DXE_DRIVER
+  UEFI_SPECIFICATION_VERSION     = 2.10
+  LIBRARY_CLASS                  = PlatformBootManagerLib|DXE_DRIVER
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC
+#
+
+[LibraryClasses]
+  BaseLib
+  MemoryAllocationLib
+  UefiBootServicesTableLib
+  UefiRuntimeServicesTableLib
+  BaseMemoryLib
+  DebugLib
+  PcdLib
+  PrintLib
+  DevicePathLib
+  UefiLib
+  HobLib
+  DxeServicesLib
+  DxeServicesTableLib
+  HiiLib
+  UefiBootManagerLib
+  PerformanceLib
+  TimerLib
+  Tcg2PhysicalPresenceLib
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  SecurityPkg/SecurityPkg.dec
+  MinPlatformPkg/MinPlatformPkg.dec
+  PurleyOpenBoardPkg/OpenBoardPkg.dec
+
+[Pcd]
+  gMinPlatformPkgTokenSpaceGuid.PcdTpm2Enable                    ## CONSUMES
+  gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut                   ## PRODUCES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution       ## PRODUCES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution         ## PRODUCES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow                       ## PRODUCES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn                    ## PRODUCES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSetupConOutColumn               ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSetupConOutRow                  ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoHorizontalResolution  ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoVerticalResolution    ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdConInConnectOnDemand            ## PRODUCES
+  gMinPlatformPkgTokenSpaceGuid.PcdPlatformMemoryCheckLevel      ## CONSUMES
+  gMinPlatformPkgTokenSpaceGuid.PcdBootToShellOnly               ## CONSUMES
+  gMinPlatformPkgTokenSpaceGuid.PcdTrustedConsoleInputDevicePath  ## CONSUMES
+  gMinPlatformPkgTokenSpaceGuid.PcdTrustedConsoleOutputDevicePath ## CONSUMES
+  gMinPlatformPkgTokenSpaceGuid.PcdTrustedStorageDevicePath       ## CONSUMES
+  gPlatformTokenSpaceGuid.PcdUpdateConsoleInBds                   ## CONSUMES
+  gPlatformTokenSpaceGuid.PcdFastBoot                             ## CONSUMES
+
+[Sources]
+  BdsPlatform.c
+  BdsPlatform.h
+  PlatformBootOption.c
+  MemoryTest.c
+
+[Protocols]
+  gEfiPciRootBridgeIoProtocolGuid               ## CONSUMES
+  gEfiPciIoProtocolGuid                         ## CONSUMES
+  gEfiCpuIo2ProtocolGuid                        ## CONSUMES
+  gEfiDxeSmmReadyToLockProtocolGuid             ## PRODUCES
+  gEfiGenericMemTestProtocolGuid                ## CONSUMES
+  gEfiDiskInfoProtocolGuid                      ## CONSUMES
+  gEfiDevicePathToTextProtocolGuid              ## CONSUMES
+  gEfiSimpleTextInputExProtocolGuid             ## CONSUMES
+  gEfiFirmwareVolume2ProtocolGuid               ## CONSUMES
+  gEfiFormBrowser2ProtocolGuid                  ## CONSUMES
+  gEfiGenericMemTestProtocolGuid                ## CONSUMES
+
+[Guids]
+  gEfiGlobalVariableGuid                        ## PRODUCES
+  gEfiMemoryOverwriteControlDataGuid            ## PRODUCES
+  gEfiEndOfDxeEventGroupGuid                    ## CONSUMES
+
+[Depex.common.DXE_DRIVER]
+  gEfiVariableArchProtocolGuid
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/MemoryTest.c b/Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/MemoryTest.c
new file mode 100644
index 0000000000..e6445fecf8
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/MemoryTest.c
@@ -0,0 +1,85 @@
+/** @file
+  Perform the platform memory test
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "BdsPlatform.h"
+#include <Protocol/GenericMemoryTest.h>
+
+/**
+  Perform the memory test base on the memory test intensive level,
+  and update the memory resource.
+
+  @param  Level         The memory test intensive level.
+
+  @retval EFI_STATUS    Success test all the system memory and update
+                        the memory resource
+
+**/
+EFI_STATUS
+MemoryTest (
+  IN EXTENDMEM_COVERAGE_LEVEL Level
+  )
+{
+  EFI_STATUS                        Status;
+  BOOLEAN                           RequireSoftECCInit;
+  EFI_GENERIC_MEMORY_TEST_PROTOCOL  *GenMemoryTest;
+  UINT64                            TestedMemorySize;
+  UINT64                            TotalMemorySize;
+  BOOLEAN                           ErrorOut;
+  BOOLEAN                           TestAbort;
+
+  TestedMemorySize  = 0;
+  TotalMemorySize   = 0;
+  ErrorOut          = FALSE;
+  TestAbort         = FALSE;
+
+  RequireSoftECCInit = FALSE;
+
+  Status = gBS->LocateProtocol (
+                  &gEfiGenericMemTestProtocolGuid,
+                  NULL,
+                  (VOID **) &GenMemoryTest
+                  );
+  if (EFI_ERROR (Status)) {
+    return EFI_SUCCESS;
+  }
+
+  Status = GenMemoryTest->MemoryTestInit (
+                                GenMemoryTest,
+                                Level,
+                                &RequireSoftECCInit
+                                );
+  if (Status == EFI_NO_MEDIA) {
+    //
+    // The PEI codes also have the relevant memory test code to check the memory,
+    // it can select to test some range of the memory or all of them. If PEI code
+    // checks all the memory, this BDS memory test will has no not-test memory to
+    // do the test, and then the status of EFI_NO_MEDIA will be returned by
+    // "MemoryTestInit". So it does not need to test memory again, just return.
+    //
+    return EFI_SUCCESS;
+  }
+
+  if (PcdGetBool (PcdFastBoot) == FALSE) {
+    do {
+      Status = GenMemoryTest->PerformMemoryTest (
+                                GenMemoryTest,
+                                &TestedMemorySize,
+                                &TotalMemorySize,
+                                &ErrorOut,
+                                TestAbort
+                                );
+      if (ErrorOut && (Status == EFI_DEVICE_ERROR)) {
+        ASSERT (0);
+      }
+    } while (Status != EFI_NOT_FOUND);
+  }
+
+  Status = GenMemoryTest->Finished (GenMemoryTest);
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/PlatformBootOption.c b/Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/PlatformBootOption.c
new file mode 100644
index 0000000000..84aa097d58
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Override/Platform/Intel/MinPlatformPkg/Bds/Library/DxePlatformBootManagerLib/PlatformBootOption.c
@@ -0,0 +1,559 @@
+/** @file
+  Driver for Platform Boot Options support.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "BdsPlatform.h"
+
+#include <Library/PcdLib.h>
+
+BOOLEAN    mContinueBoot  = FALSE;
+BOOLEAN    mBootMenuBoot  = FALSE;
+BOOLEAN    mPxeBoot       = FALSE;
+BOOLEAN    mHotKeypressed = FALSE;
+EFI_EVENT  HotKeyEvent    = NULL;
+
+UINTN      mBootMenuOptionNumber;
+
+EFI_DEVICE_PATH_PROTOCOL *
+BdsCreateShellDevicePath (
+  VOID
+  )
+/*++
+
+Routine Description:
+
+  This function will create a SHELL BootOption to boot.
+
+Arguments:
+
+  None.
+
+Returns:
+
+  Shell Device path for booting.
+
+--*/
+{
+  UINTN                             FvHandleCount;
+  EFI_HANDLE                        *FvHandleBuffer;
+  UINTN                             Index;
+  EFI_STATUS                        Status;
+  EFI_FIRMWARE_VOLUME2_PROTOCOL     *Fv;
+  UINTN                             Size;
+  UINT32                            AuthenticationStatus;
+  EFI_DEVICE_PATH_PROTOCOL          *DevicePath;
+  VOID                              *Buffer;
+
+  DevicePath  = NULL;
+  Status      = EFI_SUCCESS;
+
+  DEBUG ((DEBUG_INFO, "BdsCreateShellDevicePath\n"));
+  gBS->LocateHandleBuffer (
+        ByProtocol,
+        &gEfiFirmwareVolume2ProtocolGuid,
+        NULL,
+        &FvHandleCount,
+        &FvHandleBuffer
+        );
+
+  for (Index = 0; Index < FvHandleCount; Index++) {
+    gBS->HandleProtocol (
+          FvHandleBuffer[Index],
+          &gEfiFirmwareVolume2ProtocolGuid,
+          (VOID **) &Fv
+          );
+
+    Buffer  = NULL;
+    Size    = 0;
+    Status  = Fv->ReadSection (
+                    Fv,
+                    &gUefiShellFileGuid,
+                    EFI_SECTION_PE32,
+                    0,
+                    &Buffer,
+                    &Size,
+                    &AuthenticationStatus
+                    );
+    if (EFI_ERROR (Status)) {
+      //
+      // Skip if no shell file in the FV
+      //
+      continue;
+    } else {
+      //
+      // Found the shell
+      //
+      break;
+    }
+  }
+
+  if (EFI_ERROR (Status)) {
+    //
+    // No shell present
+    //
+    if (FvHandleCount) {
+      FreePool (FvHandleBuffer);
+    }
+    return NULL;
+  }
+  //
+  // Build the shell boot option
+  //
+  DevicePath = DevicePathFromHandle (FvHandleBuffer[Index]);
+
+  if (FvHandleCount) {
+    FreePool (FvHandleBuffer);
+  }
+
+  return DevicePath;
+}
+
+
+EFI_STATUS
+CreateFvBootOption (
+  EFI_GUID                     *FileGuid,
+  CHAR16                       *Description,
+  EFI_BOOT_MANAGER_LOAD_OPTION *BootOption,
+  UINT32                       Attributes,
+  UINT8                        *OptionalData,    OPTIONAL
+  UINT32                       OptionalDataSize
+  )
+{
+  EFI_STATUS                         Status;
+  EFI_DEVICE_PATH_PROTOCOL           *DevicePath;
+  EFI_LOADED_IMAGE_PROTOCOL          *LoadedImage;
+  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH  FileNode;
+  EFI_FIRMWARE_VOLUME2_PROTOCOL      *Fv;
+  UINT32                             AuthenticationStatus;
+  VOID                               *Buffer;
+  UINTN                              Size;
+
+  if ((BootOption == NULL) || (FileGuid == NULL) || (Description == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid);
+
+  if (!CompareGuid (&gUefiShellFileGuid, FileGuid)) {
+    Status = gBS->HandleProtocol (
+                    gImageHandle,
+                    &gEfiLoadedImageProtocolGuid,
+                    (VOID **) &LoadedImage
+                    );
+    if (!EFI_ERROR (Status)) {
+      Status = gBS->HandleProtocol (
+                      LoadedImage->DeviceHandle,
+                      &gEfiFirmwareVolume2ProtocolGuid,
+                      (VOID **) &Fv
+                      );
+      if (!EFI_ERROR (Status)) {
+        Buffer  = NULL;
+        Size    = 0;
+        Status  = Fv->ReadSection (
+                        Fv,
+                        FileGuid,
+                        EFI_SECTION_PE32,
+                        0,
+                        &Buffer,
+                        &Size,
+                        &AuthenticationStatus
+                        );
+        if (Buffer != NULL) {
+          FreePool (Buffer);
+        }
+      }
+    }
+    if (EFI_ERROR (Status)) {
+      return EFI_NOT_FOUND;
+    }
+
+    DevicePath = AppendDevicePathNode (
+                   DevicePathFromHandle (LoadedImage->DeviceHandle),
+                   (EFI_DEVICE_PATH_PROTOCOL *) &FileNode
+                   );
+  } else {
+    DevicePath = AppendDevicePathNode (
+                   BdsCreateShellDevicePath (),
+                   (EFI_DEVICE_PATH_PROTOCOL *) &FileNode
+                   );
+  }
+
+  Status = EfiBootManagerInitializeLoadOption (
+             BootOption,
+             LoadOptionNumberUnassigned,
+             LoadOptionTypeBoot,
+             Attributes,
+             Description,
+             DevicePath,
+             OptionalData,
+             OptionalDataSize
+             );
+  FreePool (DevicePath);
+  return Status;
+}
+
+EFI_GUID mUiFile = {
+  0x462CAA21, 0x7614, 0x4503, { 0x83, 0x6E, 0x8A, 0xB6, 0xF4, 0x66, 0x23, 0x31 }
+};
+EFI_GUID mBootMenuFile = {
+  0xEEC25BDC, 0x67F2, 0x4D95, { 0xB1, 0xD5, 0xF8, 0x1B, 0x20, 0x39, 0xD1, 0x1D }
+};
+
+
+/**
+  Return the index of the load option in the load option array.
+
+  The function consider two load options are equal when the
+  OptionType, Attributes, Description, FilePath and OptionalData are equal.
+
+  @param Key    Pointer to the load option to be found.
+  @param Array  Pointer to the array of load options to be found.
+  @param Count  Number of entries in the Array.
+
+  @retval -1          Key wasn't found in the Array.
+  @retval 0 ~ Count-1 The index of the Key in the Array.
+**/
+INTN
+PlatformFindLoadOption (
+  IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Key,
+  IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Array,
+  IN UINTN                              Count
+  )
+{
+  UINTN                             Index;
+
+  for (Index = 0; Index < Count; Index++) {
+    if ((Key->OptionType == Array[Index].OptionType) &&
+        (Key->Attributes == Array[Index].Attributes) &&
+        (StrCmp (Key->Description, Array[Index].Description) == 0) &&
+        (CompareMem (Key->FilePath, Array[Index].FilePath, GetDevicePathSize (Key->FilePath)) == 0) &&
+        (Key->OptionalDataSize == Array[Index].OptionalDataSize) &&
+        (CompareMem (Key->OptionalData, Array[Index].OptionalData, Key->OptionalDataSize) == 0)) {
+      return (INTN) Index;
+    }
+  }
+
+  return -1;
+}
+
+UINTN
+RegisterFvBootOption (
+  EFI_GUID                         *FileGuid,
+  CHAR16                           *Description,
+  UINTN                            Position,
+  UINT32                           Attributes,
+  UINT8                            *OptionalData,    OPTIONAL
+  UINT32                           OptionalDataSize
+  )
+{
+  EFI_STATUS                       Status;
+  UINTN                            OptionIndex;
+  EFI_BOOT_MANAGER_LOAD_OPTION     NewOption;
+  EFI_BOOT_MANAGER_LOAD_OPTION     *BootOptions;
+  UINTN                            BootOptionCount;
+
+  NewOption.OptionNumber = LoadOptionNumberUnassigned;
+  Status = CreateFvBootOption (FileGuid, Description, &NewOption, Attributes, OptionalData, OptionalDataSize);
+  if (!EFI_ERROR (Status)) {
+    BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);
+
+    OptionIndex = PlatformFindLoadOption (&NewOption, BootOptions, BootOptionCount);
+
+    if (OptionIndex == -1) {
+      Status = EfiBootManagerAddLoadOptionVariable (&NewOption, Position);
+      ASSERT_EFI_ERROR (Status);
+    } else {
+      NewOption.OptionNumber = BootOptions[OptionIndex].OptionNumber;
+    }
+    EfiBootManagerFreeLoadOption (&NewOption);
+    EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
+  }
+
+  return NewOption.OptionNumber;
+}
+
+
+
+VOID
+EFIAPI
+PlatformBootManagerWaitCallback (
+  UINT16          TimeoutRemain
+  )
+{
+  EFI_STATUS                    Status;
+  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *TxtInEx;
+  EFI_KEY_DATA                  KeyData;
+  BOOLEAN                       PausePressed;
+
+  //
+  // Pause on PAUSE key
+  //
+  Status = gBS->HandleProtocol (gST->ConsoleInHandle, &gEfiSimpleTextInputExProtocolGuid, (VOID **) &TxtInEx);
+  ASSERT_EFI_ERROR (Status);
+
+  PausePressed = FALSE;
+
+  while (TRUE) {
+    Status = TxtInEx->ReadKeyStrokeEx (TxtInEx, &KeyData);
+    if (EFI_ERROR (Status)) {
+      break;
+    }
+
+    if (KeyData.Key.ScanCode == SCAN_PAUSE) {
+      PausePressed = TRUE;
+      break;
+    }
+  }
+
+  //
+  // Loop until non-PAUSE key pressed
+  //
+  while (PausePressed) {
+    Status = TxtInEx->ReadKeyStrokeEx (TxtInEx, &KeyData);
+    if (!EFI_ERROR (Status)) {
+      DEBUG ((
+        DEBUG_INFO, "[PauseCallback] %x/%x %x/%x\n",
+        KeyData.Key.ScanCode, KeyData.Key.UnicodeChar,
+        KeyData.KeyState.KeyShiftState, KeyData.KeyState.KeyToggleState
+        ));
+      PausePressed = (BOOLEAN) (KeyData.Key.ScanCode == SCAN_PAUSE);
+    }
+  }
+}
+
+
+EFI_GUID gUefiShellFileGuid = { 0x7C04A583, 0x9E3E, 0x4f1c, { 0xAD, 0x65, 0xE0, 0x52, 0x68, 0xD0, 0xB4, 0xD1 } };
+
+#define INTERNAL_UEFI_SHELL_NAME      L"Internal UEFI Shell 2.0"
+#define UEFI_HARD_DRIVE_NAME          L"UEFI Hard Drive"
+
+VOID
+RegisterDefaultBootOption (
+  VOID
+  )
+{
+#if 0
+  EFI_DEVICE_PATH_PROTOCOL           *DevicePath;
+  EFI_LOADED_IMAGE_PROTOCOL          *LoadedImage;
+  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH  FileNode;
+#endif
+  UINT16                             *ShellData;
+  UINT32                             ShellDataSize;
+
+    ShellData = NULL;
+    ShellDataSize = 0;
+    RegisterFvBootOption (&gUefiShellFileGuid,      INTERNAL_UEFI_SHELL_NAME, (UINTN) -1, LOAD_OPTION_ACTIVE, (UINT8 *)ShellData, ShellDataSize);
+
+  //
+  // Boot Menu
+  //
+  mBootMenuOptionNumber = RegisterFvBootOption (&mBootMenuFile, L"Boot Device List",   (UINTN) -1, LOAD_OPTION_CATEGORY_APP | LOAD_OPTION_ACTIVE | LOAD_OPTION_HIDDEN, NULL, 0);
+
+  if (mBootMenuOptionNumber == LoadOptionNumberUnassigned) {
+    DEBUG ((DEBUG_INFO, "BootMenuOptionNumber (%d) should not be same to LoadOptionNumberUnassigned(%d).\n", mBootMenuOptionNumber, LoadOptionNumberUnassigned));
+  }
+#if 0
+  //
+  // Boot Manager Menu
+  //
+  EfiInitializeFwVolDevicepathNode (&FileNode, &mUiFile);
+
+  gBS->HandleProtocol (
+         gImageHandle,
+         &gEfiLoadedImageProtocolGuid,
+         (VOID **) &LoadedImage
+         );
+  DevicePath = AppendDevicePathNode (DevicePathFromHandle (LoadedImage->DeviceHandle), (EFI_DEVICE_PATH_PROTOCOL *) &FileNode);
+#endif
+
+}
+
+VOID
+RegisterBootOptionHotkey (
+  UINT16                       OptionNumber,
+  EFI_INPUT_KEY                *Key,
+  BOOLEAN                      Add
+  )
+{
+  EFI_STATUS                   Status;
+
+  if (!Add) {
+    //
+    // No enter hotkey when force to setup or there is no boot option
+    //
+    Status = EfiBootManagerDeleteKeyOptionVariable (NULL, 0, Key, NULL);
+    ASSERT (Status == EFI_SUCCESS || Status == EFI_NOT_FOUND);
+  } else {
+    //
+    // Register enter hotkey for the first boot option
+    //
+    Status = EfiBootManagerAddKeyOptionVariable (NULL, OptionNumber, 0, Key,NULL);
+    ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);
+  }
+}
+
+EFI_STATUS
+EFIAPI
+DetectKeypressCallback (
+  IN EFI_KEY_DATA     *KeyData
+)
+{
+  mHotKeypressed = TRUE;
+
+  if (HotKeyEvent != NULL) {
+    gBS->SignalEvent(HotKeyEvent);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  This function is called after all the boot options are enumerated and ordered properly.
+**/
+VOID
+RegisterStaticHotkey (
+  VOID
+  )
+{
+
+  EFI_INPUT_KEY                 Enter;
+  EFI_KEY_DATA                  F2;
+  EFI_KEY_DATA                  F7;
+  BOOLEAN                       EnterSetup;
+  EFI_STATUS                    Status;
+  EFI_BOOT_MANAGER_LOAD_OPTION  BootOption;
+
+  EnterSetup = FALSE;
+
+  //
+  // [Enter]
+  //
+  mContinueBoot = !EnterSetup;
+  if (mContinueBoot) {
+    Enter.ScanCode    = SCAN_NULL;
+    Enter.UnicodeChar = CHAR_CARRIAGE_RETURN;
+    EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL);
+  }
+
+
+  //
+  // [F2]/[F7]
+  //
+  F2.Key.ScanCode    = SCAN_F2;
+  F2.Key.UnicodeChar = CHAR_NULL;
+  F2.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;
+  F2.KeyState.KeyToggleState = 0;
+  Status = EfiBootManagerGetBootManagerMenu (&BootOption);
+  ASSERT_EFI_ERROR (Status);
+  RegisterBootOptionHotkey ((UINT16) BootOption.OptionNumber, &F2.Key, TRUE);
+  EfiBootManagerFreeLoadOption (&BootOption);
+
+  F7.Key.ScanCode    = SCAN_F7;
+  F7.Key.UnicodeChar = CHAR_NULL;
+  F7.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;
+  F7.KeyState.KeyToggleState = 0;
+  mBootMenuBoot  = !EnterSetup;
+  RegisterBootOptionHotkey ((UINT16) mBootMenuOptionNumber, &F7.Key, mBootMenuBoot);
+
+}
+
+UINT8
+BootOptionType (
+  IN EFI_DEVICE_PATH_PROTOCOL   *DevicePath
+  )
+{
+  EFI_DEVICE_PATH_PROTOCOL      *Node;
+  EFI_DEVICE_PATH_PROTOCOL      *NextNode;
+
+  for (Node = DevicePath; !IsDevicePathEndType (Node); Node = NextDevicePathNode (Node)) {
+    if (DevicePathType (Node) == MESSAGING_DEVICE_PATH) {
+      //
+      // Make sure the device path points to the driver device.
+      //
+      NextNode = NextDevicePathNode (Node);
+      if (DevicePathSubType(NextNode) == MSG_DEVICE_LOGICAL_UNIT_DP) {
+        //
+        // if the next node type is Device Logical Unit, which specify the Logical Unit Number (LUN),
+        // skip it
+        //
+        NextNode = NextDevicePathNode (NextNode);
+      }
+      if (IsDevicePathEndType (NextNode)) {
+        if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH)) {
+          return DevicePathSubType (Node);
+        } else {
+          return MSG_SATA_DP;
+        }
+      }
+    }
+  }
+
+  return (UINT8) -1;
+}
+
+/**
+  Returns the priority number.
+  OptionType                 EFI
+  ------------------------------------
+  PXE                         2
+  DVD                         4
+  USB                         6
+  NVME                        7
+  HDD                         8
+  EFI Shell                   9
+  Others                      100
+
+  @param BootOption
+**/
+UINTN
+BootOptionPriority (
+  CONST EFI_BOOT_MANAGER_LOAD_OPTION *BootOption
+  )
+{
+    //
+    // EFI boot options
+    //
+    switch (BootOptionType (BootOption->FilePath)) {
+    case MSG_MAC_ADDR_DP:
+    case MSG_VLAN_DP:
+    case MSG_IPv4_DP:
+    case MSG_IPv6_DP:
+      return 2;
+
+    case MSG_SATA_DP:
+    case MSG_ATAPI_DP:
+    case MSG_UFS_DP:
+    case MSG_NVME_NAMESPACE_DP:
+      return 4;
+
+    case MSG_USB_DP:
+      return 6;
+
+    }
+    if (StrCmp (BootOption->Description, INTERNAL_UEFI_SHELL_NAME) == 0) {
+      if (PcdGetBool (PcdBootToShellOnly)) {
+        return 0;
+      }
+      return 9;
+    }
+    if (StrCmp (BootOption->Description, UEFI_HARD_DRIVE_NAME) == 0) {
+      return 8;
+    }
+    return 100;
+}
+
+INTN
+EFIAPI
+CompareBootOption (
+  CONST VOID  *Left,
+  CONST VOID  *Right
+  )
+{
+  return BootOptionPriority ((EFI_BOOT_MANAGER_LOAD_OPTION *) Left) -
+         BootOptionPriority ((EFI_BOOT_MANAGER_LOAD_OPTION *) Right);
+}
+
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Pci/PciPlatform/IoApic.h b/Platform/Intel/PurleyOpenBoardPkg/Pci/PciPlatform/IoApic.h
new file mode 100644
index 0000000000..3ec3baa207
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Pci/PciPlatform/IoApic.h
@@ -0,0 +1,22 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _IOAPIC_H_
+#define _IOAPIC_H_
+
+#define EFI_IO_APIC_INDEX_OFFSET          0x00
+#define EFI_IO_APIC_DATA_OFFSET           0x10
+#define EFI_IO_APIC_IRQ_ASSERTION_OFFSET  0x20
+#define EFI_IO_APIC_EOI_OFFSET            0x40
+
+#define EFI_IO_APIC_ID_REGISTER           0x0
+#define EFI_IO_APIC_ID_BITSHIFT           24
+#define EFI_IO_APIC_VER_REGISTER          0x1
+#define EFI_IO_APIC_BOOT_CONFIG_REGISTER  0x3
+#define EFI_IO_APIC_FSB_INT_DELIVERY      0x1
+
+#endif
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Pci/PciPlatform/PciIovPlatformPolicy.c b/Platform/Intel/PurleyOpenBoardPkg/Pci/PciPlatform/PciIovPlatformPolicy.c
new file mode 100644
index 0000000000..0b941ccb07
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Pci/PciPlatform/PciIovPlatformPolicy.c
@@ -0,0 +1,96 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<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                                 SystemPageSize;  
+
+  CopyMem (&SystemPageSize, (UINT8 *)PcdGetPtr(PcdSetupData) + OFFSET_OF(SYSTEM_CONFIGURATION, SystemPageSize), sizeof(UINT8));
+  
+  if (SystemLowestPageSize != NULL) {
+    //
+    // Page size is 4K
+    //
+    //*SystemLowestPageSize = 1;
+    *SystemLowestPageSize = SystemPageSize;
+  }
+  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(PcdSetupData) + OFFSET_OF(SYSTEM_CONFIGURATION, ARIEnable), sizeof(UINT8));
+  CopyMem (&SRIOVEnable, (UINT8 *)PcdGetPtr(PcdSetupData) + OFFSET_OF(SYSTEM_CONFIGURATION, SRIOVEnable), sizeof(UINT8));
+  CopyMem (&MRIOVEnable, (UINT8 *)PcdGetPtr(PcdSetupData) + 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/PurleyOpenBoardPkg/Pci/PciPlatform/PciIovPlatformPolicy.h b/Platform/Intel/PurleyOpenBoardPkg/Pci/PciPlatform/PciIovPlatformPolicy.h
new file mode 100644
index 0000000000..f7a8cb06a0
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Pci/PciPlatform/PciIovPlatformPolicy.h
@@ -0,0 +1,51 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<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/PurleyOpenBoardPkg/Pci/PciPlatform/PciPlatform.c b/Platform/Intel/PurleyOpenBoardPkg/Pci/PciPlatform/PciPlatform.c
new file mode 100644
index 0000000000..b479ec5992
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Pci/PciPlatform/PciPlatform.c
@@ -0,0 +1,183 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+#include "PciPlatform.h"
+#include <Library/PcdLib.h>
+#ifdef EFI_PCI_IOV_SUPPORT
+#include "PciIovPlatformPolicy.h"
+#endif
+
+PCI_PLATFORM_PRIVATE_DATA mPciPrivateData;
+
+BOOLEAN                   FirstCall = TRUE;
+UINT8                     sSataRaidLoadEfiDriverOption;
+UINT8                     SataRaidLoadEfiDriverOption;
+UINT8                     BootNetworkOption;
+
+/**
+
+  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;
+}
+
+/**
+
+  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
+  )
+{
+  return EFI_NOT_FOUND;
+}
+
+/**
+
+  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;
+
+  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/PurleyOpenBoardPkg/Pci/PciPlatform/PciPlatform.h b/Platform/Intel/PurleyOpenBoardPkg/Pci/PciPlatform/PciPlatform.h
new file mode 100644
index 0000000000..353715688a
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Pci/PciPlatform/PciPlatform.h
@@ -0,0 +1,201 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef PCI_PLATFORM_H_
+#define PCI_PLATFORM_H_
+
+#include <PiDxe.h>
+#include <Register/PchRegsSata.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/PcdLib.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 <Guid/SetupVariable.h>
+#include <Guid/SocketVariable.h>
+#include <IndustryStandard/Pci.h>
+
+//
+// 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;
+  EFI_CPU_IO2_PROTOCOL            *CpuIo;
+  EFI_LIST_ENTRY                  PciCallbackList;
+  EFI_PCI_CALLBACK_CONTEXT        Context;
+  EFI_PCI_ENUMERATION_PHASE       PciEnumerationPhase;
+  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/PurleyOpenBoardPkg/Pci/PciPlatform/PciPlatform.inf b/Platform/Intel/PurleyOpenBoardPkg/Pci/PciPlatform/PciPlatform.inf
new file mode 100644
index 0000000000..884d151b49
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Pci/PciPlatform/PciPlatform.inf
@@ -0,0 +1,70 @@
+## @file
+#
+# Copyright (c) 2018 - 2021, Intel Corporation. All rights reserved.<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
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  MinPlatformPkg/MinPlatformPkg.dec
+  PurleyOpenBoardPkg/OpenBoardPkg.dec
+  PurleyRefreshSiliconPkg/SiPkg.dec
+
+[LibraryClasses]
+  UefiDriverEntryPoint
+  IoLib
+  BaseMemoryLib
+  DebugLib
+  UefiRuntimeServicesTableLib
+  UefiBootServicesTableLib
+  HobLib
+  S3PciLib
+  PcdLib
+
+[Protocols]
+  gEfiPciCallbackProtocolGuid
+  gEfiCpuIo2ProtocolGuid
+  gEfiFirmwareVolume2ProtocolGuid
+  gEfiPciIoProtocolGuid
+  gEfiPciPlatformProtocolGuid
+  gEfiIioUdsProtocolGuid
+  gEfiPciRootBridgeIoProtocolGuid
+  gEfiPciIovPlatformProtocolGuid
+  gEfiIioSystemProtocolGuid
+  gEfiPciHostBridgeResourceAllocationProtocolGuid
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSrIovSystemPageSize
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSrIovSupport
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAriSupport
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMrIovSupport
+  gOemSkuTokenSpaceGuid.PcdSetupData
+  gMinPlatformPkgTokenSpaceGuid.PcdIoApicId
+  gMinPlatformPkgTokenSpaceGuid.PcdPcIoApicIdBase
+
+[FixedPcd]
+  gEfiCpRcPkgTokenSpaceGuid.PcdMaxNestedLevel
+
+[Depex]
+  TRUE
+
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Pci/PciPlatform/PciPlatformHooks.c b/Platform/Intel/PurleyOpenBoardPkg/Pci/PciPlatform/PciPlatformHooks.c
new file mode 100644
index 0000000000..2556d46407
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Pci/PciPlatform/PciPlatformHooks.c
@@ -0,0 +1,527 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+#include <Protocol/IioUds.h> 
+#include <PciPlatform.h>
+#include <PciPlatformHooks.h>
+#include <PciSupportLib.h>
+#include <IoApic.h>
+#include <Library/S3BootScriptLib.h>
+#include <Protocol/IioSystem.h>
+
+EFI_IIO_UDS_PROTOCOL                    *mIioUds          = NULL;
+EFI_IIO_SYSTEM_PROTOCOL       *IioSystemProtocol = NULL;
+IIO_GLOBALS                   *IioGlobalData = NULL;
+
+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_LIST_ENTRY    *NodeEntry;
+  PCI_CALLBACK_DATA *PciCallbackData;
+
+  //
+  // Check if the node has been added
+  //
+  // DEBUG ((DEBUG_ERROR, "PCI Callback (%d,%d,%d)\n",PciAddress.Bus, PciAddress.Device, PciAddress.Function ));
+  //
+  Context->PciRootBridgeIo  = mPciPrivateData.PciRootBridgeIo;
+  NodeEntry                 = GetFirstNode (&mPciPrivateData.PciCallbackList);
+  while (!IsNull (&mPciPrivateData.PciCallbackList, NodeEntry)) {
+    PciCallbackData = PCI_CALLBACK_DATA_FROM_LINK (NodeEntry);
+    if (PciCallbackData->Phase & Phase) {
+      (PciCallbackData->Function) (RootBridgeHandle, PciAddress, Phase, Context);
+    }
+
+    NodeEntry = GetNextNode (&mPciPrivateData.PciCallbackList, NodeEntry);
+  }
+}
+
+/**
+
+    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                                        StartBus
+  )
+{
+  UINT64  PciAddress;
+  UINT8   Device;
+  UINT8   Func;
+  UINT8   SecondaryBus;
+  BOOLEAN MultiFunc;
+
+  for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
+    MultiFunc =  FALSE;
+    for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
+      if (IsPciDevicePresent (
+            mPciPrivateData.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);
+        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);
+          mPciPrivateData.PciRootBridgeIo->Pci.Read (
+                                                mPciPrivateData.PciRootBridgeIo,
+                                                EfiPciWidthUint8,
+                                                *(UINT64 *) &PciAddress,
+                                                1,
+                                                &SecondaryBus
+                                                );
+          if ((SecondaryBus > 0) && (SecondaryBus < 0xFF)) {
+            PciTreeTraverse (SecondaryBus);
+          }
+        }
+      }
+
+      if (MultiFunc == FALSE) {
+        //
+        // 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, (1 << 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;
+  //
+  // Locate the IIO Protocol Interface
+  //
+  Status = gBS->LocateProtocol (&gEfiIioUdsProtocolGuid,NULL,&mIioUds);
+  ASSERT_EFI_ERROR (Status);
+  Status = gBS->LocateProtocol (&gEfiIioSystemProtocolGuid, NULL, &IioSystemProtocol);
+  ASSERT_EFI_ERROR (Status); 
+
+  IioGlobalData = IioSystemProtocol->IioGlobalData;
+
+#ifdef EFI_PCI_IOV_SUPPORT
+  Status = PciPlatformInitPciIovData();	// Update IOV PCD values
+#endif
+  return EFI_SUCCESS;
+}
+
+
+/**
+  
+  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
+  )
+{
+  //
+  // Program all the IOAPIC in system
+  //
+  UINT8 Socket, Stack, IoApicId;
+  UINT8 Step;
+  UINT8 MaxSocket;
+
+#if MAX_SOCKET <= 4
+  Step = 6;
+  MaxSocket = 4;
+#else
+  Step = 4;
+  MaxSocket = 8;
+#endif
+
+  Stack = 0;
+  IoApicId = 0;
+  ProgramIoApicId (mIioUds->IioUdsPtr->PlatformData.IIO_resource[0].StackRes[0].IoApicBase, PcdGet8(PcdIoApicId));
+  for (Socket = 0; Socket < MAX_SOCKET; Socket++) {
+    if (!(mIioUds->IioUdsPtr->SystemStatus.socketPresentBitMap & (1 << Socket)))
+      continue;
+
+    for (Stack = 0; Stack < MAX_IIO_STACK; Stack++) {
+      if (!(mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap & (1 << Stack)))
+        continue;
+
+      if ((Socket < MaxSocket) && (Stack < Step)) {
+        IoApicId = PcdGet8(PcdPcIoApicIdBase) + Step * Socket + Stack;
+      }
+
+      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);
+      }
+    }
+  }
+  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
+  )
+{
+  if (mPciPrivateData.RootBridgeHandle == NULL) {
+    mPciPrivateData.RootBridgeHandle = RootBridge;
+  }
+
+  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;
+  UINT8       i;
+  UINT8       Stack;
+
+  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
+    //
+    Status = gBS->LocateProtocol (
+                    &gEfiPciRootBridgeIoProtocolGuid,
+                    NULL,
+                    &(mPciPrivateData.PciRootBridgeIo)
+                    );
+    ASSERT_EFI_ERROR (Status);
+
+    Status = gBS->LocateProtocol (
+                    &gEfiCpuIo2ProtocolGuid,
+                    NULL,
+                    &(mPciPrivateData.CpuIo)
+                    );
+    ASSERT_EFI_ERROR (Status);
+    mPciPrivateData.Context.CpuIo = mPciPrivateData.CpuIo;
+
+    DEBUG ((DEBUG_ERROR, "PCI Platform Pre-Initialization (Before bus scanning)\n"));
+    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 (i = 0 ; i < MaxIIO ; i++) {
+          if (mIioUds->IioUdsPtr->PlatformData.IIO_resource[i].Valid) {
+              for(Stack = 0; Stack < MAX_IIO_STACK; Stack ++) {
+                  PciTreeTraverse (mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[i].StackBus[Stack]);
+              }
+          }
+      }
+      mPciPrivateData.BusAssignedTime++;
+      DEBUG ((DEBUG_ERROR, "PCI Platform bus assigned\n"));
+    }
+    break;
+
+  case EfiPciHostBridgeBeginResourceAllocation:
+    //
+    // PCI bus number has been assigned, but resource is still empty
+    //
+    DEBUG ((DEBUG_ERROR, "PCI Platform Mid-Initialization (After bus number assignment)\n"));
+    mPciPrivateData.PciEnumerationPhase = EfiPciEnumerationBusNumberAssigned;
+    for (i = 0 ; i < MaxIIO ; i++) {
+        if (mIioUds->IioUdsPtr->PlatformData.IIO_resource[i].Valid) {
+            for(Stack = 0; Stack < MAX_IIO_STACK; Stack ++) {
+                PciTreeTraverse (mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[i].StackBus[Stack]);
+            }
+        }
+    }
+    //PciPlatformMidInit ();
+    break;
+
+  case EfiPciHostBridgeEndResourceAllocation:
+    //
+    // Resource enumeration is done.
+    // Both bus number and resource have been assigned
+    // Do any post initialization.
+    //
+    DEBUG ((DEBUG_ERROR, "PCI Platform Post-Initialization (After resource alloction)\n"));
+    mPciPrivateData.PciEnumerationPhase = EfiPciEnumerationResourceAssigned;
+    for (i = 0 ; i < MaxIIO ; i++) {
+        if (mIioUds->IioUdsPtr->PlatformData.IIO_resource[i].Valid) {
+            for(Stack = 0; Stack < MAX_IIO_STACK; Stack ++) {
+                PciTreeTraverse (mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[i].StackBus[Stack]);
+            }
+        }
+    }
+    PciPlatformPostInit ();
+    break;
+
+  default:
+    return EFI_UNSUPPORTED;
+  }
+
+  return EFI_SUCCESS;
+}
+
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Pci/PciPlatform/PciPlatformHooks.h b/Platform/Intel/PurleyOpenBoardPkg/Pci/PciPlatform/PciPlatformHooks.h
new file mode 100644
index 0000000000..a5cee1b3a5
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Pci/PciPlatform/PciPlatformHooks.h
@@ -0,0 +1,24 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef PCI_PLATFORM_HOOKS_H_
+#define PCI_PLATFORM_HOOKS_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                                        StartBus
+  );
+
+#endif
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Pci/PciPlatform/PciSupportLib.c b/Platform/Intel/PurleyOpenBoardPkg/Pci/PciPlatform/PciSupportLib.c
new file mode 100644
index 0000000000..d8bf65439f
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Pci/PciPlatform/PciSupportLib.c
@@ -0,0 +1,103 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<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,
+  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) {
+    /// PCIe card could have been assigned a temporary bus number. 
+    /// An write cycle can be used to try to rewrite the Bus number in the card
+    /// Try to write the Vendor Id register, and recheck if the card is present. 
+    Status = PciRootBridgeIo->Pci.Write(
+                                    PciRootBridgeIo, 
+                                    EfiPciWidthUint32, 
+                                    Address, 
+                                    1,							  
+                                    &Dummy
+                                    ); 
+									
+    // Retry the previous read after the PCI cycle has been tried. 
+    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/PurleyOpenBoardPkg/Pci/PciPlatform/PciSupportLib.h b/Platform/Intel/PurleyOpenBoardPkg/Pci/PciPlatform/PciSupportLib.h
new file mode 100644
index 0000000000..dc123b0d42
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Pci/PciPlatform/PciSupportLib.h
@@ -0,0 +1,44 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<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,
+  PCI_TYPE00                          *Pci,
+  UINT8                               Bus,
+  UINT8                               Device,
+  UINT8                               Func
+  );
+  
+
+#endif
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Policy/IioUdsDataDxe/IioUdsDataDxe.c b/Platform/Intel/PurleyOpenBoardPkg/Policy/IioUdsDataDxe/IioUdsDataDxe.c
new file mode 100644
index 0000000000..6c626cf05d
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Policy/IioUdsDataDxe/IioUdsDataDxe.c
@@ -0,0 +1,86 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+//
+// Statements that include other files
+//
+#include "IioUdsDataDxe.h"
+
+#define STRING_WIDTH_40    40
+
+//
+// Instantiation of Driver's private data.
+//
+EFI_IIO_UDS_DRIVER_PRIVATE          mIioUdsPrivateData;
+IIO_UDS                             *IioUdsData;          // Pointer to UDS in Allocated Memory Pool
+
+/**
+
+  Entry point for the driver.
+
+  @param ImageHandle  -  Image Handle.
+  @param SystemTable  -  EFI System Table.
+  
+  @retval EFI_SUCCESS  -  Function has completed successfully.
+  
+**/
+EFI_STATUS
+EFIAPI
+IioUdsDataInit (
+  IN EFI_HANDLE                         ImageHandle,
+  IN EFI_SYSTEM_TABLE                   *SystemTable
+  )
+{
+  EFI_STATUS                      Status;
+  EFI_HOB_GUID_TYPE               *GuidHob;
+  IIO_UDS                         *UdsHobPtr;
+  EFI_GUID                        UniversalDataGuid = IIO_UNIVERSAL_DATA_GUID;
+
+  //
+  // Time to get the IIO_UDS HOB data stored in the PEI driver
+  //
+  GuidHob    = GetFirstGuidHob (&UniversalDataGuid);
+  ASSERT (GuidHob != NULL);
+  if (GuidHob == NULL) {
+    return EFI_NOT_FOUND;
+  }
+  UdsHobPtr = GET_GUID_HOB_DATA(GuidHob); 
+
+  //
+  // Allocate Memory Pool for Universal Data Storage so that protocol can expose it
+  //
+  Status = gBS->AllocatePool ( EfiReservedMemoryType, sizeof (IIO_UDS), (VOID **) &IioUdsData );
+  ASSERT_EFI_ERROR (Status);
+  
+  //
+  // Initialize the Pool Memory with the data from the Hand-Off-Block
+  //
+  CopyMem(IioUdsData, UdsHobPtr, sizeof(IIO_UDS));
+
+  //
+  // Build the IIO_UDS driver instance for protocol publishing  
+  //
+  ZeroMem (&mIioUdsPrivateData, sizeof (mIioUdsPrivateData));
+    
+  mIioUdsPrivateData.Signature            = EFI_IIO_UDS_DRIVER_PRIVATE_SIGNATURE;
+  mIioUdsPrivateData.IioUds.IioUdsPtr     = IioUdsData;
+  mIioUdsPrivateData.IioUds.EnableVc      = NULL;
+
+  //
+  // Install the IioUds Protocol.
+  //
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &mIioUdsPrivateData.Handle,
+                  &gEfiIioUdsProtocolGuid,
+                  &mIioUdsPrivateData.IioUds,
+                  NULL
+                  );
+  ASSERT_EFI_ERROR (Status);  
+
+  return EFI_SUCCESS;
+}
+
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Policy/IioUdsDataDxe/IioUdsDataDxe.h b/Platform/Intel/PurleyOpenBoardPkg/Policy/IioUdsDataDxe/IioUdsDataDxe.h
new file mode 100644
index 0000000000..62da06d605
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Policy/IioUdsDataDxe/IioUdsDataDxe.h
@@ -0,0 +1,81 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _PLATFORM_TYPES_H_
+#define _PLATFORM_TYPES_H_
+
+#include <PiDxe.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/HobLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Protocol/VariableWrite.h>
+#include <Protocol/CpuIo2.h>
+#include <Protocol/Spi.h>
+#include <Protocol/IioUds.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include <Guid/HobList.h>
+#include <Register/PchRegsSpi.h>
+#include <Register/PchRegsLpc.h>
+#include <PchAccess.h>
+#include <Platform.h>
+
+
+
+
+#define EFI_PLATFORM_TYPE_DRIVER_PRIVATE_SIGNATURE  SIGNATURE_32 ('T', 'Y', 'P', 'P')
+#define EFI_IIO_UDS_DRIVER_PRIVATE_SIGNATURE  SIGNATURE_32 ('S', 'D', 'U', 'I')
+
+
+typedef unsigned char BYTE;     //!<  8-bit quantities
+typedef unsigned short WORD;    //!< 16-bit quantities
+typedef unsigned long DWORD;    //!< 32-bit quantities
+
+typedef enum
+{
+#ifndef SUCCESS
+    SUCCESS = 0x00,             //!< Packet it good! .data[] is valid
+#endif
+    DEFER = 0x01,               //!< Packet is defered. .data[1] = BufID
+    W_EARLY_NACK = 0x02,        //!< Packet mastered on the SMBus by the MCU was NACKed earlier than expected
+    NOT_RESP = 0x03,            //!< Packet mastered on the SMBus by the MCU was NACKed during the address byte
+    BUFFER_OVERRUN = 0x04,      //!< Too many BYTE s were stuffed into the buffer.
+    NO_BUFFER = 0x05,           //!< All the buffers are used
+    INVALID_BUF = 0x06,         //!< Command passed a buffer id that was not in range
+    BUF_NOT_IN_QUEUE = 0x07,    //!< Command passed a buffer id is not being used.
+    ARBITRATION_LOST = 0x08,    //!< While the MCU was mastering a packet on the SMBus it lost arbitration.
+    TIMEOUT = 0x0B,             //!< SMBus timed out.
+    CHECKSUM_ERR = 0x0C,        //!< Operation encountered a checksum mismatch
+    DATA_NACK = 0x0D,           //!< Still don't know what these mean?
+    BUS_ERR = 0x0E,             //!< ?
+    FAIL = 0x0F,                //!< Generic error
+    BUSY = 0x10,                //!< ?
+    R_EARLY_NACK = 0x11,        //!< ?
+    INVALID_LCD_COL_OFF = 0x12, //!< The cursor on the LCD was set to a column that was out of range.
+    INVALID_LCD_ROW_OFF = 0x13, //!< The cursor on the LCD was set to a row that was out of range.
+    INVALID_CK410_SEL = 0x14,   //!< ?
+    CMD_NOT_SUPPORTED = 0x15,   //!< This command is not supported
+    MORE_DATA_AVAILABLE = 0x16, //!< Do the command again to get more data
+} STATUS;
+
+typedef struct {
+  BYTE byte_count; 
+  STATUS status;
+  BYTE data[31];
+} BUFFER_RSLT;
+
+typedef struct {
+  UINTN                               Signature;
+  EFI_HANDLE                          Handle;         // Handle for protocol this driver installs on
+  EFI_IIO_UDS_PROTOCOL                IioUds;         // Policy protocol this driver installs
+} EFI_IIO_UDS_DRIVER_PRIVATE;
+
+#endif
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Policy/IioUdsDataDxe/IioUdsDataDxe.inf b/Platform/Intel/PurleyOpenBoardPkg/Policy/IioUdsDataDxe/IioUdsDataDxe.inf
new file mode 100644
index 0000000000..db425e3836
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Policy/IioUdsDataDxe/IioUdsDataDxe.inf
@@ -0,0 +1,36 @@
+## @file
+#
+# Copyright (c) 2018 - 2021, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = IioUdsDataDxe
+  FILE_GUID                      = 036125ED-DD4C-4BF7-AC8D-83FE11CDD5DB
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = IioUdsDataInit
+
+[Sources]
+  IioUdsDataDxe.c
+  IioUdsDataDxe.h
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  PurleyOpenBoardPkg/OpenBoardPkg.dec
+  PurleyRefreshSiliconPkg/SiPkg.dec
+
+[LibraryClasses]
+  HobLib
+  BaseMemoryLib
+  UefiDriverEntryPoint
+
+[Protocols]
+  gEfiIioUdsProtocolGuid
+
+[Depex]
+  TRUE
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Policy/PlatformCpuPolicy/PlatformCpuPolicy.c b/Platform/Intel/PurleyOpenBoardPkg/Policy/PlatformCpuPolicy/PlatformCpuPolicy.c
new file mode 100644
index 0000000000..1cd8d657c1
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Policy/PlatformCpuPolicy/PlatformCpuPolicy.c
@@ -0,0 +1,654 @@
+/** @file
+
+Copyright (c) 2018 - 2021, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+#include <Protocol/IntelCpuPcdsSetDone.h>
+#include <Setup/IioUniversalData.h>
+#include <Guid/SetupVariable.h>
+#include <Library/BaseLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/CpuConfigLib.h>
+#include <Library/HobLib.h>
+#include <Library/UefiLib.h>
+#include <Library/IoLib.h>
+#include <Library/CpuPpmLib.h>
+#include <SetupTable.h>
+#include <Platform.h>
+#include "PlatformHost.h"
+#include <Register/Cpuid.h>
+
+CHAR16 mCpuSocketStr[8][5] = {L"CPU0", L"CPU1", L"CPU2", L"CPU3", L"CPU4", L"CPU5", L"CPU6", L"CPU7"};
+CHAR16 mCpuAssetTagStr[] = L"UNKNOWN";
+IIO_UDS                     *mIioUds;
+
+/**
+
+    GC_TODO: add routine description
+
+    @param None
+
+    @retval None
+
+**/
+VOID
+CheckAndReAssignSocketId(
+  VOID
+  )
+{
+#define APICID_MASK_BIT14_8 0x7F    //current Si support programmable APICID up to 15bits
+  CPU_SOCKET_ID_INFO    *pcdSktIdPtr;
+  UINT32                i, IntraPackageIdBits;
+  UINTN                 PcdSize;
+  EFI_STATUS            Status;
+  UINT32                MaxSocketCount;
+
+  MaxSocketCount = FixedPcdGet32(PcdMaxCpuSocketCount);
+  DEBUG ((EFI_D_ERROR, "::SocketCount %08x\n", MaxSocketCount));
+  pcdSktIdPtr = (CPU_SOCKET_ID_INFO *)PcdGetPtr(PcdCpuSocketId);
+  PcdSize = PcdGetSize (PcdCpuSocketId); //MAX_SOCKET * sizeof(CPU_SOCKET_ID_INFO);
+  ASSERT(PcdSize == (MAX_SOCKET * sizeof(CPU_SOCKET_ID_INFO)));
+  Status = PcdSetPtrS (PcdCpuSocketId, &PcdSize, (VOID *)pcdSktIdPtr);
+  ASSERT_EFI_ERROR (Status);
+  if (EFI_ERROR(Status)) return;
+  DEBUG ((EFI_D_INFO, "::SockeId Pcd at %08x, size %x\n", PcdGetPtr(PcdCpuSocketId), PcdSize));
+
+  for(i = 0; i < MAX_SOCKET; i++) {
+    if(mIioUds->PlatformData.CpuQpiInfo[i].Valid) {
+      pcdSktIdPtr[i].DefaultSocketId = mIioUds->PlatformData.CpuQpiInfo[i].SocId;
+      pcdSktIdPtr[i].NewSocketId     = mIioUds->PlatformData.CpuQpiInfo[i].SocId;
+    } else {
+      pcdSktIdPtr[i].DefaultSocketId = (UINT32)-1;   //make sure Default and New are same
+      pcdSktIdPtr[i].NewSocketId     = (UINT32)-1;
+    }
+  }
+
+  AsmCpuidEx (CPUID_EXTENDED_TOPOLOGY, 1, &IntraPackageIdBits, NULL, NULL, NULL);
+  //assign new socketId
+  for(i = 0; i < MAX_SOCKET; i++) {
+
+    if(pcdSktIdPtr[i].DefaultSocketId == (UINT32)-1) continue;
+
+    switch(IntraPackageIdBits) {
+      case 4: //socket bit starts from bit4 of ApicId
+      case 5: //socket bit starts from bit5 of ApicId
+        if(MAX_SOCKET == 4) {
+          pcdSktIdPtr[i].NewSocketId |= (APICID_MASK_BIT14_8 << (8 - IntraPackageIdBits));
+        } else {
+          //3bit in lower 8bit as skt field, to avoid ApicID= FFs, leave bit8 untouched for 8S
+          pcdSktIdPtr[i].NewSocketId |= (0x7E << (8 - IntraPackageIdBits));      //leave bit8 to 0 so we don't have FFs in ApicId
+        }
+        break;
+
+     case 6: //socket bit starts from bit6 of ApicId
+        if(MAX_SOCKET == 4) {
+          //only 2bit in lower 8bit as skt field, to avoid ApicID= FFs, leave bit8 untouched for 4S
+          pcdSktIdPtr[i].NewSocketId |= (0x7E << (8 - IntraPackageIdBits));
+        } else {
+          //only 2bit in lower 8bit as skt field, to avoid ApicID= FFs, leave bit9 untouched for 8S
+          pcdSktIdPtr[i].NewSocketId |= (0x7C << (8 - IntraPackageIdBits));
+        }
+        break;
+
+     default:
+        DEBUG ((EFI_D_INFO, "::Need more info to make sure we can support!!!\n"));
+        break;
+
+    } //end switch
+  }
+}
+
+
+/**
+
+  This is the EFI driver entry point for the CpuPolicy Driver. This
+  driver is responsible for getting microcode patches from FV.
+
+  @param ImageHandle     - Handle for the image of this driver.
+  @param SystemTable     - Pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS     - Protocol installed sucessfully.
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformCpuPolicyEntryPoint (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  )
+{
+  EFI_STATUS                       Status;
+  SETUP_DATA                       SetupData;
+  UINT32                           CpuPolicy;
+  UINT32                           CpuPolicyEx1;
+  EFI_HANDLE                       Handle;
+  UINT32                           CsrSapmCtl = 0;
+  UINT32                           CsrPerfPlimitCtl = 0;
+  UINT8                            PCPSOptions = 0;
+  UINT32                           AdvPwrMgtCtl;
+  UINT8                            socket;
+  UINT32                           *UpiInPkgCEntry = NULL;
+  UINT32                           *PcieInPkgCEntry = NULL;
+  UINT32                           MsrPowerCtlLow  = 0;
+  UINT32                           MsrTurboPowerLimitHigh = 0;
+  UINT32                           MsrTurboPowerLimitLow = 0;
+  UINT32                           MsrPriPlaneCurrentCfgCtlHigh = 0;
+  UINT32                           MsrPriPlaneCurrentCfgCtlLow = 0;
+  UINT32                           CsrDynamicPerfPowerCtl = 0;
+  UINT32                           CsrPcieIltrOvrd = 0;
+  UINT32                           MsrPerfBiasConfig = 0;
+  MSR_REGISTER                     *CStateLatencyCtrl = NULL;
+  UINT32                           CpuFamilyModelStepping;
+  UINT64                           i;
+  UINT64                           *Addr;
+  EFI_PPM_STRUCT                   *ppm = NULL;
+  XE_STRUCT                        *XePtr = NULL;
+  TURBO_RATIO_LIMIT_RATIO_CORES    *TurboRatioLimitRatioCores = NULL;
+  UINT8                            PackageCStateSetting = 0;
+  UINT8                            CpuCStateValue = 0;
+
+  EFI_GUID                         UniversalDataGuid = IIO_UNIVERSAL_DATA_GUID;
+  EFI_HOB_GUID_TYPE                *GuidHob;
+
+  GuidHob   = GetFirstGuidHob (&UniversalDataGuid);
+  ASSERT (GuidHob != NULL);
+  if(GuidHob == NULL) {
+    return EFI_NOT_FOUND;
+  }
+  mIioUds   = GET_GUID_HOB_DATA(GuidHob);
+
+  AsmCpuid (1, &CpuFamilyModelStepping, NULL, NULL, NULL);
+
+  Status = gBS->AllocatePool (
+                        EfiBootServicesData,
+                        sizeof(EFI_PPM_STRUCT),
+                        (VOID **) &Addr
+                        );
+  if(Status != EFI_SUCCESS) {
+    DEBUG ((EFI_D_INFO, "::Failed to allocate mem for PPM Struct\n"));
+    ASSERT_EFI_ERROR (Status);      //may need to create a default
+  } else {
+    ZeroMem(Addr, sizeof(EFI_PPM_STRUCT));
+    i = (UINT32)(*(UINT64 *)(&Addr));
+    ppm = (EFI_PPM_STRUCT *)(Addr);
+    Status = PcdSet64S (PcdCpuPmStructAddr, i);
+    ASSERT_EFI_ERROR (Status);
+    if (EFI_ERROR(Status)) return Status;
+    DEBUG ((EFI_D_INFO, "::PPM mem allocate @ %x %X %X\n", i, PcdGet64(PcdCpuPmStructAddr), ppm));
+    UpiInPkgCEntry = (UINT32 *)(((EFI_PPM_STRUCT *)Addr)->Cst.PkgCstEntryCriteriaMaskKti);
+    PcieInPkgCEntry = (UINT32 *)(((EFI_PPM_STRUCT *)Addr)->Cst.PkgCstEntryCriteriaMaskPcie);
+    XePtr = (XE_STRUCT *)(&((EFI_PPM_STRUCT *)Addr)->Xe);
+    TurboRatioLimitRatioCores = (TURBO_RATIO_LIMIT_RATIO_CORES *)(&((EFI_PPM_STRUCT *)Addr)->TurboRatioLimitRatioCores);
+    DEBUG ((EFI_D_INFO, ":: XE @ %X\n", (UINTN) XePtr));
+
+    CStateLatencyCtrl = (MSR_REGISTER *)(ppm->Cst.LatencyCtrl);
+    DEBUG ((EFI_D_INFO, "CStateLatencyCtrl[%X]\n", (UINTN) CStateLatencyCtrl));
+  }
+
+  //
+  // Read the current system configuration variable store.
+  //
+  ZeroMem (&SetupData, sizeof(SETUP_DATA));
+  CopyMem (&SetupData.SocketConfig.IioConfig, PcdGetPtr(PcdSocketIioConfigData), sizeof(SOCKET_IIO_CONFIGURATION));
+  CopyMem (&SetupData.SocketConfig.CommonRcConfig, PcdGetPtr(PcdSocketCommonRcConfigData), sizeof(SOCKET_COMMONRC_CONFIGURATION));
+  CopyMem (&SetupData.SocketConfig.CsiConfig, PcdGetPtr(PcdSocketMpLinkConfigData), sizeof(SOCKET_MP_LINK_CONFIGURATION));
+  CopyMem (&SetupData.SocketConfig.MemoryConfig, PcdGetPtr(PcdSocketMemoryConfigData), sizeof(SOCKET_MEMORY_CONFIGURATION));
+  CopyMem (&SetupData.SocketConfig.PowerManagementConfig, PcdGetPtr(PcdSocketPowerManagementConfigData), sizeof(SOCKET_POWERMANAGEMENT_CONFIGURATION));
+  CopyMem (&SetupData.SocketConfig.SocketProcessorCoreConfiguration, PcdGetPtr(PcdSocketProcessorCoreConfigData), sizeof(SOCKET_PROCESSORCORE_CONFIGURATION));
+  CopyMem (&SetupData.SystemConfig, PcdGetPtr(PcdSetupData), sizeof(SYSTEM_CONFIGURATION));
+  CopyMem (&SetupData.PchRcConfig, PcdGetPtr(PcdPchRcConfigurationData), sizeof(PCH_RC_CONFIGURATION));
+
+  {
+
+	if (SetupData.SocketConfig.PowerManagementConfig.PackageCState == PPM_AUTO) {
+        PackageCStateSetting = 3;   //POR Default = C6
+    } else {
+        PackageCStateSetting = SetupData.SocketConfig.PowerManagementConfig.PackageCState;
+    }
+
+    // Temporary override to prevent accidental enabling until CR dungeon approves
+    if (SetupData.SocketConfig.PowerManagementConfig.PackageCState != 0) {
+      DEBUG((EFI_D_ERROR, "Crystal Ridge Configuration Warning: Package c-states are not disabled\n"));
+    }
+
+    if ((SetupData.SocketConfig.PowerManagementConfig.C6Enable == PPM_AUTO) ||
+          SetupData.SocketConfig.PowerManagementConfig.ProcessorAutonomousCstateEnable) {
+        CpuCStateValue |= C6_ENABLE;   //POR Default = Enabled
+    } else {
+        CpuCStateValue |= (SetupData.SocketConfig.PowerManagementConfig.C6Enable * C6_ENABLE);
+    }
+
+    Status = PcdSet8S (PcdCpuCoreCStateValue, CpuCStateValue);
+    ASSERT_EFI_ERROR (Status);
+    if (EFI_ERROR(Status)) return Status;
+
+    //
+    // If ACC enabled, then override C1E to be enabled
+    //
+    if (SetupData.SocketConfig.PowerManagementConfig.ProcessorAutonomousCstateEnable) {
+      SetupData.SocketConfig.PowerManagementConfig.ProcessorC1eEnable = TRUE;
+    }
+
+    //
+    // Verify that the value being set is within the valid range 0 to MAX_SOCKET - 1
+    //
+    if (SetupData.SocketConfig.SocketProcessorCoreConfiguration.BspSelection > MAX_SOCKET)
+      SetupData.SocketConfig.SocketProcessorCoreConfiguration.BspSelection= 0xFF;
+    Status = PcdSet8S (PcdSbspSelection, SetupData.SocketConfig.SocketProcessorCoreConfiguration.BspSelection);
+    ASSERT_EFI_ERROR (Status);
+    if (EFI_ERROR(Status)) return Status;
+    //
+    // Map CPU setup options to PcdCpuProcessorFeatureUserConfiguration
+    //
+    CpuPolicy = (SetupData.SocketConfig.SocketProcessorCoreConfiguration.ProcessorHyperThreadingDisable ? 0 : PCD_CPU_HT_BIT) |
+                (SetupData.SocketConfig.PowerManagementConfig.ProcessorEistEnable ? PCD_CPU_EIST_BIT : 0) |
+                (SetupData.SocketConfig.PowerManagementConfig.ProcessorC1eEnable ? PCD_CPU_C1E_BIT : 0) |
+                (SetupData.SocketConfig.SocketProcessorCoreConfiguration.ProcessorVmxEnable ? PCD_CPU_VT_BIT : 0) |
+                (SetupData.SocketConfig.SocketProcessorCoreConfiguration.ProcessorSmxEnable ? PCD_CPU_LT_BIT : 0) |
+                (SetupData.SocketConfig.SocketProcessorCoreConfiguration.FastStringEnable ? PCD_CPU_FAST_STRING_BIT : 0) |
+                (SetupData.SocketConfig.SocketProcessorCoreConfiguration.CpuidMaxValue ? PCD_CPU_MAX_CPUID_VALUE_LIMIT_BIT : 0) |
+                (SetupData.SocketConfig.SocketProcessorCoreConfiguration.ExecuteDisableBit ? PCD_CPU_EXECUTE_DISABLE_BIT : 0) |
+                (SetupData.SocketConfig.SocketProcessorCoreConfiguration.MachineCheckEnable ? PCD_CPU_MACHINE_CHECK_BIT : 0) |
+                (SetupData.SocketConfig.SocketProcessorCoreConfiguration.DCUStreamerPrefetcherEnable ? PCD_CPU_DCU_PREFETCHER_BIT : 0) |
+                (SetupData.SocketConfig.SocketProcessorCoreConfiguration.DCUIPPrefetcherEnable ? PCD_CPU_IP_PREFETCHER_BIT : 0) |
+                PCD_CPU_MONITOR_MWAIT_BIT | //never disable Mwait
+                (SetupData.SocketConfig.PowerManagementConfig.TurboMode ? PCD_CPU_TURBO_MODE_BIT : 0) |
+                (SetupData.SocketConfig.PowerManagementConfig.EnableThermalMonitor ? PCD_CPU_THERMAL_MANAGEMENT_BIT : 0);
+
+    if (SetupData.SocketConfig.PowerManagementConfig.TStateEnable && (SetupData.SocketConfig.PowerManagementConfig.OnDieThermalThrottling > 0)) {
+       CpuPolicy |= (SetupData.SocketConfig.PowerManagementConfig.TStateEnable ? PCD_CPU_TSTATE_BIT : 0);
+    }
+
+    CpuPolicyEx1 = (SetupData.SocketConfig.SocketProcessorCoreConfiguration.MlcStreamerPrefetcherEnable ? PCD_CPU_MLC_STREAMER_PREFETCHER_BIT : 0) |
+                   (SetupData.SocketConfig.SocketProcessorCoreConfiguration.MlcSpatialPrefetcherEnable ? PCD_CPU_MLC_SPATIAL_PREFETCHER_BIT : 0) |
+                   (SetupData.SocketConfig.SocketProcessorCoreConfiguration.ThreeStrikeTimer ? PCD_CPU_THREE_STRIKE_COUNTER_BIT : 0) |
+                   PCD_CPU_ENERGY_PERFORMANCE_BIAS_BIT |
+                   (SetupData.SocketConfig.SocketProcessorCoreConfiguration.ProcessorX2apic ? PCD_CPU_X2APIC_BIT : 0) |
+                   (SetupData.SocketConfig.SocketProcessorCoreConfiguration.AesEnable ? PCD_CPU_AES_BIT : 0) |
+                   (SetupData.SocketConfig.SocketProcessorCoreConfiguration.PCIeDownStreamPECIWrite ? PCD_CPU_PECI_DOWNSTREAM_WRITE_BIT : 0) |
+                   PCD_CPU_C_STATE_BIT;
+
+
+    PCPSOptions =  (SetupData.SocketConfig.PowerManagementConfig.ProcessorSinglePCTLEn ? PCD_CPU_PCPS_SINGLEPCTL : 0) |
+                   (SetupData.SocketConfig.PowerManagementConfig.ProcessorSPD ? PCD_CPU_PCPS_SPD : 0) |
+                   (SetupData.SocketConfig.PowerManagementConfig.PStateDomain ? PCD_CPU_PCPS_PSTATEDOMAIN : 0) |
+                   (UINT8) SetupData.SocketConfig.PowerManagementConfig.ProcessorEistPsdFunc;
+
+    ppm->Pst.PcpsCtrl = PCPSOptions;
+    ppm->OverclockingLock = SetupData.SocketConfig.PowerManagementConfig.OverclockingLock;
+
+    ppm->FastRaplDutyCycle = SetupData.SocketConfig.PowerManagementConfig.FastRaplDutyCycle;
+
+    if(mIioUds->PlatformData.EVMode)
+      CpuPolicy &= ~PCD_CPU_LT_BIT;
+
+    if (SetupData.SocketConfig.PowerManagementConfig.ProcessorEistEnable) {
+      Status = PcdSetBoolS (PcdCpuHwCoordination, SetupData.SocketConfig.PowerManagementConfig.ProcessorEistPsdFunc ? FALSE : TRUE);
+      ASSERT_EFI_ERROR (Status);
+      if (EFI_ERROR(Status)) return Status;
+    }
+
+    Status = PcdSet16S (PcdCpuAcpiLvl2Addr, PcdGet16 (PcdPchAcpiIoPortBaseAddress) + R_ACPI_LV2);
+    ASSERT_EFI_ERROR (Status);
+    if (EFI_ERROR(Status)) return Status;
+    Status = PcdSet8S (PcdCpuPackageCStateLimit, PackageCStateSetting);
+    ASSERT_EFI_ERROR (Status);
+    if (EFI_ERROR(Status)) return Status;
+
+    if ((SetupData.SocketConfig.PowerManagementConfig.TStateEnable) && (SetupData.SocketConfig.PowerManagementConfig.OnDieThermalThrottling > 0)) {
+      Status = PcdSet8S (PcdCpuClockModulationDutyCycle, SetupData.SocketConfig.PowerManagementConfig.OnDieThermalThrottling);
+      ASSERT_EFI_ERROR (Status);
+      if (EFI_ERROR(Status)) return Status;
+      ppm->TCCActivationOffset = SetupData.SocketConfig.PowerManagementConfig.TCCActivationOffset;
+    }
+    Status = PcdSet8S (PcdCpuDcuMode, SetupData.SocketConfig.SocketProcessorCoreConfiguration.DCUModeSelection);
+    ASSERT_EFI_ERROR (Status);
+    if (EFI_ERROR(Status)) return Status;
+
+    if((CpuFamilyModelStepping >> 4) == CPU_FAMILY_SKX) {
+      Status = PcdSetBoolS (PcdCpuSmmRuntimeCtlHooks, TRUE);
+      ASSERT_EFI_ERROR (Status);
+      if (EFI_ERROR(Status)) return Status;
+    } else {
+      Status = PcdSetBoolS (PcdCpuSmmRuntimeCtlHooks, FALSE);
+      ASSERT_EFI_ERROR (Status);
+      if (EFI_ERROR(Status)) return Status;
+    }
+    DEBUG ((EFI_D_INFO, ":: PcdCpuSmmRuntimeCtlHooks= %x\n", PcdGetBool(PcdCpuSmmRuntimeCtlHooks)));
+
+    if(mIioUds->PlatformData.EVMode || SetupData.SystemConfig.LmceEn) {
+      Status = PcdSet8S (PcdCpuProcessorMsrLockCtrl, 0);
+      ASSERT_EFI_ERROR (Status);
+      if (EFI_ERROR(Status)) return Status;
+    } else {
+      Status = PcdSet8S (PcdCpuProcessorMsrLockCtrl, SetupData.SocketConfig.SocketProcessorCoreConfiguration.ProcessorMsrLockControl);
+      ASSERT_EFI_ERROR (Status);
+      if (EFI_ERROR(Status)) return Status;
+    }
+
+    Status = PcdSet64S(PcdCpuIioLlcWaysBitMask, SetupData.SocketConfig.SocketProcessorCoreConfiguration.IioLlcWaysMask);
+    ASSERT_EFI_ERROR (Status);
+    if (EFI_ERROR(Status)) return Status;
+    Status = PcdSet64S(PcdCpuExpandedIioLlcWaysBitMask, SetupData.SocketConfig.SocketProcessorCoreConfiguration.ExpandedIioLlcWaysMask);
+    ASSERT_EFI_ERROR (Status);
+    if (EFI_ERROR(Status)) return Status;
+    Status = PcdSet64S(PcdCpuRemoteWaysBitMask, SetupData.SocketConfig.SocketProcessorCoreConfiguration.RemoteWaysMask);
+    ASSERT_EFI_ERROR (Status);
+    if (EFI_ERROR(Status)) return Status;
+    Status = PcdSet8S(PcdPchTraceHubEn, SetupData.SocketConfig.SocketProcessorCoreConfiguration.PchTraceHubEn);
+    ASSERT_EFI_ERROR (Status);
+    if (EFI_ERROR(Status)) return Status;
+    Status = PcdSet64S(PcdCpuQlruCfgBitMask, ((UINT64) SetupData.SocketConfig.SocketProcessorCoreConfiguration.QlruCfgMask_Hi << 32) | (UINT64)SetupData.SocketConfig.SocketProcessorCoreConfiguration.QlruCfgMask_Lo );
+    ASSERT_EFI_ERROR (Status);
+    if (EFI_ERROR(Status)) return Status;
+    Status = PcdSet64S(PcdCpuRRQCountThreshold, mIioUds->PlatformData.RemoteRequestThreshold);
+    ASSERT_EFI_ERROR (Status);
+    if (EFI_ERROR(Status)) return Status;
+
+    //CSR SAPM CTL
+    CsrSapmCtl = 0;
+
+   for( socket = 0; socket < MAX_SOCKET; socket++) {
+      CsrSapmCtl = (( SetupData.SocketConfig.PowerManagementConfig.Iio0PkgcClkGateDis[socket] << IIO012_PKGC_CLK_GATE_DISABLE_SHIFT) |
+                   ( SetupData.SocketConfig.PowerManagementConfig.Iio1PkgcClkGateDis[socket] << (IIO012_PKGC_CLK_GATE_DISABLE_SHIFT + 1)) |
+                   ( SetupData.SocketConfig.PowerManagementConfig.Iio2PkgcClkGateDis[socket] << (IIO012_PKGC_CLK_GATE_DISABLE_SHIFT + 2)) );
+
+      CsrSapmCtl |= (( SetupData.SocketConfig.PowerManagementConfig.Kti23PkgcClkGateDis[socket] << KTI23_PKGC_CLK_GATE_DISABLE_SHIFT ) |
+                 ( SetupData.SocketConfig.PowerManagementConfig.Kti01PkgcClkGateDis[socket] << KTI01_PKGC_CLK_GATE_DISABLE_SHIFT ) |
+                 ( SetupData.SocketConfig.PowerManagementConfig.Kti01pllOffEna[socket] << KTI_PLL_OFF_EN_SHIFT) |
+                 ( SetupData.SocketConfig.PowerManagementConfig.Kti23pllOffEna[socket] << (KTI_PLL_OFF_EN_SHIFT + 1) ) );
+
+        CsrSapmCtl |= (( SetupData.SocketConfig.PowerManagementConfig.Mc1PkgcClkGateDis[socket] << MC1_PKGC_CLK_GATE_DISABLE_SHIFT ) |
+                   ( SetupData.SocketConfig.PowerManagementConfig.Mc0PkgcClkGateDis[socket] << MC0_PKGC_CLK_GATE_DISABLE_SHIFT ) |
+                   ( SetupData.SocketConfig.PowerManagementConfig.Mc0pllOffEna[socket] << MEM_PLL_OFF_EN_SHIFT) |
+                   ( SetupData.SocketConfig.PowerManagementConfig.Mc1pllOffEna[socket] << (MEM_PLL_OFF_EN_SHIFT + 1) ));
+
+      if (SetupData.SocketConfig.MemoryConfig.OppSrefEn == 1) {
+        CsrSapmCtl |= ((1 << MC0_PKGC_IO_VOLTAGE_REDUCTION_DISABLE_SHIFT) | (1 << MC1_PKGC_IO_VOLTAGE_REDUCTION_DISABLE_SHIFT) |
+                      (1 << MC0_PKGC_DIG_VOLTAGE_REDUCTION_DISABLE_SHIFT) | (1 << MC1_PKGC_DIG_VOLTAGE_REDUCTION_DISABLE_SHIFT)) ;
+      }
+
+      CsrSapmCtl |= (( SetupData.SocketConfig.PowerManagementConfig.P0pllOffEna[socket] << IIO_PLL_OFF_EN_SHIFT) |
+                 ( SetupData.SocketConfig.PowerManagementConfig.P1pllOffEna[socket] << (IIO_PLL_OFF_EN_SHIFT + 1) ) |
+                 ( SetupData.SocketConfig.PowerManagementConfig.P2pllOffEna[socket] << (IIO_PLL_OFF_EN_SHIFT + 2) ) |
+                 ( SetupData.SocketConfig.PowerManagementConfig.SetvidDecayDisable[socket] << SETVID_DECAY_DISABLE_SHIFT ) |
+                 ( SetupData.SocketConfig.PowerManagementConfig.SapmCtlLock[socket] << SAPMCTL_LOCK_SHIFT) );
+
+      ppm->SapmCtl[socket]  = CsrSapmCtl;
+   }
+
+    ppm->PmaxConfig  = (SetupData.SocketConfig.PowerManagementConfig.UsePmaxOffsetTable ? USER_PMAX_USE_OFFSET_TABLE : 0 ) |
+                       SetupData.SocketConfig.PowerManagementConfig.PmaxOffset |
+                      (SetupData.SocketConfig.PowerManagementConfig.PmaxSign ? USER_PMAX_NEGATIVE_BIT : 0);
+
+    CsrPerfPlimitCtl = ( SetupData.SocketConfig.PowerManagementConfig.PerfPLmtThshld << PERF_PLIMIT_THRESHOLD_SHIFT ) |
+                      ( SetupData.SocketConfig.PowerManagementConfig.PerfPLimitClipC << PERF_PLIMIT_CLIP_SHIFT ) |
+                      ( SetupData.SocketConfig.PowerManagementConfig.PerfPlimitDifferential << PERF_PLIMIT_DIFFERENTIAL_SHIFT ) |
+                      ( SetupData.SocketConfig.PowerManagementConfig.PerfPLimitEn << REPERF_PLIMIT_EN_SHIFT );
+    ppm->PerPLimitCtl = CsrPerfPlimitCtl;
+
+    //
+    // IssConfigTdpLevelInfo Bit[23:16]: the currently active Config TDP Level
+    //
+    ppm->Pst.ConfigTdpLevel = (UINT8) ((mIioUds->SystemStatus.IssConfigTdpLevelInfo >> 16) & 0xFF);
+    ppm->Pst.CurrentPackageTdp = (mIioUds->SystemStatus.IssConfigTdpTdpInfo[0][ppm->Pst.ConfigTdpLevel] & 0x7FFF);
+
+    for( socket = 0; socket < MAX_SOCKET; socket++) {
+        UpiInPkgCEntry[socket] = (SetupData.SocketConfig.PowerManagementConfig.Kti0In[socket] |
+                                              (SetupData.SocketConfig.PowerManagementConfig.Kti1In[socket] << 1) |
+                                              (SetupData.SocketConfig.PowerManagementConfig.Kti2In[socket] << 2) );
+
+        if (SetupData.SocketConfig.PowerManagementConfig.PcieIio0In[socket]) {
+          PcieInPkgCEntry[socket] |= SET_PCIEx_MASK;
+        }
+        if (SetupData.SocketConfig.PowerManagementConfig.PcieIio1In[socket]) {
+          PcieInPkgCEntry[socket] |= (SET_PCIEx_MASK << 4);
+        }
+        if (SetupData.SocketConfig.PowerManagementConfig.PcieIio2In[socket]) {
+          PcieInPkgCEntry[socket] |= (SET_PCIEx_MASK << 8);
+        }
+        if (SetupData.SocketConfig.PowerManagementConfig.PcieIio3In[socket]) {
+          PcieInPkgCEntry[socket] |= (SET_PCIEx_MASK << 12);
+        }
+        if (SetupData.SocketConfig.PowerManagementConfig.PcieIio4In[socket]) {
+          PcieInPkgCEntry[socket] |= (SET_PCIEx_MASK << 16);
+        }
+        if (SetupData.SocketConfig.PowerManagementConfig.PcieIio5In[socket]) {
+          PcieInPkgCEntry[socket] |= (SET_PCIEx_MASK << 20);
+        }
+
+    }
+
+    AdvPwrMgtCtl = (SetupData.SocketConfig.PowerManagementConfig.SapmctlValCtl? PCD_CPU_SAPM_CTL_VAL_CTL : 0) |
+                  (SetupData.SocketConfig.PowerManagementConfig.CurrentConfig? PCD_CPU_CURRENT_CONFIG : 0) |
+                  (SetupData.SocketConfig.PowerManagementConfig.BootPState? PCU_CPU_EFFICIENT_BOOT : 0) |
+                  (SetupData.SocketConfig.SocketProcessorCoreConfiguration.ProcessorMsrLockControl? CPU_MSR_LOCK : 0) |
+                  (SetupData.SocketConfig.PowerManagementConfig.TurboPowerLimitCsrLock? TURBO_LIMIT_CSR_LOCK : 0);
+
+    AdvPwrMgtCtl |= SetupData.SocketConfig.PowerManagementConfig.PkgCstEntryValCtl; //PCD_CPU_PKG_CST_ENTRY_VAL_CTL
+
+    if (SetupData.SocketConfig.PowerManagementConfig.ProcessorEistEnable == 0) {
+      AdvPwrMgtCtl |= PCU_CPU_EFFICIENT_BOOT;
+    }
+
+    if (((CpuFamilyModelStepping >> 4) == CPU_FAMILY_HSX) && SetupData.SocketConfig.PowerManagementConfig.PriPlnCurCfgValCtl) {
+      AdvPwrMgtCtl |= PCD_CPU_PRI_PLN_CURR_CFG_CTL;
+    }
+
+    if ((PackageCStateSetting > 0) && SetupData.SocketConfig.PowerManagementConfig.DynamicL1) {
+      AdvPwrMgtCtl |= DYNAMIC_L1_DISABLE;
+    }
+
+    if (SetupData.SocketConfig.PowerManagementConfig.SPTWorkaround) {
+      AdvPwrMgtCtl |= SPT_PCH_WORKAROUND;
+    }
+
+    if (SetupData.SocketConfig.PowerManagementConfig.VccSAandVccIOdisable) {
+      AdvPwrMgtCtl |= VCCSA_VCCIO_DISABLE;
+    }
+    ppm->AdvPwrMgtCtlFlags = AdvPwrMgtCtl;
+
+    // MSR_POWER_CTL 0x1FC
+    MsrPowerCtlLow = ( SetupData.SocketConfig.PowerManagementConfig.PkgCLatNeg << PCH_NEG_DISABLE_SHIFT ) |
+                     ( SetupData.SocketConfig.PowerManagementConfig.LTRSwInput << LTR_SW_DISABLE_SHIFT ) |
+                     ( SetupData.SocketConfig.PowerManagementConfig.PwrPerfTuning << PWR_PERF_TUNING_CFG_MODE_SHIFT ) |
+                     ( SetupData.SocketConfig.PowerManagementConfig.PwrPerfSwitch << PWR_PERF_TUNING_ENABLE_DYN_SHIFT ) |
+                     ( SetupData.SocketConfig.PowerManagementConfig.SAPMControl << PWR_PERF_TUNING_DISABLE_SAPM_SHIFT ) |
+                     ( SetupData.SocketConfig.PowerManagementConfig.EETurboDisable << EE_TURBO_DISABLE_SHIFT ) |
+                     ( SetupData.SocketConfig.PowerManagementConfig.ProchotLock << PROCHOT_LOCK_SHIFT ) |
+                     ( SetupData.SocketConfig.PowerManagementConfig.ProcessorC1eEnable << C1E_ENABLE_SHIFT ) |
+                     ( (SetupData.SocketConfig.PowerManagementConfig.EnableProcHot & 0x1) << DIS_PROCHOT_OUT_SHIFT ) |
+                     ( (SetupData.SocketConfig.PowerManagementConfig.EnableProcHot & 0x2) >> 1 );
+
+    // 5332865	BIOS needs to set bit 25 in MSR 0x1FC when enabling HWP autonomous out of band mode
+    if (SetupData.SocketConfig.PowerManagementConfig.ProcessorHWPMEnable == 2) {   //if HWPM = OOB Mode
+        MsrPowerCtlLow |= ( 1 << PWR_PERF_TUNING_CFG_MODE_SHIFT );
+    }
+
+    ppm->PowerCtl.Dwords.Low = MsrPowerCtlLow;
+
+    ppm->ProchotRatio = SetupData.SocketConfig.PowerManagementConfig.ProchotResponseRatio;
+
+    if ((CpuFamilyModelStepping >> 4) == CPU_FAMILY_HSX) {
+      // PRIMARY_PLANE_CURRENT_CONFIG_CONTROL 0x601
+      MsrPriPlaneCurrentCfgCtlHigh = ( SetupData.SocketConfig.PowerManagementConfig.Psi3Code << PSI3_CODE_SHIFT ) |
+        ( SetupData.SocketConfig.PowerManagementConfig.Psi3Thshld << PSI3_THSHLD_SHIFT ) |
+        ( SetupData.SocketConfig.PowerManagementConfig.Psi2Code << PSI2_CODE_SHIFT ) |
+        ( SetupData.SocketConfig.PowerManagementConfig.Psi2Thshld << PSI2_THSHLD_SHIFT ) |
+        ( SetupData.SocketConfig.PowerManagementConfig.Psi1Code << PSI1_CODE_SHIFT ) |
+        ( SetupData.SocketConfig.PowerManagementConfig.Psi1Thshld << PSI1_THSHLD_SHIFT );
+    }
+
+    MsrPriPlaneCurrentCfgCtlLow = ( SetupData.SocketConfig.PowerManagementConfig.PpcccLock << PPCCC_LOCK_SHIFT ) |
+      ( SetupData.SocketConfig.PowerManagementConfig.CurrentLimit << CURRENT_LIMIT_SHIFT );
+
+    ppm->PP0CurrentCfg.Dwords.High = MsrPriPlaneCurrentCfgCtlHigh;
+    ppm->PP0CurrentCfg.Dwords.Low = MsrPriPlaneCurrentCfgCtlLow;
+
+    // MSR_TURBO_POWER_LIMIT 0x610
+    // CSR_TURBO_POWER_LIMIT 1:30:0:0xe8
+    MsrTurboPowerLimitHigh = ( SetupData.SocketConfig.PowerManagementConfig.TurboPowerLimitLock << POWER_LIMIT_LOCK_SHIFT ) |
+      ( SetupData.SocketConfig.PowerManagementConfig.PowerLimit2En << POWER_LIMIT_ENABLE_SHIFT ) |
+      ( SetupData.SocketConfig.PowerManagementConfig.PkgClmpLim2 << PKG_CLMP_LIM_SHIFT ) |
+      ( SetupData.SocketConfig.PowerManagementConfig.PowerLimit2Power );
+
+    MsrTurboPowerLimitLow = ( SetupData.SocketConfig.PowerManagementConfig.PowerLimit1Time << POWER_LIMIT_1_TIME_SHIFT ) |
+      ( SetupData.SocketConfig.PowerManagementConfig.PowerLimit1En << POWER_LIMIT_ENABLE_SHIFT ) |
+      ( SetupData.SocketConfig.PowerManagementConfig.PowerLimit1Power );
+
+    if ((CpuFamilyModelStepping >> 4) == CPU_FAMILY_HSX) {
+      MsrTurboPowerLimitLow  |= ( SetupData.SocketConfig.PowerManagementConfig.PkgClmpLim1 << PKG_CLMP_LIM_SHIFT );
+      MsrTurboPowerLimitHigh |= ( SetupData.SocketConfig.PowerManagementConfig.PkgClmpLim2 << PKG_CLMP_LIM_SHIFT );
+    }
+
+    if ((CpuFamilyModelStepping >> 4) == CPU_FAMILY_SKX) {
+      MsrTurboPowerLimitHigh |= ( SetupData.SocketConfig.PowerManagementConfig.PowerLimit2Time << POWER_LIMIT_1_TIME_SHIFT );
+    }
+
+    ppm->TurboPowerLimit.Dwords.Low = MsrTurboPowerLimitLow;
+    ppm->TurboPowerLimit.Dwords.High = MsrTurboPowerLimitHigh;
+
+    // DYNAMIC_PERF_POWER_CTL (CSR 1:30:2:0x64)
+    CsrDynamicPerfPowerCtl = ( SetupData.SocketConfig.PowerManagementConfig.UncrPerfPlmtOvrdEn << UNCORE_PERF_PLIMIT_OVERRIDE_ENABLE_SHIFT ) |
+      ( SetupData.SocketConfig.PowerManagementConfig.EetOverrideEn << EET_OVERRIDE_ENABLE_SHIFT ) |
+      ( SetupData.SocketConfig.PowerManagementConfig.IoBwPlmtOvrdEn << IO_BW_PLIMIT_OVERRIDE_ENABLE_SHIFT ) |
+      //( SetupData.SocketConfig.PowerManagementConfig.ImcApmOvrdEn << IMC_APM_OVERRIDE_ENABLE_SHIFT ) |
+      ( SetupData.SocketConfig.PowerManagementConfig.IomApmOvrdEn << IOM_APM_OVERRIDE_ENABLE_SHIFT ) |
+      ( SetupData.SocketConfig.PowerManagementConfig.QpiApmOvrdEn << QPI_APM_OVERRIDE_ENABLE_SHIFT );   //4986218: Remove both changes from 4168487
+
+    if((CpuFamilyModelStepping >> 4) == CPU_FAMILY_HSX) {
+      CsrDynamicPerfPowerCtl |= (( SetupData.SocketConfig.PowerManagementConfig.EepLOverride << EEP_L_OVERRIDE_SHIFT ) |
+        ( SetupData.SocketConfig.PowerManagementConfig.EepLOverrideEn << EEP_L_OVERRIDE_ENABLE_SHIFT ) |
+        ( SetupData.SocketConfig.PowerManagementConfig.ITurboOvrdEn << I_TURBO_OVERRIDE_ENABLE_SHIFT ) |
+        ( SetupData.SocketConfig.PowerManagementConfig.CstDemotOvrdEN << CST_DEMOTION_OVERRIDE_ENABLE_SHIFT ) |
+        ( SetupData.SocketConfig.PowerManagementConfig.TrboDemotOvrdEn << TURBO_DEMOTION_OVERRIDE_ENABLE_SHIFT ));
+    }
+
+    ppm->DynamicPerPowerCtl = CsrDynamicPerfPowerCtl;
+
+    // CSR_PCIE_ILTR_OVRD (CSR 1:30:1:78)
+    // SW_LTR_OVRD (MSR 0xa02) -- not used
+    CsrPcieIltrOvrd = ( SetupData.SocketConfig.PowerManagementConfig.SnpLatVld << SNOOP_LATENCY_VLD_SHIFT ) |
+      ( SetupData.SocketConfig.PowerManagementConfig.SnpLatOvrd << FORCE_SNOOP_OVRD_SHIFT ) |
+      ( SetupData.SocketConfig.PowerManagementConfig.SnpLatMult << SNOOP_LATENCY_MUL_SHIFT ) |
+      ( SetupData.SocketConfig.PowerManagementConfig.SnpLatVal << SNOOP_LATENCY_Value_SHIFT ) |
+      ( SetupData.SocketConfig.PowerManagementConfig.NonSnpLatVld << NON_SNOOP_LATENCY_VLD_SHIFT ) |
+      ( SetupData.SocketConfig.PowerManagementConfig.NonSnpLatOvrd << FORCE_NON_SNOOP_OVRD_SHIFT ) |
+      ( SetupData.SocketConfig.PowerManagementConfig.NonSnpLatMult << NON_SNOOP_LATENCY_MUL_SHIFT ) |
+      ( SetupData.SocketConfig.PowerManagementConfig.NonSnpLatVal << NON_SNOOP_LATENCY_Value_SHIFT );
+
+    ppm-> PcieIltrOvrd = CsrPcieIltrOvrd;
+
+    if((CpuFamilyModelStepping >> 4) == CPU_FAMILY_SKX) { //Need to check if programming needs to be limited only if Turbo mode is enabled.
+      for(i = 0; i < 8; i++) {
+        TurboRatioLimitRatioCores->RatioLimitRatio[i] = SetupData.SocketConfig.PowerManagementConfig.TurboRatioLimitRatio[i];
+
+        TurboRatioLimitRatioCores->RatioLimitRatioMask[i] = 0xFF;
+        if (SetupData.SocketConfig.PowerManagementConfig.TurboRatioLimitRatio[i] > 0) {
+          TurboRatioLimitRatioCores->RatioLimitRatioMask[i] = 0;
+        }
+
+        TurboRatioLimitRatioCores->RatioLimitCoresMask[i] = 0xFF;
+        TurboRatioLimitRatioCores->RatioLimitCores[i] = 0;
+        if (SetupData.SocketConfig.PowerManagementConfig.TurboRatioLimitCores[i] != 0xFF) {
+          TurboRatioLimitRatioCores->RatioLimitCoresMask[i] = 0;
+          TurboRatioLimitRatioCores->RatioLimitCores[i] = SetupData.SocketConfig.PowerManagementConfig.TurboRatioLimitCores[i];
+        }
+      }
+    }
+
+    MsrPerfBiasConfig = ( SetupData.SocketConfig.PowerManagementConfig.EngAvgTimeWdw1 << AVG_TIME_Window_SHIFT ) |
+      ( SetupData.SocketConfig.PowerManagementConfig.P0TtlTimeLow1 << PO_TOTAL_TIME_THSHLD_LOW_SHIFT ) |
+      ( SetupData.SocketConfig.PowerManagementConfig.P0TtlTimeHigh1 << PO_TOTAL_TIME_THSHLD_HIGH_SHIFT ) |
+      ( SetupData.SocketConfig.PowerManagementConfig.AltEngPerfBIAS << ALT_ENERGY_PERF_BIAS_SHIFT) |
+      ( SetupData.SocketConfig.PowerManagementConfig.WorkLdConfig << WORKLD_CONFIG_SHIFT );
+
+    ppm->PerfBiasConfig.Dwords.Low = MsrPerfBiasConfig;
+
+    //
+    //ProcessorHWPM-init as disabled.
+    //
+    ppm->Hwpm.HWPMNative = 0;
+    ppm->Hwpm.HWPMOOB = 0;
+    ppm->Hwpm.HWPMEnable = SetupData.SocketConfig.PowerManagementConfig.ProcessorHWPMEnable;
+    ppm->Hwpm.AutoCState = SetupData.SocketConfig.PowerManagementConfig.ProcessorAutonomousCstateEnable;
+    ppm->Hwpm.HWPMInterrupt = SetupData.SocketConfig.PowerManagementConfig.ProcessorHWPMInterrupt;
+    ppm->Hwpm.EPPEnable = SetupData.SocketConfig.PowerManagementConfig.ProcessorEPPEnable;
+    ppm->Hwpm.EPPProfile = SetupData.SocketConfig.PowerManagementConfig.ProcessorEppProfile;
+
+    if ((SetupData.SocketConfig.PowerManagementConfig.ProcessorHWPMEnable == 1) ||
+       (SetupData.SocketConfig.PowerManagementConfig.ProcessorHWPMEnable == 3)) {
+      ppm->Hwpm.HWPMNative = SetupData.SocketConfig.PowerManagementConfig.ProcessorHWPMEnable;
+    }else if (SetupData.SocketConfig.PowerManagementConfig.ProcessorHWPMEnable == 2){
+      ppm->Hwpm.HWPMOOB = SetupData.SocketConfig.PowerManagementConfig.ProcessorHWPMEnable;
+      ppm->Hwpm.HWPMInterrupt = 0;
+    }else if (SetupData.SocketConfig.PowerManagementConfig.ProcessorHWPMEnable == 0){
+      ppm->Hwpm.HWPMNative = 0;
+      ppm->Hwpm.HWPMOOB = 0;
+      ppm->Hwpm.HWPMInterrupt = 0;
+      ppm->Hwpm.EPPEnable = 0;
+    }
+
+    ppm->Hwpm.APSrocketing = SetupData.SocketConfig.PowerManagementConfig.ProcessorAPSrocketing;
+    ppm->Hwpm.Scalability = SetupData.SocketConfig.PowerManagementConfig.ProcessorScalability;
+    ppm->Hwpm.OutofBandAlternateEPB = SetupData.SocketConfig.PowerManagementConfig.ProcessorOutofBandAlternateEPB;
+
+    if(SetupData.SocketConfig.SocketProcessorCoreConfiguration.ProcessorX2apic && SetupData.SocketConfig.SocketProcessorCoreConfiguration.ForceX2ApicIds &&
+       (CpuPolicyEx1 & PCD_CPU_X2APIC_BIT)) { //if user want to reprogram > 8bit ApicId (must be X2Apic too)
+      CheckAndReAssignSocketId();
+    }
+
+    for(i = 0; i < NUM_CST_LAT_MSR; i++) {    //3 CStateLatencyCtrl CSRs
+      ppm->Cst.LatencyCtrl[i].Dwords.Low = ( SetupData.SocketConfig.PowerManagementConfig.CStateLatencyCtrlValid[i] << VALID_SHIFT ) |
+                             ( SetupData.SocketConfig.PowerManagementConfig.CStateLatencyCtrlMultiplier[i] << MULTIPLIER_SHIFT ) |
+                             ( SetupData.SocketConfig.PowerManagementConfig.CStateLatencyCtrlValue[i] << VALUE_SHIFT );
+    }
+
+    if(SetupData.SocketConfig.PowerManagementConfig.C2C3TT) { //if option is not AUTO
+      ppm->C2C3TT = (UINT32)SetupData.SocketConfig.PowerManagementConfig.C2C3TT;
+    } else {
+      ppm->C2C3TT = 0x10;
+    }
+
+  } //end - else
+
+  CpuPolicy |= PCD_CPU_L3_CACHE_BIT;
+
+  Status = PcdSet32S (PcdCpuProcessorFeatureUserConfiguration, CpuPolicy);
+  ASSERT_EFI_ERROR (Status);
+  if (EFI_ERROR(Status)) return Status;
+  Status = PcdSet32S (PcdCpuProcessorFeatureUserConfigurationEx1, CpuPolicyEx1);
+  ASSERT_EFI_ERROR (Status);
+  if (EFI_ERROR(Status)) return Status;
+  if (SetupData.SystemConfig.McBankWarmBootClearError == 1) {
+     Status = PcdSetBoolS (PcdIsPowerOnReset, TRUE);
+     ASSERT_EFI_ERROR (Status);
+     if (EFI_ERROR(Status)) return Status;
+  } else {
+     Status = PcdSetBoolS (PcdIsPowerOnReset, FALSE);
+     ASSERT_EFI_ERROR (Status);
+     if (EFI_ERROR(Status)) return Status;
+  }
+
+  //
+  // Cpu Driver could be dispatched after this protocol installed.
+  //
+  Handle = NULL;
+  Status = gBS->InstallProtocolInterface (
+                  &Handle,
+                  &gIntelCpuPcdsSetDoneProtocolGuid,
+                  EFI_NATIVE_INTERFACE,
+                  NULL
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Policy/PlatformCpuPolicy/PlatformCpuPolicy.inf b/Platform/Intel/PurleyOpenBoardPkg/Policy/PlatformCpuPolicy/PlatformCpuPolicy.inf
new file mode 100644
index 0000000000..dce03194e2
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Policy/PlatformCpuPolicy/PlatformCpuPolicy.inf
@@ -0,0 +1,80 @@
+## @file
+#
+# Copyright (c) 2018 - 2021, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                   = 0x00010005
+  BASE_NAME                     = PlatformCpuPolicy
+  FILE_GUID                     = 76A7B4FC-C8D5-462d-A4D2-6E88338A772A
+  MODULE_TYPE                   = DXE_DRIVER
+  VERSION_STRING                = 1.0
+  ENTRY_POINT                   = PlatformCpuPolicyEntryPoint
+
+[Sources]
+  PlatformCpuPolicy.c
+
+[Packages]
+  UefiCpuPkg/UefiCpuPkg.dec
+  MdePkg/MdePkg.dec
+  PurleyOpenBoardPkg/OpenBoardPkg.dec
+  PurleyRefreshSiliconPkg/SiPkg.dec
+  PurleyRefreshSiliconPkg/Override/IA32FamilyCpuPkg/IA32FamilyCpuPkg.dec
+
+[LibraryClasses]
+  UefiDriverEntryPoint
+  PcdLib
+  UefiBootServicesTableLib
+  UefiRuntimeServicesTableLib
+  BaseLib
+  MemoryAllocationLib
+  BaseMemoryLib
+  HobLib
+  IoLib
+
+[Protocols]
+  gIntelCpuPcdsSetDoneProtocolGuid
+
+[Pcd]
+  gEfiCpuTokenSpaceGuid.PcdCpuProcessorFeatureUserConfiguration
+  gEfiCpuTokenSpaceGuid.PcdCpuProcessorFeatureUserConfigurationEx1
+  gEfiCpuTokenSpaceGuid.PcdCpuEnergyPolicy
+  gEfiCpuTokenSpaceGuid.PcdCpuAcpiLvl2Addr
+  gEfiCpuTokenSpaceGuid.PcdCpuPackageCStateLimit
+  gEfiCpuTokenSpaceGuid.PcdCpuCoreCStateValue
+  gEfiCpuTokenSpaceGuid.PcdCpuClockModulationDutyCycle
+  gEfiCpuTokenSpaceGuid.PcdCpuHwCoordination
+  gEfiCpuTokenSpaceGuid.PcdPlatformCpuSocketCount
+  gEfiCpuTokenSpaceGuid.PcdPlatformCpuSocketNames
+  gEfiCpuTokenSpaceGuid.PcdPlatformCpuAssetTags
+  gEfiCpuTokenSpaceGuid.PcdIsPowerOnReset
+  gEfiCpuTokenSpaceGuid.PcdCpuDcuMode
+  gEfiCpuTokenSpaceGuid.PcdCpuTurboOverride
+  gEfiCpuTokenSpaceGuid.PcdCpuProcessorMsrLockCtrl
+  gEfiCpuTokenSpaceGuid.PcdCpuIioLlcWaysBitMask
+  gEfiCpuTokenSpaceGuid.PcdCpuExpandedIioLlcWaysBitMask
+  gEfiCpuTokenSpaceGuid.PcdPchTraceHubEn
+  gEfiCpuTokenSpaceGuid.PcdCpuQlruCfgBitMask
+  gEfiCpuTokenSpaceGuid.PcdSbspSelection
+  gEfiCpuTokenSpaceGuid.PcdCpuPmStructAddr
+  gEfiCpuTokenSpaceGuid.PcdCpuSocketId
+  gEfiPchTokenSpaceGuid.PcdPchAcpiIoPortBaseAddress
+  gEfiCpuTokenSpaceGuid.PcdCpuRemoteWaysBitMask
+  gEfiCpuTokenSpaceGuid.PcdCpuRRQCountThreshold
+  gEfiCpuTokenSpaceGuid.PcdCpuSmmRuntimeCtlHooks
+  gEfiCpRcPkgTokenSpaceGuid.PcdMaxCpuSocketCount
+  gOemSkuTokenSpaceGuid.PcdSetupData
+  gOemSkuTokenSpaceGuid.PcdPchRcConfigurationData
+  gOemSkuTokenSpaceGuid.PcdSocketIioConfigData
+  gOemSkuTokenSpaceGuid.PcdSocketCommonRcConfigData
+  gOemSkuTokenSpaceGuid.PcdSocketMpLinkConfigData
+  gOemSkuTokenSpaceGuid.PcdSocketMemoryConfigData
+  gOemSkuTokenSpaceGuid.PcdSocketPowerManagementConfigData
+  gOemSkuTokenSpaceGuid.PcdSocketProcessorCoreConfigData
+
+[Depex]
+  gEfiVariableArchProtocolGuid
+
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Policy/S3NvramSave/S3NvramSave.c b/Platform/Intel/PurleyOpenBoardPkg/Policy/S3NvramSave/S3NvramSave.c
new file mode 100644
index 0000000000..158b19c169
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Policy/S3NvramSave/S3NvramSave.c
@@ -0,0 +1,256 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "S3NvramSave.h"
+#include <Protocol/Decompress.h>
+#include <Library/CompressLib.h>
+#include <Protocol/VariableLock.h>
+
+/**
+
+  This function will retrieve the S3 data from HOBs produced by MRC
+  and will save it to NVRAM if the data is absent or different from
+  the previously saved data.
+
+  @param VOID
+
+  @retval VOID
+
+**/
+VOID
+SaveS3StructToNvram (
+  VOID
+  )
+{
+  EFI_STATUS                      Status;
+  UINTN                           BufferSize;
+  UINTN                           CurrentHobSize;
+  UINTN                           S3ChunkSize;
+  CHAR16                          EfiMemoryConfigVariable[] = L"MemoryConfig0";
+  EFI_HOB_GUID_TYPE               *GuidHob      = NULL;
+  VOID                            *HobData      = NULL;
+  VOID                            *VariableData = NULL;
+  
+  UINTN                           CompressedDataSize;
+  UINT32                          ScratchSize;
+  VOID                            *CompressedData = NULL;
+  VOID                            *Scratch = NULL;
+  EFI_DECOMPRESS_PROTOCOL         *Decompress = NULL;
+  VOID                            *CompressedVariableData = NULL;
+  UINTN                           CompressedBufferSize;
+  EDKII_VARIABLE_LOCK_PROTOCOL    *VariableLock = NULL;
+  
+  //
+  // Get first S3 data HOB
+  //
+  GuidHob = GetFirstGuidHob (&gEfiMemoryConfigDataHobGuid);
+
+  Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID **) &Decompress);
+  DEBUG((DEBUG_INFO, "[SaveMemoryConfigEntryPoint] Locate Decompress protocol - %r\n", Status));
+  if(EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    return;
+  }
+  
+  Status = gBS->LocateProtocol(&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&VariableLock);
+  DEBUG((DEBUG_INFO, "[SaveMemoryConfigEntryPoint] Locate Variable Lock protocol - %r\n", Status));
+  ASSERT_EFI_ERROR(Status); 
+
+  while (TRUE) {
+    if (GuidHob == NULL) {
+      break;
+    }
+    HobData = GET_GUID_HOB_DATA(GuidHob); 
+    CurrentHobSize = GET_GUID_HOB_DATA_SIZE (GuidHob);
+
+    DEBUG((EFI_D_INFO, "   Current Hob Size(bytes) is: %d\n", CurrentHobSize));
+    //
+    // Use the HOB data to save Memory Configuration Data
+    //
+    BufferSize = CurrentHobSize;
+    Status = gBS->AllocatePool (
+                    EfiBootServicesData,
+                    BufferSize,
+                    (VOID**)&VariableData
+                    );
+
+    ASSERT (VariableData != NULL); 
+    S3ChunkSize = MAX_HOB_ENTRY_SIZE / 8;
+    DEBUG((EFI_D_INFO, "   S3ChunkSize Hob Size(bytes): %d\n", S3ChunkSize));
+
+    while (CurrentHobSize) {
+      if (S3ChunkSize > CurrentHobSize) {
+        S3ChunkSize = CurrentHobSize;
+      }
+      BufferSize = S3ChunkSize;
+      CompressedDataSize = 0;
+      ScratchSize = 0;
+      Status = gRT->GetVariable (
+                      EfiMemoryConfigVariable,
+                      &gEfiMemoryConfigDataGuid,
+                      NULL,
+                      &CompressedDataSize,
+                      NULL
+                      );
+                    
+      if(Status == EFI_BUFFER_TOO_SMALL) {
+        Status = gBS->AllocatePool (
+                        EfiBootServicesData,
+                        CompressedDataSize,
+                        (VOID**)&CompressedData
+                        );
+        ASSERT (Status == EFI_SUCCESS); 
+      }
+
+      if(!EFI_ERROR (Status))
+      {
+        Status = gRT->GetVariable (
+                        EfiMemoryConfigVariable,
+                        &gEfiMemoryConfigDataGuid,
+                        NULL,
+                        &CompressedDataSize,
+                        CompressedData
+                        );
+
+        if (!EFI_ERROR (Status)) {
+         Status = Decompress->GetInfo (
+                                Decompress,
+                                CompressedData,
+                                (UINT32)CompressedDataSize,
+                                (UINT32*)&BufferSize,
+                                &ScratchSize
+                                );
+        }
+
+        if (!EFI_ERROR (Status)) {
+          Status = gBS->AllocatePool (
+                          EfiBootServicesData,
+                          ScratchSize,
+                          (VOID**)&Scratch
+                          );
+        }
+
+        if (!EFI_ERROR (Status)) {
+          Status = Decompress->Decompress (
+                                 Decompress,
+                                 CompressedData,
+                                 (UINT32)CompressedDataSize,
+                                 VariableData,
+                                 (UINT32)BufferSize,
+                                 Scratch,
+                                 ScratchSize
+                                 );
+        }
+
+        if (EFI_ERROR (Status)) {
+          DEBUG((EFI_D_ERROR, "Getting variables error: 0x%x\n", Status));
+          ASSERT (Status == EFI_SUCCESS); 
+        }
+
+        if(Scratch != NULL) {
+          gBS->FreePool (Scratch);
+          Scratch = NULL;
+        }
+      }
+
+      if(CompressedData != NULL) {
+        gBS->FreePool (CompressedData);
+        CompressedData = NULL;
+      }
+
+      if ( (EFI_ERROR(Status)) || (CompareMem (HobData, VariableData, S3ChunkSize) != 0) ) {
+        Status = gBS->AllocatePool (
+                        EfiBootServicesData,
+                        BufferSize,
+                        (VOID**)&CompressedVariableData
+                        );
+        ASSERT (CompressedVariableData != NULL); 
+        if (Status == EFI_SUCCESS) {
+          CompressedBufferSize = BufferSize;
+          Status = Compress(HobData, S3ChunkSize, CompressedVariableData, &CompressedBufferSize);
+          if (Status == EFI_BUFFER_TOO_SMALL){
+            gBS->FreePool(CompressedVariableData);
+            Status = gBS->AllocatePool(
+                            EfiBootServicesData,
+                            CompressedBufferSize,
+                            (VOID**)&CompressedVariableData
+                            );
+            ASSERT (CompressedVariableData != NULL);
+            Status = Compress(HobData, S3ChunkSize, CompressedVariableData, &CompressedBufferSize);
+          }
+          if(Status == EFI_SUCCESS) {
+            Status = gRT->SetVariable (
+                            EfiMemoryConfigVariable,
+                            &gEfiMemoryConfigDataGuid,
+                            EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+                            CompressedBufferSize,
+                            CompressedVariableData
+                            );
+          }
+          if(CompressedVariableData != NULL) {
+            gBS->FreePool(CompressedVariableData);
+            CompressedVariableData = NULL;
+          }
+      }
+    
+        if (EFI_ERROR (Status)) {
+          DEBUG((EFI_D_ERROR, "Set variable error. Status: 0x%x\n", Status));
+          ASSERT_EFI_ERROR (Status);
+        }
+      }
+      //
+      // Lock the Memory Config Variable
+      //
+      Status = VariableLock->RequestToLock(VariableLock, EfiMemoryConfigVariable, &gEfiMemoryConfigDataGuid);
+      ASSERT_EFI_ERROR(Status);
+      HobData = (UINT8 *) (HobData) + S3ChunkSize;
+    
+      CurrentHobSize -= S3ChunkSize;
+      EfiMemoryConfigVariable[12]++;  // Increment number in the string
+    }
+    //
+    // Get next S3 Config data hob, if none left, results NULL
+    //
+    GuidHob = GET_NEXT_HOB (GuidHob); // Increment to next HOB
+    GuidHob = GetNextGuidHob (&gEfiMemoryConfigDataHobGuid, GuidHob);  // Now search for next MemConfig HOB
+
+    if(VariableData != NULL) {
+      gBS->FreePool(VariableData);
+      VariableData = NULL;
+    }
+  }
+
+  return;
+}
+
+EFI_STATUS
+EFIAPI
+S3NvramSaveEntry ( 
+  IN EFI_HANDLE                         ImageHandle,
+  IN EFI_SYSTEM_TABLE                   *SystemTable
+  ) 
+/**
+
+  This is the main entry point of the S3 NVRAM Save module.
+
+  @param ImageHandle  -  Handle for the image of this driver.
+  @param SystemTable  -  Pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS  -  Module launched successfully.
+
+**/
+{
+  EFI_STATUS Status = EFI_SUCCESS;
+  
+  //
+  // Save the s3 strututre from MRC into NVRAM if needed
+  //
+  SaveS3StructToNvram();
+  
+  return Status;
+  
+}
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Policy/S3NvramSave/S3NvramSave.h b/Platform/Intel/PurleyOpenBoardPkg/Policy/S3NvramSave/S3NvramSave.h
new file mode 100644
index 0000000000..ad8efe572a
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Policy/S3NvramSave/S3NvramSave.h
@@ -0,0 +1,31 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/BaseMemoryLib.h>
+
+#include "SysHost.h"
+
+extern EFI_GUID gEfiMemoryConfigDataHobGuid;
+extern EFI_GUID gEfiMemoryConfigDataGuid;
+
+#define MAX_HOB_ENTRY_SIZE  60*1024
+
+EFI_STATUS
+EFIAPI
+S3NvramSaveEntry ( 
+  IN EFI_HANDLE             ImageHandle,
+  IN EFI_SYSTEM_TABLE       *SystemTable
+);
+
+VOID
+SaveS3StructToNvram (
+  VOID
+);
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Policy/S3NvramSave/S3NvramSave.inf b/Platform/Intel/PurleyOpenBoardPkg/Policy/S3NvramSave/S3NvramSave.inf
new file mode 100644
index 0000000000..0376b38bb1
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Policy/S3NvramSave/S3NvramSave.inf
@@ -0,0 +1,59 @@
+## @file
+#
+# Copyright (c) 2018 - 2021, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = S3NvramSave
+  FILE_GUID                      = 62DC08AC-A651-4EE9-AF81-EAA9261E9780
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = S3NvramSaveEntry
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
+#
+
+[Sources]
+  S3NvramSave.h
+  S3NvramSave.c
+
+[LibraryClasses]
+  UefiDriverEntryPoint
+  MemoryAllocationLib
+  UefiRuntimeServicesTableLib
+  UefiBootServicesTableLib
+  HobLib
+  BaseMemoryLib
+  CompressLib
+
+[Protocols]
+  gEfiDecompressProtocolGuid
+  gEdkiiVariableLockProtocolGuid
+
+[Guids]
+  gEfiMemoryConfigDataGuid
+  gEfiMemoryConfigDataHobGuid
+
+[FixedPcd]
+  gEfiCpRcPkgTokenSpaceGuid.PcdMaxCpuSocketCount
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  MinPlatformPkg/MinPlatformPkg.dec
+  PurleyOpenBoardPkg/OpenBoardPkg.dec
+  PurleyRefreshSiliconPkg/SiPkg.dec
+
+[Depex]
+  gEfiVariableArchProtocolGuid      AND
+  gEfiVariableWriteArchProtocolGuid AND
+  gEfiDecompressProtocolGuid        AND
+  gEdkiiVariableLockProtocolGuid
+
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Policy/SystemBoard/SystemBoardCommon.c b/Platform/Intel/PurleyOpenBoardPkg/Policy/SystemBoard/SystemBoardCommon.c
new file mode 100644
index 0000000000..6b9efae0f6
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Policy/SystemBoard/SystemBoardCommon.c
@@ -0,0 +1,625 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Platform.h>
+#include <Register/PchRegsUsb.h>
+#include <PchLimits.h>
+#include <PchPolicyCommon.h>
+#include <IioBifurcationSlotTable.h>
+
+VOID
+SetBifurcations(
+    IN OUT IIO_GLOBALS *IioGlobalData,
+    IN     IIO_BIFURCATION_ENTRY *BifurcationTable,
+    IN     UINT8                  BifurcationEntries
+)
+{
+  UINT8 Socket;
+  UINT8 Iou;
+  UINT8 Index;
+
+  for (Index = 0; Index < BifurcationEntries ; Index++) {
+    Socket = BifurcationTable[Index].Socket;
+    Iou = BifurcationTable[Index].IouNumber;
+    switch (Iou) {
+     case Iio_Iou0:
+       if (IioGlobalData->SetupData.ConfigIOU0[Socket]==IIO_BIFURCATE_AUTO) {
+         IioGlobalData->SetupData.ConfigIOU0[Socket] = BifurcationTable[Index].Bifurcation;
+       }
+       break;
+     case Iio_Iou1:
+       if (IioGlobalData->SetupData.ConfigIOU1[Socket] == IIO_BIFURCATE_AUTO) {
+         IioGlobalData->SetupData.ConfigIOU1[Socket] = BifurcationTable[Index].Bifurcation;
+       }
+       break;
+     case Iio_Iou2:
+       if (IioGlobalData->SetupData.ConfigIOU2[Socket]==IIO_BIFURCATE_AUTO) {
+         IioGlobalData->SetupData.ConfigIOU2[Socket] = BifurcationTable[Index].Bifurcation;
+       }
+       break;
+     case Iio_Mcp0:
+       if (IioGlobalData->SetupData.ConfigMCP0[Socket] == IIO_BIFURCATE_AUTO) {
+           IioGlobalData->SetupData.ConfigMCP0[Socket] = BifurcationTable[Index].Bifurcation;
+       }
+       break;
+     case Iio_Mcp1:
+       if (IioGlobalData->SetupData.ConfigMCP1[Socket] == IIO_BIFURCATE_AUTO) {
+           IioGlobalData->SetupData.ConfigMCP1[Socket] = BifurcationTable[Index].Bifurcation;
+       }
+       break;
+     default:
+       DEBUG((EFI_D_ERROR, "Invalid bifurcation table: Bad Iou (%d)", Iou));
+       ASSERT(Iou);
+       break;
+    }
+  }
+}
+
+VOID
+EnableHotPlug (
+    IN OUT IIO_GLOBALS *IioGlobalData,
+    IN UINT8 Port,
+    IN UINT8 VppPort,
+    IN UINT8 VppAddress,
+    IN UINT8 PortOwnership
+  )
+{
+  IioGlobalData->SetupData.SLOTHPCAP[Port]= ENABLE;
+  IioGlobalData->SetupData.SLOTAIP[Port]  = ENABLE;  // Attention Indicator Present
+  IioGlobalData->SetupData.SLOTPIP[Port]  = ENABLE;  // Power Indicator Present
+  IioGlobalData->SetupData.SLOTMRLSP[Port]= ENABLE; // MRL Sensor Present
+  IioGlobalData->SetupData.SLOTABP[Port]  = ENABLE; // Attention Button Present
+  IioGlobalData->SetupData.SLOTPCP[Port]  = ENABLE; // Power Controlled Present
+
+ if (PortOwnership ==  PCIEAIC_OCL_OWNERSHIP){
+    IioGlobalData->SetupData.SLOTAIP[Port]  = DISABLE;  // Attention Indicator Present
+    IioGlobalData->SetupData.SLOTPIP[Port]  = DISABLE;  // Power Indicator Present
+  }
+  if (PortOwnership ==  VMD_OWNERSHIP){
+    IioGlobalData->SetupData.SLOTABP[Port]  = DISABLE;
+    IioGlobalData->SetupData.SLOTPCP[Port]  = DISABLE;
+    IioGlobalData->SetupData.SLOTMRLSP[Port]= DISABLE;
+  }
+  //
+  // Set SLTCAP settings based on VMD/PCIe SSD Ownership
+  //
+  if ((PortOwnership == PCIEAIC_OCL_OWNERSHIP) ||
+      (PortOwnership == VMD_OWNERSHIP)){
+    IioGlobalData->SetupData.SLOTHPSUP[Port]= ENABLE;   // HotPlug Surprise
+  } 
+
+  if (VppPort!= VPP_PORT_MAX) {
+    IioGlobalData->SetupData.VppEnable[Port]= ENABLE;
+    IioGlobalData->SetupData.VppPort[Port]= VppPort;
+    IioGlobalData->SetupData.VppAddress[Port] = VppAddress;
+  } else {
+      DEBUG((EFI_D_ERROR, "PCIE HOT Plug. Missing VPP values on slot table\n"));
+  }
+}
+
+VOID
+ConfigSlots (
+    IN OUT IIO_GLOBALS        *IioGlobalData,
+    IN IIO_SLOT_CONFIG_ENTRY  *Slot,
+    IN UINT8                  SlotEntries
+  )
+{
+  UINT8 Index;
+  UINT8 Port;
+
+  for (Index =0; Index < SlotEntries; Index ++) {
+    Port=Slot[Index].PortIndex;
+    if (Slot[Index].Hidden != NOT_HIDE) {
+      IioGlobalData->SetupData.HidePEXPMenu[Port] = HIDE;
+      IioGlobalData->SetupData.PEXPHIDE[Port]= HIDE;
+    }
+    /// Check if slot is assigned.
+    if (Slot[Index].SlotNumber!= NO_SLT_IMP){
+       IioGlobalData->SetupData.SLOTIMP[Port]= SLT_IMP;
+       IioGlobalData->SetupData.SLOTPSP[Port]=Slot[Index].SlotNumber;
+       IioGlobalData->SetupData.SLOTEIP[Port]=Slot[Index].InterLockPresent;
+       if (Slot[Index].SlotPowerLimitScale!= PWR_SCL_MAX) {
+         IioGlobalData->SetupData.SLOTSPLS[Port] = Slot[Index].SlotPowerLimitScale;
+         IioGlobalData->SetupData.SLOTSPLV[Port] = Slot[Index].SlotPowerLimitValue;
+       }
+       if (Slot[Index].HotPlugCapable != DISABLE) {
+         EnableHotPlug(IioGlobalData, Port, Slot[Index].VppPort, Slot[Index].VppAddress, REGULAR_PCIE_OWNERSHIP);
+       }
+    }
+  }
+}
+
+/**
+    Verify if and Slot should be implemented based on IOUX bifurcation settings.
+
+    @param IioGlobalData           Pointer to Iio Globals.
+    @param Port                  - Port Index
+
+    @retval TRUE/FALSE         to determine if an slot shoudl be implemented or not 
+                               based on the IOUX bifurcation settings in case user want to do an 
+                               override and VMD is enabled.
+
+**/
+BOOLEAN
+SlotImplemented(
+    IN OUT IIO_GLOBALS        *IioGlobalData,
+    IN UINT8                  Port
+  ){
+  UINT8 IioIndex;
+  UINT8 PortIndex;
+  UINT8 Stack;
+  BOOLEAN  SlotImp = FALSE;
+
+  IioIndex = Port/NUMBER_PORTS_PER_SOCKET;
+  PortIndex = (Port - (NUMBER_PORTS_PER_SOCKET * IioIndex));
+ // Stack = (((PortIndex + 3)/4) - 1) + (IioIndex*VMD_STACK_PER_SOCKET);
+  Stack = IioGlobalData->IioVar.IioVData.StackPerPort[IioIndex][PortIndex];
+  DEBUG((DEBUG_INFO, "SlotImplemented:IioIndex = %x, Stack = %x, Port = %x, PortIndex =%x\n", IioIndex, Stack, Port, PortIndex));
+
+  switch(Stack){
+    case IIO_PSTACK0:
+      if (IioGlobalData->SetupData.ConfigIOU0[IioIndex] == IIO_BIFURCATE_x4x4x4x4){
+         SlotImp = TRUE;
+      } else if (IioGlobalData->SetupData.ConfigIOU0[IioIndex] == IIO_BIFURCATE_x4x4xxx8){
+        if ((PortIndex == PORT_1D_INDEX) || (PortIndex == PORT_1C_INDEX) || (PortIndex == PORT_1A_INDEX)){
+          SlotImp = TRUE;
+        }
+      } else if (IioGlobalData->SetupData.ConfigIOU0[IioIndex] == IIO_BIFURCATE_xxx8x4x4){
+        if ((PortIndex == PORT_1C_INDEX) || (PortIndex == PORT_1B_INDEX) || (PortIndex == PORT_1A_INDEX)){
+          SlotImp = TRUE;
+        }
+      } else if (IioGlobalData->SetupData.ConfigIOU0[IioIndex] == IIO_BIFURCATE_xxx8xxx8){
+        if ((PortIndex == PORT_1C_INDEX) || (PortIndex == PORT_1A_INDEX)){
+          SlotImp = TRUE;
+        }
+      } else if (IioGlobalData->SetupData.ConfigIOU0[IioIndex] == IIO_BIFURCATE_xxxxxx16){
+        if (PortIndex == PORT_1A_INDEX){
+          SlotImp = TRUE;
+        }
+      }
+      break;
+    case IIO_PSTACK1:
+      if (IioGlobalData->SetupData.ConfigIOU1[IioIndex] == IIO_BIFURCATE_x4x4x4x4){
+         SlotImp = TRUE;
+      } else if (IioGlobalData->SetupData.ConfigIOU1[IioIndex] == IIO_BIFURCATE_x4x4xxx8){
+        if ((PortIndex == PORT_2D_INDEX) || (PortIndex == PORT_2C_INDEX) || (PortIndex == PORT_2A_INDEX)){
+          SlotImp = TRUE;
+        }
+      } else if (IioGlobalData->SetupData.ConfigIOU1[IioIndex] == IIO_BIFURCATE_xxx8x4x4){
+        if ((PortIndex == PORT_2C_INDEX) || (PortIndex == PORT_2B_INDEX) || (PortIndex == PORT_2A_INDEX)){
+          SlotImp = TRUE;
+        }
+      } else if (IioGlobalData->SetupData.ConfigIOU1[IioIndex] == IIO_BIFURCATE_xxx8xxx8){
+        if ((PortIndex == PORT_2C_INDEX) || (PortIndex == PORT_2A_INDEX)){
+          SlotImp = TRUE;
+        }
+      } else if (IioGlobalData->SetupData.ConfigIOU1[IioIndex] == IIO_BIFURCATE_xxxxxx16){
+        if (PortIndex == PORT_2A_INDEX){
+          SlotImp = TRUE;
+        }
+      }
+      break;
+    case IIO_PSTACK2:
+      if (IioGlobalData->SetupData.ConfigIOU2[IioIndex] == IIO_BIFURCATE_x4x4x4x4){
+         SlotImp = TRUE;
+      } else if (IioGlobalData->SetupData.ConfigIOU2[IioIndex] == IIO_BIFURCATE_x4x4xxx8){
+        if ((PortIndex == PORT_3D_INDEX) || (PortIndex == PORT_3C_INDEX) || (PortIndex == PORT_3A_INDEX)){
+          SlotImp = TRUE;
+        }
+      } else if (IioGlobalData->SetupData.ConfigIOU2[IioIndex] == IIO_BIFURCATE_xxx8x4x4){
+        if ((PortIndex == PORT_3C_INDEX) || (PortIndex == PORT_3B_INDEX) || (PortIndex == PORT_3A_INDEX)){
+          SlotImp = TRUE;
+        }
+      } else if (IioGlobalData->SetupData.ConfigIOU2[IioIndex] == IIO_BIFURCATE_xxx8xxx8){
+        if ((PortIndex == PORT_3C_INDEX) || (PortIndex == PORT_3A_INDEX)){
+          SlotImp = TRUE;
+        }
+      } else if (IioGlobalData->SetupData.ConfigIOU2[IioIndex] == IIO_BIFURCATE_xxxxxx16){
+        if (PortIndex == PORT_3A_INDEX){
+          SlotImp = TRUE;
+        }
+      }
+      break;
+  }
+  DEBUG((DEBUG_INFO, "SlotImplemented:  = %x\n", SlotImp));
+  return SlotImp;
+}
+
+/**
+    Verify if VMD is enabled and override Slot conofgiration
+    based on the VMD settings
+
+    @param IioGlobalData           Pointer to Iio Globals.
+    @param Slot                  - Slot configuarion settings 
+    @param SlotEntries           - Number of slot entries
+
+    @retval None
+
+**/
+VOID
+OverrideConfigSlots (
+    IN OUT IIO_GLOBALS        *IioGlobalData,
+    IN IIO_SLOT_CONFIG_ENTRY  *Slot,
+    IN UINT8                  SlotEntries
+  )
+{
+  UINT8 Index;
+  UINT8 Port;
+  UINT8 IioIndex;
+  UINT8 VmdPort;
+  UINT8 Stack;
+
+  for (Index =0; Index < SlotEntries; Index ++) {
+    Port = Slot[Index].PortIndex;
+    //
+    // Check if Slot is capable of PcieSSD Solution and override the SLOT Config values
+    //
+    if (Slot[Index].PcieSSDCapable){
+      IioIndex = Port/NUMBER_PORTS_PER_SOCKET;
+      Stack = ((((Port - (NUMBER_PORTS_PER_SOCKET * IioIndex))+ 3)/4) - 1) + (IioIndex*VMD_STACK_PER_SOCKET);
+      DEBUG((DEBUG_INFO, "Stack = %x, Port = %x\n", Stack, Port));
+
+      //
+      // check if VMD will own Pcie Root Port
+      //
+      if(IioGlobalData->SetupData.VMDEnabled[Stack]){
+        VmdPort = ((IioIndex * VMD_PORTS_PER_SOCKET) + (Port - (NUMBER_PORTS_PER_SOCKET * IioIndex))) - 1;
+        if (IioGlobalData->SetupData.VMDPortEnable[VmdPort]){
+          IioGlobalData->IioVar.IioOutData.PciePortOwnership[Port] = VMD_OWNERSHIP;
+        }
+      } else {
+
+        DEBUG((DEBUG_INFO, "IioGlobalData->SetupData.PcieAICEnabled[%x] = %x\n",Stack, IioGlobalData->SetupData.PcieAICEnabled[Stack]));
+        //
+        // Check if Pcie AIC Card will be present on Pcie Root Port
+        //
+        if(IioGlobalData->SetupData.PcieAICEnabled[Stack]){
+          //
+          // Force to have this port enabled by default for hot-plug.
+          //
+          IioGlobalData->SetupData.PciePortDisable[(IioIndex * NUMBER_PORTS_PER_SOCKET) + Port] = ENABLE;
+          IioGlobalData->IioVar.IioOutData.PciePortOwnership[Port] = PCIEAIC_OCL_OWNERSHIP;
+          DEBUG((DEBUG_ERROR, "Port = %x, PciePortDisable = %x\n",Port,IioGlobalData->SetupData.PciePortDisable[(IioIndex * NUMBER_PORTS_PER_SOCKET) + Port]));
+        }
+      } // No _VMD Ownership
+
+      DEBUG((DEBUG_INFO, "PciePortOwnerShip[%x] = %x\n",Port, IioGlobalData->IioVar.IioOutData.PciePortOwnership[Port]));
+
+      // if PcieSSDSupport required do slot override settings accordingly
+      if((IioGlobalData->IioVar.IioOutData.PciePortOwnership[Port] != REGULAR_PCIE_OWNERSHIP) && 
+          (SlotImplemented(IioGlobalData, Port) == TRUE)){
+          IioGlobalData->SetupData.SLOTIMP[Port]= SLT_IMP;
+          IioGlobalData->SetupData.SLOTPSP[Port]= 0x50  + Port; // Just program a value for PCIEACI_OCL/VMD
+          IioGlobalData->SetupData.SLOTEIP[Port]= DISABLE;
+
+          if (Slot[Index].SlotPowerLimitScale!= PWR_SCL_MAX) {
+            IioGlobalData->SetupData.SLOTSPLS[Port] = Slot[Index].SlotPowerLimitScale;
+            IioGlobalData->SetupData.SLOTSPLV[Port] = Slot[Index].SlotPowerLimitValue;
+          }
+          DEBUG((DEBUG_INFO,"Slot[Index].PcieSSDVppPort = %x\n", Slot[Index].PcieSSDVppPort));
+          // Enable hot-plug if slot/port supports it
+          if (Slot[Index].PcieSSDVppPort != VPP_PORT_MAX) {
+          DEBUG((DEBUG_INFO, "IioGlobalData->SetupData.VMDHotPlugEnable[%x] = %x\n",Stack,IioGlobalData->SetupData.VMDHotPlugEnable[Stack]));
+          DEBUG((DEBUG_INFO, "IioGlobalData->SetupData.PcieAICHotPlugEnable[%x] = %x\n",Stack,IioGlobalData->SetupData.PcieAICHotPlugEnable[Stack]));
+          // Check if hot-plug is enabled for VMD or PCIeAIC case.
+            if (((IioGlobalData->IioVar.IioOutData.PciePortOwnership[Port] == VMD_OWNERSHIP) && (IioGlobalData->SetupData.VMDHotPlugEnable[Stack])) ||
+              ((IioGlobalData->IioVar.IioOutData.PciePortOwnership[Port] == PCIEAIC_OCL_OWNERSHIP) && (IioGlobalData->SetupData.PcieAICHotPlugEnable[Stack]))) {
+              EnableHotPlug(IioGlobalData, Port, Slot[Index].PcieSSDVppPort, Slot[Index].PcieSSDVppAddress, IioGlobalData->IioVar.IioOutData.PciePortOwnership[Port]);
+              DEBUG((DEBUG_INFO,"Enable HotPlug Done\n"));
+            }
+          }
+          //
+          // Unhide the port in order to get configured and it will be hide later for VMDLateSetup if VMD own the Pcie Root Port
+          //
+          IioGlobalData->SetupData.PEXPHIDE[Port]= NOT_HIDE;
+      }// PcieSSDSupport
+    }// PcieSSDCapable
+  }// Per Slot
+}
+
+
+/**
+    Auto determine which PCIe Root port to be hidden if its
+    lanes are assigned to its preceding root port...use the
+    Setup option variable of ConfigIOU to determine which ports
+    are to be hidden on each IOU for corresponding IIO
+
+    @param IOUx                  - IOUx Index
+    @param IioIndex              - Index to Iio
+    @param IioGlobalData           Pointer to Iio Globals.
+
+    @retval None
+
+**/
+VOID
+CalculatePEXPHideFromIouBif (
+    IN UINT8 Iou,
+    IN UINT8 IioIndex,
+    IN OUT IIO_GLOBALS *IioGlobalData
+)
+{
+
+  UINT8 *PXPHide, *HidePEXPMenu;
+  UINT8 CurrentIOUConfigValue;
+  UINT8 PXPOffset;
+  PXPHide = IioGlobalData->SetupData.PEXPHIDE;
+  HidePEXPMenu = IioGlobalData->SetupData.HidePEXPMenu;
+  CurrentIOUConfigValue =0;
+
+  PXPOffset=IioIndex * NUMBER_PORTS_PER_SOCKET;
+
+  switch (Iou) {
+  case Iio_Iou0:
+    CurrentIOUConfigValue = IioGlobalData->SetupData.ConfigIOU0[IioIndex];
+    PXPOffset+= PORT_1A_INDEX;
+    break;
+  case Iio_Iou1:
+    CurrentIOUConfigValue = IioGlobalData->SetupData.ConfigIOU1[IioIndex];
+    PXPOffset+= PORT_2A_INDEX;
+    break;
+  case Iio_Iou2:
+    CurrentIOUConfigValue = IioGlobalData->SetupData.ConfigIOU2[IioIndex];
+    PXPOffset+= PORT_3A_INDEX;
+    break;
+  case Iio_Mcp0:
+    CurrentIOUConfigValue = IioGlobalData->SetupData.ConfigMCP0[IioIndex];
+    PXPOffset+= PORT_4A_INDEX;
+    break;
+  case Iio_Mcp1:
+    CurrentIOUConfigValue = IioGlobalData->SetupData.ConfigMCP1[IioIndex];
+    PXPOffset += PORT_5A_INDEX;
+    break;
+  }
+
+  switch(CurrentIOUConfigValue){
+    case IIO_BIFURCATE_xxxxxxxx:
+      PXPHide[PXPOffset + Iio_PortA] = HIDE;            // hide A
+      PXPHide[PXPOffset + Iio_PortB] = HIDE;            // hide B
+      PXPHide[PXPOffset + Iio_PortC] = HIDE;            // hide C
+      PXPHide[PXPOffset + Iio_PortD] = HIDE;            // hide D
+      HidePEXPMenu[PXPOffset + Iio_PortA] = HIDE;       // hide the Setup menu for A
+      HidePEXPMenu[PXPOffset + Iio_PortB] = HIDE;       // hide the Setup menu for B
+      HidePEXPMenu[PXPOffset + Iio_PortC] = HIDE;       // hide the Setup menu for C
+      HidePEXPMenu[PXPOffset + Iio_PortD] = HIDE;       // hide the Setup menu for D
+      break;
+    case IIO_BIFURCATE_x4x4xxx8:
+      PXPHide[PXPOffset + Iio_PortA] = NOT_HIDE;        // show A
+      PXPHide[PXPOffset + Iio_PortB] = HIDE;            // hide B
+      PXPHide[PXPOffset + Iio_PortC] = NOT_HIDE;        // show C
+      PXPHide[PXPOffset + Iio_PortD] = NOT_HIDE;        // show D
+      HidePEXPMenu[PXPOffset + Iio_PortA] = NOT_HIDE;   // show the Setup menu for B
+      HidePEXPMenu[PXPOffset + Iio_PortB] = HIDE;       // hide the Setup menu for B
+      HidePEXPMenu[PXPOffset + Iio_PortC] = NOT_HIDE;   // show the Setup menu for D
+      HidePEXPMenu[PXPOffset + Iio_PortD] = NOT_HIDE;   // show the Setup menu for B
+      break;
+    case IIO_BIFURCATE_xxx8x4x4:
+      PXPHide[PXPOffset + Iio_PortA] = NOT_HIDE;        // show A
+      PXPHide[PXPOffset + Iio_PortB] = NOT_HIDE;        // show B
+      PXPHide[PXPOffset + Iio_PortC] = NOT_HIDE;        // show C
+      PXPHide[PXPOffset + Iio_PortD] = HIDE;            // hide port D
+      HidePEXPMenu[PXPOffset + Iio_PortA] = NOT_HIDE;   // show the Setup menu for A
+      HidePEXPMenu[PXPOffset + Iio_PortB] = NOT_HIDE;   // show the Setup menu for B
+      HidePEXPMenu[PXPOffset + Iio_PortC] = NOT_HIDE;   // show the Setup menu for C
+      HidePEXPMenu[PXPOffset + Iio_PortD] = HIDE;       // hide the Setup menu for D
+      break;
+    case IIO_BIFURCATE_xxx8xxx8:
+      PXPHide[PXPOffset + Iio_PortA] = NOT_HIDE;        // show A
+      PXPHide[PXPOffset + Iio_PortB] = HIDE;            // hide B
+      PXPHide[PXPOffset + Iio_PortC] = NOT_HIDE;        // show C
+      PXPHide[PXPOffset + Iio_PortD] = HIDE;            // hide D
+      HidePEXPMenu[PXPOffset + Iio_PortA] = NOT_HIDE;   // show the Setup menu for A
+      HidePEXPMenu[PXPOffset + Iio_PortB] = HIDE;       // hide the Setup menu for B
+      HidePEXPMenu[PXPOffset + Iio_PortC] = NOT_HIDE;   // show the Setup menu for C
+      HidePEXPMenu[PXPOffset + Iio_PortD] = HIDE;       // hide the Setup menu for D
+      break;
+    case IIO_BIFURCATE_xxxxxx16:
+      PXPHide[PXPOffset + Iio_PortA] = NOT_HIDE;        // show A
+      PXPHide[PXPOffset + Iio_PortB] = HIDE;            // hide B
+      PXPHide[PXPOffset + Iio_PortC] = HIDE;            // hide C
+      PXPHide[PXPOffset + Iio_PortD] = HIDE;            // hide D
+      HidePEXPMenu[PXPOffset + Iio_PortA] = NOT_HIDE;   // show the Setup menu for A
+      HidePEXPMenu[PXPOffset + Iio_PortB] = HIDE;       // hide the Setup menu for B
+      HidePEXPMenu[PXPOffset + Iio_PortC] = HIDE;       // hide the Setup menu for C
+      HidePEXPMenu[PXPOffset + Iio_PortD] = HIDE;       // hide the Setup menu for D
+      break;
+    default:
+      PXPHide[PXPOffset + Iio_PortA] = NOT_HIDE;        // show A
+      PXPHide[PXPOffset + Iio_PortB] = NOT_HIDE;        // show B
+      PXPHide[PXPOffset + Iio_PortC] = NOT_HIDE;        // show C
+      PXPHide[PXPOffset + Iio_PortD] = NOT_HIDE;        // show port D
+      HidePEXPMenu[PXPOffset + Iio_PortA] = NOT_HIDE;   // show the Setup menu for A
+      HidePEXPMenu[PXPOffset + Iio_PortB] = NOT_HIDE;   // show the Setup menu for B
+      HidePEXPMenu[PXPOffset + Iio_PortC] = NOT_HIDE;   // show the Setup menu for C
+      HidePEXPMenu[PXPOffset + Iio_PortD] = NOT_HIDE;   // show the Setup menu for D
+     break;
+  }
+
+  //
+  // Change PEXPHIDE setting to hide all PCIe port of a IOU if IIO_BIFURCATE_xxxxxxxx is set.
+  // And set ConfigIOUx/ConfigMCPx to default bifucation control value
+  // Bifurcation_Control[2:0] in IOU Bifurcation Control (PCIE_IOU_BIF_CTRL) register should be 000b ~ 100b.
+  //
+  if (CurrentIOUConfigValue == IIO_BIFURCATE_xxxxxxxx) {
+    switch (Iou) {
+    case Iio_Iou0:      
+      IioGlobalData->SetupData.ConfigIOU0[IioIndex] = IIO_BIFURCATE_x4x4x4x4;
+      break;
+    case Iio_Iou1:
+      IioGlobalData->SetupData.ConfigIOU1[IioIndex] = IIO_BIFURCATE_x4x4x4x4;
+      break;
+    case Iio_Iou2:
+      IioGlobalData->SetupData.ConfigIOU2[IioIndex] = IIO_BIFURCATE_x4x4x4x4;
+      break;
+    case Iio_Mcp0:
+      IioGlobalData->SetupData.ConfigMCP0[IioIndex] = IIO_BIFURCATE_x4x4x4x4;
+      break;
+    case Iio_Mcp1:
+      IioGlobalData->SetupData.ConfigMCP1[IioIndex] = IIO_BIFURCATE_x4x4x4x4;
+      break;
+    default:
+      break;
+    }
+  }
+}
+
+
+VOID
+DumpPort(
+    IIO_GLOBALS *IioGlobalData,
+    UINT8        Port,
+    UINT8        NumberOfPorts
+)
+{
+  UINT8 Index;
+  DEBUG((EFI_D_INFO, "IDX, Port Hide, Slot Impl, Slot Number, HotPlug, PcieSSD, VppPort, VppAddress, Interlock\n"));
+  for (Index = Port; Index < (Port + NumberOfPorts); Index++ ) {
+  DEBUG((EFI_D_INFO, "%3d|   %2d    |    %2d    |   %3d      |   %3d  |  %3d  |  0x%02x  |  0x%02x     |  %2d      \n", \
+                       Index, \
+                       IioGlobalData->SetupData.PEXPHIDE[Index],  \
+                       IioGlobalData->SetupData.SLOTIMP[Index],   \
+                       IioGlobalData->SetupData.SLOTPSP[Index],   \
+                       IioGlobalData->SetupData.SLOTHPCAP[Index], \
+                       IioGlobalData->IioVar.IioOutData.PciePortOwnership[Index],   \
+                       IioGlobalData->SetupData.VppPort[Index],   \
+                       IioGlobalData->SetupData.VppAddress[Index],\
+                       IioGlobalData->SetupData.SLOTEIP[Index]));
+            }
+          }
+/// Dump iio configuration. Dump the current IIO configuration to the serial
+/// log.
+VOID
+DumpIioConfiguration(
+    IN UINT8 iio,
+    IN IIO_GLOBALS *IioGlobalData
+)
+{
+  UINT8 Iou;
+  UINT8 PortIndex;
+  UINT8 Bifurcation;
+  UINT8 IouPorts;
+  PortIndex = iio * NUMBER_PORTS_PER_SOCKET;
+  /// First dump the socket number;
+  DEBUG((EFI_D_INFO, "Socket number: %d \n", iio));
+
+  /// Dump DMI configuration:
+  if ((iio == 0) && (PortIndex == 0)){
+      DEBUG((EFI_D_INFO, "PORT 0: DMI Port\n"));
+  } else {
+      DEBUG((EFI_D_INFO, "PORT 0: DMI Port working as PCIE\n"));
+      DumpPort(IioGlobalData, PortIndex, 1);
+  }
+  IouPorts=4;
+  /// Dump IOU bifurcations:
+  for (Iou = Iio_Iou0; Iou< Iio_IouMax; Iou ++) {
+      /// Reset port index.
+      PortIndex = iio * NUMBER_PORTS_PER_SOCKET;
+      // Get the bifurcation
+      switch (Iou) {
+        case Iio_Iou0:
+          Bifurcation = IioGlobalData->SetupData.ConfigIOU0[iio];
+          PortIndex += PORT_1A_INDEX;
+          DEBUG((EFI_D_INFO, "IUO0: Root Port 1, Bifurcation: %d\n", Bifurcation));
+          break;
+        case Iio_Iou1:
+          Bifurcation = IioGlobalData->SetupData.ConfigIOU1[iio];
+          PortIndex += PORT_2A_INDEX;
+          DEBUG((EFI_D_INFO, "IUO1: Root Port 2, Bifurcation: %d\n", Bifurcation));
+          break;
+        case Iio_Iou2:
+          Bifurcation = IioGlobalData->SetupData.ConfigIOU2[iio];
+          PortIndex += PORT_3A_INDEX;
+          DEBUG((EFI_D_INFO, "IUO2: Root Port 3, Bifurcation: %d\n", Bifurcation));
+          break;
+        case Iio_Mcp0:
+          Bifurcation = IioGlobalData->SetupData.ConfigMCP0[iio];
+          PortIndex += PORT_4A_INDEX;
+          DEBUG((EFI_D_INFO, "MCP0, Bifurcation: %d\n", Bifurcation));
+          break;
+        case Iio_Mcp1:
+          Bifurcation = IioGlobalData->SetupData.ConfigMCP1[iio];
+          PortIndex += PORT_5A_INDEX;
+          DEBUG((EFI_D_INFO, "MCP1, Bifurcation: %d\n", Bifurcation));
+          break;
+        default:
+          DEBUG((EFI_D_INFO, "Iou no detected = %d",Iou));
+          break;
+        }
+      DumpPort(IioGlobalData, PortIndex, IouPorts);
+  }
+
+}
+
+UINT8
+GetUplinkPortInformationCommon (
+    IN UINT8 IioIndex
+)
+{
+  UINT8 UplinkPortIndex = 0xFF;
+
+  if (IioIndex == 0) {
+    UplinkPortIndex = PcdGet8(PcdOemSkuUplinkPortIndex);
+  }
+
+  return UplinkPortIndex;
+}
+/**
+
+  SystemIioPortBifurcationInit - Program the UDS data structure with OEM IIO init values
+  for SLOTs and Bifurcation.
+
+  @param mSB - pointer to this protocol
+  @param IioUds - Pointer to the IIO UDS datastructure.
+
+  @retval EFI_SUCCESS
+
+**/
+VOID
+SystemIioPortBifurcationInitCommon (
+    IIO_GLOBALS *IioGlobalData,
+    IIO_BIFURCATION_ENTRY         **BifurcationTable,
+    UINT8                         *BifurcationEntries,
+    IIO_SLOT_CONFIG_ENTRY         **SlotTable,
+    UINT8                         *SlotEntries
+)
+{
+
+  UINT8                         PortIndex;//, iio;
+
+  /// This function outline:
+  //// 1 Based on platform apply the default bifurcation and slot configuration.
+  //// 2 Apply dynamic overrides based on GPIO and other configurations.
+  //// 3 Hide unused ports due bifurcation.
+
+  for (PortIndex = 0; PortIndex < MAX_SOCKET*NUMBER_PORTS_PER_SOCKET; PortIndex++) {
+    IioGlobalData->SetupData.PEXPHIDE[PortIndex] = 0;
+    IioGlobalData->SetupData.HidePEXPMenu[PortIndex] = 0;
+  }
+
+  *BifurcationEntries = 0;
+  *SlotEntries = 0;
+
+  *BifurcationTable   = (IIO_BIFURCATION_ENTRY *)(UINTN)PcdGet64 (PcdIioBifurcationTable);
+  *BifurcationEntries = PcdGet8 (PcdIioBifurcationTableEntries);
+  *SlotTable          = (IIO_SLOT_CONFIG_ENTRY *)(UINTN)PcdGet64 (PcdIioSlotTable);
+  *SlotEntries        = PcdGet8 (PcdIioSlotTableEntries);
+}
+
+VOID
+SystemHideIioPortsCommon(
+    IIO_GLOBALS *IioGlobalData,
+    UINT8       IioIndex
+)
+{
+    CalculatePEXPHideFromIouBif(Iio_Iou0, IioIndex, IioGlobalData);
+    CalculatePEXPHideFromIouBif(Iio_Iou1, IioIndex, IioGlobalData);
+    CalculatePEXPHideFromIouBif(Iio_Iou2, IioIndex, IioGlobalData);
+    CalculatePEXPHideFromIouBif(Iio_Mcp0, IioIndex, IioGlobalData);
+    CalculatePEXPHideFromIouBif(Iio_Mcp1, IioIndex, IioGlobalData);
+    DumpIioConfiguration(IioIndex, IioGlobalData);
+}
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Policy/SystemBoard/SystemBoardPei.c b/Platform/Intel/PurleyOpenBoardPkg/Policy/SystemBoard/SystemBoardPei.c
new file mode 100644
index 0000000000..9d05a39c68
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Policy/SystemBoard/SystemBoardPei.c
@@ -0,0 +1,255 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "SystemBoardPei.h"
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include <IioBifurcationSlotTable.h>
+
+extern IIO_BIFURCATION_ENTRY   mIioBifurcationTable[];
+extern UINT8 mIioBifurcationTableEntries;
+extern IIO_SLOT_CONFIG_ENTRY   mIioSlotTable[];
+extern UINT8 mIioSlotTableEntries;
+
+//
+// System board PPI structure
+//
+static SYSTEM_BOARD_PPI                mSystemBoardPpi = {
+  SystemIioPortBifurcationInit,        // Set IIO Bifurcation ports configuration
+  GetUplinkPortInformation,
+};
+
+static EFI_PEI_PPI_DESCRIPTOR       mSystemBoardPpiDesc = {
+  EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+  &gEfiPeiSystemBoardPpiGuid,
+  &mSystemBoardPpi
+};
+
+/**
+
+  GetUplinkPortInformation - Get uplink port information
+
+  @param IioIndex - socket ID.
+
+  @retval PortIndex for uplink port
+
+**/
+UINT8
+EFIAPI
+GetUplinkPortInformation (
+    IN UINT8 IioIndex
+)
+{
+  UINT8 UplinkPortIndex;
+
+  UplinkPortIndex =  GetUplinkPortInformationCommon(IioIndex);
+  return UplinkPortIndex;
+}
+
+/**
+
+  SystemIioPortBifurcationInit - Program the UDS data structure with OEM IIO init values
+  for SLOTs and Bifurcation.
+
+  @param mSB - pointer to this protocol
+  @param IioUds - Pointer to the IIO UDS datastructure.
+
+  @retval EFI_SUCCESS
+
+**/
+VOID
+InternalSystemIioPortBifurcationInitCommon (
+  IN OUT IIO_GLOBALS                   *IioGlobalData,
+  IN OUT IIO_BIFURCATION_ENTRY         **BifurcationTable,
+  IN OUT UINT8                         *BifurcationEntries,
+  IN OUT IIO_SLOT_CONFIG_ENTRY         **SlotTable,
+  IN OUT UINT8                         *SlotEntries
+)
+{
+
+  UINT8                         PortIndex;//, iio;
+  
+  /// This function outline:
+  //// 1 Based on platform apply the default bifurcation and slot configuration.
+  //// 2 Apply dynamic overrides based on GPIO and other configurations.
+  //// 3 Hide unused ports due bifurcation.
+
+  for (PortIndex = 0; PortIndex < MAX_SOCKET*NUMBER_PORTS_PER_SOCKET; PortIndex++) {
+    IioGlobalData->SetupData.PEXPHIDE[PortIndex] = 0;
+    IioGlobalData->SetupData.HidePEXPMenu[PortIndex] = 0;
+  }
+
+  *BifurcationEntries = 0;
+  *SlotEntries = 0;
+
+  // Purley Intel boards are not Multi-PCH
+  IioGlobalData->IioVar.IioVData.MultiPch = 0;
+
+  *BifurcationTable   = (IIO_BIFURCATION_ENTRY *)(UINTN)PcdGet64 (PcdIioBifurcationTable);
+  *BifurcationEntries = PcdGet8 (PcdIioBifurcationTableEntries);
+  *SlotTable          = (IIO_SLOT_CONFIG_ENTRY *)(UINTN)PcdGet64 (PcdIioSlotTable);
+  *SlotEntries        = PcdGet8 (PcdIioSlotTableEntries);
+}
+
+/**
+
+  SystemIioPortBifurcationInit - Program the IIO_GLOBALS data structure with OEM IIO init values
+  for SLOTs and Bifurcation.
+
+  @param mSB - pointer to this protocol
+  @param IioUds - Pointer to the IIO UDS datastructure.
+
+  @retval EFI_SUCCESS
+
+**/
+VOID
+SystemIioPortBifurcationInit (
+    IN IIO_GLOBALS *IioGlobalData
+)
+{
+
+  UINT8                         IioIndex;
+  IIO_BIFURCATION_ENTRY         *BifurcationTable = NULL;
+  UINT8                         BifurcationEntries;
+  IIO_SLOT_CONFIG_ENTRY         *SlotTable = NULL;
+  UINT8                         SlotEntries;
+
+  // This function outline:
+  // 1. Based on platform apply the default bifurcation and slot configuration.
+  // 2. Apply dynamic overrides based on GPIO and other configurations.
+  // 3. Hide unused ports due bifurcation.
+
+  SystemIioPortBifurcationInitCommon(IioGlobalData, &BifurcationTable, &BifurcationEntries, &SlotTable, &SlotEntries);
+  /// Set the default bifurcations for this platform.
+  SetBifurcations(IioGlobalData, BifurcationTable, BifurcationEntries);
+  ConfigSlots(IioGlobalData, SlotTable, SlotEntries);
+  OverrideConfigSlots(IioGlobalData, SlotTable, SlotEntries);
+
+  // All overrides have been applied now.
+  // Hide root ports whose lanes are assigned preceding ports.
+  for (IioIndex = Iio_Socket0; IioIndex < MaxIIO; IioIndex++) {
+    if (IioGlobalData->IioVar.IioVData.SocketPresent[IioIndex]) {
+      SystemHideIioPortsCommon(IioGlobalData, IioIndex);
+    }
+  }
+}
+
+
+/**
+
+  This function dump raw data.
+
+  @param  Data  raw data
+  @param  Size  raw data size
+
+**/
+VOID
+InternalDumpData (
+  IN UINT8  *Data,
+  IN UINTN  Size
+  )
+{
+  UINTN  Index;
+  for (Index = 0; Index < Size; Index++) {
+    DEBUG ((EFI_D_INFO, "%02x", (UINTN)Data[Index]));
+  }
+}
+
+/**
+
+  This function dump raw data with colume format.
+
+  @param  Data  raw data
+  @param  Size  raw data size
+
+**/
+VOID
+InternalDumpHex (
+  IN UINT8  *Data,
+  IN UINTN  Size
+  )
+{
+  UINTN   Index;
+  UINTN   Count;
+  UINTN   Left;
+
+#define COLUME_SIZE  (16 * 2)
+
+  Count = Size / COLUME_SIZE;
+  Left  = Size % COLUME_SIZE;
+  for (Index = 0; Index < Count; Index++) {
+    DEBUG ((EFI_D_INFO, "%04x: ", Index * COLUME_SIZE));
+    InternalDumpData (Data + Index * COLUME_SIZE, COLUME_SIZE);
+    DEBUG ((EFI_D_INFO, "\n"));
+  }
+
+  if (Left != 0) {
+    DEBUG ((EFI_D_INFO, "%04x: ", Index * COLUME_SIZE));
+    InternalDumpData (Data + Index * COLUME_SIZE, Left);
+    DEBUG ((EFI_D_INFO, "\n"));
+  }
+}
+
+VOID
+DumpConfig (
+  VOID
+  )
+{
+  DEBUG ((DEBUG_INFO, "PcdSetupData - 0x%x\n", PcdGetSize (PcdSetupData)));
+  InternalDumpHex (PcdGetPtr (PcdSetupData), PcdGetSize (PcdSetupData));
+  DEBUG ((DEBUG_INFO, "PcdPchRcConfigurationData - 0x%x\n", PcdGetSize (PcdPchRcConfigurationData)));
+  InternalDumpHex (PcdGetPtr (PcdPchRcConfigurationData), PcdGetSize (PcdPchRcConfigurationData));
+  DEBUG ((DEBUG_INFO, "PcdSocketIioConfigData - 0x%x\n", PcdGetSize (PcdSocketIioConfigData)));
+  InternalDumpHex (PcdGetPtr (PcdSocketIioConfigData), PcdGetSize (PcdSocketIioConfigData));
+  DEBUG ((DEBUG_INFO, "PcdSocketCommonRcConfigData - 0x%x\n", PcdGetSize (PcdSocketCommonRcConfigData)));
+  InternalDumpHex (PcdGetPtr (PcdSocketCommonRcConfigData), PcdGetSize (PcdSocketCommonRcConfigData));
+  DEBUG ((DEBUG_INFO, "PcdSocketMpLinkConfigData - 0x%x\n", PcdGetSize (PcdSocketMpLinkConfigData)));
+  InternalDumpHex (PcdGetPtr (PcdSocketMpLinkConfigData), PcdGetSize (PcdSocketMpLinkConfigData));
+  DEBUG ((DEBUG_INFO, "PcdSocketMemoryConfigData - 0x%x\n", PcdGetSize (PcdSocketMemoryConfigData)));
+  InternalDumpHex (PcdGetPtr (PcdSocketMemoryConfigData), PcdGetSize (PcdSocketMemoryConfigData));
+  DEBUG ((DEBUG_INFO, "PcdSocketPowerManagementConfigData - 0x%x\n", PcdGetSize (PcdSocketPowerManagementConfigData)));
+  InternalDumpHex (PcdGetPtr (PcdSocketPowerManagementConfigData), PcdGetSize (PcdSocketPowerManagementConfigData));
+  DEBUG ((DEBUG_INFO, "PcdSocketProcessorCoreConfigData - 0x%x\n", PcdGetSize (PcdSocketProcessorCoreConfigData)));
+  InternalDumpHex (PcdGetPtr (PcdSocketProcessorCoreConfigData), PcdGetSize (PcdSocketProcessorCoreConfigData));
+}
+
+//
+// PEI entry point - SystemBoardPpi entry point
+//
+/**
+
+  PEI system board PPI intialization main entry point. This will setup up a PPI that will handle providing system board level
+  configuration for the platform.
+
+  @param FileHandle         Pointer to the PEIM FFS file header.
+  @param PeiServices       General purpose services available to every PEIM.
+
+  @retval EFI_SUCCESS       Operation completed successfully.
+  @retval Otherwise         System board initialization failed.
+**/
+EFI_STATUS
+EFIAPI
+SystemBoardPeiEntry (
+  IN EFI_PEI_FILE_HANDLE       FileHandle,
+  IN CONST EFI_PEI_SERVICES    **PeiServices
+  )
+{
+  EFI_STATUS Status;
+
+  DEBUG ((EFI_D_ERROR, "--> SystemBoard PEI BoardDetection\n"));
+
+  //DumpConfig ();
+
+  //
+  // Initialize system board information PPI
+  //
+  Status = PeiServicesInstallPpi(&mSystemBoardPpiDesc);
+  ASSERT_EFI_ERROR (Status);
+  return Status;
+}
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Policy/SystemBoard/SystemBoardPei.h b/Platform/Intel/PurleyOpenBoardPkg/Policy/SystemBoard/SystemBoardPei.h
new file mode 100644
index 0000000000..1adc59cb3d
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Policy/SystemBoard/SystemBoardPei.h
@@ -0,0 +1,182 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _EFI_SYSTEM_BOARD_PPI_H_
+#define _EFI_SYSTEM_BOARD_PPI_H_
+
+#include <Platform.h>
+#include <Library/MmPciBaseLib.h>
+#include <Pi/PiHob.h>
+
+
+// GUID
+#include <Guid/SetupVariable.h>
+#include <Guid/SocketIioVariable.h>
+
+// PPI
+#include <Ppi/PchPolicy.h>
+#include <Ppi/SystemBoard.h>
+#include <Ppi/ReadOnlyVariable2.h>
+#include <Ppi/Smbus2.h>
+
+
+// Library
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PciLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/HobLib.h>
+#include <Library/PciExpressLib.h>
+
+#include <Library/GpioLib.h>
+#include <Library/PeiServicesTablePointerLib.h>
+#include <Library/PchInfoLib.h>
+#include <Platform.h>
+#include <GpioPinsSklH.h>
+#include <Library/GpioLib.h>
+
+#include <IioBifurcationSlotTable.h>
+
+// CMOS access Port address
+#define LAST_CMOS_BYTE          0x7F
+#define NMI_OFF                 0x80
+#define B_PCH_RTC_REGB_SRBRST   0x02  // Value to be reset to during POST
+#define R_PCH_RTC_REGD          0x0D  // CMOS Register D Status
+#define R_PCH_RTC_REGE          0x0E  // CMOS Register E Status
+#define B_PCH_RTC_REGE_INVTIM   0x04  // CMOS invalid time found
+
+#define TIMER1_CONTROL_PORT 0x43
+#define TIMER1_COUNT_PORT   0x41
+#define LOAD_COUNTER1_LSB   0x54
+#define COUNTER1_COUNT      0x12
+//
+// Reset Generator I/O Port
+//
+#define RESET_GENERATOR_PORT  0xCF9
+
+//-----------------------------------------------------------------------;
+// PCH: Chipset Configuration Register Equates
+//-----------------------------------------------------------------------;
+#define ICH_RCRB_IRQ0                       0
+#define ICH_RCRB_IRQA                       1
+#define ICH_RCRB_IRQB                       2
+#define ICH_RCRB_IRQC                       3
+#define ICH_RCRB_IRQD                       4
+#define ICH_RCRB_PIRQA                      0
+#define ICH_RCRB_PIRQB                      1
+#define ICH_RCRB_PIRQC                      2
+#define ICH_RCRB_PIRQD                      3
+#define ICH_RCRB_PIRQE                      4
+#define ICH_RCRB_PIRQF                      5
+#define ICH_RCRB_PIRQG                      6
+#define ICH_RCRB_PIRQH                      7
+
+//
+// From WBG Soft Straps WIP.xlsx
+//
+#define WBG_DOWNSKU_STRAP_DSKU      0x80046000
+#define WBG_DOWNSKU_STRAP_BSKU      0x8004E003
+#define WBG_DOWNSKU_STRAP_TSKU      0x00044000
+
+#define PCHSTRAP_9   9
+#define PCHSTRAP_10  10
+#define PCHSTRAP_16  16
+#define PCHSTRAP_17  17
+
+#define RESET_PORT                0x0CF9
+#define CLEAR_RESET_BITS          0x0F1
+#define COLD_RESET                0x02  // Set bit 1 for cold reset
+#define RST_CPU                   0x04  // Setting this bit triggers a reset of the CPU
+#define FULL_RESET                0x08  // Set bit 4 with bit 1 for full reset
+
+//
+// PPI functions
+//
+
+VOID
+SetBifurcations(
+    IN OUT IIO_GLOBALS *IioGlobalData,
+    IN     IIO_BIFURCATION_ENTRY *BifurcationTable,
+    IN     UINT8                  BifurcationEntries
+);
+
+VOID
+EnableHotPlug (
+    IN OUT IIO_GLOBALS *IioGlobalData,
+    IN UINT8 Port,
+    IN UINT8 VppPort,
+    IN UINT8 VppAddress,
+    IN UINT8 PortOwnership
+  );
+
+
+VOID
+ConfigSlots (
+    IN OUT IIO_GLOBALS        *IioGlobalData,
+    IN IIO_SLOT_CONFIG_ENTRY  *Slot,
+    IN UINT8                  SlotEntries
+  );
+
+VOID
+OverrideConfigSlots (
+    IN OUT IIO_GLOBALS        *IioGlobalData,
+    IN IIO_SLOT_CONFIG_ENTRY  *Slot,
+    IN UINT8                  SlotEntries
+  );
+  
+VOID
+CalculatePEXPHideFromIouBif (
+    IN UINT8 Iou,
+    IN UINT8 IioIndex,
+    IN OUT IIO_GLOBALS *IioGlobalData
+);
+
+VOID
+DumpIioConfiguration(
+    IN UINT8 iio,
+    IN IIO_GLOBALS *IioGlobalData
+);
+
+VOID
+OverrideDefaultBifSlots(
+    IN IIO_GLOBALS *IioGlobalData
+);
+
+UINT8
+GetUplinkPortInformationCommon (
+    IN UINT8 IioIndex
+);
+
+VOID
+SystemIioPortBifurcationInitCommon (
+    IIO_GLOBALS *IioGlobalData,
+    IIO_BIFURCATION_ENTRY         **BifurcationTable,
+    UINT8                         *BifurcationEntries,
+    IIO_SLOT_CONFIG_ENTRY         **SlotTable,
+    UINT8                         *SlotEntries
+);
+
+VOID
+SystemHideIioPortsCommon(
+    IIO_GLOBALS *IioGlobalData,
+    UINT8       IioIndex
+);
+
+UINT8
+GetUplinkPortInformation (
+    IN UINT8 IioIndex
+);
+
+VOID
+SystemIioPortBifurcationInit (
+  IN IIO_GLOBALS  *IioGlobalData
+  );
+
+#endif
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Policy/SystemBoard/SystemBoardPei.inf b/Platform/Intel/PurleyOpenBoardPkg/Policy/SystemBoard/SystemBoardPei.inf
new file mode 100644
index 0000000000..9bd2dfbb59
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Policy/SystemBoard/SystemBoardPei.inf
@@ -0,0 +1,76 @@
+## @file
+#
+# Copyright (c) 2018 - 2021, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = SystemBoardPei
+  FILE_GUID                      = C0989520-2F0D-470a-9BE4-2969E0EC5641
+  MODULE_TYPE                    = PEIM
+  ENTRY_POINT                    = SystemBoardPeiEntry
+
+[Sources]
+  SystemBoardPei.c
+  SystemBoardCommon.c
+
+[Packages]
+  MdeModulePkg/MdeModulePkg.dec
+  MdePkg/MdePkg.dec
+  PurleyOpenBoardPkg/OpenBoardPkg.dec
+  PurleyRefreshSiliconPkg/SiPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  MemoryAllocationLib
+  PeiServicesLib
+  PeimEntryPoint
+  DebugLib
+  HobLib
+  IoLib
+  PciLib
+  PcdLib
+  PeiServicesTablePointerLib
+  PciExpressLib
+  PchInfoLib
+  GpioLib
+  TimerLib
+  PchCycleDecodingLib
+  PchSbiAccessLib
+  PchInfoLib
+  PchP2sbLib
+  PchPcrLib
+  MmPciLib
+  PcdLib
+
+[Pcd]
+  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+  gOemSkuTokenSpaceGuid.PcdIioBifurcationTable
+  gOemSkuTokenSpaceGuid.PcdIioBifurcationTableEntries
+  gOemSkuTokenSpaceGuid.PcdIioSlotTable
+  gOemSkuTokenSpaceGuid.PcdIioSlotTableEntries
+  gOemSkuTokenSpaceGuid.PcdOemSkuUplinkPortIndex
+
+  gOemSkuTokenSpaceGuid.PcdSetupData
+  gOemSkuTokenSpaceGuid.PcdPchRcConfigurationData
+  gOemSkuTokenSpaceGuid.PcdSocketIioConfigData
+  gOemSkuTokenSpaceGuid.PcdSocketCommonRcConfigData
+  gOemSkuTokenSpaceGuid.PcdSocketMpLinkConfigData
+  gOemSkuTokenSpaceGuid.PcdSocketMemoryConfigData
+  gOemSkuTokenSpaceGuid.PcdSocketPowerManagementConfigData
+  gOemSkuTokenSpaceGuid.PcdSocketProcessorCoreConfigData
+
+
+[Ppis]
+  gEfiPeiSystemBoardPpiGuid         ## PRODUCES
+  gEfiPeiSmbus2PpiGuid
+  gPchPlatformPolicyPpiGuid
+
+[Depex]
+  gEfiPeiPcdPpiGuid AND
+  gEfiPeiReadOnlyVariable2PpiGuid
+
-- 
2.27.0.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#74977): https://edk2.groups.io/g/devel/message/74977
Mute This Topic: https://groups.io/mt/82742435/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-





More information about the edk2-devel-archive mailing list