summaryrefslogtreecommitdiff
path: root/Platform/Intel/PurleyOpenBoardPkg/Policy/SystemBoard
diff options
context:
space:
mode:
Diffstat (limited to 'Platform/Intel/PurleyOpenBoardPkg/Policy/SystemBoard')
-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
4 files changed, 1164 insertions, 0 deletions
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
+