summaryrefslogtreecommitdiff
path: root/Platform/Intel/PurleyOpenBoardPkg/Policy
diff options
context:
space:
mode:
Diffstat (limited to 'Platform/Intel/PurleyOpenBoardPkg/Policy')
-rw-r--r--Platform/Intel/PurleyOpenBoardPkg/Policy/IioUdsDataDxe/IioUdsDataDxe.c92
-rw-r--r--Platform/Intel/PurleyOpenBoardPkg/Policy/IioUdsDataDxe/IioUdsDataDxe.h87
-rw-r--r--Platform/Intel/PurleyOpenBoardPkg/Policy/IioUdsDataDxe/IioUdsDataDxe.inf44
-rw-r--r--Platform/Intel/PurleyOpenBoardPkg/Policy/Library/SiliconPolicyInitLib/SiliconPolicyInitLib.c136
-rw-r--r--Platform/Intel/PurleyOpenBoardPkg/Policy/Library/SiliconPolicyInitLib/SiliconPolicyInitLib.inf47
-rw-r--r--Platform/Intel/PurleyOpenBoardPkg/Policy/Library/SiliconPolicyUpdateLib/PchPolicyUpdateUsb.c105
-rw-r--r--Platform/Intel/PurleyOpenBoardPkg/Policy/Library/SiliconPolicyUpdateLib/SiliconPolicyUpdateLib.c665
-rw-r--r--Platform/Intel/PurleyOpenBoardPkg/Policy/Library/SiliconPolicyUpdateLib/SiliconPolicyUpdateLib.inf62
-rw-r--r--Platform/Intel/PurleyOpenBoardPkg/Policy/PlatformCpuPolicy/PlatformCpuPolicy.c661
-rw-r--r--Platform/Intel/PurleyOpenBoardPkg/Policy/PlatformCpuPolicy/PlatformCpuPolicy.inf88
-rw-r--r--Platform/Intel/PurleyOpenBoardPkg/Policy/S3NvramSave/S3NvramSave.c262
-rw-r--r--Platform/Intel/PurleyOpenBoardPkg/Policy/S3NvramSave/S3NvramSave.h37
-rw-r--r--Platform/Intel/PurleyOpenBoardPkg/Policy/S3NvramSave/S3NvramSave.inf66
-rw-r--r--Platform/Intel/PurleyOpenBoardPkg/Policy/SystemBoard/SystemBoardCommon.c631
-rw-r--r--Platform/Intel/PurleyOpenBoardPkg/Policy/SystemBoard/SystemBoardPei.c261
-rw-r--r--Platform/Intel/PurleyOpenBoardPkg/Policy/SystemBoard/SystemBoardPei.h188
-rw-r--r--Platform/Intel/PurleyOpenBoardPkg/Policy/SystemBoard/SystemBoardPei.inf84
17 files changed, 3516 insertions, 0 deletions
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Policy/IioUdsDataDxe/IioUdsDataDxe.c b/Platform/Intel/PurleyOpenBoardPkg/Policy/IioUdsDataDxe/IioUdsDataDxe.c
new file mode 100644
index 0000000000..132731a38c
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Policy/IioUdsDataDxe/IioUdsDataDxe.c
@@ -0,0 +1,92 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+//
+// 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..9453ac618d
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Policy/IioUdsDataDxe/IioUdsDataDxe.h
@@ -0,0 +1,87 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#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..74a2453bbd
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Policy/IioUdsDataDxe/IioUdsDataDxe.inf
@@ -0,0 +1,44 @@
+### @file
+#
+# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+###
+
+[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/PlatPkg.dec
+ PurleySktPkg/SocketPkg.dec
+ PurleyRcPkg/RcPkg.dec
+ LewisburgPkg/PchRcPkg.dec
+
+[LibraryClasses]
+ HobLib
+ BaseMemoryLib
+ UefiDriverEntryPoint
+
+[Protocols]
+ gEfiIioUdsProtocolGuid
+
+[Depex]
+ TRUE
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Policy/Library/SiliconPolicyInitLib/SiliconPolicyInitLib.c b/Platform/Intel/PurleyOpenBoardPkg/Policy/Library/SiliconPolicyInitLib/SiliconPolicyInitLib.c
new file mode 100644
index 0000000000..429bda6ae4
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Policy/Library/SiliconPolicyInitLib/SiliconPolicyInitLib.c
@@ -0,0 +1,136 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PchPolicyLib.h>
+
+/**
+ Performs silicon pre-mem policy initialization.
+
+ The meaning of Policy is defined by silicon code.
+ It could be the raw data, a handle, a PPI, etc.
+
+ The returned data must be used as input data for SiliconPolicyDonePreMem(),
+ and SiliconPolicyUpdateLib.SiliconPolicyUpdatePreMem().
+
+ 1) In FSP path, the input Policy should be FspmUpd.
+ Value of FspmUpd has been initialized by FSP binary default value.
+ Only a subset of FspmUpd needs to be updated for different silicon sku.
+ The return data is same FspmUpd.
+
+ 2) In non-FSP path, the input policy could be NULL.
+ The return data is the initialized policy.
+
+ @param[in, out] Policy Pointer to policy.
+
+ @return the initialized policy.
+**/
+VOID *
+EFIAPI
+SiliconPolicyInitPreMem (
+ IN OUT VOID *Policy OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ PCH_POLICY_PPI *PchPolicyPpi;
+
+ //
+ // Call PchCreatePolicyDefaults to initialize platform policy structure
+ // and get all intel default policy settings.
+ //
+ Status = PchCreatePolicyDefaults (&PchPolicyPpi);
+ ASSERT_EFI_ERROR (Status);
+
+ return PchPolicyPpi;
+}
+
+/*
+ The silicon pre-mem policy is finalized.
+ Silicon code can do initialization based upon the policy data.
+
+ The input Policy must be returned by SiliconPolicyInitPreMem().
+
+ @param[in] Policy Pointer to policy.
+
+ @retval RETURN_SUCCESS The policy is handled consumed by silicon code.
+*/
+RETURN_STATUS
+EFIAPI
+SiliconPolicyDonePreMem (
+ IN VOID *Policy
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Install PchPolicyPpi.
+ // While installed, RC assumes the Policy is ready and finalized. So please
+ // update and override any setting before calling this function.
+ //
+ Status = PchInstallPolicyPpi (Policy);
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+/**
+ Performs silicon post-mem policy initialization.
+
+ The meaning of Policy is defined by silicon code.
+ It could be the raw data, a handle, a PPI, etc.
+
+ The returned data must be used as input data for SiliconPolicyDonePostMem(),
+ and SiliconPolicyUpdateLib.SiliconPolicyUpdatePostMem().
+
+ 1) In FSP path, the input Policy should be FspsUpd.
+ Value of FspsUpd has been initialized by FSP binary default value.
+ Only a subset of FspsUpd needs to be updated for different silicon sku.
+ The return data is same FspsUpd.
+
+ 2) In non-FSP path, the input policy could be NULL.
+ The return data is the initialized policy.
+
+ @param[in, out] Policy Pointer to policy.
+
+ @return the initialized policy.
+**/
+VOID *
+EFIAPI
+SiliconPolicyInitPostMem (
+ IN OUT VOID *Policy OPTIONAL
+ )
+{
+ return Policy;
+}
+
+/*
+ The silicon post-mem policy is finalized.
+ Silicon code can do initialization based upon the policy data.
+
+ The input Policy must be returned by SiliconPolicyInitPostMem().
+
+ @param[in] Policy Pointer to policy.
+
+ @retval RETURN_SUCCESS The policy is handled consumed by silicon code.
+*/
+RETURN_STATUS
+EFIAPI
+SiliconPolicyDonePostMem (
+ IN VOID *Policy
+ )
+{
+ return RETURN_SUCCESS;
+} \ No newline at end of file
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Policy/Library/SiliconPolicyInitLib/SiliconPolicyInitLib.inf b/Platform/Intel/PurleyOpenBoardPkg/Policy/Library/SiliconPolicyInitLib/SiliconPolicyInitLib.inf
new file mode 100644
index 0000000000..69c32d39bf
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Policy/Library/SiliconPolicyInitLib/SiliconPolicyInitLib.inf
@@ -0,0 +1,47 @@
+### @file
+#
+# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+###
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SiliconPolicyInitLib
+ FILE_GUID = B494DF39-A5F8-48A1-B2D0-EF523AD91C55
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SiliconPolicyInitLib
+
+[Sources]
+ SiliconPolicyInitLib.c
+
+################################################################################
+#
+# Package Dependency Section - list of Package files that are required for
+# this module.
+#
+################################################################################
+[Packages]
+ MdePkg/MdePkg.dec
+ LewisburgPkg/PchRcPkg.dec
+ PurleySktPkg/SocketPkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ BaseLib
+ DebugLib
+ DebugPrintErrorLevelLib
+ HobLib
+ IoLib
+ MemoryAllocationLib
+ PeiServicesLib
+ PchPolicyLib
+
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Policy/Library/SiliconPolicyUpdateLib/PchPolicyUpdateUsb.c b/Platform/Intel/PurleyOpenBoardPkg/Policy/Library/SiliconPolicyUpdateLib/PchPolicyUpdateUsb.c
new file mode 100644
index 0000000000..a2780dcd5f
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Policy/Library/SiliconPolicyUpdateLib/PchPolicyUpdateUsb.c
@@ -0,0 +1,105 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+//
+// EDK and EDKII have different GUID formats
+//
+#include <Uefi/UefiBaseType.h>
+#include <Ppi/PchPolicy.h>
+#include "PlatformHost.h"
+#include <Guid/SetupVariable.h>
+#include <Guid/PchRcVariable.h>
+#include <Library/PchInfoLib.h>
+
+
+VOID
+UpdatePchUsbConfig (
+ IN PCH_USB_CONFIG *PchUsbConfig,
+ IN SYSTEM_CONFIGURATION *SetupVariables,
+ IN PCH_RC_CONFIGURATION *PchRcVariables,
+ IN VOID *Usb20OverCurrentMappings,
+ IN VOID *Usb30OverCurrentMappings
+ )
+/*++
+
+Routine Description:
+
+ This function performs PCH USB Platform Policy initialzation
+
+Arguments:
+ PchUsbConfig Pointer to PCH_USB_CONFIG data buffer
+ SetupVariables Pointer to Setup variable
+ PlatformType PlatformType specified
+ PlatformFlavor PlatformFlavor specified
+ BoardType BoardType specified
+
+Returns:
+
+--*/
+{
+ UINTN PortIndex;
+
+ PchUsbConfig->UsbPrecondition = PchRcVariables->UsbPrecondition;
+
+ for (PortIndex = 0; PortIndex < GetPchXhciMaxUsb2PortNum (); PortIndex++) {
+ if (PchRcVariables->PchUsbHsPort[PortIndex] == 1) {
+ PchUsbConfig->PortUsb20[PortIndex].Enable = TRUE;
+ } else {
+ PchUsbConfig->PortUsb20[PortIndex].Enable = FALSE;
+ }
+ }
+ for (PortIndex = 0; PortIndex < GetPchXhciMaxUsb3PortNum (); PortIndex++) {
+ if (PchRcVariables->PchUsbSsPort[PortIndex] == 1) {
+ PchUsbConfig->PortUsb30[PortIndex].Enable = TRUE;
+ } else {
+ PchUsbConfig->PortUsb30[PortIndex].Enable = FALSE;
+ }
+ }
+
+ //
+ // xDCI (USB device) related settings from setup variable
+ //
+ if(PchRcVariables->PchXdciSupport == 1) {
+ PchUsbConfig->XdciConfig.Enable= TRUE;
+ } else {
+ PchUsbConfig->XdciConfig.Enable= FALSE;
+ }
+
+ //
+ // XHCI USB Over Current Pins disabled, update it based on setup option.
+ //
+ PchUsbConfig->XhciOcMapEnabled = PchRcVariables->XhciOcMapEnabled;
+
+ //
+ // XHCI Wake On USB configured based on user input through setup option
+ //
+ PchUsbConfig->XhciWakeOnUsb = SetupVariables->XhciWakeOnUsbEnabled;
+ //
+ // XHCI option to disable MSIs
+ //
+ PchUsbConfig->XhciDisMSICapability = PchRcVariables->XhciDisMSICapability;
+
+ //
+ // Platform Board programming per the layout of each port.
+ //
+ // OC Map for USB2 Ports
+ for (PortIndex=0;PortIndex<PCH_MAX_USB2_PORTS;PortIndex++) {
+ PchUsbConfig->PortUsb20[PortIndex].OverCurrentPin = (UINT8)((PCH_USB_OVERCURRENT_PIN *)Usb20OverCurrentMappings)[PortIndex];
+ }
+
+ // OC Map for USB3 Ports
+ for (PortIndex=0;PortIndex<PCH_MAX_USB3_PORTS;PortIndex++) {
+ PchUsbConfig->PortUsb30[PortIndex].OverCurrentPin = (UINT8)((PCH_USB_OVERCURRENT_PIN *)Usb30OverCurrentMappings)[PortIndex];
+ }
+
+}
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Policy/Library/SiliconPolicyUpdateLib/SiliconPolicyUpdateLib.c b/Platform/Intel/PurleyOpenBoardPkg/Policy/Library/SiliconPolicyUpdateLib/SiliconPolicyUpdateLib.c
new file mode 100644
index 0000000000..53466d0c1b
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Policy/Library/SiliconPolicyUpdateLib/SiliconPolicyUpdateLib.c
@@ -0,0 +1,665 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiPei.h>
+
+#include "Guid/SetupVariable.h"
+#include <Guid/PchRcVariable.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Ppi/ReadOnlyVariable2.h>
+#include <Library/PeiServicesLib.h>
+
+#include <PchAccess.h>
+#include <Ppi/PchPolicy.h>
+#include <Library/MmPciBaseLib.h>
+
+#include <Register/PchRegsSata.h>
+#include <Library/HobLib.h>
+#include <Platform.h>
+#include <Guid/PchRcVariable.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/HobLib.h>
+#include <Guid/GlobalVariable.h>
+#include <Library/PchSerialIoLib.h>
+#include <Guid/SocketVariable.h>
+#include <Library/PcdLib.h>
+#include <Library/PchGbeLib.h>
+#include <Library/PchInfoLib.h>
+
+//
+// Haddock Creek
+//
+#define DIMM_SMB_SPD_P0C0D0_HC 0xA2
+#define DIMM_SMB_SPD_P0C0D1_HC 0xA0
+#define DIMM_SMB_SPD_P0C1D0_HC 0xA6
+#define DIMM_SMB_SPD_P0C1D1_HC 0xA4
+#define DIMM_SMB_SPD_P0C0D2_HC 0xAA
+#define DIMM_SMB_SPD_P0C1D2_HC 0xA8
+
+//
+// Sawtooth Peak
+// Single SPD EEPROM at 0xA2 serves both C0D0 and C1D0 (LPDDR is 1DPC only)
+//
+#define DIMM_SMB_SPD_P0C0D0_STP 0xA2
+#define DIMM_SMB_SPD_P0C0D1_STP 0xA0
+#define DIMM_SMB_SPD_P0C1D0_STP 0xA2
+#define DIMM_SMB_SPD_P0C1D1_STP 0xA0
+
+//
+// Aden Hills
+// DDR4 System (1DPC)
+//
+#define DIMM_SMB_SPD_P0C0D0_AH 0xA0
+#define DIMM_SMB_SPD_P0C0D1_AH 0xA4
+#define DIMM_SMB_SPD_P0C1D0_AH 0xA2
+#define DIMM_SMB_SPD_P0C1D1_AH 0xA6
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mSmbusHCRsvdAddresses[] = {
+ DIMM_SMB_SPD_P0C0D0_HC,
+ DIMM_SMB_SPD_P0C0D1_HC,
+ DIMM_SMB_SPD_P0C1D0_HC,
+ DIMM_SMB_SPD_P0C1D1_HC
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mSmbusSTPRsvdAddresses[] = {
+ DIMM_SMB_SPD_P0C0D0_STP,
+ DIMM_SMB_SPD_P0C0D1_STP,
+ DIMM_SMB_SPD_P0C1D0_STP,
+ DIMM_SMB_SPD_P0C1D1_STP
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mSmbusAHRsvdAddresses[] = {
+ DIMM_SMB_SPD_P0C0D0_AH,
+ DIMM_SMB_SPD_P0C0D1_AH,
+ DIMM_SMB_SPD_P0C1D0_AH,
+ DIMM_SMB_SPD_P0C1D1_AH
+};
+
+VOID
+UpdatePchUsbConfig (
+ IN PCH_USB_CONFIG *PchUsbConfig,
+ IN SYSTEM_CONFIGURATION *SetupVariables,
+ IN PCH_RC_CONFIGURATION *PchRcVariables,
+ IN VOID *Usb20OverCurrentMappings,
+ IN VOID *Usb30OverCurrentMappings
+ );
+
+static
+VOID
+InstallPlatformVerbTables (
+ IN UINTN CodecType
+ )
+{
+
+}
+
+EFI_STATUS
+EFIAPI
+UpdatePeiPchPolicy (
+ IN OUT PCH_POLICY_PPI *PchPolicy
+ )
+/*++
+
+Routine Description:
+
+ This function performs PCH PEI Policy initialzation.
+
+Arguments:
+
+ PchPolicy The PCH Policy PPI instance
+
+Returns:
+
+ EFI_SUCCESS The PPI is installed and initialized.
+ EFI ERRORS The PPI is not successfully installed.
+ EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver
+
+--*/
+{
+ UINT8 Index;
+ UINTN LpcBaseAddress;
+ UINT8 MaxSataPorts;
+ UINT8 *SmBusReservedTable;
+ UINT8 SmBusReservedNum;
+ PCH_USB_OVERCURRENT_PIN *Usb20OverCurrentMappings=NULL;
+ PCH_USB_OVERCURRENT_PIN *Usb30OverCurrentMappings=NULL;
+ UINT8 VTdSupport;
+ SYSTEM_CONFIGURATION *SetupVariables;
+ PCH_RC_CONFIGURATION *PchRcVariables;
+
+ DEBUG((EFI_D_ERROR, "platform common UpdatePeiPchPolicy entry\n"));
+
+ SetupVariables = PcdGetPtr(PcdSetupData);
+ PchRcVariables = PcdGetPtr(PcdPchRcConfigurationData);
+
+ LpcBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+
+ PchPolicy->Port80Route = PchRcVariables->IchPort80Route;
+
+ //
+ // DeviceEnables
+ //
+ if (PchIsGbeAvailable ()) {
+ PchPolicy->LanConfig.Enable = TRUE;
+ PchPolicy->LanConfig.K1OffEnable = PchRcVariables->PchLanK1Off;
+ } else {
+ PchPolicy->LanConfig.Enable = FALSE;
+ }
+
+ PchPolicy->SataConfig.Enable = PchRcVariables->PchSata;
+
+ PchPolicy->sSataConfig.Enable = PchRcVariables->PchsSata;
+ PchPolicy->SmbusConfig.Enable = TRUE;
+ //
+ // CLOCKRUN in LPC has to be disabled:
+ // - if a device is connected to LPC0
+ // - for LBG A0 stepping
+ //
+ PchPolicy->PmConfig.PciClockRun = FALSE;
+ PchPolicy->PchConfig.Crid = PchRcVariables->PchCrid;
+ PchPolicy->PchConfig.Serm = PchRcVariables->PchSerm;
+
+
+ //
+ // SMBUS reserved addresses
+ //
+ SmBusReservedTable = NULL;
+ SmBusReservedNum = 0;
+ PchPolicy->SmbusConfig.SmbusIoBase = PCH_SMBUS_BASE_ADDRESS;
+ SmBusReservedTable = mSmbusSTPRsvdAddresses;
+ SmBusReservedNum = sizeof (mSmbusSTPRsvdAddresses);
+
+ if (SmBusReservedTable != NULL) {
+ PchPolicy->SmbusConfig.NumRsvdSmbusAddresses = SmBusReservedNum;
+ CopyMem (
+ PchPolicy->SmbusConfig.RsvdSmbusAddressTable,
+ SmBusReservedTable,
+ SmBusReservedNum
+ );
+ }
+
+ //
+ // SATA Config
+ //
+ PchPolicy->SataConfig.SataMode = PchRcVariables->SataInterfaceMode;
+ MaxSataPorts = GetPchMaxSataPortNum ();
+
+ for (Index = 0; Index < MaxSataPorts; Index++) {
+ if (PchRcVariables->SataTestMode == TRUE)
+ {
+ PchPolicy->SataConfig.PortSettings[Index].Enable = TRUE;
+ } else {
+ PchPolicy->SataConfig.PortSettings[Index].Enable = PchRcVariables->SataPort[Index];
+ }
+ PchPolicy->SataConfig.PortSettings[Index].HotPlug = PchRcVariables->SataHotPlug[Index];
+ PchPolicy->SataConfig.PortSettings[Index].SpinUp = PchRcVariables->SataSpinUp[Index];
+ PchPolicy->SataConfig.PortSettings[Index].External = PchRcVariables->SataExternal[Index];
+ PchPolicy->SataConfig.PortSettings[Index].DevSlp = PchRcVariables->PxDevSlp[Index];
+ PchPolicy->SataConfig.PortSettings[Index].EnableDitoConfig = PchRcVariables->EnableDitoConfig[Index];
+ PchPolicy->SataConfig.PortSettings[Index].DmVal = PchRcVariables->DmVal[Index];
+ PchPolicy->SataConfig.PortSettings[Index].DitoVal = PchRcVariables->DitoVal[Index];
+ PchPolicy->SataConfig.PortSettings[Index].SolidStateDrive = PchRcVariables->SataType[Index];
+ }
+
+ if (PchPolicy->SataConfig.SataMode == PchSataModeRaid) {
+ PchPolicy->SataConfig.Rst.RaidAlternateId = PchRcVariables->SataAlternateId;
+ PchPolicy->SataConfig.Rst.EfiRaidDriverLoad = PchRcVariables->SataRaidLoadEfiDriver;
+ }
+ PchPolicy->SataConfig.Rst.Raid0 = PchRcVariables->SataRaidR0;
+ PchPolicy->SataConfig.Rst.Raid1 = PchRcVariables->SataRaidR1;
+ PchPolicy->SataConfig.Rst.Raid10 = PchRcVariables->SataRaidR10;
+ PchPolicy->SataConfig.Rst.Raid5 = PchRcVariables->SataRaidR5;
+ PchPolicy->SataConfig.Rst.Irrt = PchRcVariables->SataRaidIrrt;
+ PchPolicy->SataConfig.Rst.OromUiBanner = PchRcVariables->SataRaidOub;
+ PchPolicy->SataConfig.Rst.HddUnlock = PchRcVariables->SataHddlk;
+ PchPolicy->SataConfig.Rst.LedLocate = PchRcVariables->SataLedl;
+ PchPolicy->SataConfig.Rst.IrrtOnly = PchRcVariables->SataRaidIooe;
+ PchPolicy->SataConfig.Rst.SmartStorage = PchRcVariables->SataRaidSrt;
+ PchPolicy->SataConfig.Rst.OromUiDelay = PchRcVariables->SataRaidOromDelay;
+
+ PchPolicy->SataConfig.EnclosureSupport = TRUE;
+
+ PchPolicy->SataConfig.SalpSupport = PchRcVariables->SataSalp;
+ PchPolicy->SataConfig.TestMode = PchRcVariables->SataTestMode;
+
+ for (Index = 0; Index < PCH_MAX_RST_PCIE_STORAGE_CR; Index++) {
+ if ((PchRcVariables->PchSata == TRUE) && (PchRcVariables->SataInterfaceMode == PchSataModeRaid)) {
+ PchPolicy->SataConfig.RstPcieStorageRemap[Index].Enable = PchRcVariables->RstPcieStorageRemap[Index];
+ PchPolicy->SataConfig.RstPcieStorageRemap[Index].RstPcieStoragePort = PchRcVariables->RstPcieStorageRemapPort[Index];
+ } else {
+ PchPolicy->SataConfig.RstPcieStorageRemap[Index].Enable = FALSE;
+ }
+ }
+
+ //
+ // sSATA Config
+ //
+ PchPolicy->sSataConfig.SataMode = PchRcVariables->sSataInterfaceMode;
+ MaxSataPorts = GetPchMaxsSataPortNum ();
+
+ for (Index = 0; Index < MaxSataPorts; Index++) {
+ if (PchRcVariables->sSataTestMode == TRUE)
+ {
+ PchPolicy->sSataConfig.PortSettings[Index].Enable = TRUE;
+ } else {
+ PchPolicy->sSataConfig.PortSettings[Index].Enable = PchRcVariables->sSataPort[Index];
+ }
+ PchPolicy->sSataConfig.PortSettings[Index].HotPlug = PchRcVariables->sSataHotPlug[Index];
+ PchPolicy->sSataConfig.PortSettings[Index].SpinUp = PchRcVariables->sSataSpinUp[Index];
+ PchPolicy->sSataConfig.PortSettings[Index].External = PchRcVariables->sSataExternal[Index];
+ PchPolicy->sSataConfig.PortSettings[Index].DevSlp = PchRcVariables->sPxDevSlp[Index];
+ PchPolicy->sSataConfig.PortSettings[Index].EnableDitoConfig = PchRcVariables->sEnableDitoConfig[Index];
+ PchPolicy->sSataConfig.PortSettings[Index].DmVal = PchRcVariables->sDmVal[Index];
+ PchPolicy->sSataConfig.PortSettings[Index].DitoVal = PchRcVariables->sDitoVal[Index];
+ PchPolicy->sSataConfig.PortSettings[Index].SolidStateDrive = PchRcVariables->sSataType[Index];
+ }
+
+ if (PchPolicy->sSataConfig.SataMode == PchSataModeRaid) {
+ PchPolicy->sSataConfig.Rst.RaidAlternateId = PchRcVariables->sSataAlternateId;
+ PchPolicy->sSataConfig.Rst.EfiRaidDriverLoad = PchRcVariables->sSataRaidLoadEfiDriver;
+ }
+ PchPolicy->sSataConfig.Rst.Raid0 = PchRcVariables->sSataRaidR0;
+ PchPolicy->sSataConfig.Rst.Raid1 = PchRcVariables->sSataRaidR1;
+ PchPolicy->sSataConfig.Rst.Raid10 = PchRcVariables->sSataRaidR10;
+ PchPolicy->sSataConfig.Rst.Raid5 = PchRcVariables->sSataRaidR5;
+ PchPolicy->sSataConfig.Rst.Irrt = PchRcVariables->sSataRaidIrrt;
+ PchPolicy->sSataConfig.Rst.OromUiBanner = PchRcVariables->sSataRaidOub;
+ PchPolicy->sSataConfig.Rst.HddUnlock = PchRcVariables->sSataHddlk;
+ PchPolicy->sSataConfig.Rst.LedLocate = PchRcVariables->sSataLedl;
+ PchPolicy->sSataConfig.Rst.IrrtOnly = PchRcVariables->sSataRaidIooe;
+ PchPolicy->sSataConfig.Rst.SmartStorage = PchRcVariables->sSataRaidSrt;
+ PchPolicy->sSataConfig.Rst.OromUiDelay = PchRcVariables->sSataRaidOromDelay;
+
+ PchPolicy->sSataConfig.EnclosureSupport = TRUE;
+
+ PchPolicy->sSataConfig.SalpSupport = PchRcVariables->sSataSalp;
+ PchPolicy->sSataConfig.TestMode = PchRcVariables->sSataTestMode;
+ //
+ // Initiate DMI Configuration
+ //
+ if (SetupVariables->PcieDmiAspm != PLATFORM_POR) {
+ if (SetupVariables->PcieDmiAspm != 0xFF) {
+ PchPolicy->DmiConfig.DmiAspm = TRUE;
+ } else {
+ PchPolicy->DmiConfig.DmiAspm = FALSE;
+ }
+ }
+ DEBUG((DEBUG_ERROR, "PchPolicy->DmiConfig.DmiAspm =%x\n", PchPolicy->DmiConfig.DmiAspm));
+ //
+ // PCI express config
+ //
+ PchPolicy->PcieConfig.DisableRootPortClockGating = SetupVariables->PcieClockGating;
+ PchPolicy->PcieConfig.EnablePort8xhDecode = PchRcVariables->PcieRootPort8xhDecode;
+ PchPolicy->PcieConfig.PchPciePort8xhDecodePortIndex = PchRcVariables->Pcie8xhDecodePortIndex;
+ PchPolicy->PcieConfig.EnablePeerMemoryWrite = PchRcVariables->PcieRootPortPeerMemoryWriteEnable;
+ PchPolicy->PcieConfig.ComplianceTestMode = PchRcVariables->PcieComplianceTestMode;
+
+ for (Index = 0; Index < GetPchMaxPciePortNum (); Index++) {
+ PchPolicy->PcieConfig.RootPort[Index].Enable = PchRcVariables->PcieRootPortEn[Index];
+ PchPolicy->PcieConfig.RootPort[Index].PhysicalSlotNumber = (UINT8) Index;
+ if (PchRcVariables->PchPcieGlobalAspm > PchPcieAspmDisabled) {
+ // Disabled a.k.a. Per individual port
+ PchPolicy->PcieConfig.RootPort[Index].Aspm = PchRcVariables->PchPcieGlobalAspm;
+ } else {
+ PchPolicy->PcieConfig.RootPort[Index].Aspm = PchRcVariables->PcieRootPortAspm[Index];
+ }
+ PchPolicy->PcieConfig.RootPort[Index].L1Substates = PchRcVariables->PcieRootPortL1SubStates[Index];
+ PchPolicy->PcieConfig.RootPort[Index].AcsEnabled = PchRcVariables->PcieRootPortACS[Index];
+ PchPolicy->PcieConfig.RootPort[Index].PmSci = PchRcVariables->PcieRootPortPMCE[Index];
+ PchPolicy->PcieConfig.RootPort[Index].HotPlug = PchRcVariables->PcieRootPortHPE[Index];
+ PchPolicy->PcieConfig.RootPort[Index].AdvancedErrorReporting = PchRcVariables->PcieRootPortAER[Index];
+ PchPolicy->PcieConfig.RootPort[Index].UnsupportedRequestReport = PchRcVariables->PcieRootPortURE[Index];
+ PchPolicy->PcieConfig.RootPort[Index].FatalErrorReport = PchRcVariables->PcieRootPortFEE[Index];
+ PchPolicy->PcieConfig.RootPort[Index].NoFatalErrorReport = PchRcVariables->PcieRootPortNFE[Index];
+ PchPolicy->PcieConfig.RootPort[Index].CorrectableErrorReport = PchRcVariables->PcieRootPortCEE[Index];
+ PchPolicy->PcieConfig.RootPort[Index].SystemErrorOnFatalError = PchRcVariables->PcieRootPortSFE[Index];
+ PchPolicy->PcieConfig.RootPort[Index].SystemErrorOnNonFatalError = PchRcVariables->PcieRootPortSNE[Index];
+ PchPolicy->PcieConfig.RootPort[Index].SystemErrorOnCorrectableError = PchRcVariables->PcieRootPortSCE[Index];
+ PchPolicy->PcieConfig.RootPort[Index].TransmitterHalfSwing = PchRcVariables->PcieRootPortTHS[Index];
+ PchPolicy->PcieConfig.RootPort[Index].CompletionTimeout = PchRcVariables->PcieRootPortCompletionTimeout[Index];
+ PchPolicy->PcieConfig.RootPort[Index].PcieSpeed = PchRcVariables->PcieRootPortSpeed[Index];
+
+ PchPolicy->PcieConfig.RootPort[Index].MaxPayload = PchRcVariables->PcieRootPortMaxPayLoadSize[Index];
+ PchPolicy->PcieConfig.RootPort[Index].Gen3EqPh3Method = PchRcVariables->PcieRootPortEqPh3Method[Index];
+ }
+
+ for (Index = 0; Index < GetPchMaxPciePortNum (); ++Index) {
+ PchPolicy->PcieConfig.EqPh3LaneParam[Index].Cm = PchRcVariables->PcieLaneCm[Index];
+ PchPolicy->PcieConfig.EqPh3LaneParam[Index].Cp = PchRcVariables->PcieLaneCp[Index];
+ }
+ if (PchRcVariables->PcieSwEqOverride) {
+ for (Index = 0; Index < PCH_PCIE_SWEQ_COEFFS_MAX; Index++) {
+ PchPolicy->PcieConfig2.SwEqCoeffList[Index].Cm = PchRcVariables->PcieSwEqCoeffCm[Index];
+ PchPolicy->PcieConfig2.SwEqCoeffList[Index].Cp = PchRcVariables->PcieSwEqCoeffCp[Index];
+ }
+ }
+
+ PchPolicy->PcieConfig.MaxReadRequestSize = PchRcVariables->PcieRootPortMaxReadRequestSize;
+ ///
+ /// Update Competion Timeout settings for Upling ports for Server PCH
+ ///
+ PchPolicy->PcieConfig.PchPcieUX16CompletionTimeout = PchRcVariables->PchPcieUX16CompletionTimeout;
+ PchPolicy->PcieConfig.PchPcieUX8CompletionTimeout = PchRcVariables->PchPcieUX8CompletionTimeout;
+ ///
+ /// Update Max Payload Size settings for Upling ports for Server PCH
+ ///
+ PchPolicy->PcieConfig.PchPcieUX16MaxPayload = PchRcVariables->PchPcieUX16MaxPayloadSize;
+ PchPolicy->PcieConfig.PchPcieUX8MaxPayload = PchRcVariables->PchPcieUX8MaxPayloadSize;
+ CopyMem (&VTdSupport, (UINT8 *)PcdGetPtr(PcdSocketIioConfigData) + OFFSET_OF(SOCKET_IIO_CONFIGURATION, VTdSupport), sizeof(VTdSupport));
+ PchPolicy->PcieConfig.VTdSupport = VTdSupport;
+
+ ///
+ /// Assign ClkReq signal to root port. (Base 0)
+ /// For LP, Set 0 - 5
+ /// For H, Set 0 - 15
+ /// Note that if GbE is enabled, ClkReq assigned to GbE will not be available for Root Port. (TODO for Purley)
+ ///
+ //
+ // HdAudioConfig
+ //
+ PchPolicy->HdAudioConfig.Enable = PchRcVariables->PchHdAudio;
+ PchPolicy->HdAudioConfig.DspEnable = FALSE;
+ PchPolicy->HdAudioConfig.Pme = PchRcVariables->PchHdAudioPme;
+ PchPolicy->HdAudioConfig.IoBufferOwnership = PchRcVariables->PchHdAudioIoBufferOwnership;
+ PchPolicy->HdAudioConfig.IoBufferVoltage = PchRcVariables->PchHdAudioIoBufferVoltage;
+ PchPolicy->HdAudioConfig.ResetWaitTimer = 300;
+ PchPolicy->HdAudioConfig.IDispCodecDisconnect = TRUE; //iDisp is permanently disabled
+ for(Index = 0; Index < HDAUDIO_FEATURES; Index++) {
+ PchPolicy->HdAudioConfig.DspFeatureMask |= (UINT32)(PchRcVariables->PchHdAudioFeature[Index] ? (1 << Index) : 0);
+ }
+
+ for(Index = 0; Index < HDAUDIO_PP_MODULES; Index++) {
+ PchPolicy->HdAudioConfig.DspPpModuleMask |= (UINT32)(PchRcVariables->PchHdAudioPostProcessingMod[Index] ? (1 << Index) : 0);
+ }
+
+ if (PchPolicy->HdAudioConfig.Enable) {
+ InstallPlatformVerbTables (PchRcVariables->PchHdAudioCodecSelect);
+ }
+
+ PchPolicy->HdAudioConfig.VcType = PchRcVariables->RtoHdaVcType;
+ //
+ // LockDown
+ //
+
+
+ PchPolicy->LockDownConfig.RtcLock = PchRcVariables->PchRtcLock;
+ PchPolicy->LockDownConfig.BiosLock = PchRcVariables->PchBiosLock;
+ PchPolicy->LockDownConfig.SpiEiss = TRUE;
+ PchPolicy->LockDownConfig.GlobalSmi = TRUE;
+ PchPolicy->LockDownConfig.BiosInterface = TRUE;
+ PchPolicy->LockDownConfig.EvaLockDown = PchRcVariables->PchEvaLockDown;
+ PchPolicy->LockDownConfig.GpioLockDown = PchRcVariables->PchGpioLockDown;
+ PchPolicy->LockDownConfig.TcoLock = TRUE;
+
+ if(PchRcVariables->PchP2sbUnlock) {
+ PchPolicy->P2sbConfig.SbiUnlock = TRUE;
+ PchPolicy->P2sbConfig.PsfUnlock = TRUE;
+ } else {
+ PchPolicy->P2sbConfig.SbiUnlock = FALSE;
+ PchPolicy->P2sbConfig.PsfUnlock = FALSE;
+ }
+ PchPolicy->P2sbConfig.P2SbReveal = PchRcVariables->PchP2sbDevReveal;
+
+ //
+ // Update SPI policies
+ //
+ PchPolicy->SpiConfig.ShowSpiController = TRUE;
+
+ //
+ // PMC Policy
+ //
+ PchPolicy->PmConfig.PmcReadDisable = PchRcVariables->PmcReadDisable;
+
+
+ if (PchRcVariables->PchAdrEn != PLATFORM_POR) {
+ PchPolicy->AdrConfig.PchAdrEn = PchRcVariables->PchAdrEn;
+ }
+ PchPolicy->AdrConfig.AdrGpioSel = PchRcVariables->AdrGpioSel;
+ if (PchRcVariables->AdrHostPartitionReset != PLATFORM_POR) {
+ PchPolicy->AdrConfig.AdrHostPartitionReset = PchRcVariables->AdrHostPartitionReset;
+ }
+ if (PchRcVariables->AdrTimerEn != PLATFORM_POR) {
+ PchPolicy->AdrConfig.AdrTimerEn = PchRcVariables->AdrTimerEn;
+ }
+ if (PchRcVariables->AdrTimerVal != ADR_TMR_SETUP_DEFAULT_POR) {
+ PchPolicy->AdrConfig.AdrTimerVal = PchRcVariables->AdrTimerVal;
+ }
+ if (PchRcVariables->AdrMultiplierVal != ADR_MULT_SETUP_DEFAULT_POR) {
+ PchPolicy->AdrConfig.AdrMultiplierVal = PchRcVariables->AdrMultiplierVal;
+ }
+
+ //
+ // Thermal Config
+ //
+ if ((PchRcVariables->MemoryThermalManagement != FALSE) &&
+ ((PchRcVariables->ExttsViaTsOnBoard != FALSE) || (PchRcVariables->ExttsViaTsOnDimm != FALSE)))
+ {
+ PchPolicy->ThermalConfig.MemoryThrottling.Enable = TRUE;
+ PchPolicy->ThermalConfig.MemoryThrottling.TsGpioPinSetting[TsGpioC].PmsyncEnable = TRUE;
+ PchPolicy->ThermalConfig.MemoryThrottling.TsGpioPinSetting[TsGpioD].PmsyncEnable = TRUE;
+ PchPolicy->ThermalConfig.MemoryThrottling.TsGpioPinSetting[TsGpioC].C0TransmitEnable = TRUE;
+ PchPolicy->ThermalConfig.MemoryThrottling.TsGpioPinSetting[TsGpioD].C0TransmitEnable = TRUE;
+ PchPolicy->ThermalConfig.MemoryThrottling.TsGpioPinSetting[TsGpioC].PinSelection = 1;
+ PchPolicy->ThermalConfig.MemoryThrottling.TsGpioPinSetting[TsGpioD].PinSelection = 0;
+ } else {
+ PchPolicy->ThermalConfig.MemoryThrottling.Enable = FALSE;
+ }
+
+ //
+ // IOAPIC Config
+ //
+ PchPolicy->IoApicConfig.IoApicEntry24_119 = PchRcVariables->PchIoApic24119Entries;
+ PchPolicy->IoApicConfig.BdfValid = 1;
+ PchPolicy->IoApicConfig.BusNumber = 0xF0;
+ PchPolicy->IoApicConfig.DeviceNumber = 0x1F;
+ PchPolicy->IoApicConfig.FunctionNumber = 0;
+
+
+ //
+ // Misc PM Config
+ //
+ PchPolicy->PmConfig.PchDeepSxPol = PchRcVariables->DeepSxMode;
+ PchPolicy->PmConfig.WakeConfig.WolEnableOverride = PchRcVariables->PchWakeOnLan;
+ PchPolicy->PmConfig.WakeConfig.WoWlanEnable = PchRcVariables->PchWakeOnWlan;
+ PchPolicy->PmConfig.WakeConfig.WoWlanDeepSxEnable = PchRcVariables->PchWakeOnWlanDeepSx;
+ PchPolicy->PmConfig.WakeConfig.Gp27WakeFromDeepSx = PchRcVariables->Gp27WakeFromDeepSx;
+ PchPolicy->PmConfig.SlpLanLowDc = PchRcVariables->PchSlpLanLowDc;
+ PchPolicy->PmConfig.PowerResetStatusClear.MeWakeSts = TRUE;
+ PchPolicy->PmConfig.PowerResetStatusClear.MeHrstColdSts = TRUE;
+ PchPolicy->PmConfig.PowerResetStatusClear.MeHrstWarmSts = TRUE;
+ PchPolicy->PmConfig.PciePllSsc = PchRcVariables->PciePllSsc;
+
+ PchPolicy->PmConfig.DirtyWarmReset = PchRcVariables->Dwr_Enable;
+
+ PchPolicy->PmConfig.StallDirtyWarmReset = PchRcVariables->Dwr_Stall;
+ PchPolicy->PmConfig.Dwr_BmcRootPort = PchRcVariables->Dwr_BmcRootPort;
+
+ PchPolicy->PmConfig.PchGbl2HostEn.Bits.PMCGBL = PchRcVariables->DwrEn_PMCGBL;
+ PchPolicy->PmConfig.PchGbl2HostEn.Bits.MEWDT = PchRcVariables->DwrEn_MEWDT;
+ PchPolicy->PmConfig.PchGbl2HostEn.Bits.IEWDT = PchRcVariables->DwrEn_IEWDT;
+
+ PchPolicy->PmConfig.Dwr_MeResetPrepDone = PchRcVariables->Dwr_MeResetPrepDone;
+ PchPolicy->PmConfig.Dwr_IeResetPrepDone = PchRcVariables->Dwr_IeResetPrepDone;
+
+ //
+ // DefaultSvidSid Config
+ //
+ PchPolicy->PchConfig.SubSystemVendorId = V_PCH_INTEL_VENDOR_ID;
+ PchPolicy->PchConfig.SubSystemId = V_PCH_DEFAULT_SID;
+ PchPolicy->PchConfig.EnableClockSpreadSpec = PchRcVariables->EnableClockSpreadSpec;
+ //
+ // Thermal Config
+ //
+ PchPolicy->ThermalConfig.ThermalThrottling.TTLevels.PchCrossThrottling = PchRcVariables->PchCrossThrottling;
+ PchPolicy->ThermalConfig.ThermalThrottling.DmiHaAWC.SuggestedSetting = TRUE;
+ if (PchRcVariables->ThermalDeviceEnable == PchThermalDeviceAuto) {
+ if (PchStepping () == LbgA0) {
+ PchPolicy->ThermalConfig.ThermalDeviceEnable = PchThermalDeviceDisabled;
+ } else {
+ PchPolicy->ThermalConfig.ThermalDeviceEnable = PchThermalDeviceEnabledPci;
+ }
+ } else {
+ PchPolicy->ThermalConfig.ThermalDeviceEnable = PchRcVariables->ThermalDeviceEnable;
+ }
+
+ PchPolicy->ThermalConfig.ThermalThrottling.TTLevels.SuggestedSetting = TRUE;
+ PchPolicy->ThermalConfig.ThermalThrottling.SataTT.SuggestedSetting = TRUE;
+ PchPolicy->ThermalConfig.ThermalThrottling.sSataTT.SuggestedSetting = TRUE;
+
+ //
+ // DCI (EXI)
+ //
+ PchPolicy->DciConfig.DciEn = PchRcVariables->PchDciEn;
+ PchPolicy->DciConfig.DciAutoDetect = PchRcVariables->PchDciAutoDetect;
+
+
+ //
+ // Initialize Serial IRQ Config
+ //
+ PchPolicy->SerialIrqConfig.SirqEnable = TRUE;
+ PchPolicy->SerialIrqConfig.StartFramePulse = PchSfpw4Clk;
+ if (PchRcVariables->PchSirqMode == 0) {
+ PchPolicy->SerialIrqConfig.SirqMode = PchQuietMode;
+ } else {
+ PchPolicy->SerialIrqConfig.SirqMode = PchContinuousMode;
+ }
+
+ //
+ // Port 61h emulation
+ //
+ PchPolicy->Port61hSmmConfig.Enable = TRUE;
+
+ //
+ // DMI configuration
+ //
+ PchPolicy->DmiConfig.DmiLinkDownHangBypass = PchRcVariables->DmiLinkDownHangBypass;
+ PchPolicy->DmiConfig.DmiStopAndScreamEnable = PchRcVariables->PcieDmiStopAndScreamEnable;
+
+ //
+ // Update Pch Usb Config
+ //
+ Usb20OverCurrentMappings = (PCH_USB_OVERCURRENT_PIN *)(UINTN)PcdGet64 (PcdUsb20OverCurrentMappings);
+ Usb30OverCurrentMappings = (PCH_USB_OVERCURRENT_PIN *)(UINTN)PcdGet64 (PcdUsb30OverCurrentMappings);
+ UpdatePchUsbConfig (
+ &PchPolicy->UsbConfig,
+ SetupVariables,
+ PchRcVariables,
+ Usb20OverCurrentMappings,
+ Usb30OverCurrentMappings
+ );
+
+ //
+ // Update TraceHub config based on setup options
+ //
+ PchPolicy->PchTraceHubConfig.EnableMode = PchRcVariables->TraceHubEnableMode;
+
+ switch (PchRcVariables->MemRegion0BufferSize) {
+ case 0:
+ PchPolicy->PchTraceHubConfig.MemReg0Size = 0; // No memory
+ break;
+ case 1:
+ PchPolicy->PchTraceHubConfig.MemReg0Size = 0x100000; // 1MB
+ break;
+ case 2:
+ PchPolicy->PchTraceHubConfig.MemReg0Size = 0x800000; // 8MB
+ break;
+ case 3:
+ PchPolicy->PchTraceHubConfig.MemReg0Size = 0x4000000; // 64MB
+ break;
+ }
+
+ switch (PchRcVariables->MemRegion1BufferSize) {
+ case 0:
+ PchPolicy->PchTraceHubConfig.MemReg1Size = 0; // No memory
+ break;
+ case 1:
+ PchPolicy->PchTraceHubConfig.MemReg1Size = 0x100000; // 1MB
+ break;
+ case 2:
+ PchPolicy->PchTraceHubConfig.MemReg1Size = 0x800000; // 8MB
+ break;
+ case 3:
+ PchPolicy->PchTraceHubConfig.MemReg1Size = 0x4000000; // 64MB
+ break;
+ }
+
+ PchPolicy->PchTraceHubConfig.PchTraceHubHide = PchRcVariables->PchTraceHubHide;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Performs silicon pre-mem policy update.
+
+ The meaning of Policy is defined by silicon code.
+ It could be the raw data, a handle, a PPI, etc.
+
+ The input Policy must be returned by SiliconPolicyDonePreMem().
+
+ 1) In FSP path, the input Policy should be FspmUpd.
+ A platform may use this API to update the FSPM UPD policy initialized
+ by the silicon module or the default UPD data.
+ The output of FSPM UPD data from this API is the final UPD data.
+
+ 2) In non-FSP path, the board may use additional way to get
+ the silicon policy data field based upon the input Policy.
+
+ @param[in, out] Policy Pointer to policy.
+
+ @return the updated policy.
+**/
+VOID *
+EFIAPI
+SiliconPolicyUpdatePreMem (
+ IN OUT VOID *Policy
+ )
+{
+ UpdatePeiPchPolicy (Policy);
+ return Policy;
+}
+
+/**
+ Performs silicon post-mem policy update.
+
+ The meaning of Policy is defined by silicon code.
+ It could be the raw data, a handle, a PPI, etc.
+
+ The input Policy must be returned by SiliconPolicyDonePostMem().
+
+ 1) In FSP path, the input Policy should be FspsUpd.
+ A platform may use this API to update the FSPS UPD policy initialized
+ by the silicon module or the default UPD data.
+ The output of FSPS UPD data from this API is the final UPD data.
+
+ 2) In non-FSP path, the board may use additional way to get
+ the silicon policy data field based upon the input Policy.
+
+ @param[in, out] Policy Pointer to policy.
+
+ @return the updated policy.
+**/
+VOID *
+EFIAPI
+SiliconPolicyUpdatePostMem (
+ IN OUT VOID *Policy
+ )
+{
+ return Policy;
+}
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Policy/Library/SiliconPolicyUpdateLib/SiliconPolicyUpdateLib.inf b/Platform/Intel/PurleyOpenBoardPkg/Policy/Library/SiliconPolicyUpdateLib/SiliconPolicyUpdateLib.inf
new file mode 100644
index 0000000000..ffa9eed0da
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Policy/Library/SiliconPolicyUpdateLib/SiliconPolicyUpdateLib.inf
@@ -0,0 +1,62 @@
+### @file
+#
+# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+###
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SiliconPolicyUpdateLib
+ FILE_GUID = 6EA9585C-3C15-47da-9FFC-25E9E4EA4D0C
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SiliconPolicyUpdateLib
+
+[Sources]
+ SiliconPolicyUpdateLib.c
+ PchPolicyUpdateUsb.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ LewisburgPkg/PchRcPkg.dec
+ PurleySktPkg/SocketPkg.dec
+ PurleyRcPkg/RcPkg.dec
+ PurleyOpenBoardPkg/PlatPkg.dec
+
+[LibraryClasses]
+ HobLib
+ MmPciLib
+ IoLib
+ PcdLib
+ PchGbeLib
+
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemRevision
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorId
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision
+ gOemSkuTokenSpaceGuid.PcdSocketIioConfigData
+ gOemSkuTokenSpaceGuid.PcdUsb20OverCurrentMappings
+ gOemSkuTokenSpaceGuid.PcdUsb30OverCurrentMappings
+
+ gOemSkuTokenSpaceGuid.PcdSetupData
+ gOemSkuTokenSpaceGuid.PcdPchRcConfigurationData
+
+[FixedPcd]
+
+[Ppis]
+
+[Guids]
+ gEfiAcpiVariableGuid
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Policy/PlatformCpuPolicy/PlatformCpuPolicy.c b/Platform/Intel/PurleyOpenBoardPkg/Policy/PlatformCpuPolicy/PlatformCpuPolicy.c
new file mode 100644
index 0000000000..4b8a979fc2
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Policy/PlatformCpuPolicy/PlatformCpuPolicy.c
@@ -0,0 +1,661 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#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 ConfigTDPCtrl;
+ 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),
+ &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, ":: PkgC @ %X XE @ %X\n", PkgCstEntryCriteriaMask, XePtr));
+
+ CStateLatencyCtrl = (MSR_REGISTER *)(ppm->Cst.LatencyCtrl);
+
+ }
+
+ //
+ // 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->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;
+
+ ConfigTDPCtrl = ( SetupData.SocketConfig.PowerManagementConfig.ConfigTDPLevel << CONFIG_TDP_LEVEL_SHIFT );
+
+ ppm->ConfigTDP = ConfigTDPCtrl;
+
+ 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.PPOBudget = SetupData.SocketConfig.PowerManagementConfig.ProcessorPPOBudget;
+ 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..a06647e9e3
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Policy/PlatformCpuPolicy/PlatformCpuPolicy.inf
@@ -0,0 +1,88 @@
+### @file
+#
+# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+###
+
+[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/PlatPkg.dec
+ PurleySktPkg/SocketPkg.dec
+ PurleyRcPkg/RcPkg.dec
+ PurleySktPkg/Override/IA32FamilyCpuPkg/IA32FamilyCpuPkg.dec
+ LewisburgPkg/PchRcPkg.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..27d5efbeef
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Policy/S3NvramSave/S3NvramSave.c
@@ -0,0 +1,262 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#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..2627266fd5
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Policy/S3NvramSave/S3NvramSave.h
@@ -0,0 +1,37 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#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..a06c1ff2c5
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Policy/S3NvramSave/S3NvramSave.inf
@@ -0,0 +1,66 @@
+### @file
+#
+# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+###
+
+[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/PlatPkg.dec
+ PurleySktPkg/SocketPkg.dec
+ PurleyRcPkg/RcPkg.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..6f28e1e7d4
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Policy/SystemBoard/SystemBoardCommon.c
@@ -0,0 +1,631 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#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..5a1d4618e4
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Policy/SystemBoard/SystemBoardPei.c
@@ -0,0 +1,261 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#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..bf2c9201c1
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Policy/SystemBoard/SystemBoardPei.h
@@ -0,0 +1,188 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#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..6b1202bfa8
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Policy/SystemBoard/SystemBoardPei.inf
@@ -0,0 +1,84 @@
+### @file
+#
+# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+###
+
+[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
+ LewisburgPkg/PchRcPkg.dec
+ PurleyOpenBoardPkg/PlatPkg.dec
+ PurleySktPkg/SocketPkg.dec
+ PurleyRcPkg/RcPkg.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
+