summaryrefslogtreecommitdiff
path: root/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchInfoLib
diff options
context:
space:
mode:
Diffstat (limited to 'Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchInfoLib')
-rw-r--r--Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchInfoLib/PchInfoLib.c511
-rw-r--r--Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchInfoLib/PchInfoStrLib.c297
-rw-r--r--Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchInfoLib/PeiDxeSmmPchInfoLib.inf39
3 files changed, 847 insertions, 0 deletions
diff --git a/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchInfoLib/PchInfoLib.c b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchInfoLib/PchInfoLib.c
new file mode 100644
index 0000000000..31966dd609
--- /dev/null
+++ b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchInfoLib/PchInfoLib.c
@@ -0,0 +1,511 @@
+/** @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 <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MmPciBaseLib.h>
+#include <Library/PchInfoLib.h>
+#include <PchAccess.h>
+
+#define PCH_DO_STRINGIFY(x) #x
+#define PCH_STRINGIFY(x) PCH_DO_STRINGIFY(x)
+
+//
+// This module variables are used for cache the static result.
+// @note: please pay attention to the PEI phase, the module variables on ROM
+// and can't be modified.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED UINTN mLpcBaseAddr = 0;
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_STEPPING mPchStepping = PchSteppingMax;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mIsPchSupported = 0xFF;
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_SERIES mPchSeries = PchUnknownSeries;
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_GENERATION mPchGeneration = PchUnknownGeneration;
+
+/**
+ Return Pch stepping type
+
+ @retval PCH_STEPPING Pch stepping type
+**/
+PCH_STEPPING
+EFIAPI
+PchStepping (
+ VOID
+ )
+{
+ UINT8 RevId;
+ UINT16 LpcDeviceId;
+ UINTN LpcBaseAddress;
+
+ if (mPchStepping != PchSteppingMax) {
+ return mPchStepping;
+ }
+
+ LpcBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+ RevId = MmioRead8 (LpcBaseAddress + PCI_REVISION_ID_OFFSET);
+
+ LpcDeviceId = MmioRead16 (LpcBaseAddress + PCI_DEVICE_ID_OFFSET);
+
+ if (IS_PCH_H_LPC_DEVICE_ID (LpcDeviceId)) {
+ switch (RevId) {
+ case V_PCH_LPC_RID_0:
+ mPchStepping = PchHA0;
+ return PchHA0;
+
+ case V_PCH_LPC_RID_10:
+ mPchStepping = PchHB0;
+ return PchHB0;
+
+ case V_PCH_LPC_RID_20:
+ mPchStepping = PchHC0;
+ return PchHC0;
+
+ case V_PCH_LPC_RID_30:
+ mPchStepping = PchHD0;
+ return PchHD0;
+
+ case V_PCH_LPC_RID_31:
+ mPchStepping = PchHD1;
+ return PchHD1;
+
+ default:
+ DEBUG ((DEBUG_ERROR, "Unsupported PCH Stepping. Supporting PCH stepping starting from %a and above\n", PCH_STRINGIFY(PCH_H_MIN_SUPPORTED_STEPPING))) ;
+ return PchSteppingMax;
+ }
+ }
+
+ if (IS_PCH_LP_LPC_DEVICE_ID (LpcDeviceId)) {
+ switch (RevId) {
+#ifdef SIMICS_FLAG
+ case V_PCH_LPC_RID_0:
+ mPchStepping = PchLpA0;
+ return PchLpA0;
+#endif
+
+ case V_PCH_LPC_RID_10:
+ mPchStepping = PchLpB0;
+ return PchLpB0;
+
+ case V_PCH_LPC_RID_11:
+ mPchStepping = PchLpB1;
+ return PchLpB1;
+
+ case V_PCH_LPC_RID_20:
+ mPchStepping = PchLpC0;
+ return PchLpC0;
+
+ case V_PCH_LPC_RID_21:
+ mPchStepping = PchLpC1;
+ return PchLpC1;
+
+ default:
+ DEBUG ((DEBUG_ERROR, "Unsupported PCH Stepping. Supporting PCH stepping starting from %a and above\n", PCH_STRINGIFY(PCH_LP_MIN_SUPPORTED_STEPPING))) ;
+ return PchSteppingMax;
+ }
+ }
+
+#ifdef SKXD_EN
+ if (IS_PCH_LBG_D_SSKU_LPC_DEVICE_ID (LpcDeviceId)) {
+ switch (RevId) {
+ case V_PCH_LBG_LPC_RID_3:
+ return LbgB1_D;
+ default:
+ DEBUG ((DEBUG_ERROR, "Unsupported PCH Stepping. Supporting PCH stepping starting from %s and above\n", PCH_STRINGIFY(V_PCH_LBG_LPC_RID_3)));
+ return PchSteppingMax;
+ }
+ }
+#endif // SKXD_EN
+
+ if (IS_PCH_LBG_LPC_DEVICE_ID (LpcDeviceId)) {
+ if (RevId == 0) {
+ return LbgA0;
+ } else {
+ switch (RevId) {
+ case V_PCH_LBG_LPC_RID_0:
+ return LbgA0;
+ case V_PCH_LBG_LPC_RID_2:
+ return LbgB0;
+ case V_PCH_LBG_LPC_RID_3:
+ return LbgB1;
+ case V_PCH_LBG_LPC_RID_4:
+ return LbgB2;
+ case V_PCH_LBG_LPC_RID_8:
+ return LbgS0;
+ case V_PCH_LBG_LPC_RID_9:
+ return LbgS1;
+ default:
+ DEBUG ((DEBUG_ERROR, "Unsupported PCH Stepping. Supporting PCH stepping starting from %s and above\n", PCH_STRINGIFY(PCH_LBG_MIN_SUPPORTED_STEPPING)));
+ ASSERT (FALSE);
+ return PchSteppingMax;
+ }
+ }
+ }
+ return PchSteppingMax;
+}
+
+/**
+ Determine if PCH is supported
+
+ @retval TRUE PCH is supported
+ @retval FALSE PCH is not supported
+**/
+BOOLEAN
+IsPchSupported (
+ VOID
+ )
+{
+ UINT16 LpcDeviceId;
+ UINT16 LpcVendorId;
+ UINTN LpcBaseAddress;
+
+ if (mIsPchSupported != 0xFF) {
+ return (BOOLEAN) mIsPchSupported;
+ }
+
+ LpcBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+
+ LpcDeviceId = MmioRead16 (LpcBaseAddress + PCI_DEVICE_ID_OFFSET);
+ LpcVendorId = MmioRead16 (LpcBaseAddress + PCI_VENDOR_ID_OFFSET);
+
+ ///
+ /// Verify that this is a supported chipset
+ ///
+ if ((LpcVendorId == V_PCH_LPC_VENDOR_ID) &&
+ (IS_PCH_LBG_LPC_DEVICE_ID (LpcDeviceId)))
+ {
+ mIsPchSupported = TRUE;
+ return TRUE;
+ } else {
+ DEBUG ((DEBUG_ERROR, "PCH code doesn't support the LpcDeviceId: 0x%04x!\n", LpcDeviceId));
+ mIsPchSupported = FALSE;
+ return FALSE;
+ }
+}
+
+/**
+ Return Pch Series
+
+ @retval PCH_SERIES Pch Series
+**/
+PCH_SERIES
+EFIAPI
+GetPchSeries (
+ VOID
+ )
+{
+ UINT16 LpcDeviceId;
+ UINT32 PchSeries;
+ UINTN LpcBaseAddress;
+
+ if (mPchSeries != PchUnknownSeries) {
+ return mPchSeries;
+ }
+
+ LpcBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+
+ LpcDeviceId = MmioRead16 (LpcBaseAddress + PCI_DEVICE_ID_OFFSET);
+
+ if (IS_PCH_LBG_LPC_DEVICE_ID (LpcDeviceId)) {
+ PchSeries = PchH;
+ } else if (IS_PCH_LP_LPC_DEVICE_ID (LpcDeviceId)) {
+ PchSeries = PchLp;
+ } else {
+ PchSeries = PchUnknownSeries;
+ DEBUG ((DEBUG_ERROR, "Unsupported PCH SKU, LpcDeviceId: 0x%04x!\n", LpcDeviceId));
+ ASSERT (FALSE);
+ }
+ mPchSeries = PchSeries;
+
+ return PchSeries;
+}
+
+/**
+ Return Pch Generation
+
+ @retval PCH_GENERATION Pch Generation
+**/
+PCH_GENERATION
+EFIAPI
+GetPchGeneration (
+ VOID
+ )
+{
+ UINT16 LpcDeviceId;
+ UINT32 PchGen;
+ UINTN LpcBaseAddress;
+
+ if (mPchGeneration != PchUnknownGeneration) {
+ return mPchGeneration;
+ }
+
+ LpcBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+ LpcDeviceId = MmioRead16 (LpcBaseAddress + PCI_DEVICE_ID_OFFSET);
+
+ if (IS_PCH_LBG_LPC_DEVICE_ID (LpcDeviceId)) {
+ PchGen = SklPch;
+ } else {
+ PchGen = PchUnknownGeneration;
+ DEBUG ((DEBUG_ERROR, "Unsupported PCH SKU, LpcDeviceId: 0x%04x!\n", LpcDeviceId));
+ ASSERT (FALSE);
+ }
+ mPchGeneration = PchGen;
+
+ return PchGen;
+}
+
+/**
+ Get Pch Maximum Pcie Root Port Number
+
+ @retval Pch Maximum Pcie Root Port Number
+**/
+UINT8
+EFIAPI
+GetPchMaxPciePortNum (
+ VOID
+ )
+{
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries ();
+ switch (PchSeries) {
+ case PchLp:
+ return PCH_LP_PCIE_MAX_ROOT_PORTS;
+
+ case PchH:
+ return PCH_H_PCIE_MAX_ROOT_PORTS;
+
+ default:
+ return 0;
+ }
+}
+
+
+/**
+ Get Pch Maximum Sata Port Number
+
+ @retval Pch Maximum Sata Port Number
+**/
+UINT8
+EFIAPI
+GetPchMaxSataPortNum (
+ VOID
+ )
+{
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries ();
+ switch (PchSeries) {
+ case PchLp:
+ return PCH_LP_AHCI_MAX_PORTS;
+
+ case PchH:
+ return PCH_H_AHCI_MAX_PORTS;
+
+ default:
+ return 0;
+ }
+}
+
+/**
+ Get Pch Usb Maximum Physical Port Number
+
+ @retval Pch Usb Maximum Physical Port Number
+**/
+UINT8
+EFIAPI
+GetPchUsbMaxPhysicalPortNum (
+ VOID
+ )
+{
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries ();
+ switch (PchSeries) {
+ case PchLp:
+ return PCH_LP_XHCI_MAX_USB2_PHYSICAL_PORTS;
+
+ case PchH:
+ return PCH_H_XHCI_MAX_USB2_PHYSICAL_PORTS;
+
+ default:
+ return 0;
+ }
+}
+
+/**
+ Get Pch Maximum Usb2 Port Number of XHCI Controller
+
+ @retval Pch Maximum Usb2 Port Number of XHCI Controller
+**/
+UINT8
+EFIAPI
+GetPchXhciMaxUsb2PortNum (
+ VOID
+ )
+{
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries ();
+ switch (PchSeries) {
+ case PchLp:
+ return PCH_LP_XHCI_MAX_USB2_PORTS;
+
+ case PchH:
+ return PCH_H_XHCI_MAX_USB2_PORTS;
+
+ default:
+ return 0;
+ }
+}
+
+/**
+ Get Pch Maximum Usb3 Port Number of XHCI Controller
+
+ @retval Pch Maximum Usb3 Port Number of XHCI Controller
+**/
+UINT8
+EFIAPI
+GetPchXhciMaxUsb3PortNum (
+ VOID
+ )
+{
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries ();
+ switch (PchSeries) {
+ case PchLp:
+ return PCH_LP_XHCI_MAX_USB3_PORTS;
+
+ case PchH:
+ return PCH_H_XHCI_MAX_USB3_PORTS;
+
+ default:
+ return 0;
+ }
+}
+
+/**
+ Determine if sSata controller is present or not
+
+ @param[in] None
+
+ @retval TRUE or FALSE
+**/
+BOOLEAN
+EFIAPI
+GetIsPchsSataPresent (
+ VOID
+ )
+{
+ UINT16 sSataDeviceId;
+ UINTN sSataBaseAddress;
+
+ sSataBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_EVA,
+ PCI_FUNCTION_NUMBER_PCH_SSATA
+ );
+
+ sSataDeviceId = MmioRead16 ( sSataBaseAddress + PCI_DEVICE_ID_OFFSET);
+
+ if (sSataDeviceId != 0xffff){
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/**
+ Get Pch Maximum sSata Controller Number
+
+ @param[in] None
+
+ @retval Pch Maximum sSata Controller Number
+**/
+
+UINT8
+EFIAPI
+GetPchMaxsSataPortNum (
+ VOID
+ )
+{
+ return PCH_SSATA_MAX_PORTS;
+}
+
+/**
+
+ Get Pch Maximum Sata Controller Number
+
+ @param[in] None
+
+ @retval Pch Maximum Sata Controller Number
+
+**/
+UINT8
+EFIAPI
+GetPchMaxsSataControllerNum (
+ VOID
+ )
+{
+ return PCH_SSATA_MAX_CONTROLLERS;
+}
+
+/**
+ Return Pch Lpc Device Id
+
+ @retval UINT16 Pch DeviceId
+**/
+UINT16
+EFIAPI
+GetPchLpcDeviceId (
+ VOID
+ )
+{
+ UINTN LpcBaseAddress;
+
+ if (mPchSeries != PchUnknownSeries) {
+ return mPchSeries;
+ }
+
+ LpcBaseAddress = mLpcBaseAddr;
+ if (LpcBaseAddress == 0) {
+ LpcBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+ mLpcBaseAddr = LpcBaseAddress;
+ }
+
+ return MmioRead16 (LpcBaseAddress + PCI_DEVICE_ID_OFFSET);
+}
+
diff --git a/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchInfoLib/PchInfoStrLib.c b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchInfoLib/PchInfoStrLib.c
new file mode 100644
index 0000000000..641277c083
--- /dev/null
+++ b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchInfoLib/PchInfoStrLib.c
@@ -0,0 +1,297 @@
+/** @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 <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MmPciBaseLib.h>
+#include <Library/PchInfoLib.h>
+#include <PchAccess.h>
+
+/**
+ Structure for PCH stepping string mapping
+**/
+struct PCH_STEPPING_STRING {
+ PCH_STEPPING Stepping;
+ CHAR8 *String;
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+struct PCH_STEPPING_STRING mSteppingStrs[] = {
+ {PchHA0, "A0"},
+ {PchHB0, "B0"},
+ {PchHC0, "C0"},
+ {PchHD0, "D0"},
+ {PchHD1, "D1"},
+#ifdef SIMICS_FLAG
+ {PchLpA0, "A0"},
+#endif
+ {PchLpB0, "B0"},
+ {PchLpB1, "B1"},
+ {PchLpC0, "C0"},
+ {PchLpC1, "C1"},
+ {LbgA0, "A0"},
+ {LbgB0, "B0"},
+ {LbgB1, "B1"},
+ {LbgB2, "B2"},
+ {LbgS0, "S0"},
+ {LbgS1, "S1"},
+ {PchSteppingMax, NULL}
+};
+
+/**
+ Structure for PCH series string mapping
+**/
+struct PCH_SERIES_STRING {
+ PCH_SERIES Series;
+ CHAR8 *String;
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+struct PCH_SERIES_STRING mSeriesStrs[] = {
+ {PchH, "SKL PCH-H"},
+ {PchLp, "SKL PCH-LP"},
+ {PchUnknownSeries, NULL}
+};
+
+/**
+ Structure for PCH sku string mapping
+**/
+struct PCH_SKU_STRING {
+ UINT16 Id;
+ CHAR8 *String;
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+struct PCH_SKU_STRING mSkuStrs[] = {
+ //
+ // SKL PCH H Desktop LPC Device IDs
+ //
+ {V_PCH_H_LPC_DEVICE_ID_DT_SUPER_SKU, "Super SKU"},
+ {V_PCH_H_LPC_DEVICE_ID_DT_0, "Super SKU (locked)"},
+ {V_PCH_H_LPC_DEVICE_ID_DT_1, "H110"},
+ {V_PCH_H_LPC_DEVICE_ID_DT_2, "H170"},
+ {V_PCH_H_LPC_DEVICE_ID_DT_3, "Z170"},
+ {V_PCH_H_LPC_DEVICE_ID_DT_4, "Q170"},
+ {V_PCH_H_LPC_DEVICE_ID_DT_5, "Q150"},
+ {V_PCH_H_LPC_DEVICE_ID_DT_6, "B150"},
+ {V_PCH_H_LPC_DEVICE_ID_UNFUSE, "Unfused SKU"},
+ //
+ // SKL PCH H Server/WS LPC Device IDs
+ //
+ {V_PCH_H_LPC_DEVICE_ID_SVR_0, "C236"},
+ {V_PCH_H_LPC_DEVICE_ID_SVR_1, "C232"},
+ {V_PCH_H_LPC_DEVICE_ID_SVR_2, "CM236"},
+ {V_PCH_H_LPC_DEVICE_ID_A14B, "Super SKU (Unlocked)"},
+ {V_PCH_LBG_LPC_DEVICE_ID_UNFUSED, "LBG Unfused SKU"},
+ {V_PCH_LBG_LPC_DEVICE_ID_SS_0, "LBG SuperSKU - 0"},
+ {V_PCH_LBG_LPC_DEVICE_ID_SS_4_SD, "LBG SuperSKU - 4/SD"},
+ {V_PCH_LBG_LPC_DEVICE_ID_SS_T80_NS, "LBG SuperSKU - T80/SD"},
+ {V_PCH_LBG_LPC_DEVICE_ID_SS_1G, "LBG SuperSKU - 1G"},
+ {V_PCH_LBG_LPC_DEVICE_ID_SS_T, "LBG SuperSKU - T"},
+ {V_PCH_LBG_LPC_DEVICE_ID_SS_L, "LBG SuperSKU - L"},
+ {V_PCH_LBG_PROD_LPC_DEVICE_ID_0, "LBG QS/PRQ - 0"},
+ {V_PCH_LBG_PROD_LPC_DEVICE_ID_1G, "LBG QS/PRQ - 1G"},
+ {V_PCH_LBG_PROD_LPC_DEVICE_ID_2, "LBG QS/PRQ - 2"},
+ {V_PCH_LBG_PROD_LPC_DEVICE_ID_4, "LBG QS/PRQ - 4"},
+ {V_PCH_LBG_PROD_LPC_DEVICE_ID_E, "LBG QS/PRQ - E"},
+ {V_PCH_LBG_PROD_LPC_DEVICE_ID_M, "LBG QS/PRQ - M"},
+ {V_PCH_LBG_PROD_LPC_DEVICE_ID_T, "LBG QS/PRQ - T"},
+ {V_PCH_LBG_PROD_LPC_DEVICE_ID_LP, "LBG QS/PRQ - LP"},
+ //
+ // SKL PCH H Mobile LPC Device IDs
+ //
+ {V_PCH_H_LPC_DEVICE_ID_MB_0, "QM170"},
+ {V_PCH_H_LPC_DEVICE_ID_MB_1, "HM170"},
+ {V_PCH_H_LPC_DEVICE_ID_MB_2, "QMS170"},
+ {V_PCH_H_LPC_DEVICE_ID_MB_SUPER_SKU, "Super SKU"},
+ //
+ // SKL PCH LP Mobile LPC Device IDs
+ //
+ {V_PCH_LP_LPC_DEVICE_ID_UNFUSE, "Unfused SKU"},
+ {V_PCH_LP_LPC_DEVICE_ID_MB_SUPER_SKU, "Super SKU"},
+ {V_PCH_LP_LPC_DEVICE_ID_MB_0, "Super SKU (locked)"},
+ {V_PCH_LP_LPC_DEVICE_ID_MB_1, "(U) Base SKU"},
+ {V_PCH_LP_LPC_DEVICE_ID_MB_2, "(Y) Premium SKU"},
+ {V_PCH_LP_LPC_DEVICE_ID_MB_3, "(U) Premium SKU"},
+ {0xFFFF, NULL}
+};
+
+/**
+ Get PCH stepping ASCII string
+ The return string is zero terminated.
+
+ @param [in] PchStep Pch stepping
+ @param [out] Buffer Output buffer of string
+ @param [in,out] BufferSize Size of input buffer,
+ and return required string size when buffer is too small.
+
+ @retval EFI_SUCCESS String copy successfully
+ @retval EFI_INVALID_PARAMETER The stepping is not supported, or parameters are NULL
+ @retval EFI_BUFFER_TOO_SMALL Input buffer size is too small
+**/
+EFI_STATUS
+PchGetSteppingStr (
+ IN PCH_STEPPING PchStep,
+ OUT CHAR8 *Buffer,
+ IN OUT UINT32 *BufferSize
+ )
+{
+ UINTN Index;
+ UINT32 StrLength;
+ CHAR8 *Str;
+ EFI_STATUS Status;
+
+ if ((Buffer == NULL) || (BufferSize == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (*BufferSize > 0) {
+ Buffer[0] = 0;
+ }
+
+ Str = NULL;
+ StrLength = 0;
+ for (Index = 0; mSteppingStrs[Index].Stepping != PchSteppingMax; Index++) {
+ if (PchStep == mSteppingStrs[Index].Stepping) {
+ StrLength = (UINT32) AsciiStrLen (mSteppingStrs[Index].String);
+ Str = mSteppingStrs[Index].String;
+ break;
+ }
+ }
+ if (StrLength == 0) {
+ // Unsupported Stepping
+ // ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ if (*BufferSize <= StrLength) {
+ *BufferSize = StrLength + 1;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ Status = AsciiStrCpyS (Buffer, *BufferSize, Str);
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+}
+
+/**
+ Get PCH series ASCII string
+ The return string is zero terminated.
+
+ @param [in] PchSeries Pch series
+ @param [out] Buffer Output buffer of string
+ @param [in,out] BufferSize Size of input buffer,
+ and return required string size when buffer is too small.
+
+ @retval EFI_SUCCESS String copy successfully
+ @retval EFI_INVALID_PARAMETER The series is not supported, or parameters are NULL
+ @retval EFI_BUFFER_TOO_SMALL Input buffer size is too small
+**/
+EFI_STATUS
+PchGetSeriesStr (
+ IN PCH_SERIES PchSeries,
+ OUT CHAR8 *Buffer,
+ IN OUT UINT32 *BufferSize
+ )
+{
+ UINTN Index;
+ UINT32 StrLength;
+ CHAR8 *Str;
+ EFI_STATUS Status;
+
+ if ((Buffer == NULL) || (BufferSize == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (*BufferSize > 0) {
+ Buffer[0] = 0;
+ }
+
+ Str = NULL;
+ StrLength = 0;
+ for (Index = 0; mSeriesStrs[Index].Series != PchUnknownSeries; Index++) {
+ if (PchSeries == mSeriesStrs[Index].Series) {
+ StrLength = (UINT32) AsciiStrLen (mSeriesStrs[Index].String);
+ Str = mSeriesStrs[Index].String;
+ break;
+ }
+ }
+ if (StrLength == 0) {
+ // Unsupported Series
+ // ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ if (*BufferSize <= StrLength) {
+ *BufferSize = StrLength + 1;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ Status = AsciiStrCpyS (Buffer, *BufferSize, Str);
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+}
+
+/**
+ Get PCH Sku ASCII string
+ The return string is zero terminated.
+
+ @param [in] LpcDid LPC device id
+ @param [out] Buffer Output buffer of string
+ @param [in,out] BufferSize Size of input buffer,
+ and return required string size when buffer is too small.
+
+ @retval EFI_SUCCESS String copy successfully
+ @retval EFI_INVALID_PARAMETER The series is not supported, or parameters are NULL
+ @retval EFI_BUFFER_TOO_SMALL Input buffer size is too small
+**/
+EFI_STATUS
+PchGetSkuStr (
+ IN UINT16 LpcDid,
+ OUT CHAR8 *Buffer,
+ IN OUT UINT32 *BufferSize
+ )
+{
+ UINTN Index;
+ UINT32 StrLength;
+ CHAR8 *Str;
+ EFI_STATUS Status;
+
+ if ((Buffer == NULL) || (BufferSize == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (*BufferSize > 0) {
+ Buffer[0] = 0;
+ }
+
+ Str = NULL;
+ StrLength = 0;
+ for (Index = 0; mSkuStrs[Index].Id != 0xFFFF; Index++) {
+ if (LpcDid == mSkuStrs[Index].Id) {
+ StrLength = (UINT32) AsciiStrLen (mSkuStrs[Index].String);
+ Str = mSkuStrs[Index].String;
+ }
+ }
+ if (StrLength == 0) {
+ // Unsupported Sku
+ // ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ if (*BufferSize <= StrLength) {
+ *BufferSize = StrLength + 1;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ Status = AsciiStrCpyS (Buffer, *BufferSize, Str);
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+}
diff --git a/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchInfoLib/PeiDxeSmmPchInfoLib.inf b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchInfoLib/PeiDxeSmmPchInfoLib.inf
new file mode 100644
index 0000000000..2b3fdeb495
--- /dev/null
+++ b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchInfoLib/PeiDxeSmmPchInfoLib.inf
@@ -0,0 +1,39 @@
+### @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 = 0x00010017
+ BASE_NAME = PeiDxeSmmPchInfoLib
+ FILE_GUID = D43F3086-1D7E-4FF5-AE6A-3B0E15B11329
+ VERSION_STRING = 1.0
+ MODULE_TYPE = BASE
+ LIBRARY_CLASS = PchInfoLib
+
+
+[LibraryClasses]
+ BaseLib
+ IoLib
+ DebugLib
+ MmPciLib
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ LewisburgPkg/PchRcPkg.dec #SERVER_BIOS
+ PurleyRcPkg/RcPkg.dec #SERVER_BIOS
+
+
+[Sources]
+ PchInfoLib.c
+ PchInfoStrLib.c