[edk2-devel] [PATCH] KabylakeOpenBoardPkg: Fixed system hang caused by MemoryTest.

Chiu, Chasel posted 1 patch 4 years, 11 months ago
Failed in applying to current master (apply log)
There is a newer version of this series
Platform/Intel/KabylakeOpenBoardPkg/FspWrapper/Library/PeiSiliconPolicyNotifyLib/PeiPreMemSiliconPolicyNotifyLib.c   | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Platform/Intel/KabylakeOpenBoardPkg/FspWrapper/Library/PeiSiliconPolicyUpdateLibFsp/PeiSaPolicyUpdatePreMem.c        |  17 ++++++++++++++---
Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardAcpiLib/DxeMultiBoardAcpiSupportLib.c                  |   4 ++--
Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardAcpiLib/SmmMultiBoardAcpiSupportLib.c                  |   6 +++---
Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/KabylakeRvp3SpdTable.c                         | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiBoardInitPreMemLib.c                        |   7 +++++--
Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiKabylakeRvp3Detect.c                        |  83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------
Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiKabylakeRvp3InitPreMemLib.c                 | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiMultiBoardInitPostMemLib.c                  |   4 ++--
Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiMultiBoardInitPreMemLib.c                   |   4 ++--
Platform/Intel/KabylakeOpenBoardPkg/Library/BaseEcLib/BaseEcLib.c                                                    | 339 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Platform/Intel/KabylakeOpenBoardPkg/FspWrapper/Library/PeiSiliconPolicyNotifyLib/PeiPreMemSiliconPolicyNotifyLib.inf |  43 +++++++++++++++++++++++++++++++++++++++++++
Platform/Intel/KabylakeOpenBoardPkg/FspWrapper/Library/PeiSiliconPolicyUpdateLibFsp/PeiSiliconPolicyUpdateLibFsp.inf |   9 ++++++++-
Platform/Intel/KabylakeOpenBoardPkg/Include/EcCommands.h                                                             |  44 ++++++++++++++++++++++++++++++++++++++++++++
Platform/Intel/KabylakeOpenBoardPkg/Include/Library/EcLib.h                                                          | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardAcpiLib/DxeBoardAcpiTableLib.inf                       |   8 ++++----
Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiBoardInitPreMemLib.inf                      |   3 ++-
Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiKabylakeRvp3InitLib.h                       |   4 +++-
Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiMultiBoardInitPreMemLib.inf                 |   3 ++-
Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/OpenBoardPkg.dsc                                                    |  12 ++++++++++--
Platform/Intel/KabylakeOpenBoardPkg/Library/BaseEcLib/BaseEcLib.inf                                                  |  29 +++++++++++++++++++++++++++++
21 files changed, 1022 insertions(+), 50 deletions(-)
[edk2-devel] [PATCH] KabylakeOpenBoardPkg: Fixed system hang caused by MemoryTest.
Posted by Chiu, Chasel 4 years, 11 months ago
From: "Chasel, Chiu" <chasel.chiu@intel.com>

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1550

OS hang due to non-existing memory reported as usable memory.
There are 2 different RVP3 boards and one with 4GB memory down
implementation while another one with 8GB. Since rest of the
configurations are exactly the same, board detection is added
to the same RVP3 BoardInitLib and only SPD policy assigned
differently.

This also fixed below 2 issues:
1. Fixed build failuire when PcdMultiBoardSupport == FALSE.
   (Wrong Pcd TokenSpace used in DxeBoardAcpiTableLib.inf)
2. Always failed to read SPD from DIMM because SpdAddressTable
   policy was not updated properly. Fixed by a notify callback
   when policy PPI installed.

Test: Verified both RVP3 boards can boot to Windows.

Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Michael Kubacki <michael.a.kubacki@intel.com>
Signed-off-by: Chasel Chiu <chasel.chiu@intel.com>
---
 Platform/Intel/KabylakeOpenBoardPkg/FspWrapper/Library/PeiSiliconPolicyNotifyLib/PeiPreMemSiliconPolicyNotifyLib.c   | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 Platform/Intel/KabylakeOpenBoardPkg/FspWrapper/Library/PeiSiliconPolicyUpdateLibFsp/PeiSaPolicyUpdatePreMem.c        |  17 ++++++++++++++---
 Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardAcpiLib/DxeMultiBoardAcpiSupportLib.c                  |   4 ++--
 Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardAcpiLib/SmmMultiBoardAcpiSupportLib.c                  |   6 +++---
 Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/KabylakeRvp3SpdTable.c                         | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiBoardInitPreMemLib.c                        |   7 +++++--
 Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiKabylakeRvp3Detect.c                        |  83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------
 Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiKabylakeRvp3InitPreMemLib.c                 | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
 Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiMultiBoardInitPostMemLib.c                  |   4 ++--
 Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiMultiBoardInitPreMemLib.c                   |   4 ++--
 Platform/Intel/KabylakeOpenBoardPkg/Library/BaseEcLib/BaseEcLib.c                                                    | 339 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 Platform/Intel/KabylakeOpenBoardPkg/FspWrapper/Library/PeiSiliconPolicyNotifyLib/PeiPreMemSiliconPolicyNotifyLib.inf |  43 +++++++++++++++++++++++++++++++++++++++++++
 Platform/Intel/KabylakeOpenBoardPkg/FspWrapper/Library/PeiSiliconPolicyUpdateLibFsp/PeiSiliconPolicyUpdateLibFsp.inf |   9 ++++++++-
 Platform/Intel/KabylakeOpenBoardPkg/Include/EcCommands.h                                                             |  44 ++++++++++++++++++++++++++++++++++++++++++++
 Platform/Intel/KabylakeOpenBoardPkg/Include/Library/EcLib.h                                                          | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardAcpiLib/DxeBoardAcpiTableLib.inf                       |   8 ++++----
 Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiBoardInitPreMemLib.inf                      |   3 ++-
 Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiKabylakeRvp3InitLib.h                       |   4 +++-
 Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiMultiBoardInitPreMemLib.inf                 |   3 ++-
 Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/OpenBoardPkg.dsc                                                    |  12 ++++++++++--
 Platform/Intel/KabylakeOpenBoardPkg/Library/BaseEcLib/BaseEcLib.inf                                                  |  29 +++++++++++++++++++++++++++++
 21 files changed, 1022 insertions(+), 50 deletions(-)

diff --git a/Platform/Intel/KabylakeOpenBoardPkg/FspWrapper/Library/PeiSiliconPolicyNotifyLib/PeiPreMemSiliconPolicyNotifyLib.c b/Platform/Intel/KabylakeOpenBoardPkg/FspWrapper/Library/PeiSiliconPolicyNotifyLib/PeiPreMemSiliconPolicyNotifyLib.c
new file mode 100644
index 0000000000..0fedd81cd0
--- /dev/null
+++ b/Platform/Intel/KabylakeOpenBoardPkg/FspWrapper/Library/PeiSiliconPolicyNotifyLib/PeiPreMemSiliconPolicyNotifyLib.c
@@ -0,0 +1,103 @@
+/** @file
+  This library implements constructor function to register notify call back
+  when policy PPI installed.
+
+Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <PiPei.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/SiPolicyLib.h>
+
+/**
+  Callback function to update policy when policy PPI installed.
+
+  @param[in] PeiServices          General purpose services available to every PEIM.
+  @param[in] NotifyDescriptor     The notification structure this PEIM registered on install.
+  @param[in] Ppi                  The memory discovered PPI.  Not used.
+
+  @retval EFI_SUCCESS             Succeeds.
+  @retval Others                  Error code returned by sub-functions.
+**/
+EFI_STATUS
+EFIAPI
+SiPreMemPolicyPpiNotify (
+  IN  EFI_PEI_SERVICES             **PeiServices,
+  IN  EFI_PEI_NOTIFY_DESCRIPTOR    *NotifyDescriptor,
+  IN  VOID                         *Ppi
+  )
+{
+  EFI_STATUS                  Status;
+  SI_PREMEM_POLICY_PPI        *SiPreMemPolicyPpi;
+  SA_MISC_PEI_PREMEM_CONFIG   *MiscPeiPreMemConfig;
+
+  DEBUG ((DEBUG_INFO, "SiPreMemPolicyPpiNotify() Start\n"));
+
+  Status = PeiServicesLocatePpi (
+             &gSiPreMemPolicyPpiGuid,
+             0,
+             NULL,
+             (VOID **)&SiPreMemPolicyPpi
+             );
+  ASSERT_EFI_ERROR (Status);
+  if (SiPreMemPolicyPpi != NULL) {
+    //
+    // Get requisite IP Config Blocks which needs to be used here
+    //
+    Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gSaMiscPeiPreMemConfigGuid, (VOID *) &MiscPeiPreMemConfig);
+    ASSERT_EFI_ERROR (Status);
+
+    //
+    // Update SpdAddressTable policy when it is installed.
+    //
+    if (MiscPeiPreMemConfig != NULL) {
+      MiscPeiPreMemConfig->SpdAddressTable[0] = PcdGet8 (PcdMrcSpdAddressTable0);
+      DEBUG ((DEBUG_INFO, "MiscPeiPreMemConfig->SpdAddressTable[0] 0x%x\n", MiscPeiPreMemConfig->SpdAddressTable[0]));
+      MiscPeiPreMemConfig->SpdAddressTable[1] = PcdGet8 (PcdMrcSpdAddressTable1);
+      DEBUG ((DEBUG_INFO, "MiscPeiPreMemConfig->SpdAddressTable[1] 0x%x\n", MiscPeiPreMemConfig->SpdAddressTable[1]));
+      MiscPeiPreMemConfig->SpdAddressTable[2] = PcdGet8 (PcdMrcSpdAddressTable2);
+      DEBUG ((DEBUG_INFO, "MiscPeiPreMemConfig->SpdAddressTable[2] 0x%x\n", MiscPeiPreMemConfig->SpdAddressTable[2]));
+      MiscPeiPreMemConfig->SpdAddressTable[3] = PcdGet8 (PcdMrcSpdAddressTable3);
+      DEBUG ((DEBUG_INFO, "MiscPeiPreMemConfig->SpdAddressTable[3] 0x%x\n", MiscPeiPreMemConfig->SpdAddressTable[3]));
+    }
+  }
+  return Status;
+}
+
+static EFI_PEI_NOTIFY_DESCRIPTOR  mSiPreMemPolicyPpiNotifyList[] = {
+  {
+    EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+    &gSiPreMemPolicyPpiGuid,
+    SiPreMemPolicyPpiNotify
+  }
+};
+
+/**
+  The library constructuor.
+  The function register a policy install notify callback.
+
+  @param[in]  ImageHandle       The firmware allocated handle for the UEFI image.
+  @param[in]  SystemTable       A pointer to the EFI system table.
+
+  @retval     EFI_SUCCESS       The function always return EFI_SUCCESS for now.
+                                It will ASSERT on error for debug version.
+**/
+EFI_STATUS
+EFIAPI
+PeiPreMemSiliconPolicyNotifyLibConstructor (
+  IN       EFI_PEI_FILE_HANDLE  FileHandle,
+  IN CONST EFI_PEI_SERVICES     **PeiServices
+  )
+{
+  EFI_STATUS                  Status;
+  //
+  // Register call back after PPI produced
+  //
+  Status = PeiServicesNotifyPpi (mSiPreMemPolicyPpiNotifyList);
+  ASSERT_EFI_ERROR (Status);
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/FspWrapper/Library/PeiSiliconPolicyUpdateLibFsp/PeiSaPolicyUpdatePreMem.c b/Platform/Intel/KabylakeOpenBoardPkg/FspWrapper/Library/PeiSiliconPolicyUpdateLibFsp/PeiSaPolicyUpdatePreMem.c
index 8f9ad901eb..f95f82a25c 100644
--- a/Platform/Intel/KabylakeOpenBoardPkg/FspWrapper/Library/PeiSiliconPolicyUpdateLibFsp/PeiSaPolicyUpdatePreMem.c
+++ b/Platform/Intel/KabylakeOpenBoardPkg/FspWrapper/Library/PeiSiliconPolicyUpdateLibFsp/PeiSaPolicyUpdatePreMem.c
@@ -1,7 +1,7 @@
 /** @file
 Do Platform Stage System Agent initialization.
 
-Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
@@ -39,8 +39,19 @@ PeiFspSaPolicyUpdatePreMem (
 {
   VOID                        *Buffer;
 
-  CopyMem((VOID *)(UINTN)FspmUpd->FspmConfig.MemorySpdPtr00, (VOID *)(UINTN)PcdGet32 (PcdMrcSpdData), PcdGet16 (PcdMrcSpdDataSize));
-  CopyMem((VOID *)(UINTN)FspmUpd->FspmConfig.MemorySpdPtr10, (VOID *)(UINTN)PcdGet32 (PcdMrcSpdData), PcdGet16 (PcdMrcSpdDataSize));
+  //
+  // If SpdAddressTable are not all 0, it means DIMM slots implemented and
+  // MemorySpdPtr* already updated by reading SPD from DIMM in SiliconPolicyInitPreMem.
+  //
+  // If SpdAddressTable all 0, this is memory down design and hardcoded SpdData
+  // should be applied to MemorySpdPtr*.
+  //
+  if ((PcdGet8 (PcdMrcSpdAddressTable0) == 0) && (PcdGet8 (PcdMrcSpdAddressTable1) == 0)
+      && (PcdGet8 (PcdMrcSpdAddressTable2) == 0) && (PcdGet8 (PcdMrcSpdAddressTable3) == 0)) {
+    DEBUG((DEBUG_INFO, "Override MemorySpdPtr...\n"));
+    CopyMem((VOID *)(UINTN)FspmUpd->FspmConfig.MemorySpdPtr00, (VOID *)(UINTN)PcdGet32 (PcdMrcSpdData), PcdGet16 (PcdMrcSpdDataSize));
+    CopyMem((VOID *)(UINTN)FspmUpd->FspmConfig.MemorySpdPtr10, (VOID *)(UINTN)PcdGet32 (PcdMrcSpdData), PcdGet16 (PcdMrcSpdDataSize));
+  }
 
   DEBUG((DEBUG_INFO, "Updating Dq Byte Map and DQS Byte Swizzling Settings...\n"));
   Buffer = (VOID *) (UINTN) PcdGet32 (PcdMrcDqByteMap);
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardAcpiLib/DxeMultiBoardAcpiSupportLib.c b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardAcpiLib/DxeMultiBoardAcpiSupportLib.c
index da488e097c..4da685d0ac 100644
--- a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardAcpiLib/DxeMultiBoardAcpiSupportLib.c
+++ b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardAcpiLib/DxeMultiBoardAcpiSupportLib.c
@@ -1,7 +1,7 @@
 /** @file
   Platform Hook Library instances
 
-Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
@@ -35,7 +35,7 @@ DxeKabylakeRvp3MultiBoardAcpiSupportLibConstructor (
   VOID
   )
 {
-  if (LibPcdGetSku () == BoardIdKabyLakeYLpddr3Rvp3) {
+  if ((LibPcdGetSku () == BoardIdKabyLakeYLpddr3Rvp3) || (LibPcdGetSku () == BoardIdSkylakeRvp3)) {
     return RegisterBoardAcpiTableFunc (&mKabylakeRvp3BoardAcpiTableFunc);
   }
   return EFI_SUCCESS;
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardAcpiLib/SmmMultiBoardAcpiSupportLib.c b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardAcpiLib/SmmMultiBoardAcpiSupportLib.c
index 91590d5278..4a120e14eb 100644
--- a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardAcpiLib/SmmMultiBoardAcpiSupportLib.c
+++ b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardAcpiLib/SmmMultiBoardAcpiSupportLib.c
@@ -1,7 +1,7 @@
 /** @file
   Platform Hook Library instances
 
-Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
@@ -73,8 +73,8 @@ SmmKabylakeRvp3MultiBoardAcpiSupportLibConstructor (
   VOID
   )
 {
-  if (LibPcdGetSku () == BoardIdKabyLakeYLpddr3Rvp3) {
-    return RegisterBoardAcpiEnableFunc (&mKabylakeRvp3BoardAcpiEnableFunc);
+   if ((LibPcdGetSku () == BoardIdKabyLakeYLpddr3Rvp3) || (LibPcdGetSku () == BoardIdSkylakeRvp3)) {
+     return RegisterBoardAcpiEnableFunc (&mKabylakeRvp3BoardAcpiEnableFunc);
   }
   return EFI_SUCCESS;
 }
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/KabylakeRvp3SpdTable.c b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/KabylakeRvp3SpdTable.c
index 3ac9adc466..e4ad785bda 100644
--- a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/KabylakeRvp3SpdTable.c
+++ b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/KabylakeRvp3SpdTable.c
@@ -1,7 +1,7 @@
 /** @file
   GPIO definition table for KabylakeRvp3
 
-Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
@@ -423,4 +423,119 @@ GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 mSpdLpddr32133[] = {
 };
 GLOBAL_REMOVE_IF_UNREFERENCED const UINT16 mSpdLpddr32133Size = sizeof (mSpdLpddr32133);
 
+/**
+  Hynix H9CCNNN8JTMLAR-NTM_178b_DDP LPDDR3, 4Gb die (128Mx32), x32
+  or Elpida  EDF8132A1MC-GD-F
+  or Samsung K4E8E304EB-EGCE
+  1600, 12-15-15-34
+  2 rank per channel, 2 SDRAMs per rank, 4x4Gb = 2GB total per channel
+**/
+GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 mSkylakeRvp3Spd[] = {
+  0x24,                                 ///< 0   Number of Serial PD Bytes Written / SPD Device Size
+  0x20,                                 ///< 1   SPD Revision
+  0x0F,                                 ///< 2   DRAM Device Type
+  0x0E,                                 ///< 3   Module Type
+  0x14,                                 ///< 4   SDRAM Density and Banks: 8 Banks, 4 Gb SDRAM density
+  0x11,                                 ///< 5   SDRAM Addressing: 14 Rows, 10 Columns
+  0x95,                                 ///< 6   SDRAM Package Type: DDP, 1 Channel per die, Signal Loading Matrix 1
+  0x00,                                 ///< 7   SDRAM Optional Features
+  0x00,                                 ///< 8   SDRAM Thermal and Refresh Options
+  0x00,                                 ///< 9   Other SDRAM Optional Features
+  0x00,                                 ///< 10  Reserved - must be coded as 0x00
+  0x03,                                 ///< 11  Module Nominal Voltage, VDD
+  0x0B,                                 ///< 12  Module Organization, SDRAM width: 32 bits, 2 Ranks
+  0x23,                                 ///< 13  Module Memory Bus Width: 2 channels, 64 bit channel bus width
+  0x00,                                 ///< 14  Module Thermal Sensor
+  0x00,                                 ///< 15  Extended Module Type
+  0x00,                                 ///< 16  Reserved - must be coded as 0x00
+  0x00,                                 ///< 17  Timebases
+  0x0A,                                 ///< 18  SDRAM Minimum Cycle Time (tCKmin)
+  0xFF,                                 ///< 19  SDRAM Minimum Cycle Time (tCKmax)
+  0x54,                                 ///< 20  CAS Latencies Supported, First Byte (tCk): 12 10 8
+  0x00,                                 ///< 21  CAS Latencies Supported, Second Byte
+  0x00,                                 ///< 22  CAS Latencies Supported, Third Byte
+  0x00,                                 ///< 23  CAS Latencies Supported, Fourth Byte
+  0x78,                                 ///< 24  Minimum CAS Latency Time (tAAmin)
+  0x00,                                 ///< 25  Read and Write Latency Set Options
+  0x90,                                 ///< 26  Minimum RAS# to CAS# Delay Time (tRCDmin)
+  0xA8,                                 ///< 27  Minimum Row Precharge Delay Time for all banks (tRPab)
+  0x90,                                 ///< 28  Minimum Row Precharge Delay Time per bank (tRPpb)
+  0x10,                                 ///< 29  Minimum Refresh Recovery Delay Time for all banks (tRFCab), Least Significant Byte
+  0x04,                                 ///< 30  Minimum Refresh Recovery Delay Time for all banks (tRFCab), Most Significant Byte
+  0xE0,                                 ///< 31  Minimum Refresh Recovery Delay Time for per bank (tRFCpb), Least Significant Byte
+  0x01,                                 ///< 32  Minimum Refresh Recovery Delay Time for per bank (tRFCpb), Most Significant Byte
+  0, 0, 0, 0, 0, 0, 0,                  ///< 33 - 39
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 40 - 49
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 50 - 59
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 60 - 69 Connector to SDRAM Bit Mapping
+  0, 0, 0, 0, 0, 0, 0, 0,               ///< 70 - 77 Connector to SDRAM Bit Mapping
+  0, 0,                                 ///< 78 - 79
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 80 - 89
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 90 - 99
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 100 - 109
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 110 - 119
+  0x00,                                 ///< 120 Fine Offset for Minimum Row Precharge Delay Time per bank (tRPpb)
+  0x00,                                 ///< 121 Fine Offset for Minimum Row Precharge Delay Time for all banks (tRPab)
+  0x00,                                 ///< 122 Fine Offset for Minimum RAS# to CAS# Delay Time (tRCDmin)
+  0x00,                                 ///< 123 Fine Offset for Minimum CAS Latency Time (tAAmin)
+  0x7F,                                 ///< 124 Fine Offset for SDRAM Minimum Cycle Time (tCKmax)
+  0x00,                                 ///< 125 Fine Offset for SDRAM Minimum Cycle Time (tCKmin)
+  0x00,                                 ///< 126 CRC A
+  0x00,                                 ///< 127 CRC B
+  0, 0,                                 ///< 128 - 129
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 130 - 139
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 140 - 149
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 150 - 159
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 160 - 169
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 170 - 179
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 180 - 189
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 190 - 199
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 200 - 209
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 210 - 219
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 220 - 229
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 230 - 239
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 240 - 249
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 250 - 259
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 260 - 269
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 270 - 279
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 280 - 289
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 290 - 299
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 300 - 309
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 310 - 319
+  0x00,                                 ///< 320 Module Manufacturer ID Code, Least Significant Byte
+  0x00,                                 ///< 321 Module Manufacturer ID Code, Most Significant Byte
+  0x00,                                 ///< 322 Module Manufacturing Location
+  0x00,                                 ///< 323 Module Manufacturing Date Year
+  0x00,                                 ///< 324 Module Manufacturing Date Week
+  0x55,                                 ///< 325 Module Serial Number A
+  0x00,                                 ///< 326 Module Serial Number B
+  0x00,                                 ///< 327 Module Serial Number C
+  0x00,                                 ///< 328 Module Serial Number D
+  0x20, 0x20, 0x20, 0x20, 0x20,         ///< 329 - 333 Module Part Number: Unused bytes coded as ASCII Blanks (0x20)
+  0x20, 0x20, 0x20, 0x20, 0x20,         ///< 334 - 338 Module Part Number
+  0x20, 0x20, 0x20, 0x20, 0x20,         ///< 339 - 343 Module Part Number
+  0x20, 0x20, 0x20, 0x20, 0x20,         ///< 344 - 348 Module Part Number
+  0x00,                                 ///< 349 Module Revision Code
+  0x00,                                 ///< 350 DRAM Manufacturer ID Code, Least Significant Byte
+  0x00,                                 ///< 351 DRAM Manufacturer ID Code, Most Significant Byte
+  0x00,                                 ///< 352 DRAM Stepping
+  0, 0, 0, 0, 0, 0, 0,                  ///< 353 - 359
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 360 - 369
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 370 - 379
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 380 - 389
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 390 - 399
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 400 - 409
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 410 - 419
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 420 - 429
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 430 - 439
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 440 - 449
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 450 - 459
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 460 - 469
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 470 - 479
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 480 - 489
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 490 - 499
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 500 - 509
+  0, 0                                  ///< 510 - 511
+};
+GLOBAL_REMOVE_IF_UNREFERENCED const UINT16 mSkylakeRvp3SpdSize = sizeof (mSkylakeRvp3Spd);
 #endif // _KABYLAKE_RVP3_SPD_TABLE_H_
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiBoardInitPreMemLib.c b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiBoardInitPreMemLib.c
index 69e0f50282..464f67e036 100644
--- a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiBoardInitPreMemLib.c
+++ b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiBoardInitPreMemLib.c
@@ -1,7 +1,7 @@
 /** @file
   Platform Hook Library instances
 
-Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
@@ -12,6 +12,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Library/BoardInitLib.h>
 #include <Library/PcdLib.h>
 #include <Library/DebugLib.h>
+#include <KabylakeRvp3Id.h>
 
 EFI_STATUS
 EFIAPI
@@ -72,7 +73,9 @@ BoardInitBeforeMemoryInit (
   VOID
   )
 {
-  KabylakeRvp3BoardInitBeforeMemoryInit ();
+  if ((LibPcdGetSku () == BoardIdKabyLakeYLpddr3Rvp3) || (LibPcdGetSku () == BoardIdSkylakeRvp3)) {
+    KabylakeRvp3BoardInitBeforeMemoryInit ();
+  }
   return EFI_SUCCESS;
 }
 
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiKabylakeRvp3Detect.c b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiKabylakeRvp3Detect.c
index 0f4ad61f0a..429f4316dd 100644
--- a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiKabylakeRvp3Detect.c
+++ b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiKabylakeRvp3Detect.c
@@ -1,6 +1,6 @@
 /** @file
 
-Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
@@ -33,14 +33,68 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 
 #include <ConfigBlock.h>
 #include <ConfigBlock/MemoryConfig.h>
+#include <Library/EcLib.h>
+#include <EcCommands.h>
 
-BOOLEAN
-IsKabylakeRvp3 (
-  VOID
+#define BOARD_ID_MASK_8BIT                  0xff
+
+/**
+  Get board fab ID.
+
+  @param[out] DataBuffer
+
+  @retval     EFI_SUCCESS       Command success
+  @retval     EFI_DEVICE_ERROR  Command error
+**/
+EFI_STATUS
+GetBoardFabId (
+  OUT UINT8       *DataBuffer
+  )
+{
+  UINT8   DataSize;
+
+  //
+  // For 'EC_C_FAB_ID' command NumberOfSendData = 0, NumberOfReceiveData =2.
+  //
+  DataSize = 2;
+  return (LpcEcInterface (EC_C_FAB_ID, &DataSize, DataBuffer));
+}
+
+/**
+  Get RVP3 board ID.
+  There are 2 different RVP3 boards having different ID.
+  This function will return board ID to caller.
+
+  @param[out] DataBuffer
+
+  @retval     EFI_SUCCESS       Command success
+  @retval     EFI_DEVICE_ERROR  Command error
+**/
+EFI_STATUS
+GetRvp3BoardId (
+  UINT8    *BoardId
   )
 {
-  // TBD: Do detection - BoardIdKabylakeRvp3 v.s. BoardIdKabyLakeYLpddr3Rvp3
-  return TRUE;
+  EFI_STATUS    Status;
+  UINT16        EcBoardInfo;
+  UINT8         DataBuffer[2];
+
+  Status = GetBoardFabId (DataBuffer);
+  if (Status == EFI_SUCCESS) {
+    EcBoardInfo = DataBuffer[0];
+    EcBoardInfo = (EcBoardInfo << 8) | DataBuffer[1];
+    //
+    // Get the following data:
+    // [7:0]  -  BOARD_IDx
+    // [8]    -  GEN_ID
+    // [11:9] -  REV_FAB_IDx
+    // [12]   -  TP_SPD_PRSNT
+    // [15:13] - BOM_IDx
+    //
+    *BoardId = (UINT8) (EcBoardInfo & BOARD_ID_MASK_8BIT);
+    DEBUG ((DEBUG_INFO, "BoardId = %X\n", *BoardId));
+  }
+  return Status;
 }
 
 EFI_STATUS
@@ -49,17 +103,22 @@ KabylakeRvp3BoardDetect (
   VOID
   )
 {
+  UINT8     BoardId;
+
   if (LibPcdGetSku () != 0) {
     return EFI_SUCCESS;
   }
 
-  DEBUG ((EFI_D_INFO, "KabylakeRvp3DetectionCallback\n"));
-
-  if (IsKabylakeRvp3 ()) {
-    LibPcdSetSku (BoardIdKabyLakeYLpddr3Rvp3);
-
+  DEBUG ((DEBUG_INFO, "KabylakeRvp3DetectionCallback\n"));
+  if (GetRvp3BoardId (&BoardId) == EFI_SUCCESS) {
+    if (BoardId == BoardIdKabyLakeYLpddr3Rvp3) {
+      LibPcdSetSku (BoardIdKabyLakeYLpddr3Rvp3);
+      ASSERT (LibPcdGetSku() == BoardIdKabyLakeYLpddr3Rvp3);
+    } else if (BoardId == BoardIdSkylakeRvp3) {
+      LibPcdSetSku (BoardIdSkylakeRvp3);
+      ASSERT (LibPcdGetSku() == BoardIdSkylakeRvp3);
+    }
     DEBUG ((DEBUG_INFO, "SKU_ID: 0x%x\n", LibPcdGetSku()));
-    ASSERT (LibPcdGetSku() == BoardIdKabyLakeYLpddr3Rvp3);
   }
   return EFI_SUCCESS;
 }
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiKabylakeRvp3InitPreMemLib.c b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiKabylakeRvp3InitPreMemLib.c
index 1667e29067..8f2e036356 100644
--- a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiKabylakeRvp3InitPreMemLib.c
+++ b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiKabylakeRvp3InitPreMemLib.c
@@ -1,6 +1,6 @@
 /** @file
 
-Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
@@ -80,30 +80,127 @@ KabylakeRvp3InitPreMem (
   //
   PcdSet8S (PcdSaMiscUserBd, 5);
 
-  PcdSet8S (PcdMrcSpdAddressTable0, 0xA2);
-  PcdSet8S (PcdMrcSpdAddressTable1, 0xA0);
-  PcdSet8S (PcdMrcSpdAddressTable2, 0xA2);
-  PcdSet8S (PcdMrcSpdAddressTable3, 0xA0);
-
   PcdSet32S (PcdMrcDqByteMap, (UINTN) mDqByteMapSklRvp3);
   PcdSet16S (PcdMrcDqByteMapSize, sizeof (mDqByteMapSklRvp3));
   PcdSet32S (PcdMrcDqsMapCpu2Dram, (UINTN) mDqsMapCpu2DramSklRvp3);
   PcdSet16S (PcdMrcDqsMapCpu2DramSize, sizeof (mDqsMapCpu2DramSklRvp3));
   PcdSet32S (PcdMrcRcompResistor, (UINTN) RcompResistorSklRvp1);
   PcdSet32S (PcdMrcRcompTarget, (UINTN) RcompTargetSklRvp1);
+  //
+  // Example policy for DIMM slots implementation boards:
+  // 1. Assign Smbus address of DIMMs and SpdData will be updated later
+  //    by reading from DIMM SPD.
+  // 2. No need to apply hardcoded SpdData buffers here for such board.
+  //   Example:
+  //   PcdMrcSpdAddressTable0 = 0xA0
+  //   PcdMrcSpdAddressTable1 = 0xA2
+  //   PcdMrcSpdAddressTable2 = 0xA4
+  //   PcdMrcSpdAddressTable3 = 0xA6
+  //   PcdMrcSpdData = 0
+  //   PcdMrcSpdDataSize = 0
+  //
+  // Kabylake RVP3 has 8GB Memory down implementation withouit SPD,
+  // So assign all SpdAddress to 0 and apply static SpdData buffers:
+  //   PcdMrcSpdAddressTable0 = 0
+  //   PcdMrcSpdAddressTable1 = 0
+  //   PcdMrcSpdAddressTable2 = 0
+  //   PcdMrcSpdAddressTable3 = 0
+  //   PcdMrcSpdData = static data buffer
+  //   PcdMrcSpdDataSize = sizeof (static data buffer)
+  //
+  PcdSet8S (PcdMrcSpdAddressTable0, 0);
+  PcdSet8S (PcdMrcSpdAddressTable1, 0);
+  PcdSet8S (PcdMrcSpdAddressTable2, 0);
+  PcdSet8S (PcdMrcSpdAddressTable3, 0);
+  PcdSet32S (PcdMrcSpdData, (UINTN) mSkylakeRvp3Spd110);
+  PcdSet16S (PcdMrcSpdDataSize, mSkylakeRvp3Spd110Size);
+
+  PcdSetBoolS (PcdIoExpanderPresent, TRUE);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  SkylaeA0Rvp3 board configuration init function for PEI pre-memory phase.
+
+  PEI_BOARD_CONFIG_PCD_INIT
+
+  @param  Content  pointer to the buffer contain init information for board init.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_INVALID_PARAMETER   The parameter is NULL.
+**/
+EFI_STATUS
+EFIAPI
+SkylakeRvp3InitPreMem (
+  VOID
+  )
+{
+  PcdSet32S (PcdPcie0WakeGpioNo, 0);
+  PcdSet8S  (PcdPcie0HoldRstExpanderNo, 0);
+  PcdSet32S (PcdPcie0HoldRstGpioNo, 8);
+  PcdSetBoolS (PcdPcie0HoldRstActive, TRUE);
+  PcdSet8S  (PcdPcie0PwrEnableExpanderNo, 0);
+  PcdSet32S (PcdPcie0PwrEnableGpioNo, 16);
+  PcdSetBoolS (PcdPcie0PwrEnableActive, FALSE);
+
+  //
+  // HSIO PTSS Table
+  //
+  PcdSet32S (PcdSpecificLpHsioPtssTable1,     (UINTN) PchLpHsioPtss_Bx_KabylakeRvp3);
+  PcdSet16S (PcdSpecificLpHsioPtssTable1Size, (UINTN) PchLpHsioPtss_Bx_KabylakeRvp3_Size);
+  PcdSet32S (PcdSpecificLpHsioPtssTable2,     (UINTN) PchLpHsioPtss_Cx_KabylakeRvp3);
+  PcdSet16S (PcdSpecificLpHsioPtssTable2Size, (UINTN) PchLpHsioPtss_Cx_KabylakeRvp3_Size);
+
+  //
+  // DRAM related definition
+  //
+  PcdSet8S (PcdSaMiscUserBd, 5);
 
-    PcdSet32S (PcdMrcSpdData, (UINTN) mSkylakeRvp3Spd110);
-    PcdSet16S (PcdMrcSpdDataSize, mSkylakeRvp3Spd110Size);
+  PcdSet32S (PcdMrcDqByteMap, (UINTN) mDqByteMapSklRvp3);
+  PcdSet16S (PcdMrcDqByteMapSize, sizeof (mDqByteMapSklRvp3));
+  PcdSet32S (PcdMrcDqsMapCpu2Dram, (UINTN) mDqsMapCpu2DramSklRvp3);
+  PcdSet16S (PcdMrcDqsMapCpu2DramSize, sizeof (mDqsMapCpu2DramSklRvp3));
+  PcdSet32S (PcdMrcRcompResistor, (UINTN) RcompResistorSklRvp1);
+  PcdSet32S (PcdMrcRcompTarget, (UINTN) RcompTargetSklRvp1);
+  //
+  // Example policy for DIMM slots implementation boards:
+  // 1. Assign Smbus address of DIMMs and SpdData will be updated later
+  //    by reading from DIMM SPD.
+  // 2. No need to apply hardcoded SpdData buffers here for such board.
+  //   Example:
+  //   PcdMrcSpdAddressTable0 = 0xA0
+  //   PcdMrcSpdAddressTable1 = 0xA2
+  //   PcdMrcSpdAddressTable2 = 0xA4
+  //   PcdMrcSpdAddressTable3 = 0xA6
+  //   PcdMrcSpdData = 0
+  //   PcdMrcSpdDataSize = 0
+  //
+  // Skylake RVP3 has 4GB Memory down implementation withouit SPD,
+  // So assign all SpdAddress to 0 and apply static SpdData buffers:
+  //   PcdMrcSpdAddressTable0 = 0
+  //   PcdMrcSpdAddressTable1 = 0
+  //   PcdMrcSpdAddressTable2 = 0
+  //   PcdMrcSpdAddressTable3 = 0
+  //   PcdMrcSpdData = static data buffer
+  //   PcdMrcSpdDataSize = sizeof (static data buffer)
+  //
+  PcdSet8S (PcdMrcSpdAddressTable0, 0);
+  PcdSet8S (PcdMrcSpdAddressTable1, 0);
+  PcdSet8S (PcdMrcSpdAddressTable2, 0);
+  PcdSet8S (PcdMrcSpdAddressTable3, 0);
+  PcdSet32S (PcdMrcSpdData, (UINTN) mSkylakeRvp3Spd);
+  PcdSet16S (PcdMrcSpdDataSize, mSkylakeRvp3SpdSize);
 
   PcdSetBoolS (PcdIoExpanderPresent, TRUE);
-  
+
   return EFI_SUCCESS;
 }
 
 #define SIO_RUNTIME_REG_BASE_ADDRESS                          0x0680
 
 /**
-  Configures GPIO
+  Configures GPIO.
 
   @param[in]  GpioTable       Point to Platform Gpio table
   @param[in]  GpioTableCount  Number of Gpio table entries
@@ -137,7 +234,7 @@ GpioInitPreMem (
 }
 
 /**
-  Configure Super IO
+  Configure Super IO.
 
 **/
 VOID
@@ -175,7 +272,7 @@ I2CGpioExpanderInitPreMem(
 }
 
 /**
-  Configure GPIO and SIO before memory ready
+  Configure GPIO and SIO before memory ready.
 
   @retval  EFI_SUCCESS   Operation success.
 **/
@@ -185,7 +282,11 @@ KabylakeRvp3BoardInitBeforeMemoryInit (
   VOID
   )
 {
-  KabylakeRvp3InitPreMem ();
+  if (LibPcdGetSku () == BoardIdKabyLakeYLpddr3Rvp3) {
+    KabylakeRvp3InitPreMem ();
+  } else if (LibPcdGetSku () == BoardIdSkylakeRvp3) {
+    SkylakeRvp3InitPreMem ();
+  }
 
   //
   // Configures the I2CGpioExpander
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiMultiBoardInitPostMemLib.c b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiMultiBoardInitPostMemLib.c
index 3778911610..cc800b552b 100644
--- a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiMultiBoardInitPostMemLib.c
+++ b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiMultiBoardInitPostMemLib.c
@@ -1,7 +1,7 @@
 /** @file
   Platform Hook Library instances
 
-Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
@@ -33,7 +33,7 @@ PeiKabylakeRvp3MultiBoardInitLibConstructor (
   VOID
   )
 {
-  if (LibPcdGetSku () == BoardIdKabyLakeYLpddr3Rvp3) {
+  if ((LibPcdGetSku () == BoardIdKabyLakeYLpddr3Rvp3) || (LibPcdGetSku () == BoardIdSkylakeRvp3)) {
     return RegisterBoardPostMemInit (&mKabylakeRvp3BoardInitFunc);
   }
   return EFI_SUCCESS;
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiMultiBoardInitPreMemLib.c b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiMultiBoardInitPreMemLib.c
index b8b161377e..843ae9890c 100644
--- a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiMultiBoardInitPreMemLib.c
+++ b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiMultiBoardInitPreMemLib.c
@@ -1,7 +1,7 @@
 /** @file
   Platform Hook Library instances
 
-Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
@@ -66,7 +66,7 @@ KabylakeRvp3MultiBoardDetect (
   )
 {
   KabylakeRvp3BoardDetect ();
-  if (LibPcdGetSku () == BoardIdKabyLakeYLpddr3Rvp3) {
+  if ((LibPcdGetSku () == BoardIdKabyLakeYLpddr3Rvp3) || (LibPcdGetSku () == BoardIdSkylakeRvp3)) {
     RegisterBoardPreMemInit (&mKabylakeRvp3BoardPreMemInitFunc);
   }
   return EFI_SUCCESS;
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/Library/BaseEcLib/BaseEcLib.c b/Platform/Intel/KabylakeOpenBoardPkg/Library/BaseEcLib/BaseEcLib.c
new file mode 100644
index 0000000000..643712affb
--- /dev/null
+++ b/Platform/Intel/KabylakeOpenBoardPkg/Library/BaseEcLib/BaseEcLib.c
@@ -0,0 +1,339 @@
+/** @file
+  Base EC library implementation for H/W layer.
+
+Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Uefi.h>
+#include <Library/EcLib.h>
+#include <Library/IoLib.h>
+#include <Library/TimerLib.h>
+#include <Library/DebugLib.h>
+
+#ifndef SLE_FLAG
+#ifndef STALL_ONE_MICRO_SECOND
+#define STALL_ONE_MICRO_SECOND  1
+#endif
+#ifndef STALL_ONE_MILLI_SECOND
+#define STALL_ONE_MILLI_SECOND  1000
+#endif
+#else // SLE FLAG
+#ifndef STALL_ONE_MICRO_SECOND
+#define STALL_ONE_MICRO_SECOND  0
+#endif
+#ifndef STALL_ONE_MILLI_SECOND
+#define STALL_ONE_MILLI_SECOND  0
+#endif
+#endif // SLE_FLAG
+
+#ifndef EC_INIT_TIME_OUT
+#define EC_INIT_TIME_OUT       0x200
+#endif
+
+typedef struct {
+  UINT8   CommandNumber;
+  UINT8   NumberOfSendData;
+  UINT8   NumberOfReceiveData;
+  BOOLEAN CommandImplemented;
+} EC_COMMAND_TABLE;
+
+EC_COMMAND_TABLE mEcCommand[] = {
+  {EC_C_FAB_ID                   , 0, 2, TRUE}   // Get the board fab ID in the lower 3 bits
+};
+
+//
+// Function implementations
+//
+/**
+  Sends command to EC.
+
+  @param[in] Command           Command byte to send
+  @param[in] Timeout           Timeout in microseonds
+
+  @retval    EFI_SUCCESS       Command success
+  @retval    EFI_DEVICE_ERROR  Command error
+  @retval    EFI_TIMEOUT       Command timeout
+**/
+EFI_STATUS
+SendEcCommandTimeout (
+  IN UINT8                  Command,
+  IN UINT32                 Timeout
+  )
+{
+  UINTN         Index;
+  UINT8         EcStatus;
+  UINT8         DiscardData;
+
+  Index = 0;
+  EcStatus = 0;
+  DiscardData = 0;
+  //
+  // Wait for EC to be ready (with a timeout)
+  //
+  ReceiveEcStatus (&EcStatus);
+  //
+  // Check if output buffer bit(OBF) is set.
+  // Read and discard the output buffer data so that next BIOS-EC cmd is in sync
+  // OBF is cleared by h/w after all data in output buffer is read by BIOS.
+  //
+  while ((EcStatus & EC_S_OBF) != 0) {
+    //
+    // Read EC data
+    //
+    DiscardData = IoRead8 (EC_D_PORT);
+    DEBUG ((DEBUG_INFO, "OBF is Set!! DiscardData Read 0x%02X\n", DiscardData));
+    ReceiveEcStatus (&EcStatus);
+  }
+  while (((EcStatus & EC_S_IBF) != 0) && (Index < Timeout)) {
+    MicroSecondDelay (15 * STALL_ONE_MICRO_SECOND);
+    ReceiveEcStatus (&EcStatus);
+    Index++;
+  }
+
+  if (Index >= Timeout) {
+    return EFI_TIMEOUT;
+  }
+
+  //Printing EC Command Sent
+  DEBUG ((DEBUG_INFO, "Sending EC Command: %02X\n", Command));
+
+  //
+  // Send the EC command
+  //
+  IoWrite8 (EC_C_PORT, Command);
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Sends command to EC.
+
+  @param[in] Command           Command byte to send
+
+  @retval    EFI_SUCCESS       Command success
+  @retval    EFI_DEVICE_ERROR  Command error
+  @retval    EFI_TIMEOUT       Command timeout
+**/
+EFI_STATUS
+SendEcCommand (
+  IN UINT8                  Command
+  )
+{
+  return SendEcCommandTimeout (Command, EC_TIME_OUT);
+}
+
+
+/**
+  Receives status from EC.
+
+  @param[out] EcStatus       Status byte to receive
+
+  @retval     EFI_SUCCESS
+  @retval     EFI_DEVICE_ERROR
+**/
+EFI_STATUS
+ReceiveEcStatus (
+  OUT UINT8                 *EcStatus
+  )
+{
+  //
+  // Read and return the status
+  //
+  *EcStatus = IoRead8 (EC_C_PORT);
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Sends data to EC.
+
+  @param[in] Data          Data byte to send
+
+  @retval    EFI_SUCCESS
+  @retval    EFI_DEVICE_ERROR
+**/
+EFI_STATUS
+SendEcData (
+  IN UINT8                 Data
+  )
+{
+  UINTN         Index;
+  UINT8         EcStatus;
+
+  Index = 0;
+
+  //
+  // Wait for EC to be ready (with a timeout)
+  //
+  ReceiveEcStatus (&EcStatus);
+  while (((EcStatus & EC_S_IBF) != 0) && (Index < EC_TIME_OUT)) {
+    MicroSecondDelay (15);
+    ReceiveEcStatus (&EcStatus);
+    Index++;
+  }
+  if (Index >= EC_TIME_OUT) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  //
+  //Printing EC Data Sent
+  //
+  DEBUG ((DEBUG_INFO, "Sending EC Data: %02X\n", Data));
+
+  //
+  // Send the data and return
+  //
+  IoWrite8 (EC_D_PORT, Data);
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Receives data from EC.
+
+  @param[out] Data              Data byte received
+  @param[in]  Timeout           Timeout in microseonds
+
+  @retval     EFI_SUCCESS       Read success
+  @retval     EFI_DEVICE_ERROR  Read error
+  @retval     EFI_TIMEOUT       Command timeout
+--*/
+EFI_STATUS
+ReceiveEcDataTimeout (
+  OUT UINT8                  *Data,
+  IN  UINT32                 Timeout
+ )
+{
+  UINTN         Index;
+  UINT8         EcStatus;
+
+  Index = 0;
+
+  //
+  // Wait for EC to be ready (with a timeout)
+  //
+  ReceiveEcStatus (&EcStatus);
+  while (((EcStatus & EC_S_OBF) == 0) && (Index < Timeout)) {
+    MicroSecondDelay (15 * STALL_ONE_MICRO_SECOND);
+    ReceiveEcStatus (&EcStatus);
+    Index++;
+  }
+
+  if (Index >= Timeout) {
+    return EFI_TIMEOUT;
+  }
+  //
+  // Read EC data and return
+  //
+  *Data = IoRead8 (EC_D_PORT);
+
+  //Printing EC Data Received
+  DEBUG ((DEBUG_INFO, "Receiving EC Data: %02X\n", *Data));
+
+  return EFI_SUCCESS;
+}
+/**
+  Receives data from EC.
+
+  @param[out] Data              Data byte received
+
+  @retval     EFI_SUCCESS       Read success
+  @retval     EFI_DEVICE_ERROR  Read error
+  @retval     EFI_TIMEOUT       Command timeout
+**/
+EFI_STATUS
+ReceiveEcData (
+  OUT UINT8                  *Data
+ )
+{
+  return ReceiveEcDataTimeout (Data, EC_TIME_OUT);
+}
+
+/**
+  Send data to EC through LPC interface.
+
+  @param[in]      Command     Command value to send to the EC
+  @param[in][out] DataSize    Size of data to send to the EC.
+                              If the command retuned data - size of buffer returned by the EC.
+                              Be aware of the DataSize must euqal to size of DataBuffer and cannot smaller
+                              than number of send data or number of receive data, whichever is the grater.
+  @param[in][out] DataBuffer  Pointer to the data buffer including data to be sent to the EC.
+                              If the command returned data - pointer to the buffer including the data.
+                              The buffer size should be the max of receive and transmit data.
+
+  @retval         EFI_SUCCESS Success
+  @retval         Other       Failed - EFI_TIMEOUT, EFI_INVALID_PARAMETER, EFI_UNSUPPORTED,
+                                       EFI_BUFFER_TOO_SMALL, etc.
+**/
+EFI_STATUS
+LpcEcInterface (
+  IN UINT8                     Command,
+  IN OUT UINT8                 *DataSize,
+  IN OUT UINT8                 *DataBuffer
+  )
+{
+  EFI_STATUS Status;
+  UINT8      NumberOfEcCommands;
+  UINT8      Index;
+  UINT8      TxDataIndex;
+  UINT8      RxDataIndex;
+  UINT8      MaxValue;
+
+  Status = EFI_SUCCESS;
+
+  NumberOfEcCommands = sizeof (mEcCommand) / sizeof (EC_COMMAND_TABLE);
+
+  for (Index = 0; Index < NumberOfEcCommands; Index++) {
+    if (Command != mEcCommand[Index].CommandNumber) {
+      continue;
+    }
+    if (mEcCommand[Index].CommandImplemented != TRUE) {
+      Status = EFI_UNSUPPORTED;
+      break;
+    }
+
+    if ((mEcCommand[Index].NumberOfSendData != 0) || (mEcCommand[Index].NumberOfReceiveData != 0)) {
+      if (DataSize == NULL || DataBuffer == NULL) {
+        Status = EFI_INVALID_PARAMETER;
+        break;
+      } else {
+        MaxValue = MAX (mEcCommand[Index].NumberOfSendData, mEcCommand[Index].NumberOfReceiveData);
+        if (*DataSize < MaxValue) {
+          Status = EFI_BUFFER_TOO_SMALL;
+          *DataSize = MaxValue;
+          break;
+        }
+      }
+    }
+
+    Status = SendEcCommand (Command);
+    if (EFI_ERROR (Status)) {
+      break;
+    }
+    if (mEcCommand[Index].NumberOfSendData != 0) {
+     for (TxDataIndex = 0; TxDataIndex < mEcCommand[Index].NumberOfSendData; TxDataIndex++) {
+        Status = SendEcData (DataBuffer[TxDataIndex]);
+        if (EFI_ERROR (Status)) {
+          break;
+        }
+      }
+    }
+    if (mEcCommand[Index].NumberOfReceiveData != 0) {
+      for (RxDataIndex = 0; RxDataIndex < mEcCommand[Index].NumberOfReceiveData; RxDataIndex++) {
+        Status = ReceiveEcData (&DataBuffer[RxDataIndex]);
+        if (EFI_ERROR (Status)) {
+          break;
+        }
+        *DataSize = RxDataIndex + 1;
+      }
+    }
+    break;
+  }
+  return Status;
+}
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/FspWrapper/Library/PeiSiliconPolicyNotifyLib/PeiPreMemSiliconPolicyNotifyLib.inf b/Platform/Intel/KabylakeOpenBoardPkg/FspWrapper/Library/PeiSiliconPolicyNotifyLib/PeiPreMemSiliconPolicyNotifyLib.inf
new file mode 100644
index 0000000000..13c12655f6
--- /dev/null
+++ b/Platform/Intel/KabylakeOpenBoardPkg/FspWrapper/Library/PeiSiliconPolicyNotifyLib/PeiPreMemSiliconPolicyNotifyLib.inf
@@ -0,0 +1,43 @@
+## @file
+# Component information file for Silicon Policy Notify Library.
+# This library implements constructor function to register notify call back
+# when policy PPI installed.
+#
+# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PeiPreMemSiliconPolicyNotifyLib
+  FILE_GUID                      = 6D231E12-C088-47C8-8B16-61F07293EEF8
+  MODULE_TYPE                    = PEIM
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = NULL
+  CONSTRUCTOR                    = PeiPreMemSiliconPolicyNotifyLibConstructor
+
+[LibraryClasses]
+  BaseLib
+
+[Packages]
+  MdePkg/MdePkg.dec
+  KabylakeOpenBoardPkg/OpenBoardPkg.dec
+  KabylakeSiliconPkg/SiPkg.dec
+
+[Sources]
+  PeiPreMemSiliconPolicyNotifyLib.c
+
+[Guids]
+  gSaMiscPeiPreMemConfigGuid
+
+[Ppis]
+  gSiPreMemPolicyPpiGuid
+
+[Pcd]
+  # SPD Address Table
+  gBoardModuleTokenSpaceGuid.PcdMrcSpdAddressTable0
+  gBoardModuleTokenSpaceGuid.PcdMrcSpdAddressTable1
+  gBoardModuleTokenSpaceGuid.PcdMrcSpdAddressTable2
+  gBoardModuleTokenSpaceGuid.PcdMrcSpdAddressTable3
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/FspWrapper/Library/PeiSiliconPolicyUpdateLibFsp/PeiSiliconPolicyUpdateLibFsp.inf b/Platform/Intel/KabylakeOpenBoardPkg/FspWrapper/Library/PeiSiliconPolicyUpdateLibFsp/PeiSiliconPolicyUpdateLibFsp.inf
index fa8d91e076..7ce6fd8470 100644
--- a/Platform/Intel/KabylakeOpenBoardPkg/FspWrapper/Library/PeiSiliconPolicyUpdateLibFsp/PeiSiliconPolicyUpdateLibFsp.inf
+++ b/Platform/Intel/KabylakeOpenBoardPkg/FspWrapper/Library/PeiSiliconPolicyUpdateLibFsp/PeiSiliconPolicyUpdateLibFsp.inf
@@ -1,7 +1,7 @@
 ## @file
 #  Provide FSP wrapper platform related function.
 #
-# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
 #
 # SPDX-License-Identifier: BSD-2-Clause-Patent
 #
@@ -94,6 +94,13 @@
   gBoardModuleTokenSpaceGuid.PcdMrcRcompTarget         ## CONSUMES
   gBoardModuleTokenSpaceGuid.PcdMrcDqByteMap           ## CONSUMES
   gBoardModuleTokenSpaceGuid.PcdMrcDqsMapCpu2Dram      ## CONSUMES
+
+  # SPD Address Table
+  gBoardModuleTokenSpaceGuid.PcdMrcSpdAddressTable0    ## CONSUMES
+  gBoardModuleTokenSpaceGuid.PcdMrcSpdAddressTable1    ## CONSUMES
+  gBoardModuleTokenSpaceGuid.PcdMrcSpdAddressTable2    ## CONSUMES
+  gBoardModuleTokenSpaceGuid.PcdMrcSpdAddressTable3    ## CONSUMES
+
   gBoardModuleTokenSpaceGuid.PcdMrcSpdData
   gBoardModuleTokenSpaceGuid.PcdMrcSpdDataSize
 
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/Include/EcCommands.h b/Platform/Intel/KabylakeOpenBoardPkg/Include/EcCommands.h
new file mode 100644
index 0000000000..be56d134ed
--- /dev/null
+++ b/Platform/Intel/KabylakeOpenBoardPkg/Include/EcCommands.h
@@ -0,0 +1,44 @@
+/** @file
+  Definition for supported EC commands.
+
+Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef EC_COMMANDS_H_
+#define EC_COMMANDS_H_
+
+//
+// Timeout if EC command/data fails
+//
+#define EC_TIME_OUT        0x20000
+
+//
+// The EC implements an embedded controller interface at ports 0x60/0x64 and a ACPI compliant
+// system management controller at ports 0x62/0x66. Port 0x66 is the command and status port,
+// port 0x62 is the data port.
+//
+#define EC_D_PORT        0x62
+#define EC_C_PORT        0x66
+
+//
+// Status Port 0x62
+//
+#define EC_S_OVR_TMP     0x80    // Current CPU temperature exceeds the threshold
+#define EC_S_SMI_EVT     0x40    // SMI event is pending
+#define EC_S_SCI_EVT     0x20    // SCI event is pending
+#define EC_S_BURST       0x10    // EC is in burst mode or normal mode
+#define EC_S_CMD         0x08    // Byte in data register is command/data
+#define EC_S_IGN         0x04    // Ignored
+#define EC_S_IBF         0x02    // Input buffer is full/empty
+#define EC_S_OBF         0x01    // Output buffer is full/empty
+
+//
+// EC commands that are issued to the EC through the command port (0x66).
+// New commands and command parameters should only be written by the host when IBF=0.
+// Data read from the EC data port is valid only when OBF=1.
+//
+#define EC_C_FAB_ID                    0x0D    // Get the board fab ID in the lower 3 bits
+
+#endif // EC_COMMANDS_H_
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/Include/Library/EcLib.h b/Platform/Intel/KabylakeOpenBoardPkg/Include/Library/EcLib.h
new file mode 100644
index 0000000000..04ce076f91
--- /dev/null
+++ b/Platform/Intel/KabylakeOpenBoardPkg/Include/Library/EcLib.h
@@ -0,0 +1,106 @@
+/** @file
+  EC library functions and definitions.
+
+  This library provides basic EC interface.
+
+  There may be different libraries for different environments (PEI, BS, RT, SMM).
+  Make sure you meet the requirements for the library (protocol dependencies, use
+  restrictions, etc).
+
+Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _BASE_EC_LIB_H_
+#define _BASE_EC_LIB_H_
+
+//
+// Include files
+//
+#include <Base.h>
+#include <Uefi.h>
+#include <EcCommands.h>
+
+//
+// Function declarations
+//
+/**
+  Send a command to the Keyboard System Controller.
+
+  @param[in] Command      Command byte to send
+
+  @retval    EFI_SUCCESS  Command success
+  @retval    EFI_TIMEOUT  Command timeout
+  @retval    Other        Command failed
+**/
+EFI_STATUS
+SendEcCommand (
+  IN UINT8   Command
+  );
+
+/**
+  Sends data to Keyboard System Controller.
+
+  @param[in] Data          Data byte to send
+
+  @retval    EFI_SUCCESS   Success
+  @retval    EFI_TIMEOUT   Timeout
+  @retval    Other         Failed
+**/
+EFI_STATUS
+SendEcData (
+  IN UINT8   Data
+  );
+
+/**
+  Receives data from Keyboard System Controller.
+
+  @param[out] Data          Data byte received
+
+  @retval     EFI_SUCCESS   Read success
+  @retval     EFI_TIMEOUT   Read timeout
+  @retval     Other         Read failed
+**/
+EFI_STATUS
+ReceiveEcData (
+  OUT UINT8   *Data
+  );
+
+/**
+  Receives status from Keyboard System Controller.
+
+  @param[out] Status       Status byte to receive
+
+  @retval     EFI_SUCCESS  Success
+  @retval     Other        Failed
+**/
+EFI_STATUS
+ReceiveEcStatus (
+  OUT UINT8   *EcStatus
+  );
+
+/**
+  Send data to EC through LPC interface.
+
+  @param[in]      Command     Command value to send to the EC
+  @param[in][out] DataSize    Size of data to send to the EC.
+                              If the command retuned data - size of buffer returned by the EC.
+                              Be aware of the DataSize must euqal to size of DataBuffer and cannot smaller
+                              than number of send data or number of receive data, whichever is the grater.
+  @param[in][out] DataBuffer  Pointer to the data buffer including data to be sent to the EC.
+                              If the command returned data - pointer to the buffer including the data.
+                              The buffer size should be the max of receive and transmit data.
+
+  @retval         EFI_SUCCESS Success
+  @retval         Other       Failed - EFI_TIMEOUT, EFI_INVALID_PARAMETER, EFI_UNSUPPORTED,
+                                       EFI_BUFFER_TOO_SMALL, etc.
+**/
+EFI_STATUS
+LpcEcInterface (
+  IN UINT8                     Command,
+  IN OUT UINT8                 *DataSize,
+  IN OUT UINT8                 *DataBuffer
+  );
+
+#endif
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardAcpiLib/DxeBoardAcpiTableLib.inf b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardAcpiLib/DxeBoardAcpiTableLib.inf
index f3fed024ec..dd971ef97a 100644
--- a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardAcpiLib/DxeBoardAcpiTableLib.inf
+++ b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardAcpiLib/DxeBoardAcpiTableLib.inf
@@ -1,7 +1,7 @@
 ### @file
 # Platform Hook Library instance for SandyBridge Mobile/Desktop CRB.
 #
-# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
 #
 # SPDX-License-Identifier: BSD-2-Clause-Patent
 #
@@ -36,9 +36,9 @@
 
 [Pcd]
   gBoardModuleTokenSpaceGuid.PcdPs2KbMsEnable
-  gMinPlatformPkgTokenSpaceGuid.PcdPciExpNative
-  gMinPlatformPkgTokenSpaceGuid.PcdNativeAspmEnable
-  gMinPlatformPkgTokenSpaceGuid.PcdLowPowerS0Idle
+  gBoardModuleTokenSpaceGuid.PcdPciExpNative
+  gBoardModuleTokenSpaceGuid.PcdNativeAspmEnable
+  gBoardModuleTokenSpaceGuid.PcdLowPowerS0Idle
   gBoardModuleTokenSpaceGuid.PcdAcpiGnvsAddress
   
 [Sources]
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiBoardInitPreMemLib.inf b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiBoardInitPreMemLib.inf
index 51f6787e4f..7be1c180de 100644
--- a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiBoardInitPreMemLib.inf
+++ b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiBoardInitPreMemLib.inf
@@ -1,7 +1,7 @@
 ## @file
 # Component information file for PEI KabylakeRvp3 Board Init Pre-Mem Library
 #
-# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
 #
 # SPDX-License-Identifier: BSD-2-Clause-Patent
 #
@@ -22,6 +22,7 @@
   MemoryAllocationLib
   PcdLib
   SiliconInitLib
+  EcLib
 
 [Packages]
   MinPlatformPkg/MinPlatformPkg.dec
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiKabylakeRvp3InitLib.h b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiKabylakeRvp3InitLib.h
index 1878b2c6bd..bd60720137 100644
--- a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiKabylakeRvp3InitLib.h
+++ b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiKabylakeRvp3InitLib.h
@@ -1,6 +1,6 @@
 /** @file
 
-Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
@@ -24,6 +24,8 @@ extern const UINT8 mDqByteMapSklRvp3[2][6][2];
 extern const UINT8 mDqsMapCpu2DramSklRvp3[2][8];
 extern const UINT8 mSkylakeRvp3Spd110[];
 extern const UINT16 mSkylakeRvp3Spd110Size;
+extern const UINT8 mSkylakeRvp3Spd[];
+extern const UINT16 mSkylakeRvp3SpdSize;
 extern HSIO_PTSS_TABLES PchLpHsioPtss_Bx_KabylakeRvp3[];
 extern UINT16 PchLpHsioPtss_Bx_KabylakeRvp3_Size;
 extern HSIO_PTSS_TABLES PchLpHsioPtss_Cx_KabylakeRvp3[];
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiMultiBoardInitPreMemLib.inf b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiMultiBoardInitPreMemLib.inf
index 25684b00d0..2d8d26d7a1 100644
--- a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiMultiBoardInitPreMemLib.inf
+++ b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/PeiMultiBoardInitPreMemLib.inf
@@ -1,7 +1,7 @@
 ## @file
 # Component information file for PEI KabylakeRvp3 Board Init Pre-Mem Library
 #
-# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
 #
 # SPDX-License-Identifier: BSD-2-Clause-Patent
 #
@@ -24,6 +24,7 @@
   PcdLib
   SiliconInitLib
   MultiBoardInitSupportLib
+  EcLib
 
 [Packages]
   MinPlatformPkg/MinPlatformPkg.dec
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/OpenBoardPkg.dsc b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/OpenBoardPkg.dsc
index 1bef21dd42..7f19ad1eed 100644
--- a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/OpenBoardPkg.dsc
+++ b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/OpenBoardPkg.dsc
@@ -1,7 +1,7 @@
 ## @file
 #  Platform description.
 #
-# Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
 #
 # SPDX-License-Identifier: BSD-2-Clause-Patent
 #
@@ -106,6 +106,8 @@
   TbtCommonLib|$(PLATFORM_BOARD_PACKAGE)/Features/Tbt/Library/PeiDxeSmmTbtCommonLib/TbtCommonLib.inf
   DxeTbtPolicyLib|$(PLATFORM_BOARD_PACKAGE)/Features/Tbt/Library/DxeTbtPolicyLib/DxeTbtPolicyLib.inf
 !endif
+  EcLib|$(PLATFORM_BOARD_PACKAGE)/Library/BaseEcLib/BaseEcLib.inf
+
 #
 # Silicon Init Package
 #
@@ -210,7 +212,13 @@
     <LibraryClasses>
       SiliconPolicyInitLib|$(PLATFORM_SI_PACKAGE)/Library/PeiSiliconPolicyInitLibDependency/PeiPreMemSiliconPolicyInitLibDependency.inf
   }
-  $(PLATFORM_PACKAGE)/PlatformInit/SiliconPolicyPei/SiliconPolicyPeiPreMem.inf
+  $(PLATFORM_PACKAGE)/PlatformInit/SiliconPolicyPei/SiliconPolicyPeiPreMem.inf {
+    <LibraryClasses>
+    #
+    # Hook a library constructor to update some policy fields when policy installed.
+    #
+    NULL|$(PLATFORM_BOARD_PACKAGE)/FspWrapper/Library/PeiSiliconPolicyNotifyLib/PeiPreMemSiliconPolicyNotifyLib.inf
+  }
   $(PLATFORM_PACKAGE)/PlatformInit/PlatformInitPei/PlatformInitPostMem.inf {
     <LibraryClasses>
 !if gBoardModuleTokenSpaceGuid.PcdMultiBoardSupport == FALSE
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/Library/BaseEcLib/BaseEcLib.inf b/Platform/Intel/KabylakeOpenBoardPkg/Library/BaseEcLib/BaseEcLib.inf
new file mode 100644
index 0000000000..c7de77d80f
--- /dev/null
+++ b/Platform/Intel/KabylakeOpenBoardPkg/Library/BaseEcLib/BaseEcLib.inf
@@ -0,0 +1,29 @@
+## @file
+# Component information file for base EC library
+#
+# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010017
+  BASE_NAME                      = BaseEcLib
+  FILE_GUID                      = 7FE22E12-889E-48D5-9F91-B7CBE265C94C
+  VERSION_STRING                 = 1.0
+  MODULE_TYPE                    = BASE
+  LIBRARY_CLASS                  = EcLib
+
+[LibraryClasses]
+  BaseLib
+  DebugLib
+  IoLib
+  TimerLib
+
+[Packages]
+  MdePkg/MdePkg.dec
+  KabylakeOpenBoardPkg/OpenBoardPkg.dec
+
+[Sources]
+  BaseEcLib.c
-- 
2.13.3.windows.1


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#41158): https://edk2.groups.io/g/devel/message/41158
Mute This Topic: https://groups.io/mt/31698291/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-

Re: [edk2-devel] [PATCH] KabylakeOpenBoardPkg: Fixed system hang caused by MemoryTest.
Posted by Kubacki, Michael A 4 years, 11 months ago
Please promote BaseEcLib to the "GenericBoardPkg" or whatever name is decided when created.
We can extend command and vendor support there in the future.

In BaseEcLib.c, remove SLE_FLAG usage and positive logic blocks.

Thanks,
Michael

> -----Original Message-----
> From: Chiu, Chasel
> Sent: Tuesday, May 21, 2019 8:52 AM
> To: devel@edk2.groups.io
> Cc: Chiu, Chasel <chasel.chiu@intel.com>; Desimone, Nathaniel L
> <nathaniel.l.desimone@intel.com>; Kubacki, Michael A
> <michael.a.kubacki@intel.com>
> Subject: [PATCH] KabylakeOpenBoardPkg: Fixed system hang caused by
> MemoryTest.
> 
> From: "Chasel, Chiu" <chasel.chiu@intel.com>
> 
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1550
> 
> OS hang due to non-existing memory reported as usable memory.
> There are 2 different RVP3 boards and one with 4GB memory down
> implementation while another one with 8GB. Since rest of the
> configurations are exactly the same, board detection is added
> to the same RVP3 BoardInitLib and only SPD policy assigned
> differently.
> 
> This also fixed below 2 issues:
> 1. Fixed build failuire when PcdMultiBoardSupport == FALSE.
>    (Wrong Pcd TokenSpace used in DxeBoardAcpiTableLib.inf)
> 2. Always failed to read SPD from DIMM because SpdAddressTable
>    policy was not updated properly. Fixed by a notify callback
>    when policy PPI installed.
> 
> Test: Verified both RVP3 boards can boot to Windows.
> 
> Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
> Cc: Michael Kubacki <michael.a.kubacki@intel.com>
> Signed-off-by: Chasel Chiu <chasel.chiu@intel.com>
> ---
> 
> Platform/Intel/KabylakeOpenBoardPkg/FspWrapper/Library/PeiSiliconPolicy
> NotifyLib/PeiPreMemSiliconPolicyNotifyLib.c   | 103
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++
> 
> Platform/Intel/KabylakeOpenBoardPkg/FspWrapper/Library/PeiSiliconPolicy
> UpdateLibFsp/PeiSaPolicyUpdatePreMem.c        |  17 ++++++++++++++---
> 
> Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardAcpiLib/
> DxeMultiBoardAcpiSupportLib.c                  |   4 ++--
> 
> Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardAcpiLib/
> SmmMultiBoardAcpiSupportLib.c                  |   6 +++---
> 
> Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/K
> abylakeRvp3SpdTable.c                         | 117
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++++++++++++++++++++++++++++++++++++++++++++++++++++-
> 
> Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/P
> eiBoardInitPreMemLib.c                        |   7 +++++--
> 
> Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/P
> eiKabylakeRvp3Detect.c                        |  83
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++------------
> 
> Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/P
> eiKabylakeRvp3InitPreMemLib.c                 | 127
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++++++++++++++++++++++++++++++++++++++++++++++++++-------------
> 
> Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/P
> eiMultiBoardInitPostMemLib.c                  |   4 ++--
> 
> Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/P
> eiMultiBoardInitPreMemLib.c                   |   4 ++--
>  Platform/Intel/KabylakeOpenBoardPkg/Library/BaseEcLib/BaseEcLib.c
> | 339
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++
> 
> Platform/Intel/KabylakeOpenBoardPkg/FspWrapper/Library/PeiSiliconPolicy
> NotifyLib/PeiPreMemSiliconPolicyNotifyLib.inf |  43
> +++++++++++++++++++++++++++++++++++++++++++
> 
> Platform/Intel/KabylakeOpenBoardPkg/FspWrapper/Library/PeiSiliconPolicy
> UpdateLibFsp/PeiSiliconPolicyUpdateLibFsp.inf |   9 ++++++++-
>  Platform/Intel/KabylakeOpenBoardPkg/Include/EcCommands.h
> |  44 ++++++++++++++++++++++++++++++++++++++++++++
>  Platform/Intel/KabylakeOpenBoardPkg/Include/Library/EcLib.h
> | 106
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++++++++++++++++++++++++++++++++++++++++++
> 
> Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardAcpiLib/
> DxeBoardAcpiTableLib.inf                       |   8 ++++----
> 
> Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/P
> eiBoardInitPreMemLib.inf                      |   3 ++-
> 
> Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/P
> eiKabylakeRvp3InitLib.h                       |   4 +++-
> 
> Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib/P
> eiMultiBoardInitPreMemLib.inf                 |   3 ++-
>  Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/OpenBoardPkg.dsc
> |  12 ++++++++++--
>  Platform/Intel/KabylakeOpenBoardPkg/Library/BaseEcLib/BaseEcLib.inf
> |  29 +++++++++++++++++++++++++++++
>  21 files changed, 1022 insertions(+), 50 deletions(-)
> 
> diff --git
> a/Platform/Intel/KabylakeOpenBoardPkg/FspWrapper/Library/PeiSiliconPolic
> yNotifyLib/PeiPreMemSiliconPolicyNotifyLib.c
> b/Platform/Intel/KabylakeOpenBoardPkg/FspWrapper/Library/PeiSiliconPoli
> cyNotifyLib/PeiPreMemSiliconPolicyNotifyLib.c
> new file mode 100644
> index 0000000000..0fedd81cd0
> --- /dev/null
> +++
> b/Platform/Intel/KabylakeOpenBoardPkg/FspWrapper/Library/PeiSiliconPoli
> cyNotifyLib/PeiPreMemSiliconPolicyNotifyLib.c
> @@ -0,0 +1,103 @@
> +/** @file
> +  This library implements constructor function to register notify call back
> +  when policy PPI installed.
> +
> +Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +#include <PiPei.h>
> +#include <Library/DebugLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/PeiServicesLib.h>
> +#include <Library/SiPolicyLib.h>
> +
> +/**
> +  Callback function to update policy when policy PPI installed.
> +
> +  @param[in] PeiServices          General purpose services available to every
> PEIM.
> +  @param[in] NotifyDescriptor     The notification structure this PEIM
> registered on install.
> +  @param[in] Ppi                  The memory discovered PPI.  Not used.
> +
> +  @retval EFI_SUCCESS             Succeeds.
> +  @retval Others                  Error code returned by sub-functions.
> +**/
> +EFI_STATUS
> +EFIAPI
> +SiPreMemPolicyPpiNotify (
> +  IN  EFI_PEI_SERVICES             **PeiServices,
> +  IN  EFI_PEI_NOTIFY_DESCRIPTOR    *NotifyDescriptor,
> +  IN  VOID                         *Ppi
> +  )
> +{
> +  EFI_STATUS                  Status;
> +  SI_PREMEM_POLICY_PPI        *SiPreMemPolicyPpi;
> +  SA_MISC_PEI_PREMEM_CONFIG   *MiscPeiPreMemConfig;
> +
> +  DEBUG ((DEBUG_INFO, "SiPreMemPolicyPpiNotify() Start\n"));
> +
> +  Status = PeiServicesLocatePpi (
> +             &gSiPreMemPolicyPpiGuid,
> +             0,
> +             NULL,
> +             (VOID **)&SiPreMemPolicyPpi
> +             );
> +  ASSERT_EFI_ERROR (Status);
> +  if (SiPreMemPolicyPpi != NULL) {
> +    //
> +    // Get requisite IP Config Blocks which needs to be used here
> +    //
> +    Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi,
> &gSaMiscPeiPreMemConfigGuid, (VOID *) &MiscPeiPreMemConfig);
> +    ASSERT_EFI_ERROR (Status);
> +
> +    //
> +    // Update SpdAddressTable policy when it is installed.
> +    //
> +    if (MiscPeiPreMemConfig != NULL) {
> +      MiscPeiPreMemConfig->SpdAddressTable[0] = PcdGet8
> (PcdMrcSpdAddressTable0);
> +      DEBUG ((DEBUG_INFO, "MiscPeiPreMemConfig->SpdAddressTable[0]
> 0x%x\n", MiscPeiPreMemConfig->SpdAddressTable[0]));
> +      MiscPeiPreMemConfig->SpdAddressTable[1] = PcdGet8
> (PcdMrcSpdAddressTable1);
> +      DEBUG ((DEBUG_INFO, "MiscPeiPreMemConfig->SpdAddressTable[1]
> 0x%x\n", MiscPeiPreMemConfig->SpdAddressTable[1]));
> +      MiscPeiPreMemConfig->SpdAddressTable[2] = PcdGet8
> (PcdMrcSpdAddressTable2);
> +      DEBUG ((DEBUG_INFO, "MiscPeiPreMemConfig->SpdAddressTable[2]
> 0x%x\n", MiscPeiPreMemConfig->SpdAddressTable[2]));
> +      MiscPeiPreMemConfig->SpdAddressTable[3] = PcdGet8
> (PcdMrcSpdAddressTable3);
> +      DEBUG ((DEBUG_INFO, "MiscPeiPreMemConfig->SpdAddressTable[3]
> 0x%x\n", MiscPeiPreMemConfig->SpdAddressTable[3]));
> +    }
> +  }
> +  return Status;
> +}
> +
> +static EFI_PEI_NOTIFY_DESCRIPTOR  mSiPreMemPolicyPpiNotifyList[] = {
> +  {
> +    EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK |
> EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
> +    &gSiPreMemPolicyPpiGuid,
> +    SiPreMemPolicyPpiNotify
> +  }
> +};
> +
> +/**
> +  The library constructuor.
> +  The function register a policy install notify callback.
> +
> +  @param[in]  ImageHandle       The firmware allocated handle for the UEFI
> image.
> +  @param[in]  SystemTable       A pointer to the EFI system table.
> +
> +  @retval     EFI_SUCCESS       The function always return EFI_SUCCESS for
> now.
> +                                It will ASSERT on error for debug version.
> +**/
> +EFI_STATUS
> +EFIAPI
> +PeiPreMemSiliconPolicyNotifyLibConstructor (
> +  IN       EFI_PEI_FILE_HANDLE  FileHandle,
> +  IN CONST EFI_PEI_SERVICES     **PeiServices
> +  )
> +{
> +  EFI_STATUS                  Status;
> +  //
> +  // Register call back after PPI produced
> +  //
> +  Status = PeiServicesNotifyPpi (mSiPreMemPolicyPpiNotifyList);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  return EFI_SUCCESS;
> +}
> diff --git
> a/Platform/Intel/KabylakeOpenBoardPkg/FspWrapper/Library/PeiSiliconPolic
> yUpdateLibFsp/PeiSaPolicyUpdatePreMem.c
> b/Platform/Intel/KabylakeOpenBoardPkg/FspWrapper/Library/PeiSiliconPoli
> cyUpdateLibFsp/PeiSaPolicyUpdatePreMem.c
> index 8f9ad901eb..f95f82a25c 100644
> ---
> a/Platform/Intel/KabylakeOpenBoardPkg/FspWrapper/Library/PeiSiliconPolic
> yUpdateLibFsp/PeiSaPolicyUpdatePreMem.c
> +++
> b/Platform/Intel/KabylakeOpenBoardPkg/FspWrapper/Library/PeiSiliconPoli
> cyUpdateLibFsp/PeiSaPolicyUpdatePreMem.c
> @@ -1,7 +1,7 @@
>  /** @file
>  Do Platform Stage System Agent initialization.
> 
> -Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
>  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  **/
> @@ -39,8 +39,19 @@ PeiFspSaPolicyUpdatePreMem (
>  {
>    VOID                        *Buffer;
> 
> -  CopyMem((VOID *)(UINTN)FspmUpd->FspmConfig.MemorySpdPtr00,
> (VOID *)(UINTN)PcdGet32 (PcdMrcSpdData), PcdGet16
> (PcdMrcSpdDataSize));
> -  CopyMem((VOID *)(UINTN)FspmUpd->FspmConfig.MemorySpdPtr10,
> (VOID *)(UINTN)PcdGet32 (PcdMrcSpdData), PcdGet16
> (PcdMrcSpdDataSize));
> +  //
> +  // If SpdAddressTable are not all 0, it means DIMM slots implemented and
> +  // MemorySpdPtr* already updated by reading SPD from DIMM in
> SiliconPolicyInitPreMem.
> +  //
> +  // If SpdAddressTable all 0, this is memory down design and hardcoded
> SpdData
> +  // should be applied to MemorySpdPtr*.
> +  //
> +  if ((PcdGet8 (PcdMrcSpdAddressTable0) == 0) && (PcdGet8
> (PcdMrcSpdAddressTable1) == 0)
> +      && (PcdGet8 (PcdMrcSpdAddressTable2) == 0) && (PcdGet8
> (PcdMrcSpdAddressTable3) == 0)) {
> +    DEBUG((DEBUG_INFO, "Override MemorySpdPtr...\n"));
> +    CopyMem((VOID *)(UINTN)FspmUpd->FspmConfig.MemorySpdPtr00,
> (VOID *)(UINTN)PcdGet32 (PcdMrcSpdData), PcdGet16
> (PcdMrcSpdDataSize));
> +    CopyMem((VOID *)(UINTN)FspmUpd->FspmConfig.MemorySpdPtr10,
> (VOID *)(UINTN)PcdGet32 (PcdMrcSpdData), PcdGet16
> (PcdMrcSpdDataSize));
> +  }
> 
>    DEBUG((DEBUG_INFO, "Updating Dq Byte Map and DQS Byte Swizzling
> Settings...\n"));
>    Buffer = (VOID *) (UINTN) PcdGet32 (PcdMrcDqByteMap);
> diff --git
> a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardAcpiLi
> b/DxeMultiBoardAcpiSupportLib.c
> b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardAcpiLi
> b/DxeMultiBoardAcpiSupportLib.c
> index da488e097c..4da685d0ac 100644
> ---
> a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardAcpiLi
> b/DxeMultiBoardAcpiSupportLib.c
> +++
> b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardAcpiLi
> b/DxeMultiBoardAcpiSupportLib.c
> @@ -1,7 +1,7 @@
>  /** @file
>    Platform Hook Library instances
> 
> -Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
>  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  **/
> @@ -35,7 +35,7 @@
> DxeKabylakeRvp3MultiBoardAcpiSupportLibConstructor (
>    VOID
>    )
>  {
> -  if (LibPcdGetSku () == BoardIdKabyLakeYLpddr3Rvp3) {
> +  if ((LibPcdGetSku () == BoardIdKabyLakeYLpddr3Rvp3) || (LibPcdGetSku ()
> == BoardIdSkylakeRvp3)) {
>      return RegisterBoardAcpiTableFunc
> (&mKabylakeRvp3BoardAcpiTableFunc);
>    }
>    return EFI_SUCCESS;
> diff --git
> a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardAcpiLi
> b/SmmMultiBoardAcpiSupportLib.c
> b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardAcpiLi
> b/SmmMultiBoardAcpiSupportLib.c
> index 91590d5278..4a120e14eb 100644
> ---
> a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardAcpiLi
> b/SmmMultiBoardAcpiSupportLib.c
> +++
> b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardAcpiLi
> b/SmmMultiBoardAcpiSupportLib.c
> @@ -1,7 +1,7 @@
>  /** @file
>    Platform Hook Library instances
> 
> -Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
>  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  **/
> @@ -73,8 +73,8 @@
> SmmKabylakeRvp3MultiBoardAcpiSupportLibConstructor (
>    VOID
>    )
>  {
> -  if (LibPcdGetSku () == BoardIdKabyLakeYLpddr3Rvp3) {
> -    return RegisterBoardAcpiEnableFunc
> (&mKabylakeRvp3BoardAcpiEnableFunc);
> +   if ((LibPcdGetSku () == BoardIdKabyLakeYLpddr3Rvp3) || (LibPcdGetSku ()
> == BoardIdSkylakeRvp3)) {
> +     return RegisterBoardAcpiEnableFunc
> (&mKabylakeRvp3BoardAcpiEnableFunc);
>    }
>    return EFI_SUCCESS;
>  }
> diff --git
> a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib
> /KabylakeRvp3SpdTable.c
> b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib
> /KabylakeRvp3SpdTable.c
> index 3ac9adc466..e4ad785bda 100644
> ---
> a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib
> /KabylakeRvp3SpdTable.c
> +++
> b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib
> /KabylakeRvp3SpdTable.c
> @@ -1,7 +1,7 @@
>  /** @file
>    GPIO definition table for KabylakeRvp3
> 
> -Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
>  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  **/
> @@ -423,4 +423,119 @@ GLOBAL_REMOVE_IF_UNREFERENCED const UINT8
> mSpdLpddr32133[] = {
>  };
>  GLOBAL_REMOVE_IF_UNREFERENCED const UINT16 mSpdLpddr32133Size =
> sizeof (mSpdLpddr32133);
> 
> +/**
> +  Hynix H9CCNNN8JTMLAR-NTM_178b_DDP LPDDR3, 4Gb die (128Mx32),
> x32
> +  or Elpida  EDF8132A1MC-GD-F
> +  or Samsung K4E8E304EB-EGCE
> +  1600, 12-15-15-34
> +  2 rank per channel, 2 SDRAMs per rank, 4x4Gb = 2GB total per channel
> +**/
> +GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 mSkylakeRvp3Spd[] = {
> +  0x24,                                 ///< 0   Number of Serial PD Bytes Written / SPD
> Device Size
> +  0x20,                                 ///< 1   SPD Revision
> +  0x0F,                                 ///< 2   DRAM Device Type
> +  0x0E,                                 ///< 3   Module Type
> +  0x14,                                 ///< 4   SDRAM Density and Banks: 8 Banks, 4 Gb
> SDRAM density
> +  0x11,                                 ///< 5   SDRAM Addressing: 14 Rows, 10 Columns
> +  0x95,                                 ///< 6   SDRAM Package Type: DDP, 1 Channel per
> die, Signal Loading Matrix 1
> +  0x00,                                 ///< 7   SDRAM Optional Features
> +  0x00,                                 ///< 8   SDRAM Thermal and Refresh Options
> +  0x00,                                 ///< 9   Other SDRAM Optional Features
> +  0x00,                                 ///< 10  Reserved - must be coded as 0x00
> +  0x03,                                 ///< 11  Module Nominal Voltage, VDD
> +  0x0B,                                 ///< 12  Module Organization, SDRAM width: 32
> bits, 2 Ranks
> +  0x23,                                 ///< 13  Module Memory Bus Width: 2 channels, 64
> bit channel bus width
> +  0x00,                                 ///< 14  Module Thermal Sensor
> +  0x00,                                 ///< 15  Extended Module Type
> +  0x00,                                 ///< 16  Reserved - must be coded as 0x00
> +  0x00,                                 ///< 17  Timebases
> +  0x0A,                                 ///< 18  SDRAM Minimum Cycle Time (tCKmin)
> +  0xFF,                                 ///< 19  SDRAM Minimum Cycle Time (tCKmax)
> +  0x54,                                 ///< 20  CAS Latencies Supported, First Byte (tCk):
> 12 10 8
> +  0x00,                                 ///< 21  CAS Latencies Supported, Second Byte
> +  0x00,                                 ///< 22  CAS Latencies Supported, Third Byte
> +  0x00,                                 ///< 23  CAS Latencies Supported, Fourth Byte
> +  0x78,                                 ///< 24  Minimum CAS Latency Time (tAAmin)
> +  0x00,                                 ///< 25  Read and Write Latency Set Options
> +  0x90,                                 ///< 26  Minimum RAS# to CAS# Delay Time
> (tRCDmin)
> +  0xA8,                                 ///< 27  Minimum Row Precharge Delay Time for
> all banks (tRPab)
> +  0x90,                                 ///< 28  Minimum Row Precharge Delay Time per
> bank (tRPpb)
> +  0x10,                                 ///< 29  Minimum Refresh Recovery Delay Time for
> all banks (tRFCab), Least Significant Byte
> +  0x04,                                 ///< 30  Minimum Refresh Recovery Delay Time for
> all banks (tRFCab), Most Significant Byte
> +  0xE0,                                 ///< 31  Minimum Refresh Recovery Delay Time for
> per bank (tRFCpb), Least Significant Byte
> +  0x01,                                 ///< 32  Minimum Refresh Recovery Delay Time for
> per bank (tRFCpb), Most Significant Byte
> +  0, 0, 0, 0, 0, 0, 0,                  ///< 33 - 39
> +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 40 - 49
> +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 50 - 59
> +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 60 - 69 Connector to SDRAM Bit Mapping
> +  0, 0, 0, 0, 0, 0, 0, 0,               ///< 70 - 77 Connector to SDRAM Bit Mapping
> +  0, 0,                                 ///< 78 - 79
> +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 80 - 89
> +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 90 - 99
> +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 100 - 109
> +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 110 - 119
> +  0x00,                                 ///< 120 Fine Offset for Minimum Row Precharge
> Delay Time per bank (tRPpb)
> +  0x00,                                 ///< 121 Fine Offset for Minimum Row Precharge
> Delay Time for all banks (tRPab)
> +  0x00,                                 ///< 122 Fine Offset for Minimum RAS# to CAS#
> Delay Time (tRCDmin)
> +  0x00,                                 ///< 123 Fine Offset for Minimum CAS Latency Time
> (tAAmin)
> +  0x7F,                                 ///< 124 Fine Offset for SDRAM Minimum Cycle
> Time (tCKmax)
> +  0x00,                                 ///< 125 Fine Offset for SDRAM Minimum Cycle
> Time (tCKmin)
> +  0x00,                                 ///< 126 CRC A
> +  0x00,                                 ///< 127 CRC B
> +  0, 0,                                 ///< 128 - 129
> +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 130 - 139
> +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 140 - 149
> +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 150 - 159
> +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 160 - 169
> +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 170 - 179
> +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 180 - 189
> +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 190 - 199
> +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 200 - 209
> +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 210 - 219
> +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 220 - 229
> +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 230 - 239
> +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 240 - 249
> +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 250 - 259
> +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 260 - 269
> +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 270 - 279
> +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 280 - 289
> +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 290 - 299
> +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 300 - 309
> +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 310 - 319
> +  0x00,                                 ///< 320 Module Manufacturer ID Code, Least
> Significant Byte
> +  0x00,                                 ///< 321 Module Manufacturer ID Code, Most
> Significant Byte
> +  0x00,                                 ///< 322 Module Manufacturing Location
> +  0x00,                                 ///< 323 Module Manufacturing Date Year
> +  0x00,                                 ///< 324 Module Manufacturing Date Week
> +  0x55,                                 ///< 325 Module Serial Number A
> +  0x00,                                 ///< 326 Module Serial Number B
> +  0x00,                                 ///< 327 Module Serial Number C
> +  0x00,                                 ///< 328 Module Serial Number D
> +  0x20, 0x20, 0x20, 0x20, 0x20,         ///< 329 - 333 Module Part Number:
> Unused bytes coded as ASCII Blanks (0x20)
> +  0x20, 0x20, 0x20, 0x20, 0x20,         ///< 334 - 338 Module Part Number
> +  0x20, 0x20, 0x20, 0x20, 0x20,         ///< 339 - 343 Module Part Number
> +  0x20, 0x20, 0x20, 0x20, 0x20,         ///< 344 - 348 Module Part Number
> +  0x00,                                 ///< 349 Module Revision Code
> +  0x00,                                 ///< 350 DRAM Manufacturer ID Code, Least
> Significant Byte
> +  0x00,                                 ///< 351 DRAM Manufacturer ID Code, Most
> Significant Byte
> +  0x00,                                 ///< 352 DRAM Stepping
> +  0, 0, 0, 0, 0, 0, 0,                  ///< 353 - 359
> +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 360 - 369
> +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 370 - 379
> +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 380 - 389
> +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 390 - 399
> +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 400 - 409
> +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 410 - 419
> +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 420 - 429
> +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 430 - 439
> +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 440 - 449
> +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 450 - 459
> +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 460 - 469
> +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 470 - 479
> +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 480 - 489
> +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 490 - 499
> +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         ///< 500 - 509
> +  0, 0                                  ///< 510 - 511
> +};
> +GLOBAL_REMOVE_IF_UNREFERENCED const UINT16 mSkylakeRvp3SpdSize =
> sizeof (mSkylakeRvp3Spd);
>  #endif // _KABYLAKE_RVP3_SPD_TABLE_H_
> diff --git
> a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib
> /PeiBoardInitPreMemLib.c
> b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib
> /PeiBoardInitPreMemLib.c
> index 69e0f50282..464f67e036 100644
> ---
> a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib
> /PeiBoardInitPreMemLib.c
> +++
> b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib
> /PeiBoardInitPreMemLib.c
> @@ -1,7 +1,7 @@
>  /** @file
>    Platform Hook Library instances
> 
> -Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
>  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  **/
> @@ -12,6 +12,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
>  #include <Library/BoardInitLib.h>
>  #include <Library/PcdLib.h>
>  #include <Library/DebugLib.h>
> +#include <KabylakeRvp3Id.h>
> 
>  EFI_STATUS
>  EFIAPI
> @@ -72,7 +73,9 @@ BoardInitBeforeMemoryInit (
>    VOID
>    )
>  {
> -  KabylakeRvp3BoardInitBeforeMemoryInit ();
> +  if ((LibPcdGetSku () == BoardIdKabyLakeYLpddr3Rvp3) || (LibPcdGetSku ()
> == BoardIdSkylakeRvp3)) {
> +    KabylakeRvp3BoardInitBeforeMemoryInit ();
> +  }
>    return EFI_SUCCESS;
>  }
> 
> diff --git
> a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib
> /PeiKabylakeRvp3Detect.c
> b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib
> /PeiKabylakeRvp3Detect.c
> index 0f4ad61f0a..429f4316dd 100644
> ---
> a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib
> /PeiKabylakeRvp3Detect.c
> +++
> b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib
> /PeiKabylakeRvp3Detect.c
> @@ -1,6 +1,6 @@
>  /** @file
> 
> -Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
>  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  **/
> @@ -33,14 +33,68 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  #include <ConfigBlock.h>
>  #include <ConfigBlock/MemoryConfig.h>
> +#include <Library/EcLib.h>
> +#include <EcCommands.h>
> 
> -BOOLEAN
> -IsKabylakeRvp3 (
> -  VOID
> +#define BOARD_ID_MASK_8BIT                  0xff
> +
> +/**
> +  Get board fab ID.
> +
> +  @param[out] DataBuffer
> +
> +  @retval     EFI_SUCCESS       Command success
> +  @retval     EFI_DEVICE_ERROR  Command error
> +**/
> +EFI_STATUS
> +GetBoardFabId (
> +  OUT UINT8       *DataBuffer
> +  )
> +{
> +  UINT8   DataSize;
> +
> +  //
> +  // For 'EC_C_FAB_ID' command NumberOfSendData = 0,
> NumberOfReceiveData =2.
> +  //
> +  DataSize = 2;
> +  return (LpcEcInterface (EC_C_FAB_ID, &DataSize, DataBuffer));
> +}
> +
> +/**
> +  Get RVP3 board ID.
> +  There are 2 different RVP3 boards having different ID.
> +  This function will return board ID to caller.
> +
> +  @param[out] DataBuffer
> +
> +  @retval     EFI_SUCCESS       Command success
> +  @retval     EFI_DEVICE_ERROR  Command error
> +**/
> +EFI_STATUS
> +GetRvp3BoardId (
> +  UINT8    *BoardId
>    )
>  {
> -  // TBD: Do detection - BoardIdKabylakeRvp3 v.s.
> BoardIdKabyLakeYLpddr3Rvp3
> -  return TRUE;
> +  EFI_STATUS    Status;
> +  UINT16        EcBoardInfo;
> +  UINT8         DataBuffer[2];
> +
> +  Status = GetBoardFabId (DataBuffer);
> +  if (Status == EFI_SUCCESS) {
> +    EcBoardInfo = DataBuffer[0];
> +    EcBoardInfo = (EcBoardInfo << 8) | DataBuffer[1];
> +    //
> +    // Get the following data:
> +    // [7:0]  -  BOARD_IDx
> +    // [8]    -  GEN_ID
> +    // [11:9] -  REV_FAB_IDx
> +    // [12]   -  TP_SPD_PRSNT
> +    // [15:13] - BOM_IDx
> +    //
> +    *BoardId = (UINT8) (EcBoardInfo & BOARD_ID_MASK_8BIT);
> +    DEBUG ((DEBUG_INFO, "BoardId = %X\n", *BoardId));
> +  }
> +  return Status;
>  }
> 
>  EFI_STATUS
> @@ -49,17 +103,22 @@ KabylakeRvp3BoardDetect (
>    VOID
>    )
>  {
> +  UINT8     BoardId;
> +
>    if (LibPcdGetSku () != 0) {
>      return EFI_SUCCESS;
>    }
> 
> -  DEBUG ((EFI_D_INFO, "KabylakeRvp3DetectionCallback\n"));
> -
> -  if (IsKabylakeRvp3 ()) {
> -    LibPcdSetSku (BoardIdKabyLakeYLpddr3Rvp3);
> -
> +  DEBUG ((DEBUG_INFO, "KabylakeRvp3DetectionCallback\n"));
> +  if (GetRvp3BoardId (&BoardId) == EFI_SUCCESS) {
> +    if (BoardId == BoardIdKabyLakeYLpddr3Rvp3) {
> +      LibPcdSetSku (BoardIdKabyLakeYLpddr3Rvp3);
> +      ASSERT (LibPcdGetSku() == BoardIdKabyLakeYLpddr3Rvp3);
> +    } else if (BoardId == BoardIdSkylakeRvp3) {
> +      LibPcdSetSku (BoardIdSkylakeRvp3);
> +      ASSERT (LibPcdGetSku() == BoardIdSkylakeRvp3);
> +    }
>      DEBUG ((DEBUG_INFO, "SKU_ID: 0x%x\n", LibPcdGetSku()));
> -    ASSERT (LibPcdGetSku() == BoardIdKabyLakeYLpddr3Rvp3);
>    }
>    return EFI_SUCCESS;
>  }
> diff --git
> a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib
> /PeiKabylakeRvp3InitPreMemLib.c
> b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib
> /PeiKabylakeRvp3InitPreMemLib.c
> index 1667e29067..8f2e036356 100644
> ---
> a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib
> /PeiKabylakeRvp3InitPreMemLib.c
> +++
> b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib
> /PeiKabylakeRvp3InitPreMemLib.c
> @@ -1,6 +1,6 @@
>  /** @file
> 
> -Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
>  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  **/
> @@ -80,30 +80,127 @@ KabylakeRvp3InitPreMem (
>    //
>    PcdSet8S (PcdSaMiscUserBd, 5);
> 
> -  PcdSet8S (PcdMrcSpdAddressTable0, 0xA2);
> -  PcdSet8S (PcdMrcSpdAddressTable1, 0xA0);
> -  PcdSet8S (PcdMrcSpdAddressTable2, 0xA2);
> -  PcdSet8S (PcdMrcSpdAddressTable3, 0xA0);
> -
>    PcdSet32S (PcdMrcDqByteMap, (UINTN) mDqByteMapSklRvp3);
>    PcdSet16S (PcdMrcDqByteMapSize, sizeof (mDqByteMapSklRvp3));
>    PcdSet32S (PcdMrcDqsMapCpu2Dram, (UINTN)
> mDqsMapCpu2DramSklRvp3);
>    PcdSet16S (PcdMrcDqsMapCpu2DramSize, sizeof
> (mDqsMapCpu2DramSklRvp3));
>    PcdSet32S (PcdMrcRcompResistor, (UINTN) RcompResistorSklRvp1);
>    PcdSet32S (PcdMrcRcompTarget, (UINTN) RcompTargetSklRvp1);
> +  //
> +  // Example policy for DIMM slots implementation boards:
> +  // 1. Assign Smbus address of DIMMs and SpdData will be updated later
> +  //    by reading from DIMM SPD.
> +  // 2. No need to apply hardcoded SpdData buffers here for such board.
> +  //   Example:
> +  //   PcdMrcSpdAddressTable0 = 0xA0
> +  //   PcdMrcSpdAddressTable1 = 0xA2
> +  //   PcdMrcSpdAddressTable2 = 0xA4
> +  //   PcdMrcSpdAddressTable3 = 0xA6
> +  //   PcdMrcSpdData = 0
> +  //   PcdMrcSpdDataSize = 0
> +  //
> +  // Kabylake RVP3 has 8GB Memory down implementation withouit SPD,
> +  // So assign all SpdAddress to 0 and apply static SpdData buffers:
> +  //   PcdMrcSpdAddressTable0 = 0
> +  //   PcdMrcSpdAddressTable1 = 0
> +  //   PcdMrcSpdAddressTable2 = 0
> +  //   PcdMrcSpdAddressTable3 = 0
> +  //   PcdMrcSpdData = static data buffer
> +  //   PcdMrcSpdDataSize = sizeof (static data buffer)
> +  //
> +  PcdSet8S (PcdMrcSpdAddressTable0, 0);
> +  PcdSet8S (PcdMrcSpdAddressTable1, 0);
> +  PcdSet8S (PcdMrcSpdAddressTable2, 0);
> +  PcdSet8S (PcdMrcSpdAddressTable3, 0);
> +  PcdSet32S (PcdMrcSpdData, (UINTN) mSkylakeRvp3Spd110);
> +  PcdSet16S (PcdMrcSpdDataSize, mSkylakeRvp3Spd110Size);
> +
> +  PcdSetBoolS (PcdIoExpanderPresent, TRUE);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  SkylaeA0Rvp3 board configuration init function for PEI pre-memory phase.
> +
> +  PEI_BOARD_CONFIG_PCD_INIT
> +
> +  @param  Content  pointer to the buffer contain init information for board
> init.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_INVALID_PARAMETER   The parameter is NULL.
> +**/
> +EFI_STATUS
> +EFIAPI
> +SkylakeRvp3InitPreMem (
> +  VOID
> +  )
> +{
> +  PcdSet32S (PcdPcie0WakeGpioNo, 0);
> +  PcdSet8S  (PcdPcie0HoldRstExpanderNo, 0);
> +  PcdSet32S (PcdPcie0HoldRstGpioNo, 8);
> +  PcdSetBoolS (PcdPcie0HoldRstActive, TRUE);
> +  PcdSet8S  (PcdPcie0PwrEnableExpanderNo, 0);
> +  PcdSet32S (PcdPcie0PwrEnableGpioNo, 16);
> +  PcdSetBoolS (PcdPcie0PwrEnableActive, FALSE);
> +
> +  //
> +  // HSIO PTSS Table
> +  //
> +  PcdSet32S (PcdSpecificLpHsioPtssTable1,     (UINTN)
> PchLpHsioPtss_Bx_KabylakeRvp3);
> +  PcdSet16S (PcdSpecificLpHsioPtssTable1Size, (UINTN)
> PchLpHsioPtss_Bx_KabylakeRvp3_Size);
> +  PcdSet32S (PcdSpecificLpHsioPtssTable2,     (UINTN)
> PchLpHsioPtss_Cx_KabylakeRvp3);
> +  PcdSet16S (PcdSpecificLpHsioPtssTable2Size, (UINTN)
> PchLpHsioPtss_Cx_KabylakeRvp3_Size);
> +
> +  //
> +  // DRAM related definition
> +  //
> +  PcdSet8S (PcdSaMiscUserBd, 5);
> 
> -    PcdSet32S (PcdMrcSpdData, (UINTN) mSkylakeRvp3Spd110);
> -    PcdSet16S (PcdMrcSpdDataSize, mSkylakeRvp3Spd110Size);
> +  PcdSet32S (PcdMrcDqByteMap, (UINTN) mDqByteMapSklRvp3);
> +  PcdSet16S (PcdMrcDqByteMapSize, sizeof (mDqByteMapSklRvp3));
> +  PcdSet32S (PcdMrcDqsMapCpu2Dram, (UINTN)
> mDqsMapCpu2DramSklRvp3);
> +  PcdSet16S (PcdMrcDqsMapCpu2DramSize, sizeof
> (mDqsMapCpu2DramSklRvp3));
> +  PcdSet32S (PcdMrcRcompResistor, (UINTN) RcompResistorSklRvp1);
> +  PcdSet32S (PcdMrcRcompTarget, (UINTN) RcompTargetSklRvp1);
> +  //
> +  // Example policy for DIMM slots implementation boards:
> +  // 1. Assign Smbus address of DIMMs and SpdData will be updated later
> +  //    by reading from DIMM SPD.
> +  // 2. No need to apply hardcoded SpdData buffers here for such board.
> +  //   Example:
> +  //   PcdMrcSpdAddressTable0 = 0xA0
> +  //   PcdMrcSpdAddressTable1 = 0xA2
> +  //   PcdMrcSpdAddressTable2 = 0xA4
> +  //   PcdMrcSpdAddressTable3 = 0xA6
> +  //   PcdMrcSpdData = 0
> +  //   PcdMrcSpdDataSize = 0
> +  //
> +  // Skylake RVP3 has 4GB Memory down implementation withouit SPD,
> +  // So assign all SpdAddress to 0 and apply static SpdData buffers:
> +  //   PcdMrcSpdAddressTable0 = 0
> +  //   PcdMrcSpdAddressTable1 = 0
> +  //   PcdMrcSpdAddressTable2 = 0
> +  //   PcdMrcSpdAddressTable3 = 0
> +  //   PcdMrcSpdData = static data buffer
> +  //   PcdMrcSpdDataSize = sizeof (static data buffer)
> +  //
> +  PcdSet8S (PcdMrcSpdAddressTable0, 0);
> +  PcdSet8S (PcdMrcSpdAddressTable1, 0);
> +  PcdSet8S (PcdMrcSpdAddressTable2, 0);
> +  PcdSet8S (PcdMrcSpdAddressTable3, 0);
> +  PcdSet32S (PcdMrcSpdData, (UINTN) mSkylakeRvp3Spd);
> +  PcdSet16S (PcdMrcSpdDataSize, mSkylakeRvp3SpdSize);
> 
>    PcdSetBoolS (PcdIoExpanderPresent, TRUE);
> -
> +
>    return EFI_SUCCESS;
>  }
> 
>  #define SIO_RUNTIME_REG_BASE_ADDRESS                          0x0680
> 
>  /**
> -  Configures GPIO
> +  Configures GPIO.
> 
>    @param[in]  GpioTable       Point to Platform Gpio table
>    @param[in]  GpioTableCount  Number of Gpio table entries
> @@ -137,7 +234,7 @@ GpioInitPreMem (
>  }
> 
>  /**
> -  Configure Super IO
> +  Configure Super IO.
> 
>  **/
>  VOID
> @@ -175,7 +272,7 @@ I2CGpioExpanderInitPreMem(
>  }
> 
>  /**
> -  Configure GPIO and SIO before memory ready
> +  Configure GPIO and SIO before memory ready.
> 
>    @retval  EFI_SUCCESS   Operation success.
>  **/
> @@ -185,7 +282,11 @@ KabylakeRvp3BoardInitBeforeMemoryInit (
>    VOID
>    )
>  {
> -  KabylakeRvp3InitPreMem ();
> +  if (LibPcdGetSku () == BoardIdKabyLakeYLpddr3Rvp3) {
> +    KabylakeRvp3InitPreMem ();
> +  } else if (LibPcdGetSku () == BoardIdSkylakeRvp3) {
> +    SkylakeRvp3InitPreMem ();
> +  }
> 
>    //
>    // Configures the I2CGpioExpander
> diff --git
> a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib
> /PeiMultiBoardInitPostMemLib.c
> b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib
> /PeiMultiBoardInitPostMemLib.c
> index 3778911610..cc800b552b 100644
> ---
> a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib
> /PeiMultiBoardInitPostMemLib.c
> +++
> b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib
> /PeiMultiBoardInitPostMemLib.c
> @@ -1,7 +1,7 @@
>  /** @file
>    Platform Hook Library instances
> 
> -Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
>  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  **/
> @@ -33,7 +33,7 @@ PeiKabylakeRvp3MultiBoardInitLibConstructor (
>    VOID
>    )
>  {
> -  if (LibPcdGetSku () == BoardIdKabyLakeYLpddr3Rvp3) {
> +  if ((LibPcdGetSku () == BoardIdKabyLakeYLpddr3Rvp3) || (LibPcdGetSku ()
> == BoardIdSkylakeRvp3)) {
>      return RegisterBoardPostMemInit (&mKabylakeRvp3BoardInitFunc);
>    }
>    return EFI_SUCCESS;
> diff --git
> a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib
> /PeiMultiBoardInitPreMemLib.c
> b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib
> /PeiMultiBoardInitPreMemLib.c
> index b8b161377e..843ae9890c 100644
> ---
> a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib
> /PeiMultiBoardInitPreMemLib.c
> +++
> b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib
> /PeiMultiBoardInitPreMemLib.c
> @@ -1,7 +1,7 @@
>  /** @file
>    Platform Hook Library instances
> 
> -Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
>  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  **/
> @@ -66,7 +66,7 @@ KabylakeRvp3MultiBoardDetect (
>    )
>  {
>    KabylakeRvp3BoardDetect ();
> -  if (LibPcdGetSku () == BoardIdKabyLakeYLpddr3Rvp3) {
> +  if ((LibPcdGetSku () == BoardIdKabyLakeYLpddr3Rvp3) || (LibPcdGetSku ()
> == BoardIdSkylakeRvp3)) {
>      RegisterBoardPreMemInit (&mKabylakeRvp3BoardPreMemInitFunc);
>    }
>    return EFI_SUCCESS;
> diff --git
> a/Platform/Intel/KabylakeOpenBoardPkg/Library/BaseEcLib/BaseEcLib.c
> b/Platform/Intel/KabylakeOpenBoardPkg/Library/BaseEcLib/BaseEcLib.c
> new file mode 100644
> index 0000000000..643712affb
> --- /dev/null
> +++ b/Platform/Intel/KabylakeOpenBoardPkg/Library/BaseEcLib/BaseEcLib.c
> @@ -0,0 +1,339 @@
> +/** @file
> +  Base EC library implementation for H/W layer.
> +
> +Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <Base.h>
> +#include <Uefi.h>
> +#include <Library/EcLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/TimerLib.h>
> +#include <Library/DebugLib.h>
> +
> +#ifndef SLE_FLAG
> +#ifndef STALL_ONE_MICRO_SECOND
> +#define STALL_ONE_MICRO_SECOND  1
> +#endif
> +#ifndef STALL_ONE_MILLI_SECOND
> +#define STALL_ONE_MILLI_SECOND  1000
> +#endif
> +#else // SLE FLAG
> +#ifndef STALL_ONE_MICRO_SECOND
> +#define STALL_ONE_MICRO_SECOND  0
> +#endif
> +#ifndef STALL_ONE_MILLI_SECOND
> +#define STALL_ONE_MILLI_SECOND  0
> +#endif
> +#endif // SLE_FLAG
> +
> +#ifndef EC_INIT_TIME_OUT
> +#define EC_INIT_TIME_OUT       0x200
> +#endif
> +
> +typedef struct {
> +  UINT8   CommandNumber;
> +  UINT8   NumberOfSendData;
> +  UINT8   NumberOfReceiveData;
> +  BOOLEAN CommandImplemented;
> +} EC_COMMAND_TABLE;
> +
> +EC_COMMAND_TABLE mEcCommand[] = {
> +  {EC_C_FAB_ID                   , 0, 2, TRUE}   // Get the board fab ID in the lower
> 3 bits
> +};
> +
> +//
> +// Function implementations
> +//
> +/**
> +  Sends command to EC.
> +
> +  @param[in] Command           Command byte to send
> +  @param[in] Timeout           Timeout in microseonds
> +
> +  @retval    EFI_SUCCESS       Command success
> +  @retval    EFI_DEVICE_ERROR  Command error
> +  @retval    EFI_TIMEOUT       Command timeout
> +**/
> +EFI_STATUS
> +SendEcCommandTimeout (
> +  IN UINT8                  Command,
> +  IN UINT32                 Timeout
> +  )
> +{
> +  UINTN         Index;
> +  UINT8         EcStatus;
> +  UINT8         DiscardData;
> +
> +  Index = 0;
> +  EcStatus = 0;
> +  DiscardData = 0;
> +  //
> +  // Wait for EC to be ready (with a timeout)
> +  //
> +  ReceiveEcStatus (&EcStatus);
> +  //
> +  // Check if output buffer bit(OBF) is set.
> +  // Read and discard the output buffer data so that next BIOS-EC cmd is in
> sync
> +  // OBF is cleared by h/w after all data in output buffer is read by BIOS.
> +  //
> +  while ((EcStatus & EC_S_OBF) != 0) {
> +    //
> +    // Read EC data
> +    //
> +    DiscardData = IoRead8 (EC_D_PORT);
> +    DEBUG ((DEBUG_INFO, "OBF is Set!! DiscardData Read 0x%02X\n",
> DiscardData));
> +    ReceiveEcStatus (&EcStatus);
> +  }
> +  while (((EcStatus & EC_S_IBF) != 0) && (Index < Timeout)) {
> +    MicroSecondDelay (15 * STALL_ONE_MICRO_SECOND);
> +    ReceiveEcStatus (&EcStatus);
> +    Index++;
> +  }
> +
> +  if (Index >= Timeout) {
> +    return EFI_TIMEOUT;
> +  }
> +
> +  //Printing EC Command Sent
> +  DEBUG ((DEBUG_INFO, "Sending EC Command: %02X\n", Command));
> +
> +  //
> +  // Send the EC command
> +  //
> +  IoWrite8 (EC_C_PORT, Command);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +
> +/**
> +  Sends command to EC.
> +
> +  @param[in] Command           Command byte to send
> +
> +  @retval    EFI_SUCCESS       Command success
> +  @retval    EFI_DEVICE_ERROR  Command error
> +  @retval    EFI_TIMEOUT       Command timeout
> +**/
> +EFI_STATUS
> +SendEcCommand (
> +  IN UINT8                  Command
> +  )
> +{
> +  return SendEcCommandTimeout (Command, EC_TIME_OUT);
> +}
> +
> +
> +/**
> +  Receives status from EC.
> +
> +  @param[out] EcStatus       Status byte to receive
> +
> +  @retval     EFI_SUCCESS
> +  @retval     EFI_DEVICE_ERROR
> +**/
> +EFI_STATUS
> +ReceiveEcStatus (
> +  OUT UINT8                 *EcStatus
> +  )
> +{
> +  //
> +  // Read and return the status
> +  //
> +  *EcStatus = IoRead8 (EC_C_PORT);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +
> +/**
> +  Sends data to EC.
> +
> +  @param[in] Data          Data byte to send
> +
> +  @retval    EFI_SUCCESS
> +  @retval    EFI_DEVICE_ERROR
> +**/
> +EFI_STATUS
> +SendEcData (
> +  IN UINT8                 Data
> +  )
> +{
> +  UINTN         Index;
> +  UINT8         EcStatus;
> +
> +  Index = 0;
> +
> +  //
> +  // Wait for EC to be ready (with a timeout)
> +  //
> +  ReceiveEcStatus (&EcStatus);
> +  while (((EcStatus & EC_S_IBF) != 0) && (Index < EC_TIME_OUT)) {
> +    MicroSecondDelay (15);
> +    ReceiveEcStatus (&EcStatus);
> +    Index++;
> +  }
> +  if (Index >= EC_TIME_OUT) {
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +  //
> +  //Printing EC Data Sent
> +  //
> +  DEBUG ((DEBUG_INFO, "Sending EC Data: %02X\n", Data));
> +
> +  //
> +  // Send the data and return
> +  //
> +  IoWrite8 (EC_D_PORT, Data);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +
> +/**
> +  Receives data from EC.
> +
> +  @param[out] Data              Data byte received
> +  @param[in]  Timeout           Timeout in microseonds
> +
> +  @retval     EFI_SUCCESS       Read success
> +  @retval     EFI_DEVICE_ERROR  Read error
> +  @retval     EFI_TIMEOUT       Command timeout
> +--*/
> +EFI_STATUS
> +ReceiveEcDataTimeout (
> +  OUT UINT8                  *Data,
> +  IN  UINT32                 Timeout
> + )
> +{
> +  UINTN         Index;
> +  UINT8         EcStatus;
> +
> +  Index = 0;
> +
> +  //
> +  // Wait for EC to be ready (with a timeout)
> +  //
> +  ReceiveEcStatus (&EcStatus);
> +  while (((EcStatus & EC_S_OBF) == 0) && (Index < Timeout)) {
> +    MicroSecondDelay (15 * STALL_ONE_MICRO_SECOND);
> +    ReceiveEcStatus (&EcStatus);
> +    Index++;
> +  }
> +
> +  if (Index >= Timeout) {
> +    return EFI_TIMEOUT;
> +  }
> +  //
> +  // Read EC data and return
> +  //
> +  *Data = IoRead8 (EC_D_PORT);
> +
> +  //Printing EC Data Received
> +  DEBUG ((DEBUG_INFO, "Receiving EC Data: %02X\n", *Data));
> +
> +  return EFI_SUCCESS;
> +}
> +/**
> +  Receives data from EC.
> +
> +  @param[out] Data              Data byte received
> +
> +  @retval     EFI_SUCCESS       Read success
> +  @retval     EFI_DEVICE_ERROR  Read error
> +  @retval     EFI_TIMEOUT       Command timeout
> +**/
> +EFI_STATUS
> +ReceiveEcData (
> +  OUT UINT8                  *Data
> + )
> +{
> +  return ReceiveEcDataTimeout (Data, EC_TIME_OUT);
> +}
> +
> +/**
> +  Send data to EC through LPC interface.
> +
> +  @param[in]      Command     Command value to send to the EC
> +  @param[in][out] DataSize    Size of data to send to the EC.
> +                              If the command retuned data - size of buffer returned by
> the EC.
> +                              Be aware of the DataSize must euqal to size of DataBuffer
> and cannot smaller
> +                              than number of send data or number of receive data,
> whichever is the grater.
> +  @param[in][out] DataBuffer  Pointer to the data buffer including data to
> be sent to the EC.
> +                              If the command returned data - pointer to the buffer
> including the data.
> +                              The buffer size should be the max of receive and transmit
> data.
> +
> +  @retval         EFI_SUCCESS Success
> +  @retval         Other       Failed - EFI_TIMEOUT, EFI_INVALID_PARAMETER,
> EFI_UNSUPPORTED,
> +                                       EFI_BUFFER_TOO_SMALL, etc.
> +**/
> +EFI_STATUS
> +LpcEcInterface (
> +  IN UINT8                     Command,
> +  IN OUT UINT8                 *DataSize,
> +  IN OUT UINT8                 *DataBuffer
> +  )
> +{
> +  EFI_STATUS Status;
> +  UINT8      NumberOfEcCommands;
> +  UINT8      Index;
> +  UINT8      TxDataIndex;
> +  UINT8      RxDataIndex;
> +  UINT8      MaxValue;
> +
> +  Status = EFI_SUCCESS;
> +
> +  NumberOfEcCommands = sizeof (mEcCommand) / sizeof
> (EC_COMMAND_TABLE);
> +
> +  for (Index = 0; Index < NumberOfEcCommands; Index++) {
> +    if (Command != mEcCommand[Index].CommandNumber) {
> +      continue;
> +    }
> +    if (mEcCommand[Index].CommandImplemented != TRUE) {
> +      Status = EFI_UNSUPPORTED;
> +      break;
> +    }
> +
> +    if ((mEcCommand[Index].NumberOfSendData != 0) ||
> (mEcCommand[Index].NumberOfReceiveData != 0)) {
> +      if (DataSize == NULL || DataBuffer == NULL) {
> +        Status = EFI_INVALID_PARAMETER;
> +        break;
> +      } else {
> +        MaxValue = MAX (mEcCommand[Index].NumberOfSendData,
> mEcCommand[Index].NumberOfReceiveData);
> +        if (*DataSize < MaxValue) {
> +          Status = EFI_BUFFER_TOO_SMALL;
> +          *DataSize = MaxValue;
> +          break;
> +        }
> +      }
> +    }
> +
> +    Status = SendEcCommand (Command);
> +    if (EFI_ERROR (Status)) {
> +      break;
> +    }
> +    if (mEcCommand[Index].NumberOfSendData != 0) {
> +     for (TxDataIndex = 0; TxDataIndex <
> mEcCommand[Index].NumberOfSendData; TxDataIndex++) {
> +        Status = SendEcData (DataBuffer[TxDataIndex]);
> +        if (EFI_ERROR (Status)) {
> +          break;
> +        }
> +      }
> +    }
> +    if (mEcCommand[Index].NumberOfReceiveData != 0) {
> +      for (RxDataIndex = 0; RxDataIndex <
> mEcCommand[Index].NumberOfReceiveData; RxDataIndex++) {
> +        Status = ReceiveEcData (&DataBuffer[RxDataIndex]);
> +        if (EFI_ERROR (Status)) {
> +          break;
> +        }
> +        *DataSize = RxDataIndex + 1;
> +      }
> +    }
> +    break;
> +  }
> +  return Status;
> +}
> diff --git
> a/Platform/Intel/KabylakeOpenBoardPkg/FspWrapper/Library/PeiSiliconPolic
> yNotifyLib/PeiPreMemSiliconPolicyNotifyLib.inf
> b/Platform/Intel/KabylakeOpenBoardPkg/FspWrapper/Library/PeiSiliconPoli
> cyNotifyLib/PeiPreMemSiliconPolicyNotifyLib.inf
> new file mode 100644
> index 0000000000..13c12655f6
> --- /dev/null
> +++
> b/Platform/Intel/KabylakeOpenBoardPkg/FspWrapper/Library/PeiSiliconPoli
> cyNotifyLib/PeiPreMemSiliconPolicyNotifyLib.inf
> @@ -0,0 +1,43 @@
> +## @file
> +# Component information file for Silicon Policy Notify Library.
> +# This library implements constructor function to register notify call back
> +# when policy PPI installed.
> +#
> +# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = PeiPreMemSiliconPolicyNotifyLib
> +  FILE_GUID                      = 6D231E12-C088-47C8-8B16-61F07293EEF8
> +  MODULE_TYPE                    = PEIM
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = NULL
> +  CONSTRUCTOR                    = PeiPreMemSiliconPolicyNotifyLibConstructor
> +
> +[LibraryClasses]
> +  BaseLib
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  KabylakeOpenBoardPkg/OpenBoardPkg.dec
> +  KabylakeSiliconPkg/SiPkg.dec
> +
> +[Sources]
> +  PeiPreMemSiliconPolicyNotifyLib.c
> +
> +[Guids]
> +  gSaMiscPeiPreMemConfigGuid
> +
> +[Ppis]
> +  gSiPreMemPolicyPpiGuid
> +
> +[Pcd]
> +  # SPD Address Table
> +  gBoardModuleTokenSpaceGuid.PcdMrcSpdAddressTable0
> +  gBoardModuleTokenSpaceGuid.PcdMrcSpdAddressTable1
> +  gBoardModuleTokenSpaceGuid.PcdMrcSpdAddressTable2
> +  gBoardModuleTokenSpaceGuid.PcdMrcSpdAddressTable3
> diff --git
> a/Platform/Intel/KabylakeOpenBoardPkg/FspWrapper/Library/PeiSiliconPolic
> yUpdateLibFsp/PeiSiliconPolicyUpdateLibFsp.inf
> b/Platform/Intel/KabylakeOpenBoardPkg/FspWrapper/Library/PeiSiliconPoli
> cyUpdateLibFsp/PeiSiliconPolicyUpdateLibFsp.inf
> index fa8d91e076..7ce6fd8470 100644
> ---
> a/Platform/Intel/KabylakeOpenBoardPkg/FspWrapper/Library/PeiSiliconPolic
> yUpdateLibFsp/PeiSiliconPolicyUpdateLibFsp.inf
> +++
> b/Platform/Intel/KabylakeOpenBoardPkg/FspWrapper/Library/PeiSiliconPoli
> cyUpdateLibFsp/PeiSiliconPolicyUpdateLibFsp.inf
> @@ -1,7 +1,7 @@
>  ## @file
>  #  Provide FSP wrapper platform related function.
>  #
> -# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
> +# Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
>  #
>  # SPDX-License-Identifier: BSD-2-Clause-Patent
>  #
> @@ -94,6 +94,13 @@
>    gBoardModuleTokenSpaceGuid.PcdMrcRcompTarget         ## CONSUMES
>    gBoardModuleTokenSpaceGuid.PcdMrcDqByteMap           ## CONSUMES
>    gBoardModuleTokenSpaceGuid.PcdMrcDqsMapCpu2Dram      ##
> CONSUMES
> +
> +  # SPD Address Table
> +  gBoardModuleTokenSpaceGuid.PcdMrcSpdAddressTable0    ## CONSUMES
> +  gBoardModuleTokenSpaceGuid.PcdMrcSpdAddressTable1    ## CONSUMES
> +  gBoardModuleTokenSpaceGuid.PcdMrcSpdAddressTable2    ## CONSUMES
> +  gBoardModuleTokenSpaceGuid.PcdMrcSpdAddressTable3    ## CONSUMES
> +
>    gBoardModuleTokenSpaceGuid.PcdMrcSpdData
>    gBoardModuleTokenSpaceGuid.PcdMrcSpdDataSize
> 
> diff --git a/Platform/Intel/KabylakeOpenBoardPkg/Include/EcCommands.h
> b/Platform/Intel/KabylakeOpenBoardPkg/Include/EcCommands.h
> new file mode 100644
> index 0000000000..be56d134ed
> --- /dev/null
> +++ b/Platform/Intel/KabylakeOpenBoardPkg/Include/EcCommands.h
> @@ -0,0 +1,44 @@
> +/** @file
> +  Definition for supported EC commands.
> +
> +Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef EC_COMMANDS_H_
> +#define EC_COMMANDS_H_
> +
> +//
> +// Timeout if EC command/data fails
> +//
> +#define EC_TIME_OUT        0x20000
> +
> +//
> +// The EC implements an embedded controller interface at ports 0x60/0x64
> and a ACPI compliant
> +// system management controller at ports 0x62/0x66. Port 0x66 is the
> command and status port,
> +// port 0x62 is the data port.
> +//
> +#define EC_D_PORT        0x62
> +#define EC_C_PORT        0x66
> +
> +//
> +// Status Port 0x62
> +//
> +#define EC_S_OVR_TMP     0x80    // Current CPU temperature exceeds the
> threshold
> +#define EC_S_SMI_EVT     0x40    // SMI event is pending
> +#define EC_S_SCI_EVT     0x20    // SCI event is pending
> +#define EC_S_BURST       0x10    // EC is in burst mode or normal mode
> +#define EC_S_CMD         0x08    // Byte in data register is command/data
> +#define EC_S_IGN         0x04    // Ignored
> +#define EC_S_IBF         0x02    // Input buffer is full/empty
> +#define EC_S_OBF         0x01    // Output buffer is full/empty
> +
> +//
> +// EC commands that are issued to the EC through the command port
> (0x66).
> +// New commands and command parameters should only be written by the
> host when IBF=0.
> +// Data read from the EC data port is valid only when OBF=1.
> +//
> +#define EC_C_FAB_ID                    0x0D    // Get the board fab ID in the lower
> 3 bits
> +
> +#endif // EC_COMMANDS_H_
> diff --git a/Platform/Intel/KabylakeOpenBoardPkg/Include/Library/EcLib.h
> b/Platform/Intel/KabylakeOpenBoardPkg/Include/Library/EcLib.h
> new file mode 100644
> index 0000000000..04ce076f91
> --- /dev/null
> +++ b/Platform/Intel/KabylakeOpenBoardPkg/Include/Library/EcLib.h
> @@ -0,0 +1,106 @@
> +/** @file
> +  EC library functions and definitions.
> +
> +  This library provides basic EC interface.
> +
> +  There may be different libraries for different environments (PEI, BS, RT,
> SMM).
> +  Make sure you meet the requirements for the library (protocol
> dependencies, use
> +  restrictions, etc).
> +
> +Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef _BASE_EC_LIB_H_
> +#define _BASE_EC_LIB_H_
> +
> +//
> +// Include files
> +//
> +#include <Base.h>
> +#include <Uefi.h>
> +#include <EcCommands.h>
> +
> +//
> +// Function declarations
> +//
> +/**
> +  Send a command to the Keyboard System Controller.
> +
> +  @param[in] Command      Command byte to send
> +
> +  @retval    EFI_SUCCESS  Command success
> +  @retval    EFI_TIMEOUT  Command timeout
> +  @retval    Other        Command failed
> +**/
> +EFI_STATUS
> +SendEcCommand (
> +  IN UINT8   Command
> +  );
> +
> +/**
> +  Sends data to Keyboard System Controller.
> +
> +  @param[in] Data          Data byte to send
> +
> +  @retval    EFI_SUCCESS   Success
> +  @retval    EFI_TIMEOUT   Timeout
> +  @retval    Other         Failed
> +**/
> +EFI_STATUS
> +SendEcData (
> +  IN UINT8   Data
> +  );
> +
> +/**
> +  Receives data from Keyboard System Controller.
> +
> +  @param[out] Data          Data byte received
> +
> +  @retval     EFI_SUCCESS   Read success
> +  @retval     EFI_TIMEOUT   Read timeout
> +  @retval     Other         Read failed
> +**/
> +EFI_STATUS
> +ReceiveEcData (
> +  OUT UINT8   *Data
> +  );
> +
> +/**
> +  Receives status from Keyboard System Controller.
> +
> +  @param[out] Status       Status byte to receive
> +
> +  @retval     EFI_SUCCESS  Success
> +  @retval     Other        Failed
> +**/
> +EFI_STATUS
> +ReceiveEcStatus (
> +  OUT UINT8   *EcStatus
> +  );
> +
> +/**
> +  Send data to EC through LPC interface.
> +
> +  @param[in]      Command     Command value to send to the EC
> +  @param[in][out] DataSize    Size of data to send to the EC.
> +                              If the command retuned data - size of buffer returned by
> the EC.
> +                              Be aware of the DataSize must euqal to size of DataBuffer
> and cannot smaller
> +                              than number of send data or number of receive data,
> whichever is the grater.
> +  @param[in][out] DataBuffer  Pointer to the data buffer including data to
> be sent to the EC.
> +                              If the command returned data - pointer to the buffer
> including the data.
> +                              The buffer size should be the max of receive and transmit
> data.
> +
> +  @retval         EFI_SUCCESS Success
> +  @retval         Other       Failed - EFI_TIMEOUT, EFI_INVALID_PARAMETER,
> EFI_UNSUPPORTED,
> +                                       EFI_BUFFER_TOO_SMALL, etc.
> +**/
> +EFI_STATUS
> +LpcEcInterface (
> +  IN UINT8                     Command,
> +  IN OUT UINT8                 *DataSize,
> +  IN OUT UINT8                 *DataBuffer
> +  );
> +
> +#endif
> diff --git
> a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardAcpiLi
> b/DxeBoardAcpiTableLib.inf
> b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardAcpiLi
> b/DxeBoardAcpiTableLib.inf
> index f3fed024ec..dd971ef97a 100644
> ---
> a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardAcpiLi
> b/DxeBoardAcpiTableLib.inf
> +++
> b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardAcpiLi
> b/DxeBoardAcpiTableLib.inf
> @@ -1,7 +1,7 @@
>  ### @file
>  # Platform Hook Library instance for SandyBridge Mobile/Desktop CRB.
>  #
> -# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
> +# Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
>  #
>  # SPDX-License-Identifier: BSD-2-Clause-Patent
>  #
> @@ -36,9 +36,9 @@
> 
>  [Pcd]
>    gBoardModuleTokenSpaceGuid.PcdPs2KbMsEnable
> -  gMinPlatformPkgTokenSpaceGuid.PcdPciExpNative
> -  gMinPlatformPkgTokenSpaceGuid.PcdNativeAspmEnable
> -  gMinPlatformPkgTokenSpaceGuid.PcdLowPowerS0Idle
> +  gBoardModuleTokenSpaceGuid.PcdPciExpNative
> +  gBoardModuleTokenSpaceGuid.PcdNativeAspmEnable
> +  gBoardModuleTokenSpaceGuid.PcdLowPowerS0Idle
>    gBoardModuleTokenSpaceGuid.PcdAcpiGnvsAddress
> 
>  [Sources]
> diff --git
> a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib
> /PeiBoardInitPreMemLib.inf
> b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib
> /PeiBoardInitPreMemLib.inf
> index 51f6787e4f..7be1c180de 100644
> ---
> a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib
> /PeiBoardInitPreMemLib.inf
> +++
> b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib
> /PeiBoardInitPreMemLib.inf
> @@ -1,7 +1,7 @@
>  ## @file
>  # Component information file for PEI KabylakeRvp3 Board Init Pre-Mem
> Library
>  #
> -# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
> +# Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
>  #
>  # SPDX-License-Identifier: BSD-2-Clause-Patent
>  #
> @@ -22,6 +22,7 @@
>    MemoryAllocationLib
>    PcdLib
>    SiliconInitLib
> +  EcLib
> 
>  [Packages]
>    MinPlatformPkg/MinPlatformPkg.dec
> diff --git
> a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib
> /PeiKabylakeRvp3InitLib.h
> b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib
> /PeiKabylakeRvp3InitLib.h
> index 1878b2c6bd..bd60720137 100644
> ---
> a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib
> /PeiKabylakeRvp3InitLib.h
> +++
> b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib
> /PeiKabylakeRvp3InitLib.h
> @@ -1,6 +1,6 @@
>  /** @file
> 
> -Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
>  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  **/
> @@ -24,6 +24,8 @@ extern const UINT8 mDqByteMapSklRvp3[2][6][2];
>  extern const UINT8 mDqsMapCpu2DramSklRvp3[2][8];
>  extern const UINT8 mSkylakeRvp3Spd110[];
>  extern const UINT16 mSkylakeRvp3Spd110Size;
> +extern const UINT8 mSkylakeRvp3Spd[];
> +extern const UINT16 mSkylakeRvp3SpdSize;
>  extern HSIO_PTSS_TABLES PchLpHsioPtss_Bx_KabylakeRvp3[];
>  extern UINT16 PchLpHsioPtss_Bx_KabylakeRvp3_Size;
>  extern HSIO_PTSS_TABLES PchLpHsioPtss_Cx_KabylakeRvp3[];
> diff --git
> a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib
> /PeiMultiBoardInitPreMemLib.inf
> b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib
> /PeiMultiBoardInitPreMemLib.inf
> index 25684b00d0..2d8d26d7a1 100644
> ---
> a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib
> /PeiMultiBoardInitPreMemLib.inf
> +++
> b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/Library/BoardInitLib
> /PeiMultiBoardInitPreMemLib.inf
> @@ -1,7 +1,7 @@
>  ## @file
>  # Component information file for PEI KabylakeRvp3 Board Init Pre-Mem
> Library
>  #
> -# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
> +# Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
>  #
>  # SPDX-License-Identifier: BSD-2-Clause-Patent
>  #
> @@ -24,6 +24,7 @@
>    PcdLib
>    SiliconInitLib
>    MultiBoardInitSupportLib
> +  EcLib
> 
>  [Packages]
>    MinPlatformPkg/MinPlatformPkg.dec
> diff --git
> a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/OpenBoardPkg.dsc
> b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/OpenBoardPkg.dsc
> index 1bef21dd42..7f19ad1eed 100644
> ---
> a/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/OpenBoardPkg.dsc
> +++
> b/Platform/Intel/KabylakeOpenBoardPkg/KabylakeRvp3/OpenBoardPkg.dsc
> @@ -1,7 +1,7 @@
>  ## @file
>  #  Platform description.
>  #
> -# Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
> +# Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
>  #
>  # SPDX-License-Identifier: BSD-2-Clause-Patent
>  #
> @@ -106,6 +106,8 @@
> 
> TbtCommonLib|$(PLATFORM_BOARD_PACKAGE)/Features/Tbt/Library/PeiD
> xeSmmTbtCommonLib/TbtCommonLib.inf
> 
> DxeTbtPolicyLib|$(PLATFORM_BOARD_PACKAGE)/Features/Tbt/Library/DxeT
> btPolicyLib/DxeTbtPolicyLib.inf
>  !endif
> +  EcLib|$(PLATFORM_BOARD_PACKAGE)/Library/BaseEcLib/BaseEcLib.inf
> +
>  #
>  # Silicon Init Package
>  #
> @@ -210,7 +212,13 @@
>      <LibraryClasses>
> 
> SiliconPolicyInitLib|$(PLATFORM_SI_PACKAGE)/Library/PeiSiliconPolicyInitLib
> Dependency/PeiPreMemSiliconPolicyInitLibDependency.inf
>    }
> -
> $(PLATFORM_PACKAGE)/PlatformInit/SiliconPolicyPei/SiliconPolicyPeiPreMe
> m.inf
> +
> $(PLATFORM_PACKAGE)/PlatformInit/SiliconPolicyPei/SiliconPolicyPeiPreMe
> m.inf {
> +    <LibraryClasses>
> +    #
> +    # Hook a library constructor to update some policy fields when policy
> installed.
> +    #
> +
> NULL|$(PLATFORM_BOARD_PACKAGE)/FspWrapper/Library/PeiSiliconPolicy
> NotifyLib/PeiPreMemSiliconPolicyNotifyLib.inf
> +  }
> 
> $(PLATFORM_PACKAGE)/PlatformInit/PlatformInitPei/PlatformInitPostMem.i
> nf {
>      <LibraryClasses>
>  !if gBoardModuleTokenSpaceGuid.PcdMultiBoardSupport == FALSE
> diff --git
> a/Platform/Intel/KabylakeOpenBoardPkg/Library/BaseEcLib/BaseEcLib.inf
> b/Platform/Intel/KabylakeOpenBoardPkg/Library/BaseEcLib/BaseEcLib.inf
> new file mode 100644
> index 0000000000..c7de77d80f
> --- /dev/null
> +++
> b/Platform/Intel/KabylakeOpenBoardPkg/Library/BaseEcLib/BaseEcLib.inf
> @@ -0,0 +1,29 @@
> +## @file
> +# Component information file for base EC library
> +#
> +# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010017
> +  BASE_NAME                      = BaseEcLib
> +  FILE_GUID                      = 7FE22E12-889E-48D5-9F91-B7CBE265C94C
> +  VERSION_STRING                 = 1.0
> +  MODULE_TYPE                    = BASE
> +  LIBRARY_CLASS                  = EcLib
> +
> +[LibraryClasses]
> +  BaseLib
> +  DebugLib
> +  IoLib
> +  TimerLib
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  KabylakeOpenBoardPkg/OpenBoardPkg.dec
> +
> +[Sources]
> +  BaseEcLib.c
> --
> 2.13.3.windows.1


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#41173): https://edk2.groups.io/g/devel/message/41173
Mute This Topic: https://groups.io/mt/31698291/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-