public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH 1/8] AlderlakeSiliconPkg: Add package and library instances
@ 2023-06-15 17:52 Saloni Kasbekar
  2023-06-15 17:53 ` [PATCH 2/8] AlderlakeSiliconPkg: Add Cpu modules Saloni Kasbekar
                   ` (7 more replies)
  0 siblings, 8 replies; 15+ messages in thread
From: Saloni Kasbekar @ 2023-06-15 17:52 UTC (permalink / raw)
  To: devel
  Cc: Saloni Kasbekar, Sai Chaganty, Nate DeSimone, Isaac Oram,
	Rosen Chuang

Create the AlderlakeSiliconPkg to provide an initial package for
silicon initialization code for Alder Lake (ADL) products. Add the
following libraries -
- BasePciSegmentMultiSegLibPci
- BaseSiConfigBlockLib
- PeiDxeSmmReserveMmio64SizeLib
- PeiPostMemSiliconPolicyInitLib

Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Isaac Oram <isaac.w.oram@intel.com>
Cc: Rosen Chuang <rosen.chuang@intel.com>
Signed-off-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
---
 .../BasePciSegmentMultiSegLibPci.inf          |  37 ++
 .../BasePciSegmentMultiSegLibPci.uni          |  14 +
 .../PciSegmentLib.c                           | 597 ++++++++++++++++++
 .../BaseSiConfigBlockLib.c                    |  87 +++
 .../BaseSiConfigBlockLib.inf                  |  32 +
 .../PeiDxeSmmReserveMmio64SizeLib.c           |  22 +
 .../PeiDxeSmmReserveMmio64SizeLib.inf         |  28 +
 .../PeiPostMemSiliconPolicyInitLib.c          |  94 +++
 .../PeiPostMemSiliconPolicyInitLib.inf        |  39 ++
 .../PeiPreMemSiliconPolicyInitLib.c           |  98 +++
 .../PeiPreMemSiliconPolicyInitLib.inf         |  36 ++
 11 files changed, 1084 insertions(+)
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Library/BasePciSegmentMultiSegLibPci/BasePciSegmentMultiSegLibPci.inf
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Library/BasePciSegmentMultiSegLibPci/BasePciSegmentMultiSegLibPci.uni
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Library/BasePciSegmentMultiSegLibPci/PciSegmentLib.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Library/BaseSiConfigBlockLib/BaseSiConfigBlockLib.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Library/BaseSiConfigBlockLib/BaseSiConfigBlockLib.inf
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Library/PeiDxeSmmReserveMmio64SizeLib/PeiDxeSmmReserveMmio64SizeLib.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Library/PeiDxeSmmReserveMmio64SizeLib/PeiDxeSmmReserveMmio64SizeLib.inf
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Library/PeiPostMemSiliconPolicyInitLib/PeiPostMemSiliconPolicyInitLib.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Library/PeiPostMemSiliconPolicyInitLib/PeiPostMemSiliconPolicyInitLib.inf
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Library/PeiPreMemSiliconPolicyInitLib/PeiPreMemSiliconPolicyInitLib.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Library/PeiPreMemSiliconPolicyInitLib/PeiPreMemSiliconPolicyInitLib.inf

diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Library/BasePciSegmentMultiSegLibPci/BasePciSegmentMultiSegLibPci.inf b/Silicon/Intel/AlderlakeSiliconPkg/Library/BasePciSegmentMultiSegLibPci/BasePciSegmentMultiSegLibPci.inf
new file mode 100644
index 0000000000..f3764d0187
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Library/BasePciSegmentMultiSegLibPci/BasePciSegmentMultiSegLibPci.inf
@@ -0,0 +1,37 @@
+## @file
+# Instance of PCI Segment Library based on PCI Library.
+#
+# PCI Segment Library that layers on top of the PCI Library which only
+#  supports segment 0 and segment 1 PCI configuration access.
+#
+#   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+#   SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = BasePciSegmentMultiSegLibPci
+  MODULE_UNI_FILE                = BasePciSegmentMultiSegLibPci.uni
+  FILE_GUID                      = AC65B409-DF03-466e-8D2B-6FCE1079F0B2
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = PciSegmentLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
+#
+
+[Sources]
+  PciSegmentLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  AlderlakeSiliconPkg/SiPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  PciLib
+  DebugLib
+  PcdLib
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Library/BasePciSegmentMultiSegLibPci/BasePciSegmentMultiSegLibPci.uni b/Silicon/Intel/AlderlakeSiliconPkg/Library/BasePciSegmentMultiSegLibPci/BasePciSegmentMultiSegLibPci.uni
new file mode 100644
index 0000000000..dd8d74bee8
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Library/BasePciSegmentMultiSegLibPci/BasePciSegmentMultiSegLibPci.uni
@@ -0,0 +1,14 @@
+// /** @file
+// Instance of PCI Segment Library based on PCI Library.
+//
+// PCI Segment Library that layers on top of the PCI Library which only
+//  supports segment 0 and segment 1 PCI configuration access.
+//
+//   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+//   SPDX-License-Identifier: BSD-2-Clause-Patent
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "Instance of PCI Segment Library based on PCI Library."
+
+#string STR_MODULE_DESCRIPTION          #language en-US "PCI Segment Library that layers on top of the PCI Library which only supports segment 0 and segment 1 PCI configuration access."
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Library/BasePciSegmentMultiSegLibPci/PciSegmentLib.c b/Silicon/Intel/AlderlakeSiliconPkg/Library/BasePciSegmentMultiSegLibPci/PciSegmentLib.c
new file mode 100644
index 0000000000..9bcb388016
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Library/BasePciSegmentMultiSegLibPci/PciSegmentLib.c
@@ -0,0 +1,597 @@
+/** @file
+  PCI Segment Library that layers on top of the PCI Library which only
+   supports segment 0 and segment 1 PCI configuration access.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PciLib.h>
+#include <Library/PciSegmentLib.h>
+
+/**
+  Assert the validity of a PCI Segment address.
+  A valid PCI Segment address should not contain 1's in bits 28..31 and 33..63
+  and the segment should be 0 or 1.
+
+  @param  A The address to validate.
+  @param  M Additional bits to assert to be zero.
+
+**/
+#define ASSERT_INVALID_PCI_SEGMENT_ADDRESS(A,M) \
+  ASSERT (((A) & (0xfffffffef0000000ULL | (M))) == 0)
+
+/**
+  Convert the PCI Segment library address to PCI library address.
+  From ICL generation support the multiple segment, and the segment number start from BIT28,
+  So we convert the Segment Number offset from BIT32 to BIT28
+
+  @param A The address to convert.
+**/
+#define PCI_SEGMENT_TO_PCI_ADDRESS(A) ((UINTN) (UINT32) ((A) | ((RShiftU64 ((A) & BIT32, 4)))))
+
+
+
+/**
+  Reads an 8-bit PCI configuration register.
+
+  Reads and returns the 8-bit PCI configuration register specified by Address.
+  This function must guarantee that all PCI read and write operations are serialized.
+
+  If any reserved bits in Address are set, then ASSERT().
+
+  @param  Address   The address that encodes the PCI Segment, Bus, Device, Function, and Register.
+
+  @return The 8-bit PCI configuration register specified by Address.
+
+**/
+UINT8
+EFIAPI
+PciSegmentRead8 (
+  IN UINT64                    Address
+  )
+{
+  ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 0);
+
+  return PciRead8 (PCI_SEGMENT_TO_PCI_ADDRESS (Address));
+}
+
+/**
+  Writes an 8-bit PCI configuration register.
+
+  Writes the 8-bit PCI configuration register specified by Address with the value specified by Value.
+  Value is returned.  This function must guarantee that all PCI read and write operations are serialized.
+
+  If any reserved bits in Address are set, then ASSERT().
+
+  @param  Address     The address that encodes the PCI Segment, Bus, Device, Function, and Register.
+  @param  Value       The value to write.
+
+  @return The value written to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciSegmentWrite8 (
+  IN UINT64                    Address,
+  IN UINT8                     Value
+  )
+{
+  ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 0);
+
+  return PciWrite8 (PCI_SEGMENT_TO_PCI_ADDRESS (Address), Value);
+}
+
+/**
+  Performs a bitwise OR of an 8-bit PCI configuration register with an 8-bit value.
+
+  Reads the 8-bit PCI configuration register specified by Address,
+  performs a bitwise OR between the read result and the value specified by OrData,
+  and writes the result to the 8-bit PCI configuration register specified by Address.
+  The value written to the PCI configuration register is returned.
+  This function must guarantee that all PCI read and write operations are serialized.
+
+  If any reserved bits in Address are set, then ASSERT().
+
+  @param  Address   The address that encodes the PCI Segment, Bus, Device, Function, and Register.
+  @param  OrData    The value to OR with the PCI configuration register.
+
+  @return The value written to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciSegmentOr8 (
+  IN UINT64                    Address,
+  IN UINT8                     OrData
+  )
+{
+  return PciWrite8 (PCI_SEGMENT_TO_PCI_ADDRESS (Address), (UINT8) (PciSegmentRead8 (Address) | OrData));
+}
+
+/**
+  Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit value.
+
+  Reads the 8-bit PCI configuration register specified by Address,
+  performs a bitwise AND between the read result and the value specified by AndData,
+  and writes the result to the 8-bit PCI configuration register specified by Address.
+  The value written to the PCI configuration register is returned.
+  This function must guarantee that all PCI read and write operations are serialized.
+  If any reserved bits in Address are set, then ASSERT().
+
+  @param  Address   The address that encodes the PCI Segment, Bus, Device, Function, and Register.
+  @param  AndData   The value to AND with the PCI configuration register.
+
+  @return The value written to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciSegmentAnd8 (
+  IN UINT64                    Address,
+  IN UINT8                     AndData
+  )
+{
+  return PciSegmentWrite8 (Address, (UINT8) (PciSegmentRead8 (Address) & AndData));
+}
+
+/**
+  Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit value,
+  followed a  bitwise OR with another 8-bit value.
+
+  Reads the 8-bit PCI configuration register specified by Address,
+  performs a bitwise AND between the read result and the value specified by AndData,
+  performs a bitwise OR between the result of the AND operation and the value specified by OrData,
+  and writes the result to the 8-bit PCI configuration register specified by Address.
+  The value written to the PCI configuration register is returned.
+  This function must guarantee that all PCI read and write operations are serialized.
+
+  If any reserved bits in Address are set, then ASSERT().
+
+  @param  Address   The address that encodes the PCI Segment, Bus, Device, Function, and Register.
+  @param  AndData    The value to AND with the PCI configuration register.
+  @param  OrData    The value to OR with the PCI configuration register.
+
+  @return The value written to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciSegmentAndThenOr8 (
+  IN UINT64                    Address,
+  IN UINT8                     AndData,
+  IN UINT8                     OrData
+  )
+{
+  return PciSegmentWrite8 (Address, (UINT8) ((PciSegmentRead8 (Address) & AndData) | OrData));
+}
+
+/**
+  Reads a 16-bit PCI configuration register.
+
+  Reads and returns the 16-bit PCI configuration register specified by Address.
+  This function must guarantee that all PCI read and write operations are serialized.
+
+  If any reserved bits in Address are set, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+  @param  Address   The address that encodes the PCI Segment, Bus, Device, Function, and Register.
+
+  @return The 16-bit PCI configuration register specified by Address.
+
+**/
+UINT16
+EFIAPI
+PciSegmentRead16 (
+  IN UINT64                    Address
+  )
+{
+  ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 1);
+
+  return PciRead16 (PCI_SEGMENT_TO_PCI_ADDRESS (Address));
+}
+
+/**
+  Writes a 16-bit PCI configuration register.
+
+  Writes the 16-bit PCI configuration register specified by Address with the value specified by Value.
+  Value is returned.  This function must guarantee that all PCI read and write operations are serialized.
+
+  If any reserved bits in Address are set, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+  @param  Address     The address that encodes the PCI Segment, Bus, Device, Function, and Register.
+  @param  Value       The value to write.
+
+  @return The parameter of Value.
+
+**/
+UINT16
+EFIAPI
+PciSegmentWrite16 (
+  IN UINT64                    Address,
+  IN UINT16                    Value
+  )
+{
+  ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 1);
+
+  return PciWrite16 (PCI_SEGMENT_TO_PCI_ADDRESS (Address), Value);
+}
+
+/**
+  Performs a bitwise OR of a 16-bit PCI configuration register with
+  a 16-bit value.
+
+  Reads the 16-bit PCI configuration register specified by Address, performs a
+  bitwise OR between the read result and the value specified by
+  OrData, and writes the result to the 16-bit PCI configuration register
+  specified by Address. The value written to the PCI configuration register is
+  returned. This function must guarantee that all PCI read and write operations
+  are serialized.
+
+  If any reserved bits in Address are set, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+  @param  Address The address that encodes the PCI Segment, Bus, Device, Function and
+                  Register.
+  @param  OrData  The value to OR with the PCI configuration register.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciSegmentOr16 (
+  IN UINT64                    Address,
+  IN UINT16                    OrData
+  )
+{
+  return PciSegmentWrite16 (Address, (UINT16) (PciSegmentRead16 (Address) | OrData));
+}
+
+/**
+  Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit value,
+  followed a  bitwise OR with another 16-bit value.
+
+  Reads the 16-bit PCI configuration register specified by Address,
+  performs a bitwise AND between the read result and the value specified by AndData,
+  performs a bitwise OR between the result of the AND operation and the value specified by OrData,
+  and writes the result to the 16-bit PCI configuration register specified by Address.
+  The value written to the PCI configuration register is returned.
+  This function must guarantee that all PCI read and write operations are serialized.
+
+  If any reserved bits in Address are set, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+  @param  Address   The address that encodes the PCI Segment, Bus, Device, Function, and Register.
+  @param  AndData    The value to AND with the PCI configuration register.
+  @param  OrData    The value to OR with the PCI configuration register.
+
+  @return The value written to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciSegmentAndThenOr16 (
+  IN UINT64                    Address,
+  IN UINT16                    AndData,
+  IN UINT16                    OrData
+  )
+{
+  return PciSegmentWrite16 (Address, (UINT16) ((PciSegmentRead16 (Address) & AndData) | OrData));
+}
+
+/**
+  Reads a 32-bit PCI configuration register.
+
+  Reads and returns the 32-bit PCI configuration register specified by Address.
+  This function must guarantee that all PCI read and write operations are serialized.
+
+  If any reserved bits in Address are set, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+  @param  Address   The address that encodes the PCI Segment, Bus, Device, Function, and Register.
+
+  @return The 32-bit PCI configuration register specified by Address.
+
+**/
+UINT32
+EFIAPI
+PciSegmentRead32 (
+  IN UINT64                    Address
+  )
+{
+  ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 3);
+
+  return PciRead32 (PCI_SEGMENT_TO_PCI_ADDRESS (Address));
+}
+
+/**
+  Writes a 32-bit PCI configuration register.
+
+  Writes the 32-bit PCI configuration register specified by Address with the value specified by Value.
+  Value is returned.  This function must guarantee that all PCI read and write operations are serialized.
+
+  If any reserved bits in Address are set, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+  @param  Address     The address that encodes the PCI Segment, Bus, Device, Function, and Register.
+  @param  Value       The value to write.
+
+  @return The parameter of Value.
+
+**/
+UINT32
+EFIAPI
+PciSegmentWrite32 (
+  IN UINT64                    Address,
+  IN UINT32                    Value
+  )
+{
+  ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 3);
+
+  return PciWrite32 (PCI_SEGMENT_TO_PCI_ADDRESS (Address), Value);
+}
+
+/**
+  Performs a bitwise OR of a 32-bit PCI configuration register with a 32-bit value.
+
+  Reads the 32-bit PCI configuration register specified by Address,
+  performs a bitwise OR between the read result and the value specified by OrData,
+  and writes the result to the 32-bit PCI configuration register specified by Address.
+  The value written to the PCI configuration register is returned.
+  This function must guarantee that all PCI read and write operations are serialized.
+
+  If any reserved bits in Address are set, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+  @param  Address   The address that encodes the PCI Segment, Bus, Device, Function, and Register.
+  @param  OrData    The value to OR with the PCI configuration register.
+
+  @return The value written to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciSegmentOr32 (
+  IN UINT64                    Address,
+  IN UINT32                    OrData
+  )
+{
+  return PciSegmentWrite32 (Address, PciSegmentRead32 (Address) | OrData);
+}
+
+/**
+  Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit value,
+  followed a  bitwise OR with another 32-bit value.
+
+  Reads the 32-bit PCI configuration register specified by Address,
+  performs a bitwise AND between the read result and the value specified by AndData,
+  performs a bitwise OR between the result of the AND operation and the value specified by OrData,
+  and writes the result to the 32-bit PCI configuration register specified by Address.
+  The value written to the PCI configuration register is returned.
+  This function must guarantee that all PCI read and write operations are serialized.
+
+  If any reserved bits in Address are set, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+  @param  Address   The address that encodes the PCI Segment, Bus, Device, Function, and Register.
+  @param  AndData   The value to AND with the PCI configuration register.
+  @param  OrData    The value to OR with the PCI configuration register.
+
+  @return The value written to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciSegmentAndThenOr32 (
+  IN UINT64                    Address,
+  IN UINT32                    AndData,
+  IN UINT32                    OrData
+  )
+{
+  return PciSegmentWrite32 (Address, (PciSegmentRead32 (Address) & AndData) | OrData);
+}
+/**
+  Reads a range of PCI configuration registers into a caller supplied buffer.
+
+  Reads the range of PCI configuration registers specified by StartAddress and
+  Size into the buffer specified by Buffer. This function only allows the PCI
+  configuration registers from a single PCI function to be read. Size is
+  returned. When possible 32-bit PCI configuration read cycles are used to read
+  from StartAdress to StartAddress + Size. Due to alignment restrictions, 8-bit
+  and 16-bit PCI configuration read cycles may be used at the beginning and the
+  end of the range.
+
+  If any reserved bits in StartAddress are set, then ASSERT().
+  If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
+  If Size > 0 and Buffer is NULL, then ASSERT().
+
+  @param  StartAddress  The starting address that encodes the PCI Segment, Bus, Device,
+                        Function and Register.
+  @param  Size          The size in bytes of the transfer.
+  @param  Buffer        The pointer to a buffer receiving the data read.
+
+  @return Size
+
+**/
+UINTN
+EFIAPI
+PciSegmentReadBuffer (
+  IN  UINT64                   StartAddress,
+  IN  UINTN                    Size,
+  OUT VOID                     *Buffer
+  )
+{
+  UINTN                                ReturnValue;
+
+  ASSERT_INVALID_PCI_SEGMENT_ADDRESS (StartAddress, 0);
+  ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000);
+
+  if (Size == 0) {
+    return Size;
+  }
+
+  ASSERT (Buffer != NULL);
+  if (Buffer == NULL) {
+    return 0;
+  }
+
+  //
+  // Save Size for return
+  //
+  ReturnValue = Size;
+
+  if ((StartAddress & BIT0) != 0) {
+    //
+    // Read a byte if StartAddress is byte aligned
+    //
+    *(volatile UINT8 *)Buffer = PciSegmentRead8 (StartAddress);
+    StartAddress += sizeof (UINT8);
+    Size -= sizeof (UINT8);
+    Buffer = (UINT8*)Buffer + 1;
+  }
+
+  if (Size >= sizeof (UINT16) && (StartAddress & BIT1) != 0) {
+    //
+    // Read a word if StartAddress is word aligned
+    //
+    WriteUnaligned16 (Buffer, PciSegmentRead16 (StartAddress));
+    StartAddress += sizeof (UINT16);
+    Size -= sizeof (UINT16);
+    Buffer = (UINT16*)Buffer + 1;
+  }
+
+  while (Size >= sizeof (UINT32)) {
+    //
+    // Read as many double words as possible
+    //
+    WriteUnaligned32 (Buffer, PciSegmentRead32 (StartAddress));
+    StartAddress += sizeof (UINT32);
+    Size -= sizeof (UINT32);
+    Buffer = (UINT32*)Buffer + 1;
+  }
+
+  if (Size >= sizeof (UINT16)) {
+    //
+    // Read the last remaining word if exist
+    //
+    WriteUnaligned16 (Buffer, PciSegmentRead16 (StartAddress));
+    StartAddress += sizeof (UINT16);
+    Size -= sizeof (UINT16);
+    Buffer = (UINT16*)Buffer + 1;
+  }
+
+  if (Size >= sizeof (UINT8)) {
+    //
+    // Read the last remaining byte if exist
+    //
+    *(volatile UINT8 *)Buffer = PciSegmentRead8 (StartAddress);
+  }
+
+  return ReturnValue;
+}
+
+/**
+  Copies the data in a caller supplied buffer to a specified range of PCI
+  configuration space.
+
+  Writes the range of PCI configuration registers specified by StartAddress and
+  Size from the buffer specified by Buffer. This function only allows the PCI
+  configuration registers from a single PCI function to be written. Size is
+  returned. When possible 32-bit PCI configuration write cycles are used to
+  write from StartAdress to StartAddress + Size. Due to alignment restrictions,
+  8-bit and 16-bit PCI configuration write cycles may be used at the beginning
+  and the end of the range.
+
+  If any reserved bits in StartAddress are set, then ASSERT().
+  If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
+  If Size > 0 and Buffer is NULL, then ASSERT().
+
+  @param  StartAddress  The starting address that encodes the PCI Segment, Bus, Device,
+                        Function and Register.
+  @param  Size          The size in bytes of the transfer.
+  @param  Buffer        The pointer to a buffer containing the data to write.
+
+  @return The parameter of Size.
+
+**/
+UINTN
+EFIAPI
+PciSegmentWriteBuffer (
+  IN UINT64                    StartAddress,
+  IN UINTN                     Size,
+  IN VOID                      *Buffer
+  )
+{
+  UINTN                                ReturnValue;
+
+  ASSERT_INVALID_PCI_SEGMENT_ADDRESS (StartAddress, 0);
+  ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000);
+
+  if (Size == 0) {
+    return 0;
+  }
+
+  ASSERT (Buffer != NULL);
+  if (Buffer == NULL) {
+    return 0;
+  }
+
+  //
+  // Save Size for return
+  //
+  ReturnValue = Size;
+
+  if ((StartAddress & BIT0) != 0) {
+    //
+    // Write a byte if StartAddress is byte aligned
+    //
+    PciSegmentWrite8 (StartAddress, *(UINT8*) Buffer);
+    StartAddress += sizeof (UINT8);
+    Size -= sizeof (UINT8);
+    Buffer = (UINT8*) Buffer + 1;
+  }
+
+  if (Size >= sizeof (UINT16) && (StartAddress & BIT1) != 0) {
+    //
+    // Write a word if StartAddress is word aligned
+    //
+    PciSegmentWrite16 (StartAddress, ReadUnaligned16 (Buffer));
+    StartAddress += sizeof (UINT16);
+    Size -= sizeof (UINT16);
+    Buffer = (UINT16*) Buffer + 1;
+  }
+
+  while (Size >= sizeof (UINT32)) {
+    //
+    // Write as many double words as possible
+    //
+    PciSegmentWrite32 (StartAddress, ReadUnaligned32 (Buffer));
+    StartAddress += sizeof (UINT32);
+    Size -= sizeof (UINT32);
+    Buffer = (UINT32*) Buffer + 1;
+  }
+
+  if (Size >= sizeof (UINT16)) {
+    //
+    // Write the last remaining word if exist
+    //
+    PciSegmentWrite16 (StartAddress, ReadUnaligned16 (Buffer));
+    StartAddress += sizeof (UINT16);
+    Size -= sizeof (UINT16);
+    Buffer = (UINT16*) Buffer + 1;
+  }
+
+  if (Size >= sizeof (UINT8)) {
+    //
+    // Write the last remaining byte if exist
+    //
+    PciSegmentWrite8 (StartAddress, *(UINT8*) Buffer);
+  }
+
+  return ReturnValue;
+}
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Library/BaseSiConfigBlockLib/BaseSiConfigBlockLib.c b/Silicon/Intel/AlderlakeSiliconPkg/Library/BaseSiConfigBlockLib/BaseSiConfigBlockLib.c
new file mode 100644
index 0000000000..93290d8371
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Library/BaseSiConfigBlockLib/BaseSiConfigBlockLib.c
@@ -0,0 +1,87 @@
+/** @file
+  This file is BaseSiConfigBlockLib library is used to add config blocks
+  to config block header.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <ConfigBlock.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/ConfigBlockLib.h>
+#include <Library/SiConfigBlockLib.h>
+
+
+/**
+  GetComponentConfigBlockTotalSize get config block table total size.
+
+  @param[in] ComponentBlocks    Component blocks array
+  @param[in] TotalBlockCount    Number of blocks
+
+  @retval                       Size of config block table
+**/
+UINT16
+EFIAPI
+GetComponentConfigBlockTotalSize (
+  IN COMPONENT_BLOCK_ENTRY *ComponentBlocks,
+  IN UINT16                TotalBlockCount
+  )
+{
+  UINT16            TotalBlockSize;
+  UINT16            BlockCount;
+
+  TotalBlockSize = 0;
+  for (BlockCount = 0 ; BlockCount < TotalBlockCount; BlockCount++) {
+    TotalBlockSize += (UINT32) ComponentBlocks[BlockCount].Size;
+  }
+
+  return TotalBlockSize;
+}
+
+/**
+  AddComponentConfigBlocks add all config blocks.
+
+  @param[in] ConfigBlockTableAddress    The pointer to add config blocks
+  @param[in] ComponentBlocks            Config blocks array
+  @param[in] TotalBlockCount            Number of blocks
+
+  @retval EFI_SUCCESS                   The policy default is initialized.
+  @retval EFI_OUT_OF_RESOURCES          Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+AddComponentConfigBlocks (
+  IN VOID                  *ConfigBlockTableAddress,
+  IN COMPONENT_BLOCK_ENTRY *ComponentBlocks,
+  IN UINT16                TotalBlockCount
+  )
+{
+  UINT16            BlockCount;
+  VOID              *ConfigBlockPointer;
+  CONFIG_BLOCK      ConfigBlockBuf;
+  EFI_STATUS        Status;
+
+  Status = EFI_SUCCESS;
+
+  //
+  // Initialize ConfigBlockPointer to NULL
+  //
+  ConfigBlockPointer = NULL;
+  //
+  // Loop to identify each config block from ComponentBlocks[] Table and add each of them
+  //
+  for (BlockCount = 0; BlockCount < TotalBlockCount; BlockCount++) {
+    ZeroMem (&ConfigBlockBuf, sizeof (CONFIG_BLOCK));
+    CopyMem (&(ConfigBlockBuf.Header.GuidHob.Name), ComponentBlocks[BlockCount].Guid, sizeof (EFI_GUID));
+    ConfigBlockBuf.Header.GuidHob.Header.HobLength = ComponentBlocks[BlockCount].Size;
+    ConfigBlockBuf.Header.Revision                 = ComponentBlocks[BlockCount].Revision;
+    ConfigBlockPointer = (VOID *)&ConfigBlockBuf;
+    Status = AddConfigBlock ((VOID *)ConfigBlockTableAddress, (VOID *)&ConfigBlockPointer);
+    ASSERT_EFI_ERROR (Status);
+    if (ComponentBlocks[BlockCount].LoadDefault != NULL) {
+      ComponentBlocks[BlockCount].LoadDefault (ConfigBlockPointer);
+    }
+  }
+  return Status;
+}
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Library/BaseSiConfigBlockLib/BaseSiConfigBlockLib.inf b/Silicon/Intel/AlderlakeSiliconPkg/Library/BaseSiConfigBlockLib/BaseSiConfigBlockLib.inf
new file mode 100644
index 0000000000..097095ef0d
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Library/BaseSiConfigBlockLib/BaseSiConfigBlockLib.inf
@@ -0,0 +1,32 @@
+## @file
+# Component description file for the BaseSiConfigBlockLib library.
+#
+#   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+#   SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = BaseSiConfigBlockLib
+FILE_GUID = 6C068D0F-F48E-48CB-B369-433E507AF4A2
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = SiConfigBlockLib
+
+
+[LibraryClasses]
+DebugLib
+IoLib
+ConfigBlockLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+AlderlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+BaseSiConfigBlockLib.c
+
+
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Library/PeiDxeSmmReserveMmio64SizeLib/PeiDxeSmmReserveMmio64SizeLib.c b/Silicon/Intel/AlderlakeSiliconPkg/Library/PeiDxeSmmReserveMmio64SizeLib/PeiDxeSmmReserveMmio64SizeLib.c
new file mode 100644
index 0000000000..90d6be2feb
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Library/PeiDxeSmmReserveMmio64SizeLib/PeiDxeSmmReserveMmio64SizeLib.c
@@ -0,0 +1,22 @@
+/** @file
+  PEI/DXE/SMM library for reserved 64-bit MMIO space.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Library/PeiDxeSmmReserveMmio64SizeLib.h>
+
+/**
+  The function return the 64 bit MMIO size to reserve.
+
+  @retval The 64-bit MMIO size
+**/
+UINT64
+ReserveMmio64Size (
+  VOID
+  )
+{
+  return 0;
+}
\ No newline at end of file
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Library/PeiDxeSmmReserveMmio64SizeLib/PeiDxeSmmReserveMmio64SizeLib.inf b/Silicon/Intel/AlderlakeSiliconPkg/Library/PeiDxeSmmReserveMmio64SizeLib/PeiDxeSmmReserveMmio64SizeLib.inf
new file mode 100644
index 0000000000..ed2b7d6d50
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Library/PeiDxeSmmReserveMmio64SizeLib/PeiDxeSmmReserveMmio64SizeLib.inf
@@ -0,0 +1,28 @@
+## @file
+# PEI/DXE/SMM library for reserved 64-bit MMIO space.
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+#   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+#   SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmReserveMmio64Size
+FILE_GUID = 4CF5E3F4-025A-48CA-8E97-7B2BD5D4391F
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PeiDxeSmmReserveMmio64Size
+
+[LibraryClasses]
+
+[Packages]
+MdePkg/MdePkg.dec
+AlderlakeSiliconPkg/SiPkg.dec
+
+[Sources]
+PeiDxeSmmReserveMmio64SizeLib.c
+
+[Pcd]
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Library/PeiPostMemSiliconPolicyInitLib/PeiPostMemSiliconPolicyInitLib.c b/Silicon/Intel/AlderlakeSiliconPkg/Library/PeiPostMemSiliconPolicyInitLib/PeiPostMemSiliconPolicyInitLib.c
new file mode 100644
index 0000000000..a9d6c7e265
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Library/PeiPostMemSiliconPolicyInitLib/PeiPostMemSiliconPolicyInitLib.c
@@ -0,0 +1,94 @@
+/** @file
+  This library initialize Silicon Policy for PostMemory.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Ppi/SiPolicy.h>
+#include <Ppi/PeiSiDefaultPolicy.h>
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/SiPolicyLib.h>
+
+/**
+  Performs silicon post-mem policy initialization.
+
+  The returned data must be used as input data for SiliconPolicyDonePostMem (),
+  and SiliconPolicyUpdateLib.SiliconPolicyUpdatePostMem ().
+
+  @param[in, out] Policy       Pointer to policy.
+  @return the initialized policy.
+**/
+VOID *
+EFIAPI
+SiliconPolicyInitPostMem (
+  IN OUT VOID *Policy
+  )
+{
+  EFI_STATUS                        Status;
+  SI_POLICY_PPI                     *SiPolicyPpi;
+  PEI_SI_DEFAULT_POLICY_INIT_PPI    *PeiSiDefaultPolicyInitPpi;
+
+  DEBUG ((DEBUG_INFO, "Silicon PEI Policy Initialization Start in Post-Memory...\n"));
+
+  ASSERT (Policy == NULL);
+  SiPolicyPpi = NULL;
+  PeiSiDefaultPolicyInitPpi = NULL;
+
+  //
+  // Locate Policy init PPI to install default silicon policy
+  //
+  Status = PeiServicesLocatePpi (
+             &gSiDefaultPolicyInitPpiGuid,
+             0,
+             NULL,
+             (VOID **) &PeiSiDefaultPolicyInitPpi
+             );
+  ASSERT_EFI_ERROR (Status);
+  if (PeiSiDefaultPolicyInitPpi != NULL) {
+    Status = PeiSiDefaultPolicyInitPpi->PeiPolicyInit ();
+    ASSERT_EFI_ERROR (Status);
+    if (Status == EFI_SUCCESS) {
+      Status = PeiServicesLocatePpi (
+                 &gSiPolicyPpiGuid,
+                 0,
+                 NULL,
+                 (VOID **) &SiPolicyPpi
+                 );
+      ASSERT_EFI_ERROR (Status);
+    }
+  }
+
+  if (SiPolicyPpi == NULL) {
+    DEBUG ((DEBUG_ERROR, "Fail to create default policy!\n"));
+    return NULL;
+  }
+
+
+  return SiPolicyPpi;
+}
+
+/**
+  The silicon post-mem policy is finalized.
+  Silicon code can do initialization based upon the policy data.
+
+  The input Policy must be returned by SiliconPolicyInitPostMem().
+
+  @param[in] Policy       Pointer to policy.
+  @retval RETURN_SUCCESS The policy is handled consumed by silicon code.
+**/
+RETURN_STATUS
+EFIAPI
+SiliconPolicyDonePostMem (
+  IN VOID *Policy
+  )
+{
+  EFI_STATUS                   Status;
+
+  Status = SiInstallPolicyReadyPpi ();
+  ASSERT_EFI_ERROR (Status);
+  DEBUG ((DEBUG_INFO, "Silicon PEI Policy Initialization Done in Post-Memory\n"));
+
+  return Status;
+}
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Library/PeiPostMemSiliconPolicyInitLib/PeiPostMemSiliconPolicyInitLib.inf b/Silicon/Intel/AlderlakeSiliconPkg/Library/PeiPostMemSiliconPolicyInitLib/PeiPostMemSiliconPolicyInitLib.inf
new file mode 100644
index 0000000000..62184b39d2
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Library/PeiPostMemSiliconPolicyInitLib/PeiPostMemSiliconPolicyInitLib.inf
@@ -0,0 +1,39 @@
+## @file
+# Component information file for Silicon Policy Init Library
+# This library implements Silicon Policy Initialization for PostMemory.
+#
+#   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+#   SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PeiPostMemSiliconPolicyInitLib
+  FILE_GUID                      = 20B51FFB-93D3-4546-9F13-2C91AEEF9212
+  MODULE_TYPE                    = PEIM
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = SiliconPolicyInitLib
+
+[LibraryClasses]
+  BaseLib
+  PcdLib
+  PeiServicesLib
+  DebugLib
+  SiPolicyLib
+
+[Packages]
+  MdePkg/MdePkg.dec
+  AlderlakeSiliconPkg/SiPkg.dec
+
+[Sources]
+  PeiPostMemSiliconPolicyInitLib.c
+
+[Pcd]
+  gSiPkgTokenSpaceGuid.PcdDumpDefaultSiliconPolicy
+
+[Ppis]
+  gSiDefaultPolicyInitPpiGuid
+  gEfiPeiMpServicesPpiGuid
+
+[Depex]
+  gSiDefaultPolicyInitPpiGuid
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Library/PeiPreMemSiliconPolicyInitLib/PeiPreMemSiliconPolicyInitLib.c b/Silicon/Intel/AlderlakeSiliconPkg/Library/PeiPreMemSiliconPolicyInitLib/PeiPreMemSiliconPolicyInitLib.c
new file mode 100644
index 0000000000..74fb47a73d
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Library/PeiPreMemSiliconPolicyInitLib/PeiPreMemSiliconPolicyInitLib.c
@@ -0,0 +1,98 @@
+/** @file
+  This library initialize Silicon Policy for PreMemory.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Ppi/SiPolicy.h>
+#include <Ppi/PeiPreMemSiDefaultPolicy.h>
+#include <Library/DebugLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/SiPolicyLib.h>
+
+
+/**
+  Performs silicon pre-mem policy initialization.
+
+  The returned data must be used as input data for SiliconPolicyDonePreMem (),
+  and SiliconPolicyUpdateLib.SiliconPolicyUpdatePreMem ().
+
+  @param[in, out] Policy       Pointer to policy.
+  @return the initialized policy.
+**/
+VOID *
+EFIAPI
+SiliconPolicyInitPreMem (
+  IN OUT VOID *Policy
+  )
+{
+  EFI_STATUS                             Status;
+  SI_PREMEM_POLICY_PPI                   *SiPreMemPolicyPpi;
+  PEI_PREMEM_SI_DEFAULT_POLICY_INIT_PPI  *PeiPreMemSiDefaultPolicyInitPpi;
+
+  DEBUG ((DEBUG_INFO, "Silicon PEI Policy Initialization Start in Pre-Memory...\n"));
+
+  ASSERT (Policy == NULL);
+  SiPreMemPolicyPpi = NULL;
+  PeiPreMemSiDefaultPolicyInitPpi = NULL;
+
+  //
+  // Locate Policy init PPI to install default silicon policy
+  //
+  Status = PeiServicesLocatePpi (
+             &gSiPreMemDefaultPolicyInitPpiGuid,
+             0,
+             NULL,
+             (VOID **) &PeiPreMemSiDefaultPolicyInitPpi
+             );
+  ASSERT_EFI_ERROR (Status);
+  if (PeiPreMemSiDefaultPolicyInitPpi != NULL) {
+    Status = PeiPreMemSiDefaultPolicyInitPpi->PeiPreMemPolicyInit ();
+    ASSERT_EFI_ERROR (Status);
+    if (Status == EFI_SUCCESS) {
+      Status = PeiServicesLocatePpi (
+                 &gSiPreMemPolicyPpiGuid,
+                 0,
+                 NULL,
+                 (VOID **) &SiPreMemPolicyPpi
+                 );
+      ASSERT_EFI_ERROR (Status);
+    }
+  }
+
+  if (SiPreMemPolicyPpi == NULL) {
+    DEBUG ((DEBUG_ERROR, "Fail to create default policy!\n"));
+    return NULL;
+  }
+
+  return SiPreMemPolicyPpi;
+}
+
+/**
+  The silicon pre-mem policy is finalized.
+  Silicon code can do initialization based upon the policy data.
+
+  The input Policy must be returned by SiliconPolicyInitPreMem().
+
+  @param[in] Policy       Pointer to policy.
+  @retval RETURN_SUCCESS The policy is handled consumed by silicon code.
+**/
+RETURN_STATUS
+EFIAPI
+SiliconPolicyDonePreMem (
+  IN VOID *Policy
+  )
+{
+  EFI_STATUS                   Status;
+  //
+  // Install PreMem Policy Ready PPI
+  // While installs PreMemPolicyReadyPpi, RC assumes the Policy is ready and finalized. So please
+  // update and override any setting before calling this function.
+  //
+  Status = SiPreMemInstallPolicyReadyPpi ();
+  ASSERT_EFI_ERROR (Status);
+
+  DEBUG ((DEBUG_INFO, "Silicon PEI Policy Initialization Done in Pre-Memory\n"));
+
+  return Status;
+}
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Library/PeiPreMemSiliconPolicyInitLib/PeiPreMemSiliconPolicyInitLib.inf b/Silicon/Intel/AlderlakeSiliconPkg/Library/PeiPreMemSiliconPolicyInitLib/PeiPreMemSiliconPolicyInitLib.inf
new file mode 100644
index 0000000000..d5ce714ce5
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Library/PeiPreMemSiliconPolicyInitLib/PeiPreMemSiliconPolicyInitLib.inf
@@ -0,0 +1,36 @@
+## @file
+# Component information file for Silicon Policy Init Library
+# This library implements Silicon Policy Initialization for PreMemory.
+#
+#   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+#   SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PeiPreMemSiliconPolicyInitLib
+  FILE_GUID                      = 1FB4B175-0BB6-4137-A4AC-EA48FCE83862
+  MODULE_TYPE                    = PEIM
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = SiliconPolicyInitLib
+
+[LibraryClasses]
+  BaseLib
+  PeiServicesLib
+  DebugLib
+  SiPolicyLib
+
+[Packages]
+  MdePkg/MdePkg.dec
+  AlderlakeSiliconPkg/SiPkg.dec
+
+[Sources]
+  PeiPreMemSiliconPolicyInitLib.c
+
+[Pcd]
+
+[Ppis]
+  gSiPreMemDefaultPolicyInitPpiGuid
+
+[Depex]
+  gSiPreMemDefaultPolicyInitPpiGuid
-- 
2.36.1.windows.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 2/8] AlderlakeSiliconPkg: Add Cpu modules
  2023-06-15 17:52 [PATCH 1/8] AlderlakeSiliconPkg: Add package and library instances Saloni Kasbekar
@ 2023-06-15 17:53 ` Saloni Kasbekar
  2023-06-15 17:53 ` [PATCH 3/8] AlderlakeSiliconPkg/Pch: Add include headers Saloni Kasbekar
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 15+ messages in thread
From: Saloni Kasbekar @ 2023-06-15 17:53 UTC (permalink / raw)
  To: devel
  Cc: Saloni Kasbekar, Sai Chaganty, Nate DeSimone, Isaac Oram,
	Rosen Chuang

Add Cpu/Include, Cpu/IncludePrivate and Cpu/Library

Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Isaac Oram <isaac.w.oram@intel.com>
Cc: Rosen Chuang <rosen.chuang@intel.com>
Signed-off-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
---
 .../Cpu/Include/ConfigBlock/CpuConfig.h       |  86 ++++++++
 .../ConfigBlock/CpuConfigLibPreMemConfig.h    | 195 ++++++++++++++++++
 .../ConfigBlock/CpuSecurityPreMemConfig.h     |  63 ++++++
 .../AlderlakeSiliconPkg/Cpu/Include/CpuRegs.h |  63 ++++++
 .../Cpu/Include/Library/CpuPlatformLib.h      |  42 ++++
 .../Cpu/Include/Protocol/CpuPolicyProtocol.h  |  95 +++++++++
 .../Cpu/Include/Register/CommonMsr.h          |  60 ++++++
 .../IncludePrivate/Library/CpuInfoFruLib.h    |  64 ++++++
 .../CpuPlatformLibrary.c                      |  55 +++++
 .../CpuPlatformLibrary.h                      |  25 +++
 .../PeiDxeSmmCpuPlatformLib.inf               |  41 ++++
 11 files changed, 789 insertions(+)
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuConfig.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuConfigLibPreMemConfig.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuSecurityPreMemConfig.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Cpu/Include/CpuRegs.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Cpu/Include/Library/CpuPlatformLib.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Cpu/Include/Protocol/CpuPolicyProtocol.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Cpu/Include/Register/CommonMsr.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Cpu/IncludePrivate/Library/CpuInfoFruLib.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Cpu/Library/PeiDxeSmmCpuPlatformLib/CpuPlatformLibrary.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Cpu/Library/PeiDxeSmmCpuPlatformLib/CpuPlatformLibrary.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Cpu/Library/PeiDxeSmmCpuPlatformLib/PeiDxeSmmCpuPlatformLib.inf

diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuConfig.h b/Silicon/Intel/AlderlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuConfig.h
new file mode 100644
index 0000000000..9815f8b185
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuConfig.h
@@ -0,0 +1,86 @@
+/** @file
+  CPU Config Block.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _CPU_CONFIG_H_
+#define _CPU_CONFIG_H_
+
+#define CPU_CONFIG_REVISION 1
+
+extern EFI_GUID gCpuConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+  CPU Configuration Structure.
+
+  <b>Revision 1</b>:
+  - Initial version.
+**/
+typedef struct {
+  CONFIG_BLOCK_HEADER   Header;                   ///< Config Block Header
+  UINT32                MicrocodePatchRegionSize;
+  EFI_PHYSICAL_ADDRESS  MicrocodePatchAddress;    ///< Pointer to microcode patch that is suitable for this processor.
+  /**
+    Enable or Disable Advanced Encryption Standard (AES) feature.
+    For some countries, this should be disabled for legal reasons.
+    -    0: Disable
+    - <b>1: Enable</b>
+  **/
+  UINT32 AesEnable           : 1;
+  /**
+    Enable or Disable Trusted Execution Technology (TXT) feature.
+    -    0: Disable
+    - <b>1: Enable</b>
+  **/
+  UINT32 TxtEnable           : 1;
+  UINT32 SkipMpInit          : 1;                 ///< For Fsp only, Silicon Initialization will skip MP Initialization (including BSP) if enabled. For non-FSP, this should always be 0.
+  /**
+    Enable or Disable or Auto for PPIN Support to view Protected Processor Inventory Number.
+    - <b>0: Disable</b>
+    -    1: Enable
+    -    2: Auto : Feature is based on End Of Manufacturing (EOM) flag. If EOM is set, it is disabled.
+  **/
+  UINT32 PpinSupport         : 2;
+  /**
+    Enable or Disable #AC machine check on split lock.
+    - <b>0: Disable</b>
+    -    1: Enable
+  **/
+  UINT32 AcSplitLock         : 1;
+  /**
+  Enable or Disable Avx.
+  -      1: Disable
+  -  <b> 0: Enable</b>
+  **/
+  UINT32 AvxDisable          : 1;
+  /**
+  @deprecated
+  Enable or Disable Avx3.
+  -  <b> 1: Disable</b>
+  -      0: Enable
+  **/
+  UINT32 Avx3Disable         : 1;
+  /**
+    Enable or Disable X2APIC Support.
+    - <b>0: Disable</b>
+    -    1: Enable
+  **/
+  UINT32 X2ApicSupport       : 1;
+  UINT32 RsvdBits            : 23;                ///< Reserved for future use
+  /**
+    Provide the option for platform to override the MaxSpeed field of Smbios Type 4.
+    Value 4000 means 4000MHz.
+    If this value is not zero, it dominates the field.
+    If this value is zero, CPU RC will update the field according to the max radio.
+    <b>default is 0.</b>
+  **/
+  UINT16 SmbiosType4MaxSpeedOverride;
+  UINT8  Reserved0[2];                            ///< Reserved for future use
+} CPU_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _CPU_CONFIG_H_
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuConfigLibPreMemConfig.h b/Silicon/Intel/AlderlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuConfigLibPreMemConfig.h
new file mode 100644
index 0000000000..68d4effe3f
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuConfigLibPreMemConfig.h
@@ -0,0 +1,195 @@
+/** @file
+  CPU Security PreMemory Config Block.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _CPU_CONFIG_LIB_PREMEM_CONFIG_H_
+#define _CPU_CONFIG_LIB_PREMEM_CONFIG_H_
+
+#define CPU_CONFIG_LIB_PREMEM_CONFIG_REVISION 1
+
+extern EFI_GUID gCpuConfigLibPreMemConfigGuid;
+
+
+#pragma pack (push,1)
+
+/**
+  CPU Config Library PreMemory Configuration Structure.
+
+  <b>Revision 1</b>:
+  - Initial version.
+**/
+typedef struct {
+  CONFIG_BLOCK_HEADER Header;            ///< Config Block Header
+  UINT32 HyperThreading             : 1; ///< Enable or Disable Hyper Threading; 0: Disable; <b>1: Enable</b>.
+  /**
+  Sets the boot frequency starting from reset vector.
+   - 0: Maximum battery performance.
+   - 1: Maximum non-turbo performance
+   -<b>2: Turbo performance</b>.
+  @note If Turbo is selected BIOS will start in max non-turbo mode and switch to Turbo mode.
+  **/
+  UINT32 BootFrequency              : 2;
+  /**
+    Number of processor cores to enable.
+    - <b> 0: All cores</b>
+    -     1: 1 core
+    -     2: 2 cores
+    -     3: 3 cores
+  **/
+  UINT32 ActiveCoreCount            : 3; ///< @deprecated due to core active number limitaion.
+  UINT32 JtagC10PowerGateDisable    : 1; ///< False: JTAG is power gated in C10 state. True: keeps the JTAG power up during C10 and deeper power states for debug purpose. <b>0: False<\b>; 1: True.
+  UINT32 BistOnReset                : 1; ///< <b>(Test)</b> Enable or Disable BIST on Reset; <b>0: Disable</b>; 1: Enable.
+  /**
+    Enable or Disable Virtual Machine Extensions (VMX) feature.
+    -    0: Disable
+    - <b>1: Enable</b>
+  **/
+  UINT32 VmxEnable                  : 1;
+  /**
+  Processor Early Power On Configuration FCLK setting.
+   - <b>0: 800 MHz (ULT/ULX)</b>.
+   - <b>1: 1 GHz (DT/Halo)</b>. Not supported on ULT/ULX.
+   - 2: 400 MHz.
+   - 3: Reserved.
+  **/
+  UINT32 FClkFrequency              : 2;
+  /**
+  Enable or Disable CrashLog feature
+    -    0: Disable
+    - <b>1: Enable</b>
+  **/
+  UINT32 CrashLogEnable              : 1;
+
+  /**
+  Enable or Disable Total Memory Encryption (TME) feature.
+    -    0: Disable
+    - <b>1: Enable</b>
+  **/
+  UINT32 TmeEnable                  : 1;
+
+  UINT32 DebugInterfaceEnable       : 2; ///< Enable or Disable processor debug features; 0: Disable; 1: Enable; <b>2: No Change</b>.
+  UINT32 DebugInterfaceLockEnable   : 1; ///< Lock or Unlock debug interface features; 0: Disable; <b>1: Enable</b>.
+
+  /**
+    Number of big cores in processor to enable.
+    And support up to 15 cores.
+    -     0: Disable all cores for Hybrid CPU; Active all cores for Non-Hybrid CPU (MAX 16).
+    -     1: 1 core
+    -     2: 2 cores
+    -     3: 3 cores
+  **/
+  UINT32 ActiveCoreCount1           : 4;
+
+  /**
+  Enables a mailbox command to resolve rare PECI related Sx issues.
+  @note This should only be used on systems that observe PECI Sx issues.
+  - <b>0: Disable</b>
+  -    1: Enable
+  **/
+  UINT32 PeciSxReset                : 1;
+
+  /**
+  Enables the mailbox command to resolve PECI reset issues during Pkg-C10 exit.
+  If Enabled, BIOS will send the CPU message to disable peci reset on C10 exit.
+  The default value <b>0: Disable</b> for CPU's
+  - 0: Disable
+  - 1: Enable
+  **/
+  UINT32 PeciC10Reset               : 1; ///< @deprecated no longer used.
+
+  /**
+    Number of small cores in processor to enable.
+    And support up to 63 cores.
+    -     0: Disable all cores for Hybrid CPU; Active all cores for Non-Hybrid CPU (MAX 64).
+    -     1: 1 core
+    -     2: 2 cores
+    -     3: 3 cores
+  **/
+  UINT32 ActiveSmallCoreCount       : 6;
+
+  /**
+  Enable or Disable CrashLog GPRs dump
+    - <b>0: Disable</b>
+    -    1: Gprs Enabled, Smm Gprs Enabled
+         2: Gprs Enabled, Smm Gprs Disabled
+  **/
+  UINT32 CrashLogGprs               : 2;
+
+  /**
+  Enable or Disable Compute Die SSC configuration.
+    - <b>0: Disable</b>
+    -    1: Enable
+  **/
+  UINT32 ComputeDieSscEnable        : 1;
+
+  /**
+  Enable or Disable Soc Die SSC configuration.
+    - <b>0: Disable</b>
+    -    1: Enable
+  **/
+  UINT32 SocDieSscEnable            : 1;
+
+  /**
+    CpuRatio - Max non-turbo ratio (Flexible Ratio Boot) is set to CpuRatio. <b>0: Disabled</b> If disabled, doesn't override max-non turbo ratio.
+  **/
+  UINT8  CpuRatio;
+
+  /**
+    Number of enabled atom cores on SoC.
+    Default is set to supported core number.
+    -    0      - all core disabled
+    -    1      - enable 1 core
+    -    2      - enable 2 cores
+    -    others - reserved for future use
+  **/
+  UINT8  ActiveSocNorthAtomCoreCount;
+
+  /**
+    SSC configuration value of Compute Die.
+    SSC downspread field encoding. Downspread in percent = SSC_DOWNSPREAD / 100.
+      - <b>0   : invalid</b>
+      -    1   : 0.01%
+      -    2   : 0.02%
+      -    100 : 1%
+  **/
+  UINT8  ComputeDieSscValue;
+
+  /**
+    SSC configuration value of Soc Die.
+    SSC downspread field encoding. Downspread in percent = SSC_DOWNSPREAD / 100.
+      - <b>0   : invalid</b>
+      -    1   : 0.01%
+      -    2   : 0.02%
+      -    100 : 1%
+  **/
+  UINT8  SocDieSscValue;
+
+  /**
+  Clock source of BCLK OC Frequency
+    -    0: SOC
+    - <b>1: CPU</b>
+    -    2: PCH
+    -    3: Ext. Clock (optional)
+  **/
+  UINT32 BclkSource                 : 2;
+  UINT32 RsvdBits                   : 30;
+  /**
+    Determine whether to keep or shutdown INF_DFX power rail. INF_DFX power is up from cold boot.
+      - <b>0   : INF_DFX shutdown</b>
+      -    1   : INF_DFX power up </b>
+  **/
+  UINT8  InfDfxPwrEnable;
+  /**
+    Configuration for boot TDP selection; <b>0: TDP Nominal</b>; 1: TDP Down; 2: TDP Up.
+  **/
+  UINT8  ConfigTdpLevel;
+  UINT8  RsvdByte[2];
+  UINT32 CustomPowerLimit1;
+
+} CPU_CONFIG_LIB_PREMEM_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _CPU_CONFIG_LIB_PREMEM_CONFIG_H_
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuSecurityPreMemConfig.h b/Silicon/Intel/AlderlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuSecurityPreMemConfig.h
new file mode 100644
index 0000000000..c9acd48c84
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuSecurityPreMemConfig.h
@@ -0,0 +1,63 @@
+/** @file
+  CPU Security PreMemory Config Block.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _CPU_SECURITY_PREMEM_CONFIG_H_
+#define _CPU_SECURITY_PREMEM_CONFIG_H_
+
+#define CPU_SECURITY_PREMEM_CONFIG_REVISION 1
+
+extern EFI_GUID gCpuSecurityPreMemConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+  CPU Security PreMemory Configuration Structure.
+
+  <b>Revision 1</b>:
+  - Initial version.
+**/
+typedef struct {
+  CONFIG_BLOCK_HEADER Header;                      ///< Config Block Header
+  UINT32              PrmrrSize;                   ///< PRMRR Size.<b>Software Control: 0x0</b>  32MB: 0x2000000, 64MB: 0x4000000, 128 MB: 0x8000000, 256 MB: 0x10000000, 512 MB: 0x20000000
+  UINT16              BiosSize;                    ///< Flash information for BIOS Guard: BIOS Size in KB.
+  UINT8               Reserved[2];                 ///< Reserved for future use
+/**
+   Enable or Disable BIOS Guard; 0: Disable; <b>1: Enable</b>.
+    - This is an optional feature and can be opted out.
+    - If this policy is set to Disabled, the policies in the BIOS_GUARD_CONFIG will be ignored.
+    - If PeiBiosGuardLibNull is used, this policy will have no effect.
+**/
+  UINT32              BiosGuard               :  1;
+  UINT32              BiosGuardToolsInterface :  1; ///< BIOS Guard Tools Interface; <b>0: Disable</b>, 1:Enable
+/**
+   Enable or Disable Software Guard Extensions; <b>0: Disable</b>; 1: Enable.
+    - This is an optional feature and can be opted out.
+    - If this policy is set to Disabled, the policies in the CPU_SGX_CONFIG will be ignored.
+    - If BaseSoftwareGuardLibNull is used, this policy will have no effect.
+**/
+  UINT32              EnableSgx               :  1;  ///< @deprecated due to Non-POR feature.
+/**
+   Enable or Disable Trusted Execution Technology; <b>0: Disable</b>; 1: Enable.
+    - This is an optional feature and can be opted out.
+    - If this policy is set to Disabled, the policies in the CPU_TXT_PREMEM_CONFIG will be ignored.
+    - If PeiTxtLibNull is used, this policy will have no effect.
+**/
+  UINT32              Txt                     :  1;
+  UINT32              SkipStopPbet            :  1; ///< <b>(Test)</b> Skip Stop PBET Timer; <b>0: Disable</b>; 1: Enable.
+  ///
+  /// <b>(Test)</b> This policy indicates whether or not BIOS should allocate PRMRR memory for C6DRAM power gating feature.
+  ///  - 0: Don't allocate any PRMRR memory for C6DRAM power gating feature.
+  ///  - <b>1: Allocate PRMRR memory for C6DRAM power gating feature</b>.
+  ///
+  UINT32              EnableC6Dram            :  1;
+  UINT32              ResetAux                :  1; ///< <b>(Test)</b> Reset Auxiliary content, <b>0: Disabled</b>, 1: Enabled
+  UINT32              TxtAcheckRequest        :  1; ///< <b>(Test)</b> AcheckRequest <b>0: Disabled</b>, 1: Enabled. When Enabled, it will call Acheck regardless of crashcode value
+  UINT32              RsvdBits                : 24; ///< Reserved for future use
+} CPU_SECURITY_PREMEM_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _CPU_SECURITY_CONFIG_H_
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Cpu/Include/CpuRegs.h b/Silicon/Intel/AlderlakeSiliconPkg/Cpu/Include/CpuRegs.h
new file mode 100644
index 0000000000..aac4e21e2a
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Cpu/Include/CpuRegs.h
@@ -0,0 +1,63 @@
+/** @file
+  Register names for CPU registers
+
+  <b>Conventions</b>
+  - Definitions beginning with "MSR_" are MSRs
+  - Definitions beginning with "R_" are registers
+  - Definitions beginning with "B_" are bits within registers
+  - Definitions beginning with "V_" are meaningful values of bits within the registers
+  - Definitions beginning with "S_" are register sizes
+  - Definitions beginning with "N_" are the bit position
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _CPU_REGS_H_
+#define _CPU_REGS_H_
+
+///
+/// Other defines
+///
+#ifndef CPU_FEATURE_DISABLE
+#define CPU_FEATURE_DISABLE  0
+#endif
+#ifndef CPU_FEATURE_ENABLE
+#define CPU_FEATURE_ENABLE   1
+#endif
+
+//
+// Processor Definitions
+//
+#define CPUID_FULL_STEPPING                        0x0000000F
+#define CPUID_FULL_FAMILY_MODEL                    0x0FFF0FF0
+
+#define BITS(x) (1 << (x))
+
+/**
+Notes :
+  1.  Bit position always starts at 0.
+  2.  Following macros are applicable only for Word aligned integers.
+**/
+#define BIT(Pos, Value)               (1 << (Pos) & (Value))
+
+typedef UINT32       CPU_FAMILY;
+
+///
+/// Enums for CPU SKU IDs
+///
+typedef enum {
+  EnumCpuUlt        = 0,
+  EnumCpuTrad,
+  EnumCpuUlx,
+  EnumCpuHalo,
+  EnumCpuUnknown
+} CPU_SKU;
+
+///
+/// Enums for CPU Generation
+///
+typedef enum {
+  EnumAdlCpu = 0,
+  EnumCpuUnknownGeneration = 255
+} CPU_GENERATION;
+#endif
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Cpu/Include/Library/CpuPlatformLib.h b/Silicon/Intel/AlderlakeSiliconPkg/Cpu/Include/Library/CpuPlatformLib.h
new file mode 100644
index 0000000000..05afbf1db3
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Cpu/Include/Library/CpuPlatformLib.h
@@ -0,0 +1,42 @@
+/** @file
+  Header file for CpuPlatform Lib.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _CPU_PLATFORM_LIB_H_
+#define _CPU_PLATFORM_LIB_H_
+
+#include <Uefi.h>
+#include <CpuRegs.h>
+#include <CpuGenInfo.h>
+
+///
+/// Table to convert Seconds into equivalent MSR values
+/// This table is used for PL1, Pl2 and RATL TDP Time Window programming
+///
+extern GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mSecondsToMsrValueMapTable[][2];
+
+/**
+  Return CPU Sku
+
+  @retval UINT8              CPU Sku
+**/
+UINT8
+EFIAPI
+GetCpuSku (
+  VOID
+  );
+
+/**
+  This function returns the supported Physical Address Size
+
+  @retval supported Physical Address Size.
+**/
+UINT8
+GetMaxPhysicalAddressSize (
+  VOID
+  );
+
+#endif
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Cpu/Include/Protocol/CpuPolicyProtocol.h b/Silicon/Intel/AlderlakeSiliconPkg/Cpu/Include/Protocol/CpuPolicyProtocol.h
new file mode 100644
index 0000000000..e56ec3e2f2
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Cpu/Include/Protocol/CpuPolicyProtocol.h
@@ -0,0 +1,95 @@
+/** @file
+  Protocol used for specifying platform related CPU information and policy setting.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _CPU_POLICY_PROTOCOL_H_
+#define _CPU_POLICY_PROTOCOL_H_
+
+//
+// DXE_CPU_POLICY_PROTOCOL revisions
+//
+#define DXE_CPU_POLICY_PROTOCOL_REVISION 1
+
+extern EFI_GUID gDxeCpuPolicyProtocolGuid;
+
+#pragma pack (push,1)
+
+/**
+  The protocol allows the platform code to publish a set of configuration information that the
+  CPU drivers will use to configure the processor in the DXE phase.
+  This Policy Protocol needs to be initialized for CPU configuration.
+  @note The Protocol has to be published before processor DXE drivers are dispatched.
+
+  This member specifies the revision of the Cpu Policy protocol. This field is used to indicate backward
+  compatible changes to the protocol. Any such changes to this protocol will result in an update in the revision number.
+
+  <b>Revision 1</b>:
+   - Initial version
+   **/
+typedef struct {
+  /**
+  Policy to obtain DGR status from setup option.
+   - <b>0: DGR is disabled</b>.
+   - 1: DGR is enabled.
+  **/
+  UINT32                         DgrEnable           : 1;
+  /**
+  Policy to obtain DGR-SPA status from setup option.
+   - <b>0: DGR-SPA is disabled</b>.
+   - 1: DGR-SPA is enabled.
+  **/
+  UINT32                         DgrSpaEnable        : 1;
+  /**
+  Policy to obtain DGR State Save support status from setup option.
+   - <b>0: SMM can have Read/Write access to SMM State Save region </b>.
+   - 1: SMM State Save region access is protected.
+  **/
+  UINT32                         DgrStateSaveProtect  : 1;
+  /**
+  Policy to obtain DGR Skip OEM Exception Handler from setup option.
+   - <b>0: OEM exception handler will execute normal way in case of resource access violation</b>.
+   - 1: OEM Exception handler will be skipped and exceution continues in case of resource access volation.
+  **/
+  UINT32                         DgrSkipOemExceptionHandler : 1;
+  UINT32                         RsvdBit                    : 26;  ///< Reserved bits, align to multiple 32;
+
+  UINT8                          Revision;                  ///< Current revision of policy.
+  /**
+  Indidates if SMM Save State saved in MSRs.
+  if enabled, SMM Save State will use the MSRs instead of the memory.
+   - <b>0: FALSE</b> - SMM Save State will use the memory.
+   - 1: TRUE - SMM Save State will use the MSRs.
+  **/
+  UINT8                          SmmMsrSaveStateEnable;
+  /**
+  Indidates if SMM Delay feature is supported.
+   - 0: FALSE - SMM Delay feature is not supported.
+   - <b>1: TRUE</b> - SMM Delay feature is supported.
+  **/
+  UINT8                          SmmUseDelayIndication;
+  /**
+  Indidates if SMM Block feature is supported.
+   - 0: FALSE - SMM Block feature is not supported.
+   - <b>1: TRUE</b> - SMM Block feature is supported.
+  **/
+  UINT8                          SmmUseBlockIndication;
+  /**
+  Indidates if SMM Enable/Disable feature is supported.
+   - 0: FALSE - SMM Enable/Disable feature is not supported.
+   - <b>1: TRUE</b> - SMM Enable/Disable feature is supported.
+  **/
+  UINT8                          SmmUseSmmEnableIndication;
+  /**
+  Specifies if SMM Proccessor Trace will be Enabled.
+   - <b>0: FALSE</b> - SMM Proccessor Trace will be disabled.<BR>
+   - 1: TRUE - SMM Proccessor Trace will be enabled.<BR>
+  **/
+  UINT8                          SmmProcTraceEnable;
+  UINT8                          ReservedByte[6];           ///< Reserved bytes, align to multiple 8.
+} DXE_CPU_POLICY_PROTOCOL;
+
+#pragma pack (pop)
+
+#endif
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Cpu/Include/Register/CommonMsr.h b/Silicon/Intel/AlderlakeSiliconPkg/Cpu/Include/Register/CommonMsr.h
new file mode 100644
index 0000000000..dc6fb5cb08
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Cpu/Include/Register/CommonMsr.h
@@ -0,0 +1,60 @@
+
+/** @file
+  CommonMsr.h
+
+  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _COMMONMSR_h
+#define _COMMONMSR_h
+#include <Base.h>
+
+/**
+  This is a Read Only MSR that is shared in the processor package and used to
+  determine the current count of enabled Cores and Threads.
+**/
+#define MSR_CORE_THREAD_COUNT 0x00000035
+
+typedef union {
+  ///
+  /// Individual bit fields
+  ///
+  struct {
+    UINT32 Threadcount : 16;
+
+                            /* Bits[15:0], Access Type=RO_V, default=None*/
+
+                            /*
+                               The Thread Count reflects the enabled threads
+                               based on the factory-configured thread count and
+                               the value of the RESOLVED_CORES_MASK register
+                               for Server processors or the PCH Soft Reset Data
+                               register for Client processors at reset time.
+                            */
+    UINT32 Corecount : 16;
+
+                            /* Bits[31:16], Access Type=RO_V, default=None*/
+
+                            /*
+                               The Core Count reflects the enabled cores based
+                               on the factory-configured core count and the
+                               value of the RESOLVED_CORES_MASK register for
+                               Server processors or the PCH Soft Reset Data
+                               register for Client processors at reset time.
+                            */
+    UINT32 Rsvd32 : 32;
+
+                            /* Bits[63:32], Access Type=RO, default=None*/
+
+                            /* Reserved */
+
+  } Bits;
+
+  UINT32 Uint32;
+  UINT64 Uint64;
+
+} MSR_CORE_THREAD_COUNT_REGISTER;
+
+
+#endif /* _COMMONMSR_h */
\ No newline at end of file
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Cpu/IncludePrivate/Library/CpuInfoFruLib.h b/Silicon/Intel/AlderlakeSiliconPkg/Cpu/IncludePrivate/Library/CpuInfoFruLib.h
new file mode 100644
index 0000000000..4095c51efb
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Cpu/IncludePrivate/Library/CpuInfoFruLib.h
@@ -0,0 +1,64 @@
+ /** @file
+  This file contains Cpu Information for specific generation.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _CPU_INFO_FRU_LIB_H_
+#define _CPU_INFO_FRU_LIB_H_
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <CpuRegs.h>
+#include <CpuGenInfo.h>
+#include <Register/SaRegsHostBridge.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PcdLib.h>
+
+///
+/// Override table structure for cTDP and non-cTDP skus.
+/// Non-cTDP parts would have '0' data for TDP level information.
+///
+typedef struct {
+  UINTN  CpuIdentifier;
+  UINT16 SkuPackageTdp;
+  UINTN  MsrPowerLimit1;
+  UINTN  MsrPowerLimit2;
+  UINTN  CtdpUpPowerLimit1;
+  UINTN  CtdpUpPowerLimit2;
+  UINTN  CtdpNominalPowerLimit1;
+  UINTN  CtdpNominalPowerLimit2;
+  UINTN  CtdpDownPowerLimit1;
+  UINTN  CtdpDownPowerLimit2;
+  UINTN  MsrPowerLimit4;             /// PL4 value if FVM is enabled or system does not support FVM
+  UINTN  MsrPowerLimit4DisableFvm;   /// PL4 value if FVM is supported but disabled.
+} PPM_OVERRIDE_TABLE;
+
+/**
+  Return CPU Sku
+
+  @param[in]  UINT32             CpuFamilyModel
+  @param[in]  UINT16             CpuDid
+
+  @retval     UINT8              CPU Sku
+**/
+UINT8
+GetCpuSkuInfo (
+  IN UINT32    CpuFamilyModel,
+  IN UINT16    CpuDid
+  );
+
+/**
+  This function returns the supported Physical Address Size
+
+  @retval returns the supported Physical Address Size.
+**/
+UINT8
+GetMaxPhysicalAddressSizeFru (
+  VOID
+  );
+
+#endif // _CPU_INFO_FRU_LIB_H_
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Cpu/Library/PeiDxeSmmCpuPlatformLib/CpuPlatformLibrary.c b/Silicon/Intel/AlderlakeSiliconPkg/Cpu/Library/PeiDxeSmmCpuPlatformLib/CpuPlatformLibrary.c
new file mode 100644
index 0000000000..5245a49719
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Cpu/Library/PeiDxeSmmCpuPlatformLib/CpuPlatformLibrary.c
@@ -0,0 +1,55 @@
+/** @file
+  CPU Platform Lib implementation.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "CpuPlatformLibrary.h"
+#include <Library/PciSegmentLib.h>
+#include <Register/SaRegsHostBridge.h>
+#include <CpuRegs.h>
+#include <Register/IgdRegs.h>
+#include <Library/CpuInfoFruLib.h>
+#include <Register/CommonMsr.h>
+#include <CpuGenInfoFruLib.h>
+#include <Pi/PiStatusCode.h>
+#include <Library/ReportStatusCodeLib.h>
+
+/**
+  Return CPU Sku
+
+  @retval UINT8              CPU Sku
+**/
+UINT8
+EFIAPI
+GetCpuSku (
+  VOID
+  )
+{
+  UINT16                  CpuDid;
+  UINT32                  CpuFamilyModel;
+  CPUID_VERSION_INFO_EAX  Eax;
+
+  ///
+  /// Read the CPUID & DID information
+  ///
+  AsmCpuid (CPUID_VERSION_INFO, &Eax.Uint32, NULL, NULL, NULL);
+  CpuFamilyModel = Eax.Uint32 & CPUID_FULL_FAMILY_MODEL;
+  CpuDid = PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, SA_MC_BUS, SA_MC_DEV, SA_MC_FUN, R_SA_MC_DEVICE_ID));
+
+  return GetCpuSkuInfo (CpuFamilyModel, CpuDid);
+
+}
+
+/**
+  This function returns the supported Physical Address Size
+
+  @retval supported Physical Address Size.
+**/
+UINT8
+GetMaxPhysicalAddressSize (
+  VOID
+  )
+{
+  return GetMaxPhysicalAddressSizeFru ();
+}
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Cpu/Library/PeiDxeSmmCpuPlatformLib/CpuPlatformLibrary.h b/Silicon/Intel/AlderlakeSiliconPkg/Cpu/Library/PeiDxeSmmCpuPlatformLib/CpuPlatformLibrary.h
new file mode 100644
index 0000000000..a85fe62e81
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Cpu/Library/PeiDxeSmmCpuPlatformLib/CpuPlatformLibrary.h
@@ -0,0 +1,25 @@
+/** @file
+  Header file for Cpu Platform Lib implementation.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _CPU_PLATFORM_LIBRARY_IMPLEMENTATION_H_
+#define _CPU_PLATFORM_LIBRARY_IMPLEMENTATION_H_
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/CpuLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/TimerLib.h>
+#include <Library/SynchronizationLib.h>
+
+#include <Register/Cpuid.h>
+#include <Register/Msr.h>
+#include <Library/CpuPlatformLib.h>
+
+#endif
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Cpu/Library/PeiDxeSmmCpuPlatformLib/PeiDxeSmmCpuPlatformLib.inf b/Silicon/Intel/AlderlakeSiliconPkg/Cpu/Library/PeiDxeSmmCpuPlatformLib/PeiDxeSmmCpuPlatformLib.inf
new file mode 100644
index 0000000000..bacef9003b
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Cpu/Library/PeiDxeSmmCpuPlatformLib/PeiDxeSmmCpuPlatformLib.inf
@@ -0,0 +1,41 @@
+## @file
+# Component description file for CPU Platform Lib
+#
+#   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+#   SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmCpuPlatformLib
+FILE_GUID = 11647130-6AA4-41A4-A3A8-5FA296ABD977
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = CpuPlatformLib
+
+
+[LibraryClasses]
+BaseLib
+BaseMemoryLib
+DebugLib
+IoLib
+PcdLib
+CpuLib
+TimerLib
+SynchronizationLib
+PciSegmentLib
+CpuInfoFruLib
+ReportStatusCodeLib
+
+[FixedPcd]
+
+[Packages]
+MdePkg/MdePkg.dec
+UefiCpuPkg/UefiCpuPkg.dec
+AlderlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+CpuPlatformLibrary.h
+CpuPlatformLibrary.c
-- 
2.36.1.windows.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 3/8] AlderlakeSiliconPkg/Pch: Add include headers
  2023-06-15 17:52 [PATCH 1/8] AlderlakeSiliconPkg: Add package and library instances Saloni Kasbekar
  2023-06-15 17:53 ` [PATCH 2/8] AlderlakeSiliconPkg: Add Cpu modules Saloni Kasbekar
@ 2023-06-15 17:53 ` Saloni Kasbekar
  2023-07-24  7:38   ` [edk2-devel] " Chaganty, Rangasai V
  2023-06-15 17:53 ` [PATCH 4/8] AlderlakeSiliconPkg/Pch: Add libraries Saloni Kasbekar
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 15+ messages in thread
From: Saloni Kasbekar @ 2023-06-15 17:53 UTC (permalink / raw)
  To: devel
  Cc: Saloni Kasbekar, Sai Chaganty, Nate DeSimone, Isaac Oram,
	Rosen Chuang

Adds the following header files:
* Pch/Include

Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Isaac Oram <isaac.w.oram@intel.com>
Cc: Rosen Chuang <rosen.chuang@intel.com>
Signed-off-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
---
 .../Include/ConfigBlock/PchGeneralConfig.h    |  86 ++++++++
 .../Pch/Include/Library/PchCycleDecodingLib.h |  59 ++++++
 .../Pch/Include/Library/PchInfoDefs.h         |  19 ++
 .../Pch/Include/Library/PchInfoLib.h          | 108 ++++++++++
 .../Pch/Include/Library/PchPciBdfLib.h        | 187 ++++++++++++++++++
 .../Pch/Include/PchPolicyCommon.h             |  30 +++
 .../Pch/Include/PchPreMemPolicyCommon.h       |  53 +++++
 .../Pch/Include/PchResetPlatformSpecific.h    |  21 ++
 .../Pch/Include/Protocol/PchAcpiSmiDispatch.h | 134 +++++++++++++
 .../Pch/Include/Protocol/PchPcieSmiDispatch.h | 166 ++++++++++++++++
 .../Pch/Include/Protocol/PchSmiDispatch.h     | 132 +++++++++++++
 .../Include/Protocol/PchSmmIoTrapControl.h    |  65 ++++++
 .../Protocol/PchSmmPeriodicTimerControl.h     |  65 ++++++
 .../Pch/Include/Protocol/PchTcoSmiDispatch.h  | 150 ++++++++++++++
 .../Pch/Include/Protocol/SmmSmbus.h           |  13 ++
 .../Pch/Include/Register/PchRegs.h            |  45 +++++
 16 files changed, 1333 insertions(+)
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/ConfigBlock/PchGeneralConfig.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Library/PchCycleDecodingLib.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Library/PchInfoDefs.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Library/PchInfoLib.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Library/PchPciBdfLib.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/PchPolicyCommon.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/PchPreMemPolicyCommon.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/PchResetPlatformSpecific.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchAcpiSmiDispatch.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchPcieSmiDispatch.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchSmiDispatch.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchSmmIoTrapControl.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchSmmPeriodicTimerControl.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchTcoSmiDispatch.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/SmmSmbus.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Register/PchRegs.h

diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/ConfigBlock/PchGeneralConfig.h b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/ConfigBlock/PchGeneralConfig.h
new file mode 100644
index 0000000000..4501537fe2
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/ConfigBlock/PchGeneralConfig.h
@@ -0,0 +1,86 @@
+/** @file
+  PCH General policy
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_GENERAL_CONFIG_H_
+#define _PCH_GENERAL_CONFIG_H_
+
+
+extern EFI_GUID gPchGeneralConfigGuid;
+extern EFI_GUID gPchGeneralPreMemConfigGuid;
+
+#pragma pack (push,1)
+
+enum PCH_RESERVED_PAGE_ROUTE {
+  PchReservedPageToLpc,                   ///< Port 80h cycles are sent to LPC.
+  PchReservedPageToPcie                   ///< Port 80h cycles are sent to PCIe.
+};
+
+/**
+  PCH General Configuration
+  <b>Revision 1</b>:  - Initial version.
+  <b>Revision 2</b>:  - Added AcpiL6dPmeHandling
+**/
+typedef struct {
+  CONFIG_BLOCK_HEADER   Header;                   ///< Config Block Header
+  /**
+    This member describes whether or not the Compatibility Revision ID (CRID) feature
+    of PCH should be enabled. <b>0: Disable</b>; 1: Enable
+  **/
+  UINT32    Crid            :  1;
+  /**
+    Set to enable low latency of legacy IO.
+    Some systems require lower IO latency irrespective of power.
+    This is a tradeoff between power and IO latency.
+    @note: Once this is enabled, DmiAspm, Pcie DmiAspm in SystemAgent
+    and ITSS Clock Gating are forced to disabled.
+    <b>0: Disable</b>, 1: Enable
+  **/
+  UINT32    LegacyIoLowLatency  :  1;
+  /**
+  Enables _L6D ACPI handler.
+  PME GPE is shared by multiple devices So BIOS must verify the same in the ASL handler by reading offset for PMEENABLE and PMESTATUS bit
+  <b>0: Disable</b>, 1: Enable
+  **/
+  UINT32    AcpiL6dPmeHandling  :  1;
+  UINT32    RsvdBits0           : 29;       ///< Reserved bits
+} PCH_GENERAL_CONFIG;
+
+/**
+  PCH General Pre-Memory Configuration
+  <b>Revision 1</b>:  - Initial version.
+  <b>Revision 2</b>:  - Added GpioOverride.
+  <b>Revision 3</b>:  - Added IoeDebugEn, PmodeClkEn
+**/
+typedef struct {
+  CONFIG_BLOCK_HEADER   Header;                   ///< Config Block Header
+  /**
+    Control where the Port 80h cycles are sent, <b>0: LPC</b>; 1: PCI.
+  **/
+  UINT32    Port80Route     :  1;
+  UINT32    IotgPllSscEn    :  1;       ///< Need to disable CPU Side SSC for A0 PO
+  /**
+    Gpio override Level
+    -- <b>0: Disable</b>;
+    -  1: Override Level 1 - Skips GPIO configuration in PEI/FSPM/FSPT phase
+    -  2: Override Level 2 - Reserved for future use
+  **/
+  UINT32    GpioOverride    :  3;
+  /**
+    Enable/Disable IOE Debug. When enabled, IOE D2D Dfx link and clock will keep up for debug
+    <b>0: Disable</b>; 1: Enable
+  **/
+  UINT32    IoeDebugEn      :  1;
+  /**
+    Enable/Disable PMODE clock. When enabled, Pmode clock will toggle for XDP use
+    <b>0: Disable</b>; 1: Enable
+  **/
+  UINT32    PmodeClkEn      :  1;
+  UINT32    RsvdBits0       : 25;       ///< Reserved bits
+} PCH_GENERAL_PREMEM_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _PCH_GENERAL_CONFIG_H_
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Library/PchCycleDecodingLib.h b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Library/PchCycleDecodingLib.h
new file mode 100644
index 0000000000..65ecd58de1
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Library/PchCycleDecodingLib.h
@@ -0,0 +1,59 @@
+/** @file
+  Header file for PchCycleDecodingLib.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_CYCLE_DECODING_LIB_H_
+#define _PCH_CYCLE_DECODING_LIB_H_
+
+/**
+  Get PCH TCO base address.
+
+  @param[out] Address                   Address of TCO base address.
+
+  @retval EFI_SUCCESS                   Successfully completed.
+  @retval EFI_INVALID_PARAMETER         Invalid pointer passed.
+**/
+EFI_STATUS
+PchTcoBaseGet (
+  OUT UINT16                            *Address
+  );
+
+/**
+  Set PCH LPC IO decode ranges.
+  Program LPC I/O Decode Ranges, PCR[DMI] + 2770h[15:0] to the same value programmed in LPC offset 80h.
+  Please check EDS for detail of Lpc IO decode ranges bit definition.
+  Bit  12: FDD range
+  Bit 9:8: LPT range
+  Bit 6:4: ComB range
+  Bit 2:0: ComA range
+
+  @param[in] LpcIoDecodeRanges          Lpc IO decode ranges bit settings.
+
+  @retval EFI_SUCCESS                   Successfully completed.
+  @retval EFI_UNSUPPORTED               DMIC.SRL is set.
+**/
+EFI_STATUS
+PchLpcIoDecodeRangesSet (
+  IN  UINT16                            LpcIoDecodeRanges
+  );
+
+/**
+  Set PCH LPC and eSPI CS0# IO enable decoding.
+  Setup I/O Enables in DMI to the same value program in LPC/eSPI PCI offset 82h.
+  Note: Bit[15:10] of the source decode register is Read-Only. The IO range indicated by the Enables field
+  in LPC/eSPI PCI offset 82h[13:10] is always forwarded by DMI to subtractive agent for handling.
+  Please check EDS for detail of LPC/eSPI IO decode ranges bit definition.
+
+  @param[in] LpcIoEnableDecoding        LPC IO enable decoding bit settings.
+
+  @retval EFI_SUCCESS                   Successfully completed.
+  @retval EFI_UNSUPPORTED               DMIC.SRL is set.
+**/
+EFI_STATUS
+PchLpcIoEnableDecodingSet (
+  IN  UINT16                            LpcIoEnableDecoding
+  );
+
+#endif // _PCH_CYCLE_DECODING_LIB_H_
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Library/PchInfoDefs.h b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Library/PchInfoDefs.h
new file mode 100644
index 0000000000..9328e1899c
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Library/PchInfoDefs.h
@@ -0,0 +1,19 @@
+/** @file
+  Header file for PchInfoDefs.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_INFO_DEFS_H_
+#define _PCH_INFO_DEFS_H_
+
+#define PCH_STEPPING_MAX      0xFF
+
+#define PCH_LP                  2
+#define PCH_N                   3
+#define PCH_S                   4
+#define PCH_P                   5
+#define PCH_M                   6
+#define PCH_UNKNOWN_SERIES      0xFF
+
+#endif
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Library/PchInfoLib.h b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Library/PchInfoLib.h
new file mode 100644
index 0000000000..d5d412c9f2
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Library/PchInfoLib.h
@@ -0,0 +1,108 @@
+/** @file
+  Header file for PchInfoLib.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_INFO_LIB_H_
+#define _PCH_INFO_LIB_H_
+
+#include <Uefi/UefiBaseType.h>
+#include "PchInfoDefs.h"
+
+typedef UINT8 PCH_STEPPING;
+typedef UINT8 PCH_SERIES;
+typedef UINT8 PCH_GENERATION;
+
+typedef enum {
+  RstUnsupported  = 0,
+  RstPremium,
+  RstOptane,
+  RstMaxMode
+} RST_MODE;
+
+/**
+  Return LPC Device Id
+
+  @retval PCH_LPC_DEVICE_ID         PCH Lpc Device ID
+**/
+UINT16
+PchGetLpcDid (
+  VOID
+  );
+
+/**
+  Return Pch stepping type
+
+  @retval PCH_STEPPING            Pch stepping type
+**/
+PCH_STEPPING
+PchStepping (
+  VOID
+  );
+
+/**
+  Return Pch Series
+
+  @retval PCH_SERIES                Pch Series
+**/
+PCH_SERIES
+PchSeries (
+  VOID
+  );
+
+/**
+  Check if this is PCH LP series
+
+  @retval TRUE                It's PCH LP series
+  @retval FALSE               It's not PCH LP series
+**/
+BOOLEAN
+IsPchLp (
+  VOID
+  );
+
+
+/**
+  Check if this is PCH P series
+
+  @retval TRUE                It's PCH P series
+  @retval FALSE               It's not PCH P series
+**/
+BOOLEAN
+IsPchP (
+  VOID
+  );
+
+/**
+  Get Pch Maximum Pcie Root Port Number
+
+  @retval PcieMaxRootPort         Pch Maximum Pcie Root Port Number
+**/
+UINT8
+GetPchMaxPciePortNum (
+  VOID
+  );
+
+/**
+  Get Pch Maximum Serial IO I2C controllers number
+
+  @retval Pch Maximum Serial IO I2C controllers number
+**/
+UINT8
+GetPchMaxSerialIoI2cControllersNum (
+  VOID
+  );
+
+/**
+  return support status for P2SB PCR 20-bit addressing
+
+  @retval    TRUE
+  @retval    FALSE
+**/
+BOOLEAN
+IsP2sb20bPcrSupported (
+  VOID
+  );
+
+#endif // _PCH_INFO_LIB_H_
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Library/PchPciBdfLib.h b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Library/PchPciBdfLib.h
new file mode 100644
index 0000000000..0c8e4d21a1
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Library/PchPciBdfLib.h
@@ -0,0 +1,187 @@
+/** @file
+  Header file for PchPciBdfLib.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_PCI_BDF_LIB_H_
+#define _PCH_PCI_BDF_LIB_H_
+
+/**
+  Get P2SB controller address that can be passed to the PCI Segment Library functions.
+
+  @retval P2SB controller address in PCI Segment Library representation
+**/
+UINT64
+P2sbPciCfgBase (
+  VOID
+  );
+
+/**
+  Get P2SB PCI device number
+
+  @retval PCI dev number
+**/
+UINT8
+P2sbDevNumber (
+  VOID
+  );
+
+/**
+  Get P2SB PCI function number
+
+  @retval PCI fun number
+**/
+UINT8
+P2sbFuncNumber (
+  VOID
+  );
+
+/**
+  Returns SPI PCI Config Space base address
+
+  @retval  UINT64  SPI Config Space base address
+**/
+UINT64
+SpiPciCfgBase (
+  VOID
+  );
+
+/**
+  Returns SPI Device number
+
+  @retval UINT8   PCH SPI Device number
+**/
+UINT8
+SpiDevNumber (
+  VOID
+  );
+
+/**
+  Returns SPI Function number
+
+  @retval UINT8   PCH SPI Function number
+**/
+UINT8
+SpiFuncNumber (
+  VOID
+  );
+
+/**
+  Get XHCI controller address that can be passed to the PCI Segment Library functions.
+
+  @retval XHCI controller address in PCI Segment Library representation
+**/
+UINT64
+PchXhciPciCfgBase (
+  VOID
+  );
+
+/**
+  Get XHCI controller PCIe Device Number
+
+  @retval XHCI controller PCIe Device Number
+**/
+UINT8
+PchXhciDevNumber (
+  VOID
+  );
+
+/**
+  Get XHCI controller PCIe Function Number
+
+  @retval XHCI controller PCIe Function Number
+**/
+UINT8
+PchXhciFuncNumber (
+  VOID
+  );
+
+/**
+  Returns PCH LPC device PCI base address.
+
+  @retval                   PCH LPC PCI base address.
+**/
+UINT64
+LpcPciCfgBase (
+  VOID
+  );
+
+/**
+  Get LPC controller PCIe Device Number
+
+  @retval LPC controller PCIe Device Number
+**/
+UINT8
+LpcDevNumber (
+  VOID
+  );
+
+
+/**
+  Get LPC controller PCIe Function Number
+
+  @retval LPC controller PCIe Function Number
+**/
+UINT8
+LpcFuncNumber (
+  VOID
+  );
+
+
+/**
+  Get PCH PCIe controller PCIe Device Number
+
+  @param[in]  RpIndex       Root port physical number. (0-based)
+
+  @retval PCH PCIe controller PCIe Device Number
+**/
+UINT8
+PchPcieRpDevNumber (
+  IN  UINTN   RpIndex
+  );
+
+/**
+  Get PCH PCIe controller PCIe Function Number
+
+  @param[in]  RpIndex       Root port physical number. (0-based)
+
+  @retval PCH PCIe controller PCIe Function Number
+**/
+UINT8
+PchPcieRpFuncNumber (
+  IN  UINTN   RpIndex
+  );
+
+/**
+  Get HECI1 controller address that can be passed to the PCI Segment Library functions.
+
+  @retval HECI1 controller address in PCI Segment Library representation
+**/
+UINT64
+PchHeci1PciCfgBase (
+  VOID
+  );
+
+/**
+  Get HECI3 PCI device number
+
+  @retval PCI dev number
+**/
+UINT8
+PchHeci3DevNumber (
+  VOID
+  );
+
+/**
+  Get HECI3 PCI function number
+
+  @retval PCI fun number
+**/
+UINT8
+PchHeci3FuncNumber (
+  VOID
+  );
+
+
+#endif //_PCH_PCI_BDF_LIB_H_
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/PchPolicyCommon.h b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/PchPolicyCommon.h
new file mode 100644
index 0000000000..f8a07098f0
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/PchPolicyCommon.h
@@ -0,0 +1,30 @@
+/** @file
+  PCH configuration based on PCH policy
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_POLICY_COMMON_H_
+#define _PCH_POLICY_COMMON_H_
+
+#include <ConfigBlock.h>
+
+#include "PchLimits.h"
+#include "ConfigBlock/PchGeneralConfig.h"
+#include <PchPcieRpConfig.h>
+#include <PchDmiConfig.h>
+#include <PmConfig.h>
+#include <SerialIoConfig.h>
+
+#ifndef FORCE_ENABLE
+#define FORCE_ENABLE  1
+#endif
+#ifndef FORCE_DISABLE
+#define FORCE_DISABLE 2
+#endif
+#ifndef PLATFORM_POR
+#define PLATFORM_POR  0
+#endif
+
+
+#endif // _PCH_POLICY_COMMON_H_
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/PchPreMemPolicyCommon.h b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/PchPreMemPolicyCommon.h
new file mode 100644
index 0000000000..2100a01071
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/PchPreMemPolicyCommon.h
@@ -0,0 +1,53 @@
+/** @file
+  PCH configuration based on PCH policy
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_PREMEM_POLICY_COMMON_H_
+#define _PCH_PREMEM_POLICY_COMMON_H_
+
+#include <ConfigBlock.h>
+
+#include "PchLimits.h"
+#include "ConfigBlock/PchGeneralConfig.h"
+#include <WatchDogConfig.h>
+#include <SmbusConfig.h>
+#include <LpcConfig.h>
+#include <PchDmiConfig.h>
+
+#pragma pack (push,1)
+
+#ifndef FORCE_ENABLE
+#define FORCE_ENABLE  1
+#endif
+#ifndef FORCE_DISABLE
+#define FORCE_DISABLE 2
+#endif
+#ifndef PLATFORM_POR
+#define PLATFORM_POR  0
+#endif
+
+/**
+  PCH Policy revision number
+  Any backwards compatible changes to this structure will result in an update in the revision number
+**/
+#define PCH_PREMEM_POLICY_REVISION  1
+
+/**
+  PCH Policy PPI\n
+  All PCH config block change history will be listed here\n\n
+
+  - <b>Revision 1</b>:
+    - Initial version.\n
+**/
+typedef struct _PCH_PREMEM_POLICY {
+  CONFIG_BLOCK_TABLE_HEADER      TableHeader;
+/*
+  Individual Config Block Structures are added here in memory as part of AddConfigBlock()
+*/
+} PCH_PREMEM_POLICY;
+
+#pragma pack (pop)
+
+#endif // _PCH_PREMEM_POLICY_COMMON_H_
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/PchResetPlatformSpecific.h b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/PchResetPlatformSpecific.h
new file mode 100644
index 0000000000..88884cac25
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/PchResetPlatformSpecific.h
@@ -0,0 +1,21 @@
+/** @file
+  PCH Reset Platform Specific definitions.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_RESET_PLATFORM_SPECIFIC_H_
+#define _PCH_RESET_PLATFORM_SPECIFIC_H_
+
+#define PCH_PLATFORM_SPECIFIC_RESET_STRING   L"PCH_RESET"
+#define PCH_RESET_DATA_STRING_MAX_LENGTH     (sizeof (PCH_PLATFORM_SPECIFIC_RESET_STRING) / sizeof (UINT16))
+
+extern EFI_GUID gPchGlobalResetGuid;
+
+typedef struct _RESET_DATA {
+  CHAR16   Description[PCH_RESET_DATA_STRING_MAX_LENGTH];
+  EFI_GUID Guid;
+} PCH_RESET_DATA;
+
+#endif // _PCH_RESET_PLATFORM_SPECIFIC_H_
+
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchAcpiSmiDispatch.h b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchAcpiSmiDispatch.h
new file mode 100644
index 0000000000..f22da50262
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchAcpiSmiDispatch.h
@@ -0,0 +1,134 @@
+/** @file
+  APIs of PCH ACPI SMI Dispatch Protocol.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_ACPI_SMI_DISPATCH_PROTOCOL_H_
+#define _PCH_ACPI_SMI_DISPATCH_PROTOCOL_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID                         gPchAcpiSmiDispatchProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_ACPI_SMI_DISPATCH_PROTOCOL    PCH_ACPI_SMI_DISPATCH_PROTOCOL;
+
+//
+// Member functions
+//
+
+/**
+  Callback function for an PCH ACPI SMI handler dispatch.
+
+  @param[in] DispatchHandle             The unique handle assigned to this handler by register function.
+
+**/
+typedef
+VOID
+(EFIAPI *PCH_ACPI_SMI_DISPATCH_CALLBACK) (
+  IN EFI_HANDLE                         DispatchHandle
+  );
+
+/**
+  Register a child SMI source dispatch function for PCH ACPI SMI events.
+
+  @param[in] This                       Protocol instance pointer.
+  @param[in] DispatchFunction           Pointer to dispatch function to be invoked for
+                                        this SMI source
+  @param[out] DispatchHandle            Handle of dispatch function, for when interfacing
+                                        with the parent SMM driver.
+
+  @retval EFI_SUCCESS                   The dispatch function has been successfully
+                                        registered and the SMI source has been enabled.
+  @retval EFI_DEVICE_ERROR              The driver was unable to enable the SMI source.
+  @retval EFI_OUT_OF_RESOURCES          Not enough memory (system or SMM) to manage this child.
+  @retval EFI_ACCESS_DENIED             Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_ACPI_SMI_DISPATCH_REGISTER) (
+  IN  PCH_ACPI_SMI_DISPATCH_PROTOCOL    *This,
+  IN  PCH_ACPI_SMI_DISPATCH_CALLBACK    DispatchFunction,
+  OUT EFI_HANDLE                        *DispatchHandle
+  );
+
+/**
+  Unregister a child SMI source dispatch function with a parent ACPI SMM driver
+
+  @param[in] This                       Protocol instance pointer.
+  @param[in] DispatchHandle             Handle of dispatch function to deregister.
+
+  @retval EFI_SUCCESS                   The dispatch function has been successfully
+                                        unregistered and the SMI source has been disabled
+                                        if there are no other registered child dispatch
+                                        functions for this SMI source.
+  @retval EFI_INVALID_PARAMETER         Handle is invalid.
+  @retval EFI_ACCESS_DENIED             Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_ACPI_SMI_DISPATCH_UNREGISTER) (
+  IN  PCH_ACPI_SMI_DISPATCH_PROTOCOL    *This,
+  IN  EFI_HANDLE                        DispatchHandle
+  );
+
+/**
+  Interface structure for PCH ACPI SMIs Dispatch Protocol
+  The PCH ACPI SMI DISPATCH PROTOCOL provides the ability to dispatch function for PCH ACPI related SMIs.
+  It contains SMI types of Pme, RtcAlarm, PmeB0, and Time overflow.
+**/
+struct _PCH_ACPI_SMI_DISPATCH_PROTOCOL {
+  /**
+    This member specifies the revision of this structure. This field is used to
+    indicate backwards compatible changes to the protocol.
+  **/
+  UINT8                                 Revision;
+  /**
+    Smi unregister function for PCH ACPI SMI DISPATCH PROTOCOL.
+  **/
+  PCH_ACPI_SMI_DISPATCH_UNREGISTER      UnRegister;
+  /**
+    Pme
+    The event is triggered by hardware when the PME# signal goes active.
+    Additionally, the event is only triggered when SCI_EN is not set.
+  **/
+  PCH_ACPI_SMI_DISPATCH_REGISTER        PmeRegister;
+  /**
+    PmeB0
+    The event is triggered PCH when any internal device with PCI Power Management
+    capabilities on bus 0 asserts the equivalent of the PME# signal.
+    Additionally, the event is only triggered when SCI_EN is not set.
+    The following are internal devices which can set this bit:
+    Intel HD Audio, Intel Management Engine "maskable" wake events, Integrated LAN,
+    SATA, xHCI, Intel SST
+  **/
+  PCH_ACPI_SMI_DISPATCH_REGISTER        PmeB0Register;
+  /**
+    RtcAlarm
+    The event is triggered by hardware when the RTC generates an alarm
+    (assertion of the IRQ8# signal).
+  **/
+  PCH_ACPI_SMI_DISPATCH_REGISTER        RtcAlarmRegister;
+  /**
+    TmrOverflow
+    The event is triggered any time bit 22 of the 24-bit timer goes high
+    (bits are numbered from 0 to 23).
+    This will occur every 2.3435 seconds. When the TMROF_EN bit (ABASE + 02h, bit 0) is set,
+    then the setting of the TMROF_STS bit will additionally generate an SMI#
+    Additionally, the event is only triggered when SCI_EN is not set.
+  **/
+  PCH_ACPI_SMI_DISPATCH_REGISTER        TmrOverflowRegister;
+};
+
+/**
+  PCH ACPI SMI dispatch revision number
+
+  Revision 1:   Initial version
+**/
+#define PCH_ACPI_SMI_DISPATCH_REVISION            1
+
+#endif
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchPcieSmiDispatch.h b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchPcieSmiDispatch.h
new file mode 100644
index 0000000000..0c0f1ab962
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchPcieSmiDispatch.h
@@ -0,0 +1,166 @@
+/** @file
+  APIs of PCH PCIE SMI Dispatch Protocol.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_PCIE_SMI_DISPATCH_PROTOCOL_H_
+#define _PCH_PCIE_SMI_DISPATCH_PROTOCOL_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID                         gPchPcieSmiDispatchProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_PCIE_SMI_DISPATCH_PROTOCOL    PCH_PCIE_SMI_DISPATCH_PROTOCOL;
+
+typedef enum {
+  PchRpIndex0      = 0,
+  PchRpIndex1      = 1,
+  PchRpIndex2      = 2,
+  PchRpIndex3      = 3,
+  PchRpIndex4      = 4,
+  PchRpIndex5      = 5,
+  PchRpIndex6      = 6,
+  PchRpIndex7      = 7,
+  PchRpIndex8      = 8,
+  PchRpIndex9      = 9,
+  PchRpIndex10     = 10,
+  PchRpIndex11     = 11,
+  PchRpIndex12     = 12,
+  PchRpIndex13     = 13,
+  PchRpIndex14     = 14,
+  PchRpIndex15     = 15,
+  PchRpIndex16     = 16,
+  PchRpIndex17     = 17,
+  PchRpIndex18     = 18,
+  PchRpIndex19     = 19,
+  PchRpIndex20     = 20,
+  PchRpIndex21     = 21,
+  PchRpIndex22     = 22,
+  PchRpIndex23     = 23,
+  /**
+    Quantity of PCH and CPU PCIe ports, as well as their encoding in this enum, may change between
+    silicon generations and series. Do not assume that PCH port 0 will be always encoded by 0.
+    Instead, it is recommended to use (PchRpIndex0 + PchPortIndex) style to be forward-compatible
+  **/
+  CpuRpIndex0      = 0x40,
+  CpuRpIndex1      = 0x41,
+  CpuRpIndex2      = 0x42,
+  CpuRpIndex3      = 0x43
+} PCIE_COMBINED_RPINDEX;
+
+//
+// Member functions
+//
+
+typedef struct {
+  UINT8                                 RpIndex; ///< Root port index (0-based), 0: RP1, 1: RP2, n: RP(N+1)
+  UINT8                                 BusNum;  ///< Root port pci bus number
+  UINT8                                 DevNum;  ///< Root port pci device number
+  UINT8                                 FuncNum; ///< Root port pci function number
+} PCH_PCIE_SMI_RP_CONTEXT;
+
+/**
+  Callback function for an PCH PCIE RP SMI handler dispatch.
+
+  @param[in] DispatchHandle             The unique handle assigned to this handler by register function.
+  @param[in] RpContext                  Pointer of PCH PCIE Root Port context.
+
+**/
+typedef
+VOID
+(EFIAPI *PCH_PCIE_SMI_RP_DISPATCH_CALLBACK) (
+  IN EFI_HANDLE                         DispatchHandle,
+  IN PCH_PCIE_SMI_RP_CONTEXT            *RpContext
+  );
+
+/**
+  Register a child SMI source dispatch function for PCH PCIERP SMI events.
+
+  @param[in] This                       Protocol instance pointer.
+  @param[in] DispatchFunction           Pointer to dispatch function to be invoked for
+                                        this SMI source
+  @param[in] RpIndex                    Refer PCIE_COMBINED_RPINDEX for PCH RP index and CPU RP index.
+                                        0: RP1, 1: RP2, n: RP(N+1)
+  @param[out] DispatchHandle            Handle of dispatch function, for when interfacing
+                                        with the parent SMM driver.
+
+  @retval EFI_SUCCESS                   The dispatch function has been successfully
+                                        registered and the SMI source has been enabled.
+  @retval EFI_DEVICE_ERROR              The driver was unable to enable the SMI source.
+  @retval EFI_OUT_OF_RESOURCES          Not enough memory (system or SMM) to manage this child.
+  @retval EFI_ACCESS_DENIED             Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_PCIE_SMI_RP_DISPATCH_REGISTER) (
+  IN  PCH_PCIE_SMI_DISPATCH_PROTOCOL    *This,
+  IN  PCH_PCIE_SMI_RP_DISPATCH_CALLBACK DispatchFunction,
+  IN  UINTN                             RpIndex,
+  OUT EFI_HANDLE                        *DispatchHandle
+  );
+
+/**
+  Unregister a child SMI source dispatch function with a parent PCIE SMM driver
+
+  @param[in] This                       Protocol instance pointer.
+  @param[in] DispatchHandle             Handle of dispatch function to deregister.
+
+  @retval EFI_SUCCESS                   The dispatch function has been successfully
+                                        unregistered and the SMI source has been disabled
+                                        if there are no other registered child dispatch
+                                        functions for this SMI source.
+  @retval EFI_INVALID_PARAMETER         Handle is invalid.
+  @retval EFI_ACCESS_DENIED             Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_PCIE_SMI_DISPATCH_UNREGISTER) (
+  IN  PCH_PCIE_SMI_DISPATCH_PROTOCOL    *This,
+  IN  EFI_HANDLE                        DispatchHandle
+  );
+
+/**
+  Interface structure for PCH PCIE SMIs Dispatch Protocol
+  The PCH PCIE SMI DISPATCH PROTOCOL provides the ability to dispatch function for PCH PCIE related SMIs.
+  It contains SMI types of HotPlug, LinkActive, and Link EQ.
+**/
+struct _PCH_PCIE_SMI_DISPATCH_PROTOCOL {
+  /**
+    This member specifies the revision of this structure. This field is used to
+    indicate backwards compatible changes to the protocol.
+  **/
+  UINT8                                 Revision;
+  /**
+    Smi unregister function for PCH PCIE SMI DISPATCH PROTOCOL.
+  **/
+  PCH_PCIE_SMI_DISPATCH_UNREGISTER      UnRegister;
+  /**
+    PcieRpXHotPlug
+    The event is triggered when PCIE root port Hot-Plug Presence Detect.
+  **/
+  PCH_PCIE_SMI_RP_DISPATCH_REGISTER     HotPlugRegister;
+  /**
+    PcieRpXLinkActive
+    The event is triggered when Hot-Plug Link Active State Changed.
+  **/
+  PCH_PCIE_SMI_RP_DISPATCH_REGISTER     LinkActiveRegister;
+  /**
+    PcieRpXLinkEq
+    The event is triggered when Device Requests Software Link Equalization.
+  **/
+  PCH_PCIE_SMI_RP_DISPATCH_REGISTER     LinkEqRegister;
+};
+
+/**
+  PCH PCIE SMI dispatch revision number
+
+  Revision 1:   Initial version
+**/
+#define PCH_PCIE_SMI_DISPATCH_REVISION            1
+
+#endif
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchSmiDispatch.h b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchSmiDispatch.h
new file mode 100644
index 0000000000..fd270fe72a
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchSmiDispatch.h
@@ -0,0 +1,132 @@
+/** @file
+  APIs of PCH SMI Dispatch Protocol.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_SMI_DISPATCH_PROTOCOL_H_
+#define _PCH_SMI_DISPATCH_PROTOCOL_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID                         gPchSmiDispatchProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_SMI_DISPATCH_PROTOCOL         PCH_SMI_DISPATCH_PROTOCOL;
+
+//
+// Member functions
+//
+
+/**
+  Callback function for an PCH SMI handler dispatch.
+
+  @param[in] DispatchHandle             The unique handle assigned to this handler by register function.
+
+**/
+typedef
+VOID
+(EFIAPI *PCH_SMI_DISPATCH_CALLBACK) (
+  IN EFI_HANDLE                         DispatchHandle
+  );
+
+/**
+  Register a child SMI source dispatch function for specific PCH SMI dispatch event.
+
+  @param[in] This                       Protocol instance pointer.
+  @param[in] DispatchFunction           Pointer to dispatch function to be invoked for
+                                        this SMI source
+  @param[out] DispatchHandle            Handle of dispatch function, for when interfacing
+                                        with the parent SMM driver.
+
+  @retval EFI_SUCCESS                   The dispatch function has been successfully
+                                        registered and the SMI source has been enabled.
+  @retval EFI_DEVICE_ERROR              The driver was unable to enable the SMI source.
+  @retval EFI_OUT_OF_RESOURCES          Not enough memory (system or SMM) to manage this child.
+  @retval EFI_ACCESS_DENIED             Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SMI_DISPATCH_REGISTER) (
+  IN  PCH_SMI_DISPATCH_PROTOCOL         *This,
+  IN  PCH_SMI_DISPATCH_CALLBACK         DispatchFunction,
+  OUT EFI_HANDLE                        *DispatchHandle
+  );
+
+/**
+  Unregister a child SMI source dispatch function with a parent SMM driver
+
+  @param[in] This                       Protocol instance pointer.
+  @param[in] DispatchHandle             Handle of dispatch function to deregister.
+
+  @retval EFI_SUCCESS                   The dispatch function has been successfully
+                                        unregistered and the SMI source has been disabled
+                                        if there are no other registered child dispatch
+                                        functions for this SMI source.
+  @retval EFI_INVALID_PARAMETER         Handle is invalid.
+  @retval EFI_ACCESS_DENIED             Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SMI_DISPATCH_UNREGISTER) (
+  IN  PCH_SMI_DISPATCH_PROTOCOL         *This,
+  IN  EFI_HANDLE                        DispatchHandle
+  );
+
+/**
+  Interface structure for PCH specific SMIs Dispatch Protocol
+  The PCH SMI DISPATCH PROTOCOL provides the ability to dispatch function for PCH misc SMIs.
+  It contains legacy SMIs and new PCH SMI types like:
+  SerialIrq, McSmi, Smbus, ...
+**/
+struct _PCH_SMI_DISPATCH_PROTOCOL {
+  /**
+    This member specifies the revision of this structure. This field is used to
+    indicate backwards compatible changes to the protocol.
+  **/
+  UINT8                                 Revision;
+  /**
+    Smi unregister function for PCH SMI DISPATCH PROTOCOL.
+  **/
+  PCH_SMI_DISPATCH_UNREGISTER           UnRegister;
+  /**
+    SerialIrq
+    The event is triggered while the SMI# was caused by the SERIRQ decoder.
+  **/
+  PCH_SMI_DISPATCH_REGISTER             SerialIrqRegister;
+  /**
+    McSmi
+    The event is triggered if there has been an access to the power management
+    microcontroller range (62h or 66h) and the Microcontroller Decode Enable #1 bit
+    in the LPC Bridge I/O Enables configuration register is 1 .
+  **/
+  PCH_SMI_DISPATCH_REGISTER             McSmiRegister;
+  /**
+    SmBus
+    The event is triggered while the SMI# was caused by:
+    1. The SMBus target receiving a message that an SMI# should be caused, or
+    2. The SMBALERT# signal goes active and the SMB_SMI_EN bit is set and the
+       SMBALERT_DIS bit is cleared, or
+    3. The SMBus target receiving a Host Notify message and the HOST_NOTIFY_INTREN and
+       the SMB_SMI_EN bits are set, or
+    4. The PCH detecting the SMLINK_SLAVE_SMI command while in the S0 state.
+  **/
+  PCH_SMI_DISPATCH_REGISTER             SmbusRegister;
+  /**
+    SPI Asynchronous
+    When registered, the flash controller will generate an SMI when it blocks a BIOS write or erase.
+  **/
+  PCH_SMI_DISPATCH_REGISTER             SpiAsyncRegister;
+};
+
+/**
+  PCH SMI dispatch revision number
+
+  Revision 1:   Initial version
+**/
+#define PCH_SMI_DISPATCH_REVISION                 1
+
+#endif
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchSmmIoTrapControl.h b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchSmmIoTrapControl.h
new file mode 100644
index 0000000000..87c301901e
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchSmmIoTrapControl.h
@@ -0,0 +1,65 @@
+/** @file
+  PCH SMM IO Trap Control Protocol
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_SMM_IO_TRAP_CONTROL_H_
+#define _PCH_SMM_IO_TRAP_CONTROL_H_
+
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID                                   gPchSmmIoTrapControlGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_SMM_IO_TRAP_CONTROL_PROTOCOL  PCH_SMM_IO_TRAP_CONTROL_PROTOCOL;
+
+//
+// Related Definitions
+//
+
+//
+// Member functions
+//
+
+/**
+  The Prototype of Pause and Resume IoTrap callback function.
+
+  @param[in] This                 Pointer to the PCH_SMM_IO_TRAP_CONTROL_PROTOCOL instance.
+  @param[in] DispatchHandle       Handle of the child service to change state.
+
+  @retval EFI_SUCCESS             This operation is complete.
+  @retval EFI_INVALID_PARAMETER   The DispatchHandle is invalid.
+  @retval EFI_ACCESS_DENIED       The SMI status is alrady PAUSED/RESUMED.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SMM_IO_TRAP_CONTROL_FUNCTION) (
+  IN PCH_SMM_IO_TRAP_CONTROL_PROTOCOL           * This,
+  IN EFI_HANDLE                                 DispatchHandle
+  );
+
+/**
+  Interface structure for the SMM IO trap pause and resume protocol
+  This protocol provides the functions to runtime control the IoTrap SMI enabled/disable.
+  This applys the capability to the DispatchHandle which returned by IoTrap callback
+  registration, and the DispatchHandle which must be MergeDisable = TRUE and Address != 0.
+  Besides, when S3 resuem, it only restores the state of IoTrap callback registration.
+  The Paused/Resume state won't be restored after S3 resume.
+**/
+struct _PCH_SMM_IO_TRAP_CONTROL_PROTOCOL {
+  /**
+    This runtime pauses a registered IoTrap handler.
+  **/
+  PCH_SMM_IO_TRAP_CONTROL_FUNCTION      Pause;
+  /**
+    This runtime resumes a registered IoTrap handler.
+  **/
+  PCH_SMM_IO_TRAP_CONTROL_FUNCTION      Resume;
+};
+
+#endif
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchSmmPeriodicTimerControl.h b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchSmmPeriodicTimerControl.h
new file mode 100644
index 0000000000..f4773c3dd3
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchSmmPeriodicTimerControl.h
@@ -0,0 +1,65 @@
+/** @file
+  PCH SMM Periodic Timer Control Protocol
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_SMM_PERIODIC_TIMER_CONTROL_H_
+#define _PCH_SMM_PERIODIC_TIMER_CONTROL_H_
+
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID                                             gPchSmmPeriodicTimerControlGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_SMM_PERIODIC_TIMER_CONTROL_PROTOCOL     PCH_SMM_PERIODIC_TIMER_CONTROL_PROTOCOL;
+
+//
+// Related Definitions
+//
+
+//
+// Member functions
+//
+
+/**
+  The Prototype of Pause and Resume SMM PERIODIC TIMER function.
+
+  @param[in] This                       Pointer to the PCH_SMM_PERIODIC_TIMER_CONTROL_PROTOCOL instance.
+  @param[in] DispatchHandle             Handle of the child service to change state.
+
+  @retval EFI_SUCCESS                   This operation is complete.
+  @retval EFI_INVALID_PARAMETER         The DispatchHandle is invalid.
+  @retval EFI_ACCESS_DENIED             The SMI status is alrady PAUSED/RESUMED.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SMM_PERIODIC_TIMER_CONTROL_FUNCTION) (
+  IN PCH_SMM_PERIODIC_TIMER_CONTROL_PROTOCOL      *This,
+  IN EFI_HANDLE                                   DispatchHandle
+  );
+
+/**
+  Interface structure for the SMM PERIODIC TIMER pause and resume protocol
+  This protocol provides the functions to runtime control the SM periodic timer enabled/disable.
+  This applies the capability to the DispatchHandle which returned by SMM periodic timer callback
+  registration.
+  Besides, when S3 resume, it only restores the state of callback registration.
+  The Paused/Resume state won't be restored after S3 resume.
+**/
+struct _PCH_SMM_PERIODIC_TIMER_CONTROL_PROTOCOL {
+  /**
+    This runtime pauses the registered periodic timer handler.
+  **/
+  PCH_SMM_PERIODIC_TIMER_CONTROL_FUNCTION         Pause;
+  /**
+    This runtime resumes the registered periodic timer handler.
+  **/
+  PCH_SMM_PERIODIC_TIMER_CONTROL_FUNCTION         Resume;
+};
+
+#endif // _PCH_SMM_PERIODIC_TIMER_CONTROL_H_
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchTcoSmiDispatch.h b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchTcoSmiDispatch.h
new file mode 100644
index 0000000000..f39773e420
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchTcoSmiDispatch.h
@@ -0,0 +1,150 @@
+/** @file
+  APIs of PCH TCO SMI Dispatch Protocol.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_TCO_SMI_DISPATCH_PROTOCOL_H_
+#define _PCH_TCO_SMI_DISPATCH_PROTOCOL_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID                         gPchTcoSmiDispatchProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_TCO_SMI_DISPATCH_PROTOCOL     PCH_TCO_SMI_DISPATCH_PROTOCOL;
+
+//
+// Member functions
+//
+
+/**
+  Callback function for an PCH TCO SMI handler dispatch.
+
+  @param[in] DispatchHandle             The unique handle assigned to this handler by register function.
+
+**/
+typedef
+VOID
+(EFIAPI *PCH_TCO_SMI_DISPATCH_CALLBACK) (
+  IN EFI_HANDLE                         DispatchHandle
+  );
+
+/**
+  Register a child SMI source dispatch function for PCH TCO SMI events.
+
+  @param[in] This                       Protocol instance pointer.
+  @param[in] DispatchFunction           Pointer to dispatch function to be invoked for
+                                        this SMI source
+  @param[out] DispatchHandle            Handle of dispatch function, for when interfacing
+                                        with the parent SMM driver.
+
+  @retval EFI_SUCCESS                   The dispatch function has been successfully
+                                        registered and the SMI source has been enabled.
+  @retval EFI_DEVICE_ERROR              The driver was unable to enable the SMI source.
+  @retval EFI_OUT_OF_RESOURCES          Not enough memory (system or SMM) to manage this child.
+  @retval EFI_ACCESS_DENIED             Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_TCO_SMI_DISPATCH_REGISTER) (
+  IN  PCH_TCO_SMI_DISPATCH_PROTOCOL     *This,
+  IN  PCH_TCO_SMI_DISPATCH_CALLBACK     DispatchFunction,
+  OUT EFI_HANDLE                        *DispatchHandle
+  );
+
+/**
+  Unregister a child SMI source dispatch function with a parent TCO SMM driver
+
+  @param[in] This                       Protocol instance pointer.
+  @param[in] DispatchHandle             Handle of dispatch function to deregister.
+
+  @retval EFI_SUCCESS                   The dispatch function has been successfully
+                                        unregistered and the SMI source has been disabled
+                                        if there are no other registered child dispatch
+                                        functions for this SMI source.
+  @retval EFI_INVALID_PARAMETER         Handle is invalid.
+  @retval EFI_ACCESS_DENIED             Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_TCO_SMI_DISPATCH_UNREGISTER) (
+  IN  PCH_TCO_SMI_DISPATCH_PROTOCOL     *This,
+  IN  EFI_HANDLE                        DispatchHandle
+  );
+
+/**
+  Interface structure for PCH TCO SMIs Dispatch Protocol
+  The PCH TCO SMI DISPATCH PROTOCOL provides the ability to dispatch function for PCH TCO related SMIs.
+  It contains SMI types of Mch, TcoTimeout, OsTco, Nmi, IntruderDectect, and BiowWp.
+**/
+struct _PCH_TCO_SMI_DISPATCH_PROTOCOL {
+  /**
+    This member specifies the revision of this structure. This field is used to
+    indicate backwards compatible changes to the protocol.
+  **/
+  UINT8                                 Revision;
+  /**
+    Smi unregister function for PCH TCO SMI DISPATCH PROTOCOL.
+  **/
+  PCH_TCO_SMI_DISPATCH_UNREGISTER       UnRegister;
+  /**
+    Mch
+    The event is triggered when PCH received a DMI special cycle message using DMI indicating that
+    it wants to cause an SMI.
+    The software must read the processor to determine the reason for the SMI.
+  **/
+  PCH_TCO_SMI_DISPATCH_REGISTER         MchRegister;
+  /**
+    TcoTimeout
+    The event is triggered by PCH to indicate that the SMI was caused by the TCO timer reaching 0.
+  **/
+  PCH_TCO_SMI_DISPATCH_REGISTER         TcoTimeoutRegister;
+  /**
+    OsTco
+    The event is triggered when software caused an SMI# by writing to the TCO_DAT_IN register (TCOBASE + 02h).
+  **/
+  PCH_TCO_SMI_DISPATCH_REGISTER         OsTcoRegister;
+  /**
+    Nmi
+    The event is triggered by the PCH when an SMI# occurs because an event occurred that would otherwise have
+    caused an NMI (because NMI2SMI_EN is set)
+  **/
+  PCH_TCO_SMI_DISPATCH_REGISTER         NmiRegister;
+  /**
+    IntruderDectect
+    The event is triggered by PCH to indicate that an intrusion was detected.
+  **/
+  PCH_TCO_SMI_DISPATCH_REGISTER         IntruderDetRegister;
+  /**
+    SpiBiosWp
+    This event is triggered when SMI# was caused by the TCO logic and
+    SPI flash controller asserted Synchronous SMI by BIOS lock enable set.
+  **/
+  PCH_TCO_SMI_DISPATCH_REGISTER         SpiBiosWpRegister;
+  /**
+    LpcBiosWp
+    This event is triggered when SMI# was caused by the TCO logic and
+    LPC/eSPI BIOS lock enable set.
+  **/
+  PCH_TCO_SMI_DISPATCH_REGISTER         LpcBiosWpRegister;
+  /**
+    NewCentury
+    This event is triggered when SMI# was caused by the TCO logic and
+    year of RTC date rolls over a century (99 to 00).
+  **/
+  PCH_TCO_SMI_DISPATCH_REGISTER         NewCenturyRegister;
+};
+
+/**
+  PCH TCO SMI dispatch revision number
+
+  Revision 1:   Initial version
+  Revision 2:   Add NEWCENTURY support
+**/
+#define PCH_TCO_SMI_DISPATCH_REVISION             2
+
+#endif
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/SmmSmbus.h b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/SmmSmbus.h
new file mode 100644
index 0000000000..fa1a79ca84
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/SmmSmbus.h
@@ -0,0 +1,13 @@
+/** @file
+  SmmSmbus Protocol
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef __EFI_SMM_SMBUS_PROTOCOL_H__
+#define __EFI_SMM_SMBUS_PROTOCOL_H__
+
+extern EFI_GUID               gEfiSmmSmbusProtocolGuid;
+
+#endif
+
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Register/PchRegs.h b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Register/PchRegs.h
new file mode 100644
index 0000000000..33b75e82fd
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Register/PchRegs.h
@@ -0,0 +1,45 @@
+/** @file
+  Generic register definitions for PCH.
+
+Conventions:
+
+  - Register definition format:
+    Prefix_[GenerationName]_[ComponentName]_SubsystemName_RegisterSpace_RegisterName
+  - Prefix:
+    Definitions beginning with "R_" are registers
+    Definitions beginning with "B_" are bits within registers
+    Definitions beginning with "V_" are meaningful values within the bits
+    Definitions beginning with "S_" are register size
+    Definitions beginning with "N_" are the bit position
+  - [GenerationName]:
+    Three letter acronym of the generation is used (e.g. SKL,KBL,CNL etc.).
+    Register name without GenerationName applies to all generations.
+  - [ComponentName]:
+    This field indicates the component name that the register belongs to (e.g. PCH, SA etc.)
+    Register name without ComponentName applies to all components.
+    Register that is specific to -H denoted by "_PCH_H_" in component name.
+    Register that is specific to -LP denoted by "_PCH_LP_" in component name.
+  - SubsystemName:
+    This field indicates the subsystem name of the component that the register belongs to
+    (e.g. PCIE, USB, SATA, GPIO, PMC etc.).
+  - RegisterSpace:
+    MEM - MMIO space register of subsystem.
+    IO  - IO space register of subsystem.
+    PCR - Private configuration register of subsystem.
+    CFG - PCI configuration space register of subsystem.
+  - RegisterName:
+    Full register name.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_REGS_H_
+#define _PCH_REGS_H_
+
+///
+/// The default PCH PCI segment and bus number
+///
+#define DEFAULT_PCI_SEGMENT_NUMBER_PCH  0
+#define DEFAULT_PCI_BUS_NUMBER_PCH      0
+
+#endif //_PCH_REGS_H_
-- 
2.36.1.windows.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 4/8] AlderlakeSiliconPkg/Pch: Add libraries
  2023-06-15 17:52 [PATCH 1/8] AlderlakeSiliconPkg: Add package and library instances Saloni Kasbekar
  2023-06-15 17:53 ` [PATCH 2/8] AlderlakeSiliconPkg: Add Cpu modules Saloni Kasbekar
  2023-06-15 17:53 ` [PATCH 3/8] AlderlakeSiliconPkg/Pch: Add include headers Saloni Kasbekar
@ 2023-06-15 17:53 ` Saloni Kasbekar
  2023-07-24  7:42   ` [edk2-devel] " Chaganty, Rangasai V
  2023-06-15 17:53 ` [PATCH 5/8] AlderlakeSiliconPkg/Pch: Add drivers Saloni Kasbekar
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 15+ messages in thread
From: Saloni Kasbekar @ 2023-06-15 17:53 UTC (permalink / raw)
  To: devel
  Cc: Saloni Kasbekar, Sai Chaganty, Nate DeSimone, Isaac Oram,
	Rosen Chuang

Adds the following libraries:
- BasePchPciBdfLib
- BaseResetSystemLib
- PeiDxeSmmPchCycleDecodingLib

Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Isaac Oram <isaac.w.oram@intel.com>
Cc: Rosen Chuang <rosen.chuang@intel.com>
Signed-off-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
---
 .../BasePchPciBdfLib/BasePchPciBdfLib.inf     |  32 ++
 .../Library/BasePchPciBdfLib/PchPciBdfLib.c   | 308 ++++++++++++++++++
 .../BaseResetSystemLib/BaseResetSystemLib.c   | 114 +++++++
 .../BaseResetSystemLib/BaseResetSystemLib.inf |  37 +++
 .../PchCycleDecodingLib.c                     | 194 +++++++++++
 .../PeiDxeSmmPchCycleDecodingLib.inf          |  41 +++
 6 files changed, 726 insertions(+)
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/BasePchPciBdfLib/BasePchPciBdfLib.inf
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/BasePchPciBdfLib/PchPciBdfLib.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/BaseResetSystemLib/BaseResetSystemLib.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/BaseResetSystemLib/BaseResetSystemLib.inf
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PchCycleDecodingLib.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PeiDxeSmmPchCycleDecodingLib.inf

diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/BasePchPciBdfLib/BasePchPciBdfLib.inf b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/BasePchPciBdfLib/BasePchPciBdfLib.inf
new file mode 100644
index 0000000000..e65f564c1b
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/BasePchPciBdfLib/BasePchPciBdfLib.inf
@@ -0,0 +1,32 @@
+## @file
+# PCH PCIe Bus Device Function Library.
+#
+# All functions from this library are available in PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+#   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+#   SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmPchPciBdfLib
+FILE_GUID = A36363FC-2951-4DCF-AC81-16F4ED3FDA47
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchPciBdfLib
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+PciSegmentLib
+PchInfoLib
+PchPcieRpLib
+
+[Packages]
+MdePkg/MdePkg.dec
+AlderlakeSiliconPkg/SiPkg.dec
+
+[Sources]
+PchPciBdfLib.c
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/BasePchPciBdfLib/PchPciBdfLib.c b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/BasePchPciBdfLib/PchPciBdfLib.c
new file mode 100644
index 0000000000..c26625e2eb
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/BasePchPciBdfLib/PchPciBdfLib.c
@@ -0,0 +1,308 @@
+/** @file
+  PCH PCIe Bus Device Function Library.
+  All functions from this library are available in PEI, DXE, and SMM,
+  But do not support UEFI RUNTIME environment call.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchPcieRpLib.h>
+#include <Register/PchRegs.h>
+#include <PchBdfAssignment.h>
+
+/**
+  Check if a Device is present for PCH FRU
+  If the data is defined for PCH RFU return it
+  If the data is not defined (Device is NOT present) assert.
+
+  @param[in]  DataToCheck       Device or Function number to check
+
+  @retval Device or Function number value if defined for PCH FRU
+          0xFF if not present in PCH FRU
+**/
+UINT8
+CheckAndReturn (
+  UINT8 DataToCheck
+  )
+{
+  if (DataToCheck == NOT_PRESENT) {
+    ASSERT (FALSE);
+  }
+  return DataToCheck;
+}
+
+/**
+  Get P2SB PCI device number
+
+  @retval PCI dev number
+**/
+UINT8
+P2sbDevNumber (
+  VOID
+  )
+{
+  return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_P2SB);
+}
+
+/**
+  Get P2SB PCI function number
+
+  @retval PCI fun number
+**/
+UINT8
+P2sbFuncNumber (
+  VOID
+  )
+{
+  return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_P2SB);
+}
+
+/**
+  Get P2SB controller address that can be passed to the PCI Segment Library functions.
+
+  @retval P2SB controller address in PCI Segment Library representation
+**/
+UINT64
+P2sbPciCfgBase (
+  VOID
+  )
+{
+  return PCI_SEGMENT_LIB_ADDRESS (
+           DEFAULT_PCI_SEGMENT_NUMBER_PCH,
+           DEFAULT_PCI_BUS_NUMBER_PCH,
+           P2sbDevNumber (),
+           P2sbFuncNumber (),
+           0
+           );
+}
+
+
+
+/**
+  Returns PCH SPI Device number
+
+  @retval UINT8   PCH SPI Device number
+**/
+UINT8
+SpiDevNumber (
+  VOID
+  )
+{
+  return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_SPI);
+}
+
+/**
+  Returns PCH SPI Function number
+
+  @retval UINT8   PCH SPI Function number
+**/
+UINT8
+SpiFuncNumber (
+  VOID
+  )
+{
+  return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_SPI);
+}
+
+/**
+  Returns PCH SPI PCI Config Space base address
+
+  @retval  UINT64  PCH SPI Config Space base address
+**/
+UINT64
+SpiPciCfgBase (
+  VOID
+  )
+{
+  return PCI_SEGMENT_LIB_ADDRESS (
+           DEFAULT_PCI_SEGMENT_NUMBER_PCH,
+           DEFAULT_PCI_BUS_NUMBER_PCH,
+           SpiDevNumber (),
+           SpiFuncNumber (),
+           0
+           );
+}
+
+/**
+  Get XHCI controller PCIe Device Number
+
+  @retval XHCI controller PCIe Device Number
+**/
+UINT8
+PchXhciDevNumber (
+  VOID
+  )
+{
+  return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_XHCI);
+}
+
+/**
+  Get XHCI controller PCIe Function Number
+
+  @retval XHCI controller PCIe Function Number
+**/
+UINT8
+PchXhciFuncNumber (
+  VOID
+  )
+{
+  return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_XHCI);
+}
+
+/**
+  Get LPC controller PCIe Device Number
+
+  @retval LPC controller PCIe Device Number
+**/
+UINT8
+LpcDevNumber (
+  VOID
+  )
+{
+  return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_LPC);
+}
+
+/**
+  Get LPC controller PCIe Function Number
+
+  @retval LPC controller PCIe Function Number
+**/
+UINT8
+LpcFuncNumber (
+  VOID
+  )
+{
+  return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_LPC);
+}
+
+/**
+  Returns PCH LPC device PCI base address.
+
+  @retval                   PCH LPC PCI base address.
+**/
+UINT64
+LpcPciCfgBase (
+  VOID
+  )
+{
+  return PCI_SEGMENT_LIB_ADDRESS (
+           DEFAULT_PCI_SEGMENT_NUMBER_PCH,
+           DEFAULT_PCI_BUS_NUMBER_PCH,
+           LpcDevNumber (),
+           LpcFuncNumber (),
+           0
+           );
+}
+
+
+
+/**
+  Get PCH PCIe controller PCIe Device Number
+
+  @param[in]  RpIndex       Root port physical number. (0-based)
+
+  @retval PCH PCIe controller PCIe Device Number
+**/
+UINT8
+PchPcieRpDevNumber (
+  IN  UINTN   RpIndex
+  )
+{
+  switch (RpIndex) {
+    case 0:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_1);
+    case 1:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_2);
+    case 2:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_3);
+    case 3:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_4);
+    case 4:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_5);
+    case 5:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_6);
+    case 6:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_7);
+    case 7:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_8);
+    case 8:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_9);
+    case 9:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_10);
+    case 10:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_11);
+    case 11:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_12);
+    case 12:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_13);
+    case 13:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_14);
+    case 14:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_15);
+    case 15:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_16);
+    case 16:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_17);
+    case 17:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_18);
+    case 18:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_19);
+    case 19:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_20);
+    case 20:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_21);
+    case 21:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_22);
+    case 22:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_23);
+    case 23:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_24);
+    case 24:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_25);
+    case 25:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_26);
+    case 26:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_27);
+    case 27:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_28);
+
+    default:
+      ASSERT (FALSE);
+      return 0xFF;
+  }
+}
+
+/**
+  Get PCH PCIe controller PCIe Function Number
+  Note:
+  For Client PCH generations Function Number can be various
+  depending on "Root Port Function Swapping". For such cases
+  Function Number  MUST be obtain from proper register.
+  For Server PCHs we have no "Root Port Function Swapping"
+  and we can return fixed Function Number.
+  To address this difference in this, PCH generation independent,
+  library we should call specific function in PchPcieRpLib.
+
+  @param[in]  RpIndex       Root port physical number. (0-based)
+
+  @retval PCH PCIe controller PCIe Function Number
+**/
+UINT8
+PchPcieRpFuncNumber (
+  IN  UINTN   RpIndex
+  )
+{
+  UINTN   Device;
+  UINTN   Function;
+
+  GetPchPcieRpDevFun (RpIndex, &Device, &Function);
+
+  return (UINT8)Function;
+}
+
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/BaseResetSystemLib/BaseResetSystemLib.c b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/BaseResetSystemLib/BaseResetSystemLib.c
new file mode 100644
index 0000000000..86eeff9407
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/BaseResetSystemLib/BaseResetSystemLib.c
@@ -0,0 +1,114 @@
+/** @file
+  System reset library services.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Uefi.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/ResetSystemLib.h>
+#include <Library/PmcLib.h>
+#include <Library/BaseLib.h>
+#include <Register/PchRegsLpc.h>
+#include <Register/PmcRegs.h>
+
+/**
+  Calling this function causes a system-wide reset. This sets
+  all circuitry within the system to its initial state. This type of reset
+  is asynchronous to system operation and operates without regard to
+  cycle boundaries.
+
+  System reset should not return, if it returns, it means the system does
+  not support cold reset.
+**/
+VOID
+EFIAPI
+ResetCold (
+  VOID
+  )
+{
+  IoWrite8 (R_PCH_IO_RST_CNT, V_PCH_IO_RST_CNT_FULLRESET);
+}
+
+/**
+  Calling this function causes a system-wide initialization. The processors
+  are set to their initial state, and pending cycles are not corrupted.
+
+  System reset should not return, if it returns, it means the system does
+  not support warm reset.
+**/
+VOID
+EFIAPI
+ResetWarm (
+  VOID
+  )
+{
+  IoWrite8 (R_PCH_IO_RST_CNT, V_PCH_IO_RST_CNT_HARDRESET);
+}
+
+/**
+  Calling this function causes the system to enter a power state equivalent
+  to the ACPI G2/S5 or G3 states.
+
+  System shutdown should not return, if it returns, it means the system does
+  not support shut down reset.
+**/
+VOID
+EFIAPI
+ResetShutdown (
+  VOID
+  )
+{
+  UINT16         ABase;
+  UINT32         Data32;
+
+  ABase = PmcGetAcpiBase ();
+
+  ///
+  /// Firstly, GPE0_EN should be disabled to avoid any GPI waking up the system from S5
+  ///
+  IoWrite32 (ABase + R_ACPI_IO_GPE0_EN_127_96, 0);
+
+  ///
+  /// Secondly, PwrSts register must be cleared
+  ///
+  /// Write a "1" to bit[8] of power button status register at
+  /// (PM_BASE + PM1_STS_OFFSET) to clear this bit
+  ///
+  IoWrite16 (ABase + R_ACPI_IO_PM1_STS, B_ACPI_IO_PM1_STS_PWRBTN);
+
+  ///
+  /// Finally, transform system into S5 sleep state
+  ///
+  Data32 = IoRead32 (ABase + R_ACPI_IO_PM1_CNT);
+
+  Data32 = (UINT32) ((Data32 &~(B_ACPI_IO_PM1_CNT_SLP_TYP + B_ACPI_IO_PM1_CNT_SLP_EN)) | V_ACPI_IO_PM1_CNT_S5);
+
+  IoWrite32 (ABase + R_ACPI_IO_PM1_CNT, Data32);
+
+  Data32 = Data32 | B_ACPI_IO_PM1_CNT_SLP_EN;
+
+  IoWrite32 (ABase + R_ACPI_IO_PM1_CNT, Data32);
+
+  return;
+}
+
+/**
+  Calling this function causes the system to enter a power state for platform specific.
+
+  @param[in] DataSize             The size of ResetData in bytes.
+  @param[in] ResetData            Optional element used to introduce a platform specific reset.
+                                  The exact type of the reset is defined by the EFI_GUID that follows
+                                  the Null-terminated Unicode string.
+
+**/
+VOID
+EFIAPI
+ResetPlatformSpecific (
+  IN UINTN            DataSize,
+  IN VOID             *ResetData OPTIONAL
+  )
+{
+  IoWrite8 (R_PCH_IO_RST_CNT, V_PCH_IO_RST_CNT_FULLRESET);
+}
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/BaseResetSystemLib/BaseResetSystemLib.inf b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/BaseResetSystemLib/BaseResetSystemLib.inf
new file mode 100644
index 0000000000..f0a987d671
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/BaseResetSystemLib/BaseResetSystemLib.inf
@@ -0,0 +1,37 @@
+## @file
+# Component description file for Intel Ich7 Reset System Library.
+#
+#   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+#   SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = BaseResetSystemLib
+FILE_GUID = D4FF05AA-3C7D-4B8A-A1EE-AA5EFA0B1732
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+UEFI_SPECIFICATION_VERSION = 2.00
+LIBRARY_CLASS = ResetSystemLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF
+#
+
+[LibraryClasses]
+IoLib
+BaseLib
+DebugLib
+PmcLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+AlderlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+BaseResetSystemLib.c
+
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PchCycleDecodingLib.c b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PchCycleDecodingLib.c
new file mode 100644
index 0000000000..ccdac7c5ab
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PchCycleDecodingLib.c
@@ -0,0 +1,194 @@
+/** @file
+  PCH cycle decoding configuration and query library.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/PchDmiLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Register/PchRegs.h>
+#include <Register/PchRegsLpc.h>
+#include <Register/SpiRegs.h>
+#include <Library/EspiLib.h>
+#include <Library/PchPciBdfLib.h>
+
+typedef enum {
+  SlaveLpcEspiCS0,
+  SlaveEspiCS1,
+  SlaveId_Max
+} SLAVE_ID_INDEX;
+
+/**
+  Get PCH TCO base address.
+
+  @param[out] Address                   Address of TCO base address.
+
+  @retval EFI_SUCCESS                   Successfully completed.
+  @retval EFI_INVALID_PARAMETER         Invalid pointer passed.
+**/
+EFI_STATUS
+PchTcoBaseGet (
+  OUT UINT16                            *Address
+  )
+{
+  if (Address == NULL) {
+    DEBUG ((DEBUG_ERROR, "PchTcoBaseGet Error. Invalid pointer.\n"));
+    ASSERT (FALSE);
+    return EFI_INVALID_PARAMETER;
+  }
+  //
+  // Read "TCO Base Address" from DMI
+  // Don't read TCO base address from SMBUS PCI register since SMBUS might be disabled.
+  //
+  *Address = PchDmiGetTcoBase ();
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Set PCH LPC/eSPI IO decode ranges.
+  Program LPC/eSPI I/O Decode Ranges in DMI to the same value programmed in LPC/eSPI PCI offset 80h.
+  Please check EDS for detail of LPC/eSPI IO decode ranges bit definition.
+  Bit  12: FDD range
+  Bit 9:8: LPT range
+  Bit 6:4: ComB range
+  Bit 2:0: ComA range
+
+  @param[in] LpcIoDecodeRanges          LPC/eSPI IO decode ranges bit settings.
+
+  @retval EFI_SUCCESS                   Successfully completed.
+  @retval EFI_UNSUPPORTED               DMIC.SRL is set.
+**/
+EFI_STATUS
+PchLpcIoDecodeRangesSet (
+  IN  UINT16                            LpcIoDecodeRanges
+  )
+{
+  UINT64                                LpcBaseAddr;
+  EFI_STATUS                            Status;
+
+  //
+  // Note: Inside this function, don't use debug print since it's could used before debug print ready.
+  //
+
+  LpcBaseAddr = LpcPciCfgBase ();
+
+  //
+  // check if setting is identical
+  //
+  if (LpcIoDecodeRanges == PciSegmentRead16 (LpcBaseAddr + R_LPC_CFG_IOD)) {
+    return EFI_SUCCESS;
+  }
+
+  Status = PchDmiSetLpcIoDecodeRanges (LpcIoDecodeRanges);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    return Status;
+  }
+
+  //
+  // program LPC/eSPI PCI offset 80h.
+  //
+  PciSegmentWrite16 (LpcBaseAddr + R_LPC_CFG_IOD, LpcIoDecodeRanges);
+
+  return Status;
+}
+
+/**
+  Set PCH LPC/eSPI and eSPI CS1# IO enable decoding.
+  Setup I/O Enables in DMI to the same value program in LPC/eSPI PCI offset 82h (LPC, eSPI CS0#) or A0h (eSPI CS1#).
+  Note: Bit[15:10] of the source decode register is Read-Only. The IO range indicated by the Enables field
+  in LPC/eSPI PCI offset 82h[13:10] or A0h[13:10] is always forwarded by DMI to subtractive agent for handling.
+  Please check EDS for detail of Lpc/eSPI IO decode ranges bit definition.
+
+  @param[in] IoEnableDecoding           LPC/eSPI IO enable decoding bit settings.
+  @param[in] SlaveId                    Target ID (refer to SLAVE_ID_INDEX)
+
+  @retval EFI_SUCCESS                   Successfully completed.
+  @retval EFI_UNSUPPORTED               DMI configuration is locked
+**/
+EFI_STATUS
+LpcEspiIoEnableDecodingSetHelper (
+  IN  UINT16                            IoEnableDecoding,
+  IN  SLAVE_ID_INDEX                    SlaveId
+  )
+{
+  UINT64      LpcBaseAddr;
+  EFI_STATUS  Status;
+  UINT16      Cs1IoEnableDecodingOrg;
+  UINT16      Cs0IoEnableDecodingOrg;
+  UINT16      IoEnableDecodingMerged;
+
+  LpcBaseAddr = LpcPciCfgBase ();
+
+  Cs0IoEnableDecodingOrg = PciSegmentRead16 (LpcBaseAddr + R_LPC_CFG_IOE);
+
+  if (IsEspiSecondSlaveSupported ()) {
+    Cs1IoEnableDecodingOrg = PciSegmentRead16 (LpcBaseAddr + R_ESPI_CFG_CS1IORE);
+  } else {
+    Cs1IoEnableDecodingOrg = 0;
+  }
+
+  if (SlaveId == SlaveEspiCS1) {
+    if (IoEnableDecoding == Cs1IoEnableDecodingOrg) {
+      return EFI_SUCCESS;
+    } else {
+      IoEnableDecodingMerged = (Cs0IoEnableDecodingOrg | IoEnableDecoding);
+    }
+  } else {
+    if ((IoEnableDecoding | Cs1IoEnableDecodingOrg) == Cs0IoEnableDecodingOrg) {
+      return EFI_SUCCESS;
+    } else {
+      IoEnableDecodingMerged = (Cs1IoEnableDecodingOrg | IoEnableDecoding);
+    }
+  }
+
+  Status = PchDmiSetLpcIoEnable (IoEnableDecodingMerged);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    return Status;
+  }
+
+  //
+  // program PCI offset 82h for LPC/eSPI.
+  //
+  PciSegmentWrite16 (LpcBaseAddr + R_LPC_CFG_IOE, IoEnableDecodingMerged);
+
+  if (SlaveId == SlaveEspiCS1) {
+    //
+    // For eSPI CS1# device program eSPI PCI offset A0h.
+    //
+    PciSegmentWrite16 (LpcBaseAddr + R_ESPI_CFG_CS1IORE, IoEnableDecoding);
+  }
+
+  return Status;
+}
+
+/**
+  Set PCH LPC and eSPI CS0# IO enable decoding.
+  Setup I/O Enables in DMI to the same value program in LPC/eSPI PCI offset 82h.
+  Note: Bit[15:10] of the source decode register is Read-Only. The IO range indicated by the Enables field
+  in LPC/eSPI PCI offset 82h[13:10] is always forwarded by DMI to subtractive agent for handling.
+  Please check EDS for detail of LPC/eSPI IO decode ranges bit definition.
+
+  @param[in] LpcIoEnableDecoding        LPC IO enable decoding bit settings.
+
+  @retval EFI_SUCCESS                   Successfully completed.
+  @retval EFI_UNSUPPORTED               DMIC.SRL is set.
+**/
+EFI_STATUS
+PchLpcIoEnableDecodingSet (
+  IN  UINT16                            LpcIoEnableDecoding
+  )
+{
+  return LpcEspiIoEnableDecodingSetHelper (LpcIoEnableDecoding, SlaveLpcEspiCS0);
+}
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PeiDxeSmmPchCycleDecodingLib.inf b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PeiDxeSmmPchCycleDecodingLib.inf
new file mode 100644
index 0000000000..a381c0f0f7
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PeiDxeSmmPchCycleDecodingLib.inf
@@ -0,0 +1,41 @@
+## @file
+# PCH cycle decoding Lib.
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+#   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+#   SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmPchCycleDecodingLib
+FILE_GUID = 676C749F-9CD1-46B7-BAFD-4B1BC36B4C8E
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchCycleDecodingLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+PciSegmentLib
+PchInfoLib
+PchPcrLib
+PchDmiLib
+EspiLib
+PchPciBdfLib
+
+[Packages]
+MdePkg/MdePkg.dec
+AlderlakeSiliconPkg/SiPkg.dec
+
+[Sources]
+PchCycleDecodingLib.c
+
+[Pcd]
+gSiPkgTokenSpaceGuid.PcdSiHpetBaseAddress        ## CONSUMES
+gSiPkgTokenSpaceGuid.PcdSiIoApicBaseAddress      ## CONSUMES
-- 
2.36.1.windows.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 5/8] AlderlakeSiliconPkg/Pch: Add drivers
  2023-06-15 17:52 [PATCH 1/8] AlderlakeSiliconPkg: Add package and library instances Saloni Kasbekar
                   ` (2 preceding siblings ...)
  2023-06-15 17:53 ` [PATCH 4/8] AlderlakeSiliconPkg/Pch: Add libraries Saloni Kasbekar
@ 2023-06-15 17:53 ` Saloni Kasbekar
  2023-07-24  7:54   ` [edk2-devel] " Chaganty, Rangasai V
  2023-06-15 17:53 ` [PATCH 6/8] AlderlakeSiliconPkg/SystemAgent: Add NVS support Saloni Kasbekar
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 15+ messages in thread
From: Saloni Kasbekar @ 2023-06-15 17:53 UTC (permalink / raw)
  To: devel
  Cc: Saloni Kasbekar, Sai Chaganty, Nate DeSimone, Isaac Oram,
	Rosen Chuang

Adds the following drivers:
- PchSmiDispatcher
- SmmControl

Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Isaac Oram <isaac.w.oram@intel.com>
Cc: Rosen Chuang <rosen.chuang@intel.com>
Signed-off-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
---
 .../Pch/PchSmiDispatcher/Smm/PchSmiDispatch.c | 1857 +++++++++++++++++
 .../PchSmiDispatcher/Smm/PchSmiDispatcher.inf |  106 +
 .../Pch/PchSmiDispatcher/Smm/PchSmiHelper.h   |   34 +
 .../Pch/PchSmiDispatcher/Smm/PchSmm.h         | 1028 +++++++++
 .../Pch/PchSmiDispatcher/Smm/PchSmmCore.c     |  905 ++++++++
 .../Pch/PchSmiDispatcher/Smm/PchSmmGpi.c      |  255 +++
 .../Pch/PchSmiDispatcher/Smm/PchSmmHelpers.c  |  332 +++
 .../Pch/PchSmiDispatcher/Smm/PchSmmHelpers.h  |  163 ++
 .../Smm/PchSmmPeriodicTimer.c                 |  670 ++++++
 .../PchSmiDispatcher/Smm/PchSmmPowerButton.c  |   77 +
 .../Pch/PchSmiDispatcher/Smm/PchSmmSw.c       |  381 ++++
 .../Pch/PchSmiDispatcher/Smm/PchSmmSx.c       |  117 ++
 .../Pch/PchSmiDispatcher/Smm/PchSmmUsb.c      |  244 +++
 .../Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.c |  682 ++++++
 .../Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.h |  107 +
 .../Pch/PchSmiDispatcher/Smm/PcieSmmClient.c  |   38 +
 .../Pch/PchSmiDispatcher/Smm/SmmGlobalsPch.c  |   20 +
 .../Pch/SmmControl/RuntimeDxe/SmmControl.inf  |   53 +
 .../SmmControl/RuntimeDxe/SmmControlDriver.c  |  338 +++
 .../SmmControl/RuntimeDxe/SmmControlDriver.h  |  122 ++
 20 files changed, 7529 insertions(+)
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiDispatch.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiDispatcher.inf
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiHelper.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmm.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmCore.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmGpi.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmHelpers.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmHelpers.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmPeriodicTimer.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmPowerButton.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmSw.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmSx.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmUsb.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PcieSmmClient.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/SmmGlobalsPch.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControl.inf
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.h

diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiDispatch.c b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiDispatch.c
new file mode 100644
index 0000000000..be81459009
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiDispatch.c
@@ -0,0 +1,1857 @@
+/** @file
+  This function handle the register/unregister of PCH specific SMI events.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "PchSmmHelpers.h"
+#include <Library/SmiHandlerProfileLib.h>
+#include <Register/PchRegs.h>
+#include <Register/PmcRegs.h>
+#include <Register/TcoRegs.h>
+#include <Register/PchRegsLpc.h>
+#include <Register/SpiRegs.h>
+#include <Library/PchPciBdfLib.h>
+#include <Library/S3BootScriptLib.h>
+#include "PchSmiHelper.h"
+
+
+/**
+  The internal function used to create and insert a database record
+  for SMI record of Pch Smi types.
+
+  @param[in]  SrcDesc                   The pointer to the SMI source description
+  @param[in]  DispatchFunction          Pointer to dispatch function to be invoked for this SMI source
+  @param[in]  PchSmiType                Specific SMI type of PCH SMI
+  @param[out] DispatchHandle            Handle of dispatch function to register.
+
+  @retval EFI_INVALID_PARAMETER         Error with NULL SMI source description
+  @retval EFI_OUT_OF_RESOURCES          Fail to allocate pool for database record
+  @retval EFI_SUCCESS                   The database record is created successfully.
+**/
+EFI_STATUS
+PchSmiRecordInsert (
+  IN  CONST PCH_SMM_SOURCE_DESC         *SrcDesc,
+  IN  PCH_SMI_CALLBACK_FUNCTIONS        DispatchFunction,
+  IN  PCH_SMI_TYPES                     PchSmiType,
+  OUT EFI_HANDLE                        *DispatchHandle
+  )
+{
+  EFI_STATUS                            Status;
+  DATABASE_RECORD                       Record;
+
+  if (SrcDesc == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  ZeroMem (&Record, sizeof (DATABASE_RECORD));
+  //
+  // Gather information about the registration request
+  //
+  Record.Signature                      = DATABASE_RECORD_SIGNATURE;
+  Record.PchSmiCallback                 = DispatchFunction;
+  Record.ProtocolType                   = PchSmiDispatchType;
+  Record.PchSmiType                     = PchSmiType;
+
+  CopyMem (&Record.SrcDesc, SrcDesc, sizeof (PCH_SMM_SOURCE_DESC));
+  Status = SmmCoreInsertRecord (
+             &Record,
+             DispatchHandle
+             );
+  ASSERT_EFI_ERROR (Status);
+
+  return EFI_SUCCESS;
+}
+
+
+//
+// TCO_STS bit that needs to be cleared
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mDescSrcTcoSts = {
+  PCH_SMM_NO_FLAGS,
+  {
+    NULL_BIT_DESC_INITIALIZER,
+    NULL_BIT_DESC_INITIALIZER
+  },
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_STS}
+      },
+      S_ACPI_IO_SMI_STS,
+      N_ACPI_IO_SMI_STS_TCO
+    }
+  },
+  NULL_BIT_DESC_INITIALIZER
+};
+
+/**
+  Clear the TCO SMI status bit and block after the SMI handling is done
+
+  @param[in] SrcDesc                    Pointer to the PCH SMI source description table
+
+**/
+VOID
+EFIAPI
+PchTcoSmiClearSourceAndBlock (
+  CONST PCH_SMM_SOURCE_DESC             *SrcDesc
+  )
+{
+  PchSmmClearSourceAndBlock (SrcDesc);
+  //
+  // Any TCO-based status bits require special handling.
+  // SMI_STS.TCO_STS must be cleared in addition to the status bit in the TCO registers
+  //
+  PchSmmClearSource (&mDescSrcTcoSts);
+}
+
+/**
+  Clear the TCO SMI status bit after the SMI handling is done
+
+  @param[in] SrcDesc                    Pointer to the PCH SMI source description table
+
+**/
+VOID
+EFIAPI
+PchTcoSmiClearSource (
+  CONST PCH_SMM_SOURCE_DESC             *SrcDesc
+  )
+{
+  PchSmmClearSource (SrcDesc);
+  //
+  // Any TCO-based status bits require special handling.
+  // SMI_STS.TCO_STS must be cleared in addition to the status bit in the TCO registers
+  //
+  PchSmmClearSource (&mDescSrcTcoSts);
+}
+
+/**
+  Initialize Source descriptor structure
+
+   @param[in] SrcDesc                    Pointer to the PCH SMI source description table
+
+**/
+VOID
+EFIAPI
+NullInitSourceDesc (
+   PCH_SMM_SOURCE_DESC                   *SrcDesc
+   )
+{
+  ZeroMem (SrcDesc, sizeof (PCH_SMM_SOURCE_DESC));
+  SrcDesc->En[0].Reg.Type = PCH_SMM_ADDR_TYPE_NULL;
+  SrcDesc->En[1].Reg.Type = PCH_SMM_ADDR_TYPE_NULL;
+  SrcDesc->Sts[0].Reg.Type = PCH_SMM_ADDR_TYPE_NULL;
+  SrcDesc->PmcSmiSts.Reg.Type = PCH_SMM_ADDR_TYPE_NULL;
+}
+
+//
+// Mch srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescMch = {
+  PCH_SMM_NO_FLAGS,
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_EN}
+      },
+      S_ACPI_IO_SMI_EN,
+      N_ACPI_IO_SMI_EN_TCO
+    },
+    NULL_BIT_DESC_INITIALIZER
+  },
+  {
+    {
+      {
+        TCO_ADDR_TYPE,
+        {R_TCO_IO_TCO1_STS}
+      },
+      S_TCO_IO_TCO1_STS,
+      N_TCO_IO_TCO1_STS_DMISMI
+    }
+  },
+  {
+    {
+      ACPI_ADDR_TYPE,
+      {R_ACPI_IO_SMI_STS}
+    },
+    S_ACPI_IO_SMI_STS,
+    N_ACPI_IO_SMI_STS_TCO
+  }
+};
+
+/**
+  The register function used to register SMI handler of MCH event.
+
+  @param[in]  This                      The pointer to the protocol itself
+  @param[in]  DispatchFunction          Pointer to dispatch function to be invoked for this SMI source
+  @param[out] DispatchHandle            Handle of dispatch function to register.
+
+  @retval EFI_INVALID_PARAMETER         Error with NULL SMI source description
+  @retval EFI_OUT_OF_RESOURCES          Fail to allocate pool for database record
+  @retval EFI_SUCCESS                   The database record is created successfully.
+  @retval EFI_ACCESS_DENIED             Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiMchRegister (
+  IN  PCH_TCO_SMI_DISPATCH_PROTOCOL     *This,
+  IN  PCH_TCO_SMI_DISPATCH_CALLBACK     DispatchFunction,
+  OUT EFI_HANDLE                        *DispatchHandle
+  )
+{
+  EFI_STATUS                            Status;
+  DATABASE_RECORD                       *Record;
+
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  Status = PchSmiRecordInsert (
+             &mSrcDescMch,
+             (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+             PchTcoSmiMchType,
+             DispatchHandle
+             );
+  if (!EFI_ERROR (Status)) {
+    Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+    Record->ClearSource = PchTcoSmiClearSource;
+    PchSmmClearSource (&Record->SrcDesc);
+    PchSmmEnableSource (&Record->SrcDesc);
+    SmiHandlerProfileRegisterHandler (&gPchTcoSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+  }
+  return Status;
+}
+
+//
+// TcoTimeout srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescTcoTimeout = {
+  PCH_SMM_NO_FLAGS,
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_EN}
+      },
+      S_ACPI_IO_SMI_EN,
+      N_ACPI_IO_SMI_EN_TCO
+    },
+    NULL_BIT_DESC_INITIALIZER
+  },
+  {
+    {
+      {
+        TCO_ADDR_TYPE,
+        {R_TCO_IO_TCO1_STS}
+      },
+      S_TCO_IO_TCO1_STS,
+      N_TCO_IO_TCO1_STS_TIMEOUT
+    }
+  },
+  {
+    {
+      ACPI_ADDR_TYPE,
+      {R_ACPI_IO_SMI_STS}
+    },
+    S_ACPI_IO_SMI_STS,
+    N_ACPI_IO_SMI_STS_TCO
+  }
+};
+
+/**
+  The register function used to register SMI handler of TcoTimeout event.
+
+  @param[in]  This                      The pointer to the protocol itself
+  @param[in]  DispatchFunction          Pointer to dispatch function to be invoked for this SMI source
+  @param[out] DispatchHandle            Handle of dispatch function to register.
+
+  @retval EFI_INVALID_PARAMETER         Error with NULL SMI source description
+  @retval EFI_OUT_OF_RESOURCES          Fail to allocate pool for database record
+  @retval EFI_SUCCESS                   The database record is created successfully.
+  @retval EFI_ACCESS_DENIED             Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiTcoTimeoutRegister (
+  IN  PCH_TCO_SMI_DISPATCH_PROTOCOL     *This,
+  IN  PCH_TCO_SMI_DISPATCH_CALLBACK     DispatchFunction,
+  OUT EFI_HANDLE                        *DispatchHandle
+  )
+{
+  EFI_STATUS                            Status;
+  DATABASE_RECORD                       *Record;
+
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  Status = PchSmiRecordInsert (
+             &mSrcDescTcoTimeout,
+             (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+             PchTcoSmiTcoTimeoutType,
+             DispatchHandle
+             );
+  if (!EFI_ERROR (Status)) {
+    Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+    Record->ClearSource = PchTcoSmiClearSource;
+    PchSmmClearSource (&Record->SrcDesc);
+    PchSmmEnableSource (&Record->SrcDesc);
+    SmiHandlerProfileRegisterHandler (&gPchTcoSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+  }
+  return Status;
+}
+
+//
+// OsTco srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescOsTco = {
+  PCH_SMM_NO_FLAGS,
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_EN}
+      },
+      S_ACPI_IO_SMI_EN,
+      N_ACPI_IO_SMI_EN_TCO
+    },
+    NULL_BIT_DESC_INITIALIZER
+  },
+  {
+    {
+      {
+        TCO_ADDR_TYPE,
+        {R_TCO_IO_TCO1_STS}
+      },
+      S_TCO_IO_TCO1_STS,
+      N_TCO_IO_TCO1_STS_SW_TCO_SMI
+    }
+  },
+  {
+    {
+      ACPI_ADDR_TYPE,
+      {R_ACPI_IO_SMI_STS}
+    },
+    S_ACPI_IO_SMI_STS,
+    N_ACPI_IO_SMI_STS_TCO
+  }
+};
+
+/**
+  The register function used to register SMI handler of OS TCO event.
+
+  @param[in]  This                      The pointer to the protocol itself
+  @param[in]  DispatchFunction          Pointer to dispatch function to be invoked for this SMI source
+  @param[out] DispatchHandle            Handle of dispatch function to register.
+
+  @retval EFI_INVALID_PARAMETER         Error with NULL SMI source description
+  @retval EFI_OUT_OF_RESOURCES          Fail to allocate pool for database record
+  @retval EFI_SUCCESS                   The database record is created successfully.
+  @retval EFI_ACCESS_DENIED             Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiOsTcoRegister (
+  IN  PCH_TCO_SMI_DISPATCH_PROTOCOL     *This,
+  IN  PCH_TCO_SMI_DISPATCH_CALLBACK     DispatchFunction,
+  OUT EFI_HANDLE                        *DispatchHandle
+  )
+{
+  EFI_STATUS                            Status;
+  DATABASE_RECORD                       *Record;
+
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  Status = PchSmiRecordInsert (
+             &mSrcDescOsTco,
+             (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+             PchTcoSmiOsTcoType,
+             DispatchHandle
+             );
+  if (!EFI_ERROR (Status)) {
+    Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+    Record->ClearSource = PchTcoSmiClearSource;
+    PchSmmClearSource (&Record->SrcDesc);
+    PchSmmEnableSource (&Record->SrcDesc);
+    SmiHandlerProfileRegisterHandler (&gPchTcoSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+  }
+  return Status;
+}
+
+//
+// Nmi
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescNmi = {
+  PCH_SMM_NO_FLAGS,
+  {
+    {
+      {
+        TCO_ADDR_TYPE,
+        {R_TCO_IO_TCO1_CNT}
+      },
+      S_TCO_IO_TCO1_CNT,
+      N_TCO_IO_TCO1_CNT_NMI2SMI_EN
+    },
+    NULL_BIT_DESC_INITIALIZER
+  },
+  {
+    {
+      {
+        TCO_ADDR_TYPE,
+        {R_TCO_IO_TCO1_STS}
+      },
+      S_TCO_IO_TCO1_STS,
+      N_TCO_IO_TCO1_STS_NMI2SMI
+    }
+  },
+  //
+  // NOTE: The status of NMI2SMI won't reflect to PMC SMI_STS.
+  //       So skip the top level status check and check the TCO1_STS directly.
+  //
+  NULL_BIT_DESC_INITIALIZER
+};
+
+/**
+  The register function used to register SMI handler of NMI event.
+
+  @param[in]  This                      The pointer to the protocol itself
+  @param[in]  DispatchFunction          Pointer to dispatch function to be invoked for this SMI source
+  @param[out] DispatchHandle            Handle of dispatch function to register.
+
+  @retval EFI_INVALID_PARAMETER         Error with NULL SMI source description
+  @retval EFI_OUT_OF_RESOURCES          Fail to allocate pool for database record
+  @retval EFI_SUCCESS                   The database record is created successfully.
+  @retval EFI_ACCESS_DENIED             Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiNmiRegister (
+  IN  PCH_TCO_SMI_DISPATCH_PROTOCOL     *This,
+  IN  PCH_TCO_SMI_DISPATCH_CALLBACK     DispatchFunction,
+  OUT EFI_HANDLE                        *DispatchHandle
+  )
+{
+  EFI_STATUS                            Status;
+  DATABASE_RECORD                       *Record;
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  Status = PchSmiRecordInsert (
+             &mSrcDescNmi,
+             (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+             PchTcoSmiNmiType,
+             DispatchHandle
+             );
+  if (!EFI_ERROR (Status)) {
+    Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+    Record->ClearSource = PchTcoSmiClearSource;
+    PchSmmClearSource (&Record->SrcDesc);
+    PchSmmEnableSource (&Record->SrcDesc);
+    SmiHandlerProfileRegisterHandler (&gPchTcoSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+  }
+  return Status;
+}
+
+//
+// IntruderDetect srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescIntruderDet = {
+  PCH_SMM_NO_FLAGS,
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_EN}
+      },
+      S_ACPI_IO_SMI_EN,
+      N_ACPI_IO_SMI_EN_TCO
+    },
+    {
+      {
+        TCO_ADDR_TYPE,
+        {R_TCO_IO_TCO2_CNT}
+      },
+      S_TCO_IO_TCO2_CNT,
+      N_TCO_IO_TCO2_CNT_INTRD_SEL
+    }
+  },
+  {
+    {
+      {
+        TCO_ADDR_TYPE,
+        {R_TCO_IO_TCO2_STS}
+      },
+      S_TCO_IO_TCO2_STS,
+      N_TCO_IO_TCO2_STS_INTRD_DET
+    }
+  },
+  {
+    {
+      ACPI_ADDR_TYPE,
+      {R_ACPI_IO_SMI_STS}
+    },
+    S_ACPI_IO_SMI_STS,
+    N_ACPI_IO_SMI_STS_TCO
+  }
+};
+
+/**
+  The register function used to register SMI handler of Intruder Detect event.
+
+  @param[in]  This                      The pointer to the protocol itself
+  @param[in]  DispatchFunction          Pointer to dispatch function to be invoked for this SMI source
+  @param[out] DispatchHandle            Handle of dispatch function to register.
+
+  @retval EFI_INVALID_PARAMETER         Error with NULL SMI source description
+  @retval EFI_OUT_OF_RESOURCES          Fail to allocate pool for database record
+  @retval EFI_SUCCESS                   The database record is created successfully.
+  @retval EFI_ACCESS_DENIED             Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiIntruderDetRegister (
+  IN  PCH_TCO_SMI_DISPATCH_PROTOCOL     *This,
+  IN  PCH_TCO_SMI_DISPATCH_CALLBACK     DispatchFunction,
+  OUT EFI_HANDLE                        *DispatchHandle
+  )
+{
+  EFI_STATUS                            Status;
+  DATABASE_RECORD                       *Record;
+
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  Status = PchSmiRecordInsert (
+             &mSrcDescIntruderDet,
+             (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+             PchTcoSmiIntruderDetectType,
+             DispatchHandle
+             );
+  if (!EFI_ERROR (Status)) {
+    Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+    Record->ClearSource = PchTcoSmiClearSourceAndBlock;
+    PchSmmClearSource (&Record->SrcDesc);
+    PchSmmEnableSource (&Record->SrcDesc);
+    SmiHandlerProfileRegisterHandler (&gPchTcoSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+  }
+  return Status;
+}
+
+//
+// SpiBiosWp srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_SMM_SOURCE_DESC mSrcDescSpiBiosWp = {
+  PCH_SMM_NO_FLAGS,
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_EN}
+      },
+      S_ACPI_IO_SMI_EN,
+      N_ACPI_IO_SMI_EN_TCO
+    },
+    {
+      {
+        PCIE_ADDR_TYPE,
+        { 0xFFFFFFFF } // to be updated in PchSmiDispatchUpdateDescriptors
+      },
+      S_SPI_CFG_BC,
+      N_SPI_CFG_BC_BLE
+    },
+  },
+  {
+    {
+      {
+        PCIE_ADDR_TYPE,
+        { 0xFFFFFFFF } // to be updated in PchSmiDispatchUpdateDescriptors
+      },
+      S_SPI_CFG_BC,
+      N_SPI_CFG_BC_SYNC_SS
+    }
+  },
+  {
+    {
+      ACPI_ADDR_TYPE,
+      {R_ACPI_IO_SMI_STS}
+    },
+    S_ACPI_IO_SMI_STS,
+    N_ACPI_IO_SMI_STS_TCO
+  }
+};
+
+/**
+  Special handling for SPI Write Protect
+
+  @param[in]  SrcDesc   Not used
+**/
+VOID
+EFIAPI
+PchTcoSpiWpClearSource (
+  CONST PCH_SMM_SOURCE_DESC             *SrcDesc
+  )
+{
+  UINT64 SpiRegBase;
+  UINT32 BiosControl;
+  UINT32 Timeout;
+
+  SpiRegBase = SpiPciCfgBase ();
+  PciSegmentAndThenOr32 (
+    SpiRegBase + R_SPI_CFG_BC,
+    (UINT32) ~B_SPI_CFG_BC_ASYNC_SS,
+    B_SPI_CFG_BC_SYNC_SS
+    );
+  //
+  // Ensure the SYNC is cleared
+  //
+  Timeout = 1000;
+  do {
+    BiosControl = PciSegmentRead32 (SpiRegBase + R_SPI_CFG_BC);
+    Timeout--;
+  } while ((BiosControl & B_SPI_CFG_BC_SYNC_SS) && (Timeout > 0));
+
+  //
+  // Any TCO-based status bits require special handling.
+  // SMI_STS.TCO_STS must be cleared in addition to the status bit in the TCO registers
+  //
+  PchSmmClearSource (&mDescSrcTcoSts);
+}
+
+/**
+  Set SMI_EN_TCO to enable TCO SMI.
+**/
+STATIC
+VOID
+PchSetSmiEnTco (
+  VOID
+  )
+{
+  IoOr32 (mAcpiBaseAddr + R_ACPI_IO_SMI_EN, B_ACPI_IO_SMI_EN_TCO);
+}
+
+/**
+  The register function used to register SMI handler of BIOS write protect event.
+
+  @param[in]  This                      The pointer to the protocol itself
+  @param[in]  DispatchFunction          Pointer to dispatch function to be invoked for this SMI source
+  @param[out] DispatchHandle            Handle of dispatch function to register.
+
+  @retval EFI_INVALID_PARAMETER         Error with NULL SMI source description
+  @retval EFI_OUT_OF_RESOURCES          Fail to allocate pool for database record
+  @retval EFI_SUCCESS                   The database record is created successfully.
+  @retval EFI_ACCESS_DENIED             Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiSpiBiosWpRegister (
+  IN  PCH_TCO_SMI_DISPATCH_PROTOCOL     *This,
+  IN  PCH_TCO_SMI_DISPATCH_CALLBACK     DispatchFunction,
+  OUT EFI_HANDLE                        *DispatchHandle
+  )
+{
+  EFI_STATUS                            Status;
+  DATABASE_RECORD                       *Record;
+
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  Status = PchSmiRecordInsert (
+             &mSrcDescSpiBiosWp,
+             (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+             PchTcoSmiSpiBiosWpType,
+             DispatchHandle
+             );
+  if (!EFI_ERROR (Status)) {
+    Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+    Record->ClearSource = PchTcoSpiWpClearSource;
+    PchTcoSpiWpClearSource (NULL);
+    //
+    // It doesn't enable the BIOSLOCK here. Enable it by policy in DXE.
+    // Only enable SMI_EN_TCO.
+    //
+    PchSetSmiEnTco ();
+    SmiHandlerProfileRegisterHandler (&gPchTcoSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+  }
+  return Status;
+}
+
+//
+// LpcBiosWp srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_SMM_SOURCE_DESC mSrcDescLpcBiosWp = {
+  PCH_SMM_NO_FLAGS,
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_EN}
+      },
+      S_ACPI_IO_SMI_EN,
+      N_ACPI_IO_SMI_EN_TCO
+    },
+    {
+      {
+        PCIE_ADDR_TYPE,
+        { 0xFFFFFFFF } // to be updated in PchSmiDispatchUpdateDescriptors
+      },
+      S_LPC_CFG_BC,
+      N_LPC_CFG_BC_LE
+    }
+  },
+  {
+    {
+      {
+        TCO_ADDR_TYPE,
+        {R_TCO_IO_TCO1_STS}
+      },
+      S_TCO_IO_TCO1_STS,
+      N_TCO_IO_TCO1_STS_BIOSWR
+    }
+  },
+  {
+    {
+      ACPI_ADDR_TYPE,
+      {R_ACPI_IO_SMI_STS}
+    },
+    S_ACPI_IO_SMI_STS,
+    N_ACPI_IO_SMI_STS_TCO
+  }
+};
+
+/**
+  The register function used to register SMI handler of LPC BIOS write protect event.
+
+  @param[in]  This                      The pointer to the protocol itself
+  @param[in]  DispatchFunction          Pointer to dispatch function to be invoked for this SMI source
+  @param[out] DispatchHandle            Handle of dispatch function to register.
+
+  @retval EFI_INVALID_PARAMETER         Error with NULL SMI source description
+  @retval EFI_OUT_OF_RESOURCES          Fail to allocate pool for database record
+  @retval EFI_SUCCESS                   The database record is created successfully.
+  @retval EFI_ACCESS_DENIED             Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiLpcBiosWpRegister (
+  IN  PCH_TCO_SMI_DISPATCH_PROTOCOL     *This,
+  IN  PCH_TCO_SMI_DISPATCH_CALLBACK     DispatchFunction,
+  OUT EFI_HANDLE                        *DispatchHandle
+  )
+{
+  EFI_STATUS                            Status;
+  DATABASE_RECORD                       *Record;
+
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  if (IsEspiEnabled ()) {
+    //
+    // Status is D31F0's PCBC.BWPDS
+    //
+    ASSERT (FALSE);
+    return EFI_UNSUPPORTED;
+  }
+
+  Status = PchSmiRecordInsert (
+             &mSrcDescLpcBiosWp,
+             (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+             PchTcoSmiLpcBiosWpType,
+             DispatchHandle
+             );
+  if (!EFI_ERROR (Status)) {
+    Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+    Record->ClearSource = PchTcoSmiClearSource;
+    PchSmmClearSource (&Record->SrcDesc);
+    //
+    // It doesn't enable the BIOSLOCK here. Enable it by policy in DXE.
+    // Only enable SMI_EN_TCO.
+    //
+    PchSetSmiEnTco ();
+    SmiHandlerProfileRegisterHandler (&gPchTcoSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+  }
+  return Status;
+}
+
+//
+// NEWCENTURY_STS bit that needs to be cleared
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescNewCentury = {
+  PCH_SMM_NO_FLAGS,
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_EN}
+      },
+      S_ACPI_IO_SMI_EN,
+      N_ACPI_IO_SMI_EN_TCO
+    },
+    NULL_BIT_DESC_INITIALIZER
+  },
+  {
+    {
+      {
+        TCO_ADDR_TYPE,
+        {R_TCO_IO_TCO1_STS}
+      },
+      S_TCO_IO_TCO1_STS,
+      N_TCO_IO_TCO1_STS_NEWCENTURY
+    }
+  },
+  {
+    {
+      ACPI_ADDR_TYPE,
+      {R_ACPI_IO_SMI_STS}
+    },
+    S_ACPI_IO_SMI_STS,
+    N_ACPI_IO_SMI_STS_TCO
+  }
+};
+
+/**
+  The register function used to register SMI handler of NEW CENTURY event.
+
+  @param[in]  This                      The pointer to the protocol itself
+  @param[in]  DispatchFunction          Pointer to dispatch function to be invoked for this SMI source
+  @param[out] DispatchHandle            Handle of dispatch function to register.
+
+  @retval EFI_INVALID_PARAMETER         Error with NULL SMI source description
+  @retval EFI_OUT_OF_RESOURCES          Fail to allocate pool for database record
+  @retval EFI_SUCCESS                   The database record is created successfully.
+  @retval EFI_ACCESS_DENIED             Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiNewCenturyRegister (
+  IN  PCH_TCO_SMI_DISPATCH_PROTOCOL     *This,
+  IN  PCH_TCO_SMI_DISPATCH_CALLBACK     DispatchFunction,
+  OUT EFI_HANDLE                        *DispatchHandle
+  )
+{
+  EFI_STATUS                            Status;
+  DATABASE_RECORD                       *Record;
+
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  Status = PchSmiRecordInsert (
+             &mSrcDescNewCentury,
+             (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+             PchTcoSmiNewCenturyType,
+             DispatchHandle
+             );
+  if (!EFI_ERROR (Status)) {
+    Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+    Record->ClearSource = PchTcoSmiClearSourceAndBlock;
+    PchSmmClearSource (&Record->SrcDesc);
+    PchSmmEnableSource (&Record->SrcDesc);
+    SmiHandlerProfileRegisterHandler (&gPchTcoSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+  }
+  return Status;
+}
+
+/**
+  Unregister a child SMI source dispatch function with a parent SMM driver
+
+  @param[in] This                       Protocol instance pointer.
+  @param[in] DispatchHandle             Handle of dispatch function to deregister.
+
+  @retval EFI_SUCCESS                   The dispatch function has been successfully
+                                        unregistered and the SMI source has been disabled
+                                        if there are no other registered child dispatch
+                                        functions for this SMI source.
+  @retval EFI_INVALID_PARAMETER         Handle is invalid.
+  @retval EFI_ACCESS_DENIED             Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiUnRegister (
+  IN  PCH_TCO_SMI_DISPATCH_PROTOCOL     *This,
+  IN  EFI_HANDLE                        DispatchHandle
+  )
+{
+  return EFI_SUCCESS;
+}
+
+//
+// Pme srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescPme = {
+  PCH_SMM_SCI_EN_DEPENDENT,
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_GPE0_EN_127_96}
+      },
+      S_ACPI_IO_GPE0_EN_127_96,
+      N_ACPI_IO_GPE0_EN_127_96_PME
+    },
+    NULL_BIT_DESC_INITIALIZER
+  },
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_GPE0_STS_127_96}
+      },
+      S_ACPI_IO_GPE0_STS_127_96,
+      N_ACPI_IO_GPE0_STS_127_96_PME
+    }
+  },
+  {
+    {
+      ACPI_ADDR_TYPE,
+      {R_ACPI_IO_SMI_STS}
+    },
+    S_ACPI_IO_SMI_STS,
+    N_ACPI_IO_SMI_STS_GPE0
+  }
+};
+
+/**
+  The register function used to register SMI handler of PME event.
+
+  @param[in]  This                      The pointer to the protocol itself
+  @param[in]  DispatchFunction          Pointer to dispatch function to be invoked for this SMI source
+  @param[out] DispatchHandle            Handle of dispatch function to register.
+
+  @retval EFI_INVALID_PARAMETER         Error with NULL SMI source description
+  @retval EFI_OUT_OF_RESOURCES          Fail to allocate pool for database record
+  @retval EFI_SUCCESS                   The database record is created successfully.
+  @retval EFI_ACCESS_DENIED             Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchAcpiSmiPmeRegister (
+  IN  PCH_ACPI_SMI_DISPATCH_PROTOCOL    *This,
+  IN  PCH_ACPI_SMI_DISPATCH_CALLBACK    DispatchFunction,
+  OUT EFI_HANDLE                        *DispatchHandle
+  )
+{
+  EFI_STATUS                            Status;
+
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  Status = PchSmiRecordInsert (
+             &mSrcDescPme,
+             (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+             PchAcpiSmiPmeType,
+             DispatchHandle
+             );
+  PchSmmClearSource (&mSrcDescPme);
+  PchSmmEnableSource (&mSrcDescPme);
+  if (!EFI_ERROR (Status)) {
+    SmiHandlerProfileRegisterHandler (&gPchAcpiSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+  }
+  return Status;
+}
+
+//
+// PmeB0 srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescPmeB0 = {
+  PCH_SMM_SCI_EN_DEPENDENT,
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_GPE0_EN_127_96}
+      },
+      S_ACPI_IO_GPE0_EN_127_96,
+      N_ACPI_IO_GPE0_EN_127_96_PME_B0
+    },
+    NULL_BIT_DESC_INITIALIZER
+  },
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_GPE0_STS_127_96}
+      },
+      S_ACPI_IO_GPE0_STS_127_96,
+      N_ACPI_IO_GPE0_STS_127_96_PME_B0
+    }
+  },
+  {
+    {
+      ACPI_ADDR_TYPE,
+      {R_ACPI_IO_SMI_STS}
+    },
+    S_ACPI_IO_SMI_STS,
+    N_ACPI_IO_SMI_STS_GPE0
+  }
+};
+/**
+  The register function used to register SMI handler of PME B0 event.
+
+  @param[in]  This                      The pointer to the protocol itself
+  @param[in]  DispatchFunction          Pointer to dispatch function to be invoked for this SMI source
+  @param[out] DispatchHandle            Handle of dispatch function to register.
+
+  @retval EFI_INVALID_PARAMETER         Error with NULL SMI source description
+  @retval EFI_OUT_OF_RESOURCES          Fail to allocate pool for database record
+  @retval EFI_SUCCESS                   The database record is created successfully.
+  @retval EFI_ACCESS_DENIED             Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchAcpiSmiPmeB0Register (
+  IN  PCH_ACPI_SMI_DISPATCH_PROTOCOL    *This,
+  IN  PCH_ACPI_SMI_DISPATCH_CALLBACK    DispatchFunction,
+  OUT EFI_HANDLE                        *DispatchHandle
+  )
+{
+  EFI_STATUS                            Status;
+
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  Status = PchSmiRecordInsert (
+             &mSrcDescPmeB0,
+             (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+             PchAcpiSmiPmeB0Type,
+             DispatchHandle
+             );
+  PchSmmClearSource (&mSrcDescPmeB0);
+  PchSmmEnableSource (&mSrcDescPmeB0);
+  if (!EFI_ERROR (Status)) {
+    SmiHandlerProfileRegisterHandler (&gPchAcpiSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+  }
+  return Status;
+}
+
+//
+// RtcAlarm srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescRtcAlarm = {
+  PCH_SMM_SCI_EN_DEPENDENT,
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_PM1_EN}
+      },
+      S_ACPI_IO_PM1_EN,
+      N_ACPI_IO_PM1_EN_RTC
+    },
+    NULL_BIT_DESC_INITIALIZER
+  },
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_PM1_STS}
+      },
+      S_ACPI_IO_PM1_STS,
+      N_ACPI_IO_PM1_STS_RTC
+    }
+  },
+  {
+    {
+      ACPI_ADDR_TYPE,
+      {R_ACPI_IO_SMI_STS}
+    },
+    S_ACPI_IO_SMI_STS,
+    N_ACPI_IO_SMI_STS_PM1_STS_REG
+  }
+};
+
+/**
+  The register function used to register SMI handler of RTC alarm event.
+
+  @param[in]  This                      The pointer to the protocol itself
+  @param[in]  DispatchFunction          Pointer to dispatch function to be invoked for this SMI source
+  @param[out] DispatchHandle            Handle of dispatch function to register.
+
+  @retval EFI_INVALID_PARAMETER         Error with NULL SMI source description
+  @retval EFI_OUT_OF_RESOURCES          Fail to allocate pool for database record
+  @retval EFI_SUCCESS                   The database record is created successfully.
+  @retval EFI_ACCESS_DENIED             Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchAcpiSmiRtcAlarmRegister (
+  IN  PCH_ACPI_SMI_DISPATCH_PROTOCOL    *This,
+  IN  PCH_ACPI_SMI_DISPATCH_CALLBACK    DispatchFunction,
+  OUT EFI_HANDLE                        *DispatchHandle
+  )
+{
+  EFI_STATUS                            Status;
+
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  Status = PchSmiRecordInsert (
+             &mSrcDescRtcAlarm,
+             (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+             PchAcpiSmiRtcAlarmType,
+             DispatchHandle
+             );
+
+  PchSmmClearSource (&mSrcDescRtcAlarm);
+  PchSmmEnableSource (&mSrcDescRtcAlarm);
+  if (!EFI_ERROR (Status)) {
+    SmiHandlerProfileRegisterHandler (&gPchAcpiSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+  }
+  return Status;
+}
+
+//
+// TmrOverflow srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescTmrOverflow = {
+  PCH_SMM_SCI_EN_DEPENDENT,
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_PM1_EN}
+      },
+      S_ACPI_IO_PM1_EN,
+      N_ACPI_IO_PM1_EN_TMROF
+    },
+    NULL_BIT_DESC_INITIALIZER
+  },
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_PM1_STS}
+      },
+      S_ACPI_IO_PM1_STS,
+      N_ACPI_IO_PM1_STS_TMROF
+    }
+  },
+  {
+    {
+      ACPI_ADDR_TYPE,
+      {R_ACPI_IO_SMI_STS}
+    },
+    S_ACPI_IO_SMI_STS,
+    N_ACPI_IO_SMI_STS_PM1_STS_REG
+  }
+};
+
+/**
+  The register function used to register SMI handler of Timer Overflow event.
+
+  @param[in]  This                      The pointer to the protocol itself
+  @param[in]  DispatchFunction          Pointer to dispatch function to be invoked for this SMI source
+  @param[out] DispatchHandle            Handle of dispatch function to register.
+
+  @retval EFI_INVALID_PARAMETER         Error with NULL SMI source description
+  @retval EFI_OUT_OF_RESOURCES          Fail to allocate pool for database record
+  @retval EFI_SUCCESS                   The database record is created successfully.
+  @retval EFI_ACCESS_DENIED             Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchAcpiSmiTmrOverflowRegister (
+  IN  PCH_ACPI_SMI_DISPATCH_PROTOCOL    *This,
+  IN  PCH_ACPI_SMI_DISPATCH_CALLBACK    DispatchFunction,
+  OUT EFI_HANDLE                        *DispatchHandle
+  )
+{
+  EFI_STATUS                            Status;
+
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  Status = PchSmiRecordInsert (
+             &mSrcDescTmrOverflow,
+             (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+             PchAcpiSmiTmrOverflowType,
+             DispatchHandle
+             );
+  PchSmmClearSource (&mSrcDescTmrOverflow);
+  PchSmmEnableSource (&mSrcDescTmrOverflow);
+  if (!EFI_ERROR (Status)) {
+    SmiHandlerProfileRegisterHandler (&gPchAcpiSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+  }
+
+  return Status;
+}
+
+/**
+  Unregister a child SMI source dispatch function with a parent SMM driver
+
+  @param[in] This                       Protocol instance pointer.
+  @param[in] DispatchHandle             Handle of dispatch function to deregister.
+
+  @retval EFI_SUCCESS                   The dispatch function has been successfully
+                                        unregistered and the SMI source has been disabled
+                                        if there are no other registered child dispatch
+                                        functions for this SMI source.
+  @retval EFI_INVALID_PARAMETER         Handle is invalid.
+  @retval EFI_ACCESS_DENIED             Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchAcpiSmiUnRegister (
+  IN  PCH_ACPI_SMI_DISPATCH_PROTOCOL    *This,
+  IN  EFI_HANDLE                        DispatchHandle
+  )
+{
+  DATABASE_RECORD                   *RecordToDelete;
+  EFI_STATUS                        Status;
+
+  RecordToDelete = DATABASE_RECORD_FROM_LINK (DispatchHandle);
+  Status = PchSmmCoreUnRegister (NULL, DispatchHandle);
+  if (!EFI_ERROR (Status)) {
+    SmiHandlerProfileUnregisterHandler (&gPchAcpiSmiDispatchProtocolGuid, RecordToDelete->Callback, NULL, 0);
+  }
+  return Status;
+}
+
+//
+// SerialIrq srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescSerialIrq = {
+  PCH_SMM_NO_FLAGS,
+  {
+    NULL_BIT_DESC_INITIALIZER,
+    NULL_BIT_DESC_INITIALIZER
+  },
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_STS}
+      },
+      S_ACPI_IO_SMI_STS,
+      N_ACPI_IO_SMI_STS_SERIRQ
+    }
+  },
+  {
+    {
+      ACPI_ADDR_TYPE,
+      {R_ACPI_IO_SMI_STS}
+    },
+    S_ACPI_IO_SMI_STS,
+    N_ACPI_IO_SMI_STS_SERIRQ
+  }
+};
+
+/**
+  The register function used to register SMI handler of Serial IRQ event.
+
+  @param[in]  This                      The pointer to the protocol itself
+  @param[in]  DispatchFunction          Pointer to dispatch function to be invoked for this SMI source
+  @param[out] DispatchHandle            Handle of dispatch function to register.
+
+  @retval EFI_INVALID_PARAMETER         Error with NULL SMI source description
+  @retval EFI_OUT_OF_RESOURCES          Fail to allocate pool for database record
+  @retval EFI_SUCCESS                   The database record is created successfully.
+  @retval EFI_ACCESS_DENIED             Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchSmiSerialIrqRegister (
+  IN  PCH_SMI_DISPATCH_PROTOCOL         *This,
+  IN  PCH_SMI_DISPATCH_CALLBACK         DispatchFunction,
+  OUT EFI_HANDLE                        *DispatchHandle
+  )
+{
+  EFI_STATUS                            Status;
+
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  Status = PchSmiRecordInsert (
+             &mSrcDescSerialIrq,
+             (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+             PchSmiSerialIrqType,
+             DispatchHandle
+             );
+  PchSmmClearSource (&mSrcDescSerialIrq);
+  PchSmmEnableSource (&mSrcDescSerialIrq);
+  if (!EFI_ERROR (Status)) {
+     SmiHandlerProfileRegisterHandler (&gPchSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+  }
+  return Status;
+}
+
+//
+// McSmi srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescMcSmi = {
+  PCH_SMM_NO_FLAGS,
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_EN}
+      },
+      S_ACPI_IO_SMI_EN,
+      N_ACPI_IO_SMI_EN_MCSMI
+    },
+    NULL_BIT_DESC_INITIALIZER
+  },
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_STS}
+      },
+      S_ACPI_IO_SMI_STS,
+      N_ACPI_IO_SMI_STS_MCSMI
+    }
+  },
+  {
+    {
+      ACPI_ADDR_TYPE,
+      {R_ACPI_IO_SMI_STS}
+    },
+    S_ACPI_IO_SMI_STS,
+    N_ACPI_IO_SMI_STS_MCSMI
+  }
+};
+
+/**
+  The register function used to register SMI handler of MCSMI event.
+
+  @param[in]  This                      The pointer to the protocol itself
+  @param[in]  DispatchFunction          Pointer to dispatch function to be invoked for this SMI source
+  @param[out] DispatchHandle            Handle of dispatch function to register.
+
+  @retval EFI_INVALID_PARAMETER         Error with NULL SMI source description
+  @retval EFI_OUT_OF_RESOURCES          Fail to allocate pool for database record
+  @retval EFI_SUCCESS                   The database record is created successfully.
+  @retval EFI_ACCESS_DENIED             Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchSmiMcSmiRegister (
+  IN  PCH_SMI_DISPATCH_PROTOCOL         *This,
+  IN  PCH_SMI_DISPATCH_CALLBACK         DispatchFunction,
+  OUT EFI_HANDLE                        *DispatchHandle
+  )
+{
+  EFI_STATUS                            Status;
+
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  Status = PchSmiRecordInsert (
+             &mSrcDescMcSmi,
+             (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+             PchSmiMcSmiType,
+             DispatchHandle
+             );
+  PchSmmClearSource (&mSrcDescMcSmi);
+  PchSmmEnableSource (&mSrcDescMcSmi);
+  if (!EFI_ERROR (Status)) {
+    SmiHandlerProfileRegisterHandler (&gPchSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+  }
+  return Status;
+}
+
+//
+// SmBus srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescSmbus = {
+  PCH_SMM_NO_FLAGS,
+  {
+    NULL_BIT_DESC_INITIALIZER,
+    NULL_BIT_DESC_INITIALIZER
+  },
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_STS}
+      },
+      S_ACPI_IO_SMI_STS,
+      N_ACPI_IO_SMI_STS_SMBUS
+    }
+  },
+  {
+    {
+      ACPI_ADDR_TYPE,
+      {R_ACPI_IO_SMI_STS}
+    },
+    S_ACPI_IO_SMI_STS,
+    N_ACPI_IO_SMI_STS_SMBUS
+  }
+};
+
+/**
+  The register function used to register SMI handler of SMBUS event.
+
+  @param[in]  This                      The pointer to the protocol itself
+  @param[in]  DispatchFunction          Pointer to dispatch function to be invoked for this SMI source
+  @param[out] DispatchHandle            Handle of dispatch function to register.
+
+  @retval EFI_INVALID_PARAMETER         Error with NULL SMI source description
+  @retval EFI_OUT_OF_RESOURCES          Fail to allocate pool for database record
+  @retval EFI_SUCCESS                   The database record is created successfully.
+  @retval EFI_ACCESS_DENIED             Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchSmiSmbusRegister (
+  IN  PCH_SMI_DISPATCH_PROTOCOL         *This,
+  IN  PCH_SMI_DISPATCH_CALLBACK         DispatchFunction,
+  OUT EFI_HANDLE                        *DispatchHandle
+  )
+{
+  EFI_STATUS                            Status;
+
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  Status = PchSmiRecordInsert (
+             &mSrcDescSmbus,
+             (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+             PchSmiSmBusType,
+             DispatchHandle
+             );
+  PchSmmClearSource (&mSrcDescSmbus);
+  PchSmmEnableSource (&mSrcDescSmbus);
+  if (!EFI_ERROR (Status)) {
+    SmiHandlerProfileRegisterHandler (&gPchSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+  }
+  return Status;
+}
+
+//
+// SpiAsyncSmi srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_SMM_SOURCE_DESC mSrcDescSpiAsyncSmi = {
+  PCH_SMM_NO_FLAGS,
+  {
+    {
+      {
+        PCIE_ADDR_TYPE,
+        { 0xFFFFFFFF } // to be updated in PchSmiDispatchUpdateDescriptors
+      },
+      S_SPI_CFG_BC,
+      N_SPI_CFG_BC_ASE_BWP
+    },
+    NULL_BIT_DESC_INITIALIZER
+  },
+  {
+    {
+      {
+        PCIE_ADDR_TYPE,
+        { 0xFFFFFFFF } // to be updated in PchSmiDispatchUpdateDescriptors
+      },
+      S_SPI_CFG_BC,
+      N_SPI_CFG_BC_ASYNC_SS
+    }
+  },
+  {
+    {
+      ACPI_ADDR_TYPE,
+      {R_ACPI_IO_SMI_STS}
+    },
+    S_ACPI_IO_SMI_STS,
+    N_ACPI_IO_SMI_STS_SPI
+  }
+};
+
+/**
+  Special handling for SPI Asynchronous SMI.
+  If SPI ASYNC SMI is enabled, De-assert SMI is sent when Flash Cycle Done
+  transitions from 1 to 0 or when the SMI enable becomes false.
+
+  @param[in]  SrcDesc   Not used
+**/
+VOID
+EFIAPI
+PchSmiSpiAsyncClearSource (
+  CONST PCH_SMM_SOURCE_DESC             *SrcDesc
+  )
+{
+  UINT64                                SpiRegBase;
+  UINT32                                SpiBar0;
+
+  SpiRegBase = SpiPciCfgBase ();
+  SpiBar0 = PciSegmentRead32 (SpiRegBase + R_SPI_CFG_BAR0) & ~(B_SPI_CFG_BAR0_MASK);
+  if (SpiBar0 != PCH_SPI_BASE_ADDRESS) {
+    //
+    // Temporary disable MSE, and override with SPI reserved MMIO address, then enable MSE.
+    //
+    SpiBar0 = PCH_SPI_BASE_ADDRESS;
+    PciSegmentAnd8 (SpiRegBase + PCI_COMMAND_OFFSET, (UINT8) ~EFI_PCI_COMMAND_MEMORY_SPACE);
+    PciSegmentWrite32 (SpiRegBase + R_SPI_CFG_BAR0, SpiBar0);
+    PciSegmentOr8 (SpiRegBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);
+  }
+
+  MmioOr32 (SpiBar0 + R_SPI_MEM_HSFSC, B_SPI_MEM_HSFSC_FDONE);
+}
+
+/**
+  Special handling to enable SPI Asynchronous SMI
+**/
+VOID
+PchSmiSpiAsyncEnableSource (
+  VOID
+  )
+{
+  UINT64 SpiRegBase;
+  UINT32 Data32And;
+  UINT32 Data32Or;
+
+  SpiRegBase = SpiPciCfgBase ();
+  Data32And = (UINT32) ~B_SPI_CFG_BC_SYNC_SS;
+  Data32Or = B_SPI_CFG_BC_ASE_BWP;
+
+  PciSegmentAndThenOr32 (
+    SpiRegBase + R_SPI_CFG_BC,
+    Data32And,
+    Data32Or
+    );
+  S3BootScriptSavePciCfgReadWrite (
+    S3BootScriptWidthUint32,
+    SpiRegBase + R_SPI_CFG_BC,
+    (VOID*) &Data32Or,
+    (VOID*) &Data32And
+    );
+
+  //
+  // Clear the source
+  //
+  PchSmiSpiAsyncClearSource (NULL);
+}
+
+/**
+  The register function used to register SMI handler of SPI Asynchronous event.
+
+  @param[in]  This                      The pointer to the protocol itself
+  @param[in]  DispatchFunction          Pointer to dispatch function to be invoked for this SMI source
+  @param[out] DispatchHandle            Handle of dispatch function to register.
+
+  @retval EFI_INVALID_PARAMETER         Error with NULL SMI source description
+  @retval EFI_OUT_OF_RESOURCES          Fail to allocate pool for database record
+  @retval EFI_SUCCESS                   The database record is created successfully.
+  @retval EFI_ACCESS_DENIED             Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchSmiSpiAsyncRegister (
+  IN  PCH_SMI_DISPATCH_PROTOCOL         *This,
+  IN  PCH_SMI_DISPATCH_CALLBACK         DispatchFunction,
+  OUT EFI_HANDLE                        *DispatchHandle
+  )
+{
+  EFI_STATUS                            Status;
+  DATABASE_RECORD                       *Record;
+
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  Status = PchSmiRecordInsert (
+             &mSrcDescSpiAsyncSmi,
+             (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+             PchSmiSpiAsyncType,
+             DispatchHandle
+             );
+
+  if (!EFI_ERROR (Status)) {
+    Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+    Record->ClearSource = PchSmiSpiAsyncClearSource;
+    PchSmiSpiAsyncClearSource (NULL);
+    PchSmiSpiAsyncEnableSource ();
+    SmiHandlerProfileRegisterHandler (&gPchSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+  }
+  return Status;
+}
+
+/**
+  Unregister a child SMI source dispatch function with a parent SMM driver
+
+  @param[in] This                       Protocol instance pointer.
+  @param[in] DispatchHandle             Handle of dispatch function to deregister.
+
+  @retval EFI_SUCCESS                   The dispatch function has been successfully
+                                        unregistered and the SMI source has been disabled
+                                        if there are no other registered child dispatch
+                                        functions for this SMI source.
+  @retval EFI_INVALID_PARAMETER         Handle is invalid.
+  @retval EFI_ACCESS_DENIED             Return access denied if the SmmReadyToLock event has been triggered
+  @retval EFI_ACCESS_DENIED             Return access denied since SPI aync SMI handler is not able to disabled.
+**/
+EFI_STATUS
+EFIAPI
+PchSmiUnRegister (
+  IN  PCH_SMI_DISPATCH_PROTOCOL         *This,
+  IN  EFI_HANDLE                        DispatchHandle
+  )
+{
+  DATABASE_RECORD                       *Record;
+  UINT64                                SpiRegBase;
+  EFI_STATUS                            Status;
+
+  Record = DATABASE_RECORD_FROM_LINK (DispatchHandle);
+  if ((Record->SrcDesc.En[0].Reg.Type == PCIE_ADDR_TYPE) &&
+      (Record->SrcDesc.En[0].Reg.Data.pcie.Fields.Dev == SpiDevNumber ()) &&
+      (Record->SrcDesc.En[0].Reg.Data.pcie.Fields.Fnc == SpiFuncNumber ()) &&
+      (Record->SrcDesc.En[0].Reg.Data.pcie.Fields.Reg == R_SPI_CFG_BC) &&
+      (Record->SrcDesc.En[0].Bit == N_SPI_CFG_BC_ASE_BWP)) {
+    SpiRegBase = SpiPciCfgBase ();
+    if (PciSegmentRead8 (SpiRegBase + R_SPI_CFG_BC) & B_SPI_CFG_BC_BILD) {
+      //
+      // SPI Asynchronous SMI cannot be disabled
+      //
+      return EFI_ACCESS_DENIED;
+    }
+  }
+  Status = PchSmmCoreUnRegister (NULL, DispatchHandle);
+  if (!EFI_ERROR (Status)) {
+    SmiHandlerProfileUnregisterHandler (&gPchSmiDispatchProtocolGuid, Record->Callback, NULL, 0);
+  }
+  return Status;
+}
+
+
+/**
+  Declaration of PCH TCO SMI DISPATCH PROTOCOL instance
+**/
+PCH_TCO_SMI_DISPATCH_PROTOCOL mPchTcoSmiDispatchProtocol = {
+  PCH_TCO_SMI_DISPATCH_REVISION,        // Revision
+  PchTcoSmiUnRegister,                  // Unregister
+  PchTcoSmiMchRegister,                 // Mch
+  PchTcoSmiTcoTimeoutRegister,          // TcoTimeout
+  PchTcoSmiOsTcoRegister,               // OsTco
+  PchTcoSmiNmiRegister,                 // Nmi
+  PchTcoSmiIntruderDetRegister,         // IntruderDectect
+  PchTcoSmiSpiBiosWpRegister,           // SpiBiosWp
+  PchTcoSmiLpcBiosWpRegister,           // LpcBiosWp
+  PchTcoSmiNewCenturyRegister           // NewCentury
+};
+
+/**
+  Declaration of PCH ACPI SMI DISPATCH PROTOCOL instance
+**/
+PCH_ACPI_SMI_DISPATCH_PROTOCOL mPchAcpiSmiDispatchProtocol = {
+  PCH_ACPI_SMI_DISPATCH_REVISION,       // Revision
+  PchAcpiSmiUnRegister,                 // Unregister
+  PchAcpiSmiPmeRegister,                // Pme
+  PchAcpiSmiPmeB0Register,              // PmeB0
+  PchAcpiSmiRtcAlarmRegister,           // RtcAlarm
+  PchAcpiSmiTmrOverflowRegister         // TmrOverflow
+};
+
+/**
+  Declaration of MISC PCH SMI DISPATCH PROTOCOL instance
+**/
+PCH_SMI_DISPATCH_PROTOCOL mPchSmiDispatchProtocol = {
+  PCH_SMI_DISPATCH_REVISION,            // Revision
+  PchSmiUnRegister,                     // Unregister
+  PchSmiSerialIrqRegister,              // SerialIrq
+  PchSmiMcSmiRegister,                  // McSmi
+  PchSmiSmbusRegister,                  // SmBus
+  PchSmiSpiAsyncRegister                // SpiAsync
+};
+
+/**
+  Install protocols of PCH specifics SMI types, including
+  PCH TCO SMI types, PCH PCIE SMI types, PCH ACPI SMI types, PCH MISC SMI types.
+
+  @retval                               the result of protocol installation
+**/
+EFI_STATUS
+InstallPchSmiDispatchProtocols (
+  VOID
+  )
+{
+  EFI_HANDLE                            Handle;
+  EFI_STATUS                            Status;
+
+  Handle = NULL;
+  Status = gSmst->SmmInstallProtocolInterface (
+                    &Handle,
+                    &gPchTcoSmiDispatchProtocolGuid,
+                    EFI_NATIVE_INTERFACE,
+                    &mPchTcoSmiDispatchProtocol
+                    );
+
+  Status = gSmst->SmmInstallProtocolInterface (
+                    &Handle,
+                    &gPchAcpiSmiDispatchProtocolGuid,
+                    EFI_NATIVE_INTERFACE,
+                    &mPchAcpiSmiDispatchProtocol
+                    );
+  Status = gSmst->SmmInstallProtocolInterface (
+                    &Handle,
+                    &gPchSmiDispatchProtocolGuid,
+                    EFI_NATIVE_INTERFACE,
+                    &mPchSmiDispatchProtocol
+                    );
+
+  return Status;
+}
+
+/**
+  The function to dispatch all callback function of PCH SMI types.
+
+  @retval EFI_SUCCESS                   Function successfully completed
+  @retval EFI_UNSUPPORTED               no
+**/
+EFI_STATUS
+PchSmiTypeCallbackDispatcher (
+  IN  DATABASE_RECORD                   *Record
+  )
+{
+  EFI_STATUS                            Status;
+  PCH_SMI_TYPES                         PchSmiType;
+
+  PchSmiType = Record->PchSmiType;
+  Status     = EFI_SUCCESS;
+
+  switch (PchSmiType) {
+    case PchTcoSmiMchType:
+    case PchTcoSmiTcoTimeoutType:
+    case PchTcoSmiOsTcoType:
+    case PchTcoSmiNmiType:
+    case PchTcoSmiIntruderDetectType:
+    case PchTcoSmiSpiBiosWpType:
+    case PchTcoSmiLpcBiosWpType:
+    case PchTcoSmiNewCenturyType:
+      ((PCH_TCO_SMI_DISPATCH_CALLBACK) (Record->PchSmiCallback)) ((EFI_HANDLE)&Record->Link);
+      break;
+    case PchPcieSmiRpHotplugType:
+    case PchPcieSmiRpLinkActiveType:
+    case PchPcieSmiRpLinkEqType:
+      break;
+    case PchAcpiSmiPmeType:
+    case PchAcpiSmiPmeB0Type:
+    case PchAcpiSmiRtcAlarmType:
+    case PchAcpiSmiTmrOverflowType:
+      ((PCH_ACPI_SMI_DISPATCH_CALLBACK) (Record->PchSmiCallback)) ((EFI_HANDLE)&Record->Link);
+      break;
+    case PchSmiSerialIrqType:
+    case PchSmiMcSmiType:
+    case PchSmiSmBusType:
+    case PchSmiSpiAsyncType:
+    case PchIoTrapSmiType:                ///< internal type for IoTrap
+      ((PCH_SMI_DISPATCH_CALLBACK) (Record->PchSmiCallback)) ((EFI_HANDLE)&Record->Link);
+      break;
+    default:
+      Status = EFI_UNSUPPORTED;
+      break;
+  }
+
+  return Status;
+}
+
+/**
+  Performs update of SmiDispatch descriptors with values that have to be evaluated during runtime.
+**/
+VOID
+PchSmiDispatchUpdateDescriptors (
+  VOID
+  )
+{
+  UINT32     SpiPcieAddr;
+  UINT32     LpcPcieAddr;
+
+  SpiPcieAddr = ((DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+                (SpiDevNumber ()             << 19) |
+                (SpiFuncNumber ()            << 16) |
+                R_SPI_CFG_BC);
+  LpcPcieAddr = ((DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+                (LpcDevNumber ()             << 19) |
+                (LpcFuncNumber ()            << 16) |
+                R_LPC_CFG_BC);
+  //
+  // mSrcDescSpiBiosWp
+  //
+  mSrcDescSpiBiosWp.En[1].Reg.Data.raw    = SpiPcieAddr;
+  mSrcDescSpiBiosWp.Sts[0].Reg.Data.raw   = SpiPcieAddr;
+
+  //
+  // mSrcDescLpcBiosWp
+  //
+  mSrcDescLpcBiosWp.En[1].Reg.Data.raw    = LpcPcieAddr;
+
+  //
+  // mSrcDescSpiAsyncSmi
+  //
+  mSrcDescSpiAsyncSmi.En[0].Reg.Data.raw  = SpiPcieAddr;
+  mSrcDescSpiAsyncSmi.Sts[0].Reg.Data.raw = SpiPcieAddr;
+}
\ No newline at end of file
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiDispatcher.inf b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiDispatcher.inf
new file mode 100644
index 0000000000..7031b5193a
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiDispatcher.inf
@@ -0,0 +1,106 @@
+## @file
+# Component description file for the Pch SMI Dispatch Handlers module
+#
+#   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+#   SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PchSmiDispatcher
+FILE_GUID = B0D6ED53-B844-43f5-BD2F-61095264E77E
+VERSION_STRING = 1.0
+MODULE_TYPE = DXE_SMM_DRIVER
+PI_SPECIFICATION_VERSION = 1.10
+ENTRY_POINT = InitializePchSmmDispatcher
+
+
+[LibraryClasses]
+UefiBootServicesTableLib
+UefiDriverEntryPoint
+IoLib
+DebugLib
+PcdLib
+BaseLib
+BaseMemoryLib
+HobLib
+DevicePathLib
+PchCycleDecodingLib
+PchPcieRpLib
+PchPcrLib
+SmmServicesTableLib
+ReportStatusCodeLib
+PerformanceLib
+DxeServicesTableLib
+GpioLib
+GpioPrivateLib
+EspiLib
+S3BootScriptLib
+ConfigBlockLib
+PmcPrivateLib
+PmcLib
+SmiHandlerProfileLib
+PchPciBdfLib
+P2SbSidebandAccessLib
+CpuPcieInfoFruLib
+
+[Packages]
+MdePkg/MdePkg.dec
+AlderlakeSiliconPkg/SiPkg.dec
+
+
+[Pcd]
+# Progress Code for S3 Suspend start.
+# PROGRESS_CODE_S3_SUSPEND_START = (EFI_SOFTWARE_SMM_DRIVER | (EFI_OEM_SPECIFIC | 0x00000000))    = 0x03078000
+gSiPkgTokenSpaceGuid.PcdProgressCodeS3SuspendStart
+# Progress Code for S3 Suspend end.
+# PROGRESS_CODE_S3_SUSPEND_END   = (EFI_SOFTWARE_SMM_DRIVER | (EFI_OEM_SPECIFIC | 0x00000001))    = 0x03078001
+gSiPkgTokenSpaceGuid.PcdProgressCodeS3SuspendEnd
+gSiPkgTokenSpaceGuid.PcdEfiGcdAllocateType
+
+
+[Sources]
+PchSmm.h
+PchSmmCore.c
+PchSmmHelpers.c
+PchxSmmHelpers.c
+SmmGlobalsPch.c
+PchSmmUsb.c
+PchSmmGpi.c
+PchSmmPowerButton.c
+PchSmmSw.c
+PchSmmSx.c
+PchSmmPeriodicTimer.c
+PchSmiDispatch.c
+PcieSmmClient.c
+
+
+[Protocols]
+gEfiPciRootBridgeIoProtocolGuid ## CONSUMES
+gEfiSmmGpiDispatch2ProtocolGuid ## PRODUCES
+gEfiSmmSxDispatch2ProtocolGuid ## PRODUCES
+gEfiSmmSwDispatch2ProtocolGuid ## PRODUCES
+gEfiSmmUsbDispatch2ProtocolGuid ## PRODUCES
+gEfiSmmPowerButtonDispatch2ProtocolGuid ## PRODUCES
+gEfiSmmPeriodicTimerDispatch2ProtocolGuid ## PRODUCES
+gEfiSmmBase2ProtocolGuid ## CONSUMES
+gEfiSmmCpuProtocolGuid ## CONSUMES
+gEfiSmmReadyToLockProtocolGuid ## CONSUMES
+gPchTcoSmiDispatchProtocolGuid ## PRODUCES
+gPchPcieSmiDispatchProtocolGuid ## PRODUCES
+gPchAcpiSmiDispatchProtocolGuid ## PRODUCES
+gPchSmiDispatchProtocolGuid ## PRODUCES
+gPchEspiSmiDispatchProtocolGuid ## PRODUCES
+gPchSmmPeriodicTimerControlGuid ## PRODUCES
+
+
+[Guids]
+
+
+[Depex]
+gEfiPciRootBridgeIoProtocolGuid AND
+gEfiPciHostBridgeResourceAllocationProtocolGuid AND ## This is to ensure that PCI MMIO resource has been prepared and available for this driver to allocate.
+gEfiSmmCpuProtocolGuid AND
+gEfiSmmBase2ProtocolGuid
+
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiHelper.h b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiHelper.h
new file mode 100644
index 0000000000..5ec9455797
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiHelper.h
@@ -0,0 +1,34 @@
+/** @file
+  eSPI SMI Dispatch header
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PCH_SMI_HELPER_H_
+#define _PCH_SMI_HELPER_H_
+#include <Uefi/UefiBaseType.h>
+
+/**
+  Get CPU or PCH Pcie Root Port Device and Function Number by Root Port physical Number
+
+  @param[in]  RpNumber              Root port physical number. (0-based)
+  @param[out] RpDev                 Return corresponding root port device number.
+  @param[out] RpFun                 Return corresponding root port function number.
+**/
+VOID
+GetPcieRpDevFun (
+  IN  UINTN   RpIndex,
+  OUT UINTN   *RpDev,
+  OUT UINTN   *RpFun
+  );
+
+/**
+  Performs update of SmiDispatch descriptors with values that have to be evaluated during runtime.
+**/
+VOID
+PchSmiDispatchUpdateDescriptors (
+  VOID
+  );
+
+#endif
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmm.h b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmm.h
new file mode 100644
index 0000000000..41969a0ec7
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmm.h
@@ -0,0 +1,1028 @@
+/** @file
+  Prototypes and defines for the PCH SMM Dispatcher.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_SMM_H_
+#define _PCH_SMM_H_
+
+#include <Uefi.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/SmmControl2.h>
+#include <Protocol/SmmUsbDispatch2.h>
+#include <Protocol/SmmSxDispatch2.h>
+#include <Protocol/SmmSwDispatch2.h>
+#include <Protocol/SmmGpiDispatch2.h>
+#include <Protocol/SmmPowerButtonDispatch2.h>
+#include <Protocol/SmmPeriodicTimerDispatch2.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Library/ReportStatusCodeLib.h>
+#include <Library/PerformanceLib.h>
+#include <Protocol/SmmReadyToLock.h>
+#include <IndustryStandard/Pci30.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/GpioLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/EspiLib.h>
+#include <Library/GpioPrivateLib.h>
+#include <Protocol/PchTcoSmiDispatch.h>
+#include <Protocol/PchPcieSmiDispatch.h>
+#include <Protocol/PchAcpiSmiDispatch.h>
+#include <Protocol/PchSmiDispatch.h>
+#include <Library/PmcLib.h>
+
+#define EFI_BAD_POINTER          0xAFAFAFAFAFAFAFAFULL
+
+extern BOOLEAN                   mReadyToLock;
+
+///
+/// Define an enumeration for all the supported protocols
+///
+#define PCH_SMM_PROTOCOL_TYPE_MAX       6
+
+typedef enum {
+  UsbType,
+  SxType,
+  SwType,
+  GpiType,
+  PowerButtonType,
+  PeriodicTimerType,
+  PchSmiDispatchType,
+  PchSmmProtocolTypeMax
+} PCH_SMM_PROTOCOL_TYPE;
+
+///
+/// Define all the supported types of PCH SMI
+///
+typedef enum {
+  PchTcoSmiMchType,
+  PchTcoSmiTcoTimeoutType,
+  PchTcoSmiOsTcoType,
+  PchTcoSmiNmiType,
+  PchTcoSmiIntruderDetectType,
+  PchTcoSmiSpiBiosWpType,
+  PchTcoSmiLpcBiosWpType,
+  PchTcoSmiNewCenturyType,
+  PchPcieSmiRpHotplugType,
+  PchPcieSmiRpLinkActiveType,
+  PchPcieSmiRpLinkEqType,
+  PchAcpiSmiPmeType,
+  PchAcpiSmiPmeB0Type,
+  PchAcpiSmiRtcAlarmType,
+  PchAcpiSmiTmrOverflowType,
+  PchEspiSmiEspiSlaveType,
+  PchSmiSerialIrqType,
+  PchSmiMcSmiType,
+  PchSmiSmBusType,
+  PchSmiSpiAsyncType,
+  PchIoTrapSmiType                      ///< internal SMI type
+} PCH_SMI_TYPES;
+
+///
+/// Generic funciton pointer to cover all Pch SMI function pointer types
+///
+typedef
+VOID
+(EFIAPI *PCH_SMI_CALLBACK_FUNCTIONS) (
+  IN EFI_HANDLE                         DispatchHandle,
+  ...
+  );
+
+
+///
+/// SPECIFYING A REGISTER
+/// We want a general way of referring to addresses.  For this case, we'll only
+/// need addresses in the ACPI table (and the TCO entries within the ACPI table).
+/// However, it's interesting to consider what it would take to support other types
+/// of addresses.  To address Will's concern, I think it prudent to accommodate it
+/// early on in the design.
+///
+/// Addresses we need to consider:
+///
+///  Type:                           Required:
+///  I/O                             Yes
+///    ACPI (special case of I/O)    Only if we want to
+///    TCO  (special case of I/O)    Only if we want to
+///  GPIO  (special case of MMIO)    Only if we want to
+///  Memory (or Memory Mapped I/O)   Only if we want to
+///  PCIE                            Yes, for BiosWp
+///
+typedef enum {
+  ///
+  ///  IO_ADDR_TYPE, /// unimplemented
+  ///
+  ACPI_ADDR_TYPE,
+  TCO_ADDR_TYPE,
+  ///
+  ///  MEMORY_ADDR_TYPE, /// unimplemented
+  ///
+  GPIO_ADDR_TYPE,
+  MEMORY_MAPPED_IO_ADDRESS_TYPE,
+  PCIE_ADDR_TYPE,
+  PCR_ADDR_TYPE,
+  NUM_ADDR_TYPES,                     ///< count of items in this enum
+  PCH_SMM_ADDR_TYPE_NULL        = -1  ///< sentinel to indicate NULL or to signal end of arrays
+} ADDR_TYPE;
+
+//
+// Assumption: 32-bits -- enum's evaluate to integer
+// Assumption: This code will only run on IA-32.  Justification: IA-64 doesn't have SMIs.
+// We don't have to worry about 64-bit addresses.
+// Typedef the size of addresses in case the numbers I'm using are wrong or in case
+// this changes.  This is a good idea because PCI_ADDR will change, for example, when
+// we add support for PciExpress.
+//
+typedef UINT16 IO_ADDR;
+typedef IO_ADDR ACPI_ADDR;  ///< can omit
+typedef IO_ADDR TCO_ADDR;   ///< can omit
+typedef UINTN MEM_ADDR;
+typedef MEM_ADDR *MEMORY_MAPPED_IO_ADDRESS;
+typedef MEM_ADDR *GPIO_ADDR;
+typedef union {
+  UINT32  Raw;
+  struct {
+    UINT32 Reg: 16;
+    UINT32 Fnc: 3;
+    UINT32 Dev: 5;
+    UINT32 Bus: 8;
+  } Fields;
+} PCIE_ADDR;
+
+typedef union {
+  UINT32  Raw;
+  struct {
+    UINT16 Offset;
+    UINT8  Pid;
+    UINT8  Base;
+  } Fields;
+} PCR_ADDR;
+
+typedef struct {
+  ADDR_TYPE Type;
+  union {
+    ///
+    /// used to initialize during declaration/definition
+    ///
+    UINT32                    raw;
+
+    ///
+    /// used to access useful data
+    ///
+    IO_ADDR                   io;
+    ACPI_ADDR                 acpi;
+    TCO_ADDR                  tco;
+    GPIO_ADDR                 gpio;
+    MEM_ADDR                  mem;
+    MEMORY_MAPPED_IO_ADDRESS  Mmio;
+    PCIE_ADDR                 pcie;
+    PCR_ADDR                  Pcr;
+
+  } Data;
+
+} PCH_SMM_ADDRESS;
+
+///
+/// SPECIFYING BITS WITHIN A REGISTER
+/// Here's a struct that helps us specify a source or enable bit.
+///
+typedef struct {
+  PCH_SMM_ADDRESS Reg;
+  UINT8           SizeInBytes;  ///< of the register
+  UINT8           Bit;
+} PCH_SMM_BIT_DESC;
+
+//
+// Sometimes, we'll have bit descriptions that are unused.  It'd be great to have a
+// way to easily identify them:
+//
+#define IS_BIT_DESC_NULL(BitDesc)   ((BitDesc).Reg.Type == PCH_SMM_ADDR_TYPE_NULL)  ///< "returns" true when BitDesc is NULL
+#define NULL_THIS_BIT_DESC(BitDesc) ((BitDesc).Reg.Type = PCH_SMM_ADDR_TYPE_NULL)   ///< will "return" an integer w/ value of 0
+#define NULL_BIT_DESC_INITIALIZER \
+  { \
+    { \
+      PCH_SMM_ADDR_TYPE_NULL, \
+      { \
+        0 \
+      } \
+    }, \
+    0, 0 \
+  }
+//
+// I'd like a type to specify the callback's Sts & En bits because they'll
+// be commonly used together:
+//
+#define NUM_EN_BITS   2
+#define NUM_STS_BITS  1
+
+//
+// Flags
+//
+typedef UINT8 PCH_SMM_SOURCE_FLAGS;
+
+//
+// Flags required to describe the event source
+//
+#define PCH_SMM_NO_FLAGS          0
+#define PCH_SMM_SCI_EN_DEPENDENT  1
+
+typedef struct {
+  PCH_SMM_SOURCE_FLAGS  Flags;
+  PCH_SMM_BIT_DESC      En[NUM_EN_BITS];    ///< Describes the enable bit(s) for the SMI event
+  PCH_SMM_BIT_DESC      Sts[NUM_STS_BITS];  ///< Describes the secondary status bit for the SMI event. Might be the same as TopLevelSmi
+  PCH_SMM_BIT_DESC      PmcSmiSts;          ///< Refereing to the top level status bit in PMC SMI_STS, i.e. R_PCH_SMI_STS
+} PCH_SMM_SOURCE_DESC;
+
+///
+/// Used to initialize null source descriptor
+///
+#define NULL_SOURCE_DESC_INITIALIZER \
+  { \
+    PCH_SMM_NO_FLAGS, \
+    { \
+      NULL_BIT_DESC_INITIALIZER, NULL_BIT_DESC_INITIALIZER \
+    }, \
+    { \
+      NULL_BIT_DESC_INITIALIZER \
+    }, \
+    NULL_BIT_DESC_INITIALIZER \
+  }
+
+///
+/// Define a PCIE RP event context for SmiProfileHandlerInfo tool
+///
+typedef struct {
+  PCH_SMI_TYPES               PchSmiType;
+  UINTN                       RpIndex;
+} PCH_SMM_PCIE_REGISTER_CONTEXT;
+
+///
+/// CHILD CONTEXTS
+/// To keep consistent w/ the architecture, we'll need to provide the context
+/// to the child when we call its callback function.  After talking with Will,
+/// we agreed that we'll need functions to "dig" the context out of the hardware
+/// in many cases (Sx, Trap, Gpi, etc), and we'll need a function to compare those
+/// contexts to prevent unnecessary dispatches.  I'd like a general type for these
+/// "GetContext" functions, so I'll need a union of all the protocol contexts for
+/// our internal use:
+///
+typedef union {
+  //
+  // (in no particular order)
+  //
+  EFI_SMM_SX_REGISTER_CONTEXT             Sx;
+  EFI_SMM_PERIODIC_TIMER_REGISTER_CONTEXT PeriodicTimer;
+  EFI_SMM_SW_REGISTER_CONTEXT             Sw;
+  EFI_SMM_POWER_BUTTON_REGISTER_CONTEXT   PowerButton;
+  EFI_SMM_USB_REGISTER_CONTEXT            Usb;
+  EFI_SMM_GPI_REGISTER_CONTEXT            Gpi;
+  PCH_SMM_PCIE_REGISTER_CONTEXT           Pcie;
+} PCH_SMM_CONTEXT;
+
+///
+/// Misc data for PchDispatcher usage.
+/// For PeriodicTimer, since the ElapsedTime is removed from EFI_SMM_PERIODIC_TIMER_REGISTER_CONTEXT of EDKII,
+/// and PchDispatcher needs it for every record. Thus move it here to support ElapsedTime.
+///
+typedef struct {
+  UINTN    ElapsedTime;
+  ///
+  /// A switch to control periodic timer SMI enabling
+  ///
+  BOOLEAN  TimerSmiEnabled;
+} PCH_SMM_MISC_DATA;
+
+//
+// Assumption: PeriodicTimer largest at 3x64-bits or 24 bytes
+//
+typedef struct _DATABASE_RECORD DATABASE_RECORD;
+
+///
+/// Assumption: the GET_CONTEXT function will be as small and simple as possible.
+/// Assumption: We don't need to pass in an enumeration for the protocol because each
+///    GET_CONTEXT function is written for only one protocol.
+/// We also need a function to compare contexts to see if the child should be dispatched
+/// In addition, we need a function to acquire CommBuffer and CommBufferSize for
+///    dispatch callback function of EDKII native support.
+///
+typedef
+VOID
+(EFIAPI *GET_CONTEXT) (
+  IN  DATABASE_RECORD    * Record,
+  OUT PCH_SMM_CONTEXT    * Context
+  );
+
+typedef
+BOOLEAN
+(EFIAPI *CMP_CONTEXT) (
+  IN PCH_SMM_CONTEXT     * Context1,
+  IN PCH_SMM_CONTEXT     * Context2
+  );
+
+typedef
+VOID
+(EFIAPI *GET_COMMBUFFER) (
+  IN  DATABASE_RECORD    * Record,
+  OUT VOID               **CommBuffer,
+  OUT UINTN              * CommBufferSize
+  );
+
+///
+/// Finally, every protocol will require a "Get Context" and "Compare Context" call, so
+/// we may as well wrap that up in a table, too.
+///
+typedef struct {
+  GET_CONTEXT     GetContext;
+  CMP_CONTEXT     CmpContext;
+  GET_COMMBUFFER  GetCommBuffer;
+} CONTEXT_FUNCTIONS;
+
+extern CONTEXT_FUNCTIONS          ContextFunctions[PCH_SMM_PROTOCOL_TYPE_MAX];
+
+///
+/// MAPPING CONTEXT TO BIT DESCRIPTIONS
+/// I'd like to have a general approach to mapping contexts to bit descriptions.
+/// Sometimes, we'll find that we can use table lookups or constant assignments;
+/// other times, we'll find that we'll need to use a function to perform the mapping.
+/// If we define a macro to mask that process, we'll never have to change the code.
+/// I don't know if this is desirable or not -- if it isn't, then we can get rid
+/// of the macros and just use function calls or variable assignments.  Doesn't matter
+/// to me.
+/// Mapping complex contexts requires a function
+///
+
+/**
+  Maps a USB context to a source description.
+
+  @param[in] Context              The context we need to map.  Type must be USB.
+  @param[out] SrcDesc             The source description that corresponds to the given context.
+
+**/
+VOID
+MapUsbToSrcDesc (
+  IN  PCH_SMM_CONTEXT         *Context,
+  OUT PCH_SMM_SOURCE_DESC     *SrcDesc
+  );
+
+/**
+  Figure out which timer the child is requesting and
+  send back the source description
+
+  @param[in] DispatchContext      The pointer to the Dispatch Context instances
+  @param[out] SrcDesc             The pointer to the source description
+
+**/
+VOID
+MapPeriodicTimerToSrcDesc (
+  IN  PCH_SMM_CONTEXT                                         *DispatchContext,
+  OUT PCH_SMM_SOURCE_DESC                                     *SrcDesc
+  );
+
+//
+// Mapping simple contexts can be done by assignment or lookup table
+//
+extern CONST PCH_SMM_SOURCE_DESC  mSxSourceDesc;
+extern CONST PCH_SMM_SOURCE_DESC  mPowerButtonSourceDesc;
+extern CONST PCH_SMM_SOURCE_DESC  mSrcDescNewCentury;
+extern CONST PCH_SMM_SOURCE_DESC  mGpiSourceDescTemplate;
+
+///
+/// For PCHx, APMC is UINT8 port, so the MAX SWI Value is 0xFF.
+///
+#define MAXIMUM_SWI_VALUE 0xFF
+///
+/// Open: Need to make sure this kind of type cast will actually work.
+///   May need an intermediate form w/ two VOID* arguments.  I'll figure
+///   that out when I start compiling.
+///
+typedef
+VOID
+(EFIAPI *PCH_SMM_CLEAR_SOURCE) (
+  CONST PCH_SMM_SOURCE_DESC * SrcDesc
+  );
+
+///
+/// "DATABASE" RECORD
+/// Linked list data structures
+///
+#define DATABASE_RECORD_SIGNATURE SIGNATURE_32 ('D', 'B', 'R', 'C')
+
+struct _DATABASE_RECORD {
+  UINT32                        Signature;
+  LIST_ENTRY                    Link;
+  BOOLEAN                       Processed;
+  ///
+  /// Status and Enable bit description
+  ///
+  PCH_SMM_SOURCE_DESC           SrcDesc;
+
+  ///
+  /// Callback function
+  ///
+  EFI_SMM_HANDLER_ENTRY_POINT2  Callback;
+  PCH_SMM_CONTEXT               ChildContext;
+  UINTN                         ContextSize;
+
+  ///
+  /// Special handling hooks -- init them to NULL if unused/unneeded
+  ///
+  PCH_SMM_CLEAR_SOURCE          ClearSource;
+
+  ///
+  /// Functions required to make callback code general
+  ///
+  CONTEXT_FUNCTIONS             ContextFunctions;
+
+  ///
+  /// The protocol that this record dispatches
+  ///
+  PCH_SMM_PROTOCOL_TYPE         ProtocolType;
+
+  ///
+  /// Misc data for private usage
+  ///
+  PCH_SMM_MISC_DATA             MiscData;
+
+  ///
+  /// PCH SMI callback function
+  ///
+  PCH_SMI_CALLBACK_FUNCTIONS    PchSmiCallback;
+  ///
+  /// Indicate the PCH SMI types.
+  ///
+  PCH_SMI_TYPES                 PchSmiType;
+};
+
+#define DATABASE_RECORD_FROM_LINK(_record)  CR (_record, DATABASE_RECORD, Link, DATABASE_RECORD_SIGNATURE)
+#define DATABASE_RECORD_FROM_CHILDCONTEXT(_record)  CR (_record, DATABASE_RECORD, ChildContext, DATABASE_RECORD_SIGNATURE)
+
+///
+/// HOOKING INTO THE ARCHITECTURE
+///
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SMM_GENERIC_REGISTER) (
+  IN  VOID                                    **This,
+  IN  VOID                                    *DispatchFunction,
+  IN  VOID                                    *DispatchContext,
+  OUT EFI_HANDLE                              *DispatchHandle
+  );
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SMM_GENERIC_UNREGISTER) (
+  IN  VOID                                    **This,
+  IN  EFI_HANDLE                              DispatchHandle
+  );
+
+///
+/// Define a memory "stamp" equivalent in size and function to most of the protocols
+///
+typedef struct {
+  PCH_SMM_GENERIC_REGISTER    Register;
+  PCH_SMM_GENERIC_UNREGISTER  Unregister;
+  UINTN                       Extra1;
+  UINTN                       Extra2; ///< may not need this one
+} PCH_SMM_GENERIC_PROTOCOL;
+
+/**
+  Register a child SMI dispatch function with a parent SMM driver.
+
+  @param[in] This                 Pointer to the PCH_SMM_GENERIC_PROTOCOL instance.
+  @param[in] DispatchFunction     Pointer to dispatch function to be invoked for this SMI source.
+  @param[in] DispatchContext      Pointer to the dispatch function's context.
+  @param[out] DispatchHandle      Handle of dispatch function, for when interfacing
+                                  with the parent SMM driver, will be the address of linked
+                                  list link in the call back record.
+
+  @retval EFI_OUT_OF_RESOURCES    Insufficient resources to create database record
+  @retval EFI_INVALID_PARAMETER   The input parameter is invalid
+  @retval EFI_SUCCESS             The dispatch function has been successfully
+                                  registered and the SMI source has been enabled.
+**/
+EFI_STATUS
+EFIAPI
+PchPiSmmCoreRegister (
+  IN  PCH_SMM_GENERIC_PROTOCOL                          *This,
+  IN  EFI_SMM_HANDLER_ENTRY_POINT2                      DispatchFunction,
+  IN  PCH_SMM_CONTEXT                                   *DispatchContext,
+  OUT EFI_HANDLE                                        *DispatchHandle
+  );
+
+/**
+  Unregister a child SMI source dispatch function with a parent SMM driver
+
+  @param[in] This                       Protocol instance pointer.
+  @param[in] DispatchHandle             Handle of dispatch function to deregister.
+
+  @retval EFI_SUCCESS                   The dispatch function has been successfully
+                                        unregistered and the SMI source has been disabled
+                                        if there are no other registered child dispatch
+                                        functions for this SMI source.
+  @retval EFI_INVALID_PARAMETER         Handle is invalid.
+  @retval EFI_ACCESS_DENIED             Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchPiSmmCoreUnRegister (
+  IN PCH_SMM_GENERIC_PROTOCOL                           *This,
+  IN EFI_HANDLE                                         *DispatchHandle
+  );
+
+
+/**
+  Unregister a child SMI source dispatch function with a parent SMM driver.
+
+  @param[in] This                 Pointer to the PCH_SMM_GENERIC_PROTOCOL instance.
+  @param[in] DispatchHandle       Handle of dispatch function to deregister.
+
+  @retval EFI_SUCCESS             The dispatch function has been successfully
+                                  unregistered and the SMI source has been disabled
+                                  if there are no other registered child dispatch
+                                  functions for this SMI source.
+  @retval EFI_INVALID_PARAMETER   Handle is invalid.
+**/
+EFI_STATUS
+EFIAPI
+PchSmmCoreUnRegister (
+  IN  PCH_SMM_GENERIC_PROTOCOL                         *This,
+  IN  EFI_HANDLE                                       *DispatchHandle
+  );
+
+typedef union {
+  PCH_SMM_GENERIC_PROTOCOL                    Generic;
+  EFI_SMM_USB_DISPATCH2_PROTOCOL              Usb;
+  EFI_SMM_SX_DISPATCH2_PROTOCOL               Sx;
+  EFI_SMM_SW_DISPATCH2_PROTOCOL               Sw;
+  EFI_SMM_GPI_DISPATCH2_PROTOCOL              Gpi;
+  EFI_SMM_POWER_BUTTON_DISPATCH2_PROTOCOL     PowerButton;
+  EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL   PeriodicTimer;
+} PCH_SMM_PROTOCOL;
+
+///
+/// Define a structure to help us identify the generic protocol
+///
+#define PROTOCOL_SIGNATURE  SIGNATURE_32 ('P', 'R', 'O', 'T')
+
+typedef struct {
+  UINTN                 Signature;
+
+  PCH_SMM_PROTOCOL_TYPE Type;
+  EFI_GUID              *Guid;
+  PCH_SMM_PROTOCOL      Protocols;
+} PCH_SMM_QUALIFIED_PROTOCOL;
+
+#define QUALIFIED_PROTOCOL_FROM_GENERIC(_generic) \
+  CR ( \
+  _generic, \
+  PCH_SMM_QUALIFIED_PROTOCOL, \
+  Protocols, \
+  PROTOCOL_SIGNATURE \
+  )
+
+///
+/// Create private data for the protocols that we'll publish
+///
+typedef struct {
+  LIST_ENTRY                  CallbackDataBase;
+  EFI_HANDLE                  SmiHandle;
+  EFI_HANDLE                  InstallMultProtHandle;
+  PCH_SMM_QUALIFIED_PROTOCOL  Protocols[PCH_SMM_PROTOCOL_TYPE_MAX];
+} PRIVATE_DATA;
+
+extern PRIVATE_DATA           mPrivateData;
+extern UINT16                 mAcpiBaseAddr;
+extern UINT16                 mTcoBaseAddr;
+
+/**
+  The internal function used to create and insert a database record
+
+  @param[in]  InsertRecord              Record to insert to database.
+  @param[out] DispatchHandle            Handle of dispatch function to register.
+
+  @retval EFI_INVALID_PARAMETER         Error with NULL SMI source description
+  @retval EFI_OUT_OF_RESOURCES          Fail to allocate pool for database record
+  @retval EFI_SUCCESS                   The database record is created successfully.
+**/
+EFI_STATUS
+SmmCoreInsertRecord (
+  IN  DATABASE_RECORD                   *NewRecord,
+  OUT EFI_HANDLE                        *DispatchHandle
+  );
+
+/**
+  Get the Sleep type
+
+  @param[in] Record               No use
+  @param[out] Context             The context that includes SLP_TYP bits to be filled
+**/
+VOID
+EFIAPI
+SxGetContext (
+  IN  DATABASE_RECORD    *Record,
+  OUT PCH_SMM_CONTEXT    *Context
+  );
+
+/**
+  Register a child SMI source dispatch function for the specified software SMI.
+
+  This service registers a function (DispatchFunction) which will be called when the software
+  SMI source specified by RegisterContext->SwSmiCpuIndex is detected. On return,
+  DispatchHandle contains a unique handle which may be used later to unregister the function
+  using UnRegister().
+
+  @param[in]  This                 Pointer to the EFI_SMM_SW_DISPATCH2_PROTOCOL instance.
+  @param[in]  DispatchFunction     Function to register for handler when the specified software
+                                   SMI is generated.
+  @param[in, out] RegisterContext  Pointer to the dispatch function's context.
+                                   The caller fills this context in before calling
+                                   the register function to indicate to the register
+                                   function which Software SMI input value the
+                                   dispatch function should be invoked for.
+  @param[out] DispatchHandle       Handle generated by the dispatcher to track the
+                                   function instance.
+
+  @retval EFI_SUCCESS            The dispatch function has been successfully
+                                 registered and the SMI source has been enabled.
+  @retval EFI_DEVICE_ERROR       The SW driver was unable to enable the SMI source.
+  @retval EFI_INVALID_PARAMETER  RegisterContext is invalid. The SW SMI input value
+                                 is not within a valid range or is already in use.
+  @retval EFI_OUT_OF_RESOURCES   There is not enough memory (system or SMM) to manage this
+                                 child.
+  @retval EFI_OUT_OF_RESOURCES   A unique software SMI value could not be assigned
+                                 for this dispatch.
+**/
+EFI_STATUS
+EFIAPI
+PchSwSmiRegister (
+  IN  EFI_SMM_SW_DISPATCH2_PROTOCOL       *This,
+  IN  EFI_SMM_HANDLER_ENTRY_POINT2        DispatchFunction,
+  IN  EFI_SMM_SW_REGISTER_CONTEXT         *DispatchContext,
+  OUT EFI_HANDLE                          *DispatchHandle
+  );
+
+/**
+  Unregister a child SMI source dispatch function for the specified software SMI.
+
+  This service removes the handler associated with DispatchHandle so that it will no longer be
+  called in response to a software SMI.
+
+  @param[in] This                Pointer to the EFI_SMM_SW_DISPATCH2_PROTOCOL instance.
+  @param[in] DispatchHandle      Handle of dispatch function to deregister.
+
+  @retval EFI_SUCCESS            The dispatch function has been successfully unregistered.
+  @retval EFI_INVALID_PARAMETER  The DispatchHandle was not valid.
+**/
+EFI_STATUS
+EFIAPI
+PchSwSmiUnRegister (
+  IN CONST EFI_SMM_SW_DISPATCH2_PROTOCOL  *This,
+  IN       EFI_HANDLE                     DispatchHandle
+  );
+
+/**
+  Init required protocol for Pch Sw Dispatch protocol.
+**/
+VOID
+PchSwDispatchInit (
+  VOID
+  );
+
+/**
+  Check whether sleep type of two contexts match
+
+  @param[in] Context1             Context 1 that includes sleep type 1
+  @param[in] Context2             Context 2 that includes sleep type 2
+
+  @retval FALSE                   Sleep types match
+  @retval TRUE                    Sleep types don't match
+**/
+BOOLEAN
+EFIAPI
+SxCmpContext (
+  IN PCH_SMM_CONTEXT     *Context1,
+  IN PCH_SMM_CONTEXT     *Context2
+  );
+
+/**
+  Update the elapsed time from the Interval data of DATABASE_RECORD
+
+  @param[in] Record               The pointer to the DATABASE_RECORD.
+  @param[out] HwContext           The Context to be updated.
+**/
+VOID
+EFIAPI
+PeriodicTimerGetContext (
+  IN  DATABASE_RECORD    *Record,
+  OUT PCH_SMM_CONTEXT    *Context
+  );
+
+/**
+  Check whether Periodic Timer of two contexts match
+
+  @param[in] Context1             Context 1 that includes Periodic Timer  1
+  @param[in] Context2             Context 2 that includes Periodic Timer  2
+
+  @retval FALSE                   Periodic Timer match
+  @retval TRUE                    Periodic Timer don't match
+**/
+BOOLEAN
+EFIAPI
+PeriodicTimerCmpContext (
+  IN PCH_SMM_CONTEXT     *Context1,
+  IN PCH_SMM_CONTEXT     *Context2
+  );
+
+/**
+  Gather the CommBuffer information of SmmPeriodicTimerDispatch2.
+
+  @param[in]  Record              No use
+  @param[out] CommBuffer          Point to the CommBuffer structure
+  @param[out] CommBufferSize      Point to the Size of CommBuffer structure
+**/
+VOID
+EFIAPI
+PeriodicTimerGetCommBuffer (
+  IN  DATABASE_RECORD    *Record,
+  OUT VOID               **CommBuffer,
+  OUT UINTN              *CommBufferSize
+  );
+
+/**
+  Get the power button status.
+
+  @param[in] Record               The pointer to the DATABASE_RECORD.
+  @param[out] Context             Calling context from the hardware, will be updated with the current power button status.
+**/
+VOID
+EFIAPI
+PowerButtonGetContext (
+  IN  DATABASE_RECORD    *Record,
+  OUT PCH_SMM_CONTEXT    *Context
+  );
+
+/**
+  Check whether Power Button status of two contexts match
+
+  @param[in] Context1             Context 1 that includes Power Button status 1
+  @param[in] Context2             Context 2 that includes Power Button status 2
+
+  @retval FALSE                   Power Button status match
+  @retval TRUE                    Power Button status don't match
+**/
+BOOLEAN
+EFIAPI
+PowerButtonCmpContext (
+  IN PCH_SMM_CONTEXT     *Context1,
+  IN PCH_SMM_CONTEXT     *Context2
+  );
+
+/**
+  This function is responsible for calculating and enabling any timers that are required
+  to dispatch messages to children. The SrcDesc argument isn't acutally used.
+
+  @param[in] SrcDesc              Pointer to the PCH_SMM_SOURCE_DESC instance.
+**/
+VOID
+EFIAPI
+PchSmmPeriodicTimerClearSource (
+  IN CONST PCH_SMM_SOURCE_DESC    *SrcDesc
+  );
+
+/**
+  This services returns the next SMI tick period that is supported by the chipset.
+  The order returned is from longest to shortest interval period.
+
+  @param[in] This                 Pointer to the EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL instance.
+  @param[in, out] SmiTickInterval Pointer to pointer of the next shorter SMI interval period that is supported by the child.
+
+  @retval EFI_SUCCESS             The service returned successfully.
+  @retval EFI_INVALID_PARAMETER   The parameter SmiTickInterval is invalid.
+**/
+EFI_STATUS
+PchSmmPeriodicTimerDispatchGetNextShorterInterval (
+  IN CONST EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL    *This,
+  IN OUT UINT64                                         **SmiTickInterval
+  );
+
+/**
+  Install PCH SMM periodic timer control protocol
+
+  @param[in] Handle                     handle for this driver
+
+  @retval EFI_SUCCESS                   Driver initialization completed successfully
+**/
+EFI_STATUS
+EFIAPI
+InstallPchSmmPeriodicTimerControlProtocol (
+  IN EFI_HANDLE                         Handle
+  );
+
+/**
+  Install protocols of PCH specifics SMI types, including
+  PCH TCO SMI types, PCH PCIE SMI types, PCH ACPI SMI types, PCH MISC SMI types.
+
+  @retval                               the result of protocol installation
+**/
+EFI_STATUS
+InstallPchSmiDispatchProtocols (
+  VOID
+  );
+
+/**
+  The function to dispatch all callback function of PCH SMI types.
+
+  @retval EFI_SUCCESS                   Function successfully completed
+  @retval EFI_UNSUPPORTED               no
+**/
+EFI_STATUS
+PchSmiTypeCallbackDispatcher (
+  IN  DATABASE_RECORD                   *Record
+  );
+
+/**
+  The register function used to register SMI handler of IoTrap event.
+  This is internal function and only used by Iotrap module.
+
+  @param[in]  DispatchFunction          Pointer to dispatch function to be invoked for this SMI source
+  @param[in]  IoTrapIndex               Index number of IOTRAP register
+  @param[out] DispatchHandle            Handle of dispatch function to register.
+
+  @retval EFI_INVALID_PARAMETER         Error with NULL SMI source description
+  @retval EFI_OUT_OF_RESOURCES          Fail to allocate pool for database record
+  @retval EFI_SUCCESS                   The database record is created successfully.
+**/
+EFI_STATUS
+PchInternalIoTrapSmiRegister (
+  IN  PCH_SMI_DISPATCH_CALLBACK         DispatchFunction,
+  IN  UINTN                             IoTrapIndex,
+  OUT EFI_HANDLE                        *DispatchHandle
+  );
+
+/**
+  Unregister a child SMI source dispatch function with a parent SMM driver
+
+  @param[in] DispatchHandle             Handle of dispatch function to deregister.
+
+  @retval EFI_SUCCESS                   The dispatch function has been successfully
+                                        unregistered and the SMI source has been disabled
+                                        if there are no other registered child dispatch
+                                        functions for this SMI source.
+  @retval EFI_INVALID_PARAMETER         Handle is invalid.
+**/
+EFI_STATUS
+PchInternalIoTrapSmiUnRegister (
+  IN  EFI_HANDLE                        DispatchHandle
+  );
+
+/**
+  Register an eSPI SMI handler based on the type
+
+  @param[in]  DispatchFunction        Callback in an event of eSPI SMI
+  @param[in]  PchSmiTypes             The eSPI type published by PchSmiDispatch
+  @param[out] DispatchHandle          The callback handle
+
+  @retval     EFI_INVALID_PARAMETER   Error with NULL SMI source description
+  @retval     EFI_OUT_OF_RESOURCES    Fail to allocate pool for database record
+  @retval     EFI_SUCCESS             Registration is successful.
+**/
+EFI_STATUS
+PchInternalEspiSmiRegister (
+  IN  PCH_SMI_DISPATCH_CALLBACK         DispatchFunction,
+  IN  PCH_SMI_TYPES                     PchSmiTypes,
+  OUT EFI_HANDLE                        *DispatchHandle
+  );
+
+/**
+  Unregister an eSPI SMI handler
+
+  @param[in] DispatchHandle             Handle of dispatch function to deregister.
+
+  @retval EFI_SUCCESS                   The dispatch function has been successfully
+                                        unregistered and the SMI source has been disabled
+                                        if there are no other registered child dispatch
+                                        functions for this SMI source.
+  @retval EFI_INVALID_PARAMETER         Handle is invalid.
+**/
+EFI_STATUS
+PchInternalEspiSmiUnRegister (
+  IN  EFI_HANDLE                        DispatchHandle
+  );
+
+/**
+  The internal function used to create and insert a database record
+  for SMI record of Pch Smi types.
+
+  @param[in]  SrcDesc                   The pointer to the SMI source description
+  @param[in]  DispatchFunction          Pointer to dispatch function to be invoked for this SMI source
+  @param[in]  PchSmiType                Specific SMI type of PCH SMI
+  @param[out] DispatchHandle            Handle of dispatch function to register.
+
+  @retval EFI_INVALID_PARAMETER         Error with NULL SMI source description
+  @retval EFI_OUT_OF_RESOURCES          Fail to allocate pool for database record
+  @retval EFI_SUCCESS                   The database record is created successfully.
+**/
+EFI_STATUS
+PchSmiRecordInsert (
+  IN  CONST PCH_SMM_SOURCE_DESC         *SrcDesc,
+  IN  PCH_SMI_CALLBACK_FUNCTIONS        DispatchFunction,
+  IN  PCH_SMI_TYPES                     PchSmiType,
+  OUT EFI_HANDLE                        *DispatchHandle
+  );
+
+extern CONST PCH_SMM_SOURCE_DESC mSrcDescSerialIrq;
+extern PCH_SMM_SOURCE_DESC mSrcDescLpcBiosWp;
+
+/**
+  Clear the TCO SMI status bit and block after the SMI handling is done
+
+  @param[in] SrcDesc                    Pointer to the PCH SMI source description table
+
+**/
+VOID
+EFIAPI
+PchTcoSmiClearSourceAndBlock (
+  CONST PCH_SMM_SOURCE_DESC             *SrcDesc
+  );
+
+/**
+  Clear the TCO SMI status bit after the SMI handling is done
+
+  @param[in] SrcDesc                    Pointer to the PCH SMI source description table
+
+**/
+VOID
+EFIAPI
+PchTcoSmiClearSource (
+  CONST PCH_SMM_SOURCE_DESC             *SrcDesc
+  );
+
+/**
+  Initialize Source descriptor structure
+
+  @param[in] SrcDesc                    Pointer to the PCH SMI source description table
+**/
+VOID
+EFIAPI
+NullInitSourceDesc (
+  PCH_SMM_SOURCE_DESC                   *SrcDesc
+  );
+
+/**
+  The register function used to register SMI handler of GPI SMI event.
+
+  @param[in]  This               Pointer to the EFI_SMM_GPI_DISPATCH2_PROTOCOL instance.
+  @param[in]  DispatchFunction   Function to register for handler when the specified GPI causes an SMI.
+  @param[in]  RegisterContext    Pointer to the dispatch function's context.
+                                 The caller fills this context in before calling
+                                 the register function to indicate to the register
+                                 function the GPI(s) for which the dispatch function
+                                 should be invoked.
+  @param[out] DispatchHandle     Handle generated by the dispatcher to track the
+                                 function instance.
+
+  @retval EFI_SUCCESS            The dispatch function has been successfully
+                                 registered and the SMI source has been enabled.
+  @retval EFI_ACCESS_DENIED      Register is not allowed
+  @retval EFI_INVALID_PARAMETER  RegisterContext is invalid. The GPI input value
+                                 is not within valid range.
+  @retval EFI_OUT_OF_RESOURCES   There is not enough memory (system or SMM) to manage this child.
+**/
+EFI_STATUS
+EFIAPI
+PchGpiSmiRegister (
+  IN CONST EFI_SMM_GPI_DISPATCH2_PROTOCOL  *This,
+  IN       EFI_SMM_HANDLER_ENTRY_POINT2    DispatchFunction,
+  IN       EFI_SMM_GPI_REGISTER_CONTEXT    *RegisterContext,
+  OUT      EFI_HANDLE                      *DispatchHandle
+  );
+
+/**
+  Unregister a GPI SMI source dispatch function with a parent SMM driver
+
+  @param[in] This                 Pointer to the EFI_SMM_GPI_DISPATCH2_PROTOCOL instance.
+  @param[in] DispatchHandle       Handle of dispatch function to deregister.
+
+  @retval EFI_SUCCESS             The dispatch function has been successfully
+                                  unregistered and the SMI source has been disabled
+                                  if there are no other registered child dispatch
+                                  functions for this SMI source.
+  @retval EFI_INVALID_PARAMETER   Handle is invalid.
+**/
+EFI_STATUS
+EFIAPI
+PchGpiSmiUnRegister (
+  IN CONST EFI_SMM_GPI_DISPATCH2_PROTOCOL  *This,
+  IN       EFI_HANDLE                      DispatchHandle
+  );
+
+#endif
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmCore.c b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmCore.c
new file mode 100644
index 0000000000..cb889b5ce3
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmCore.c
@@ -0,0 +1,905 @@
+/** @file
+  This driver is responsible for the registration of child drivers
+  and the abstraction of the PCH SMI sources.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "PchSmm.h"
+#include "PchSmmHelpers.h"
+#include "PchSmiHelper.h"
+#include <Library/SmiHandlerProfileLib.h>
+#include <Register/GpioRegs.h>
+#include <Register/PmcRegs.h>
+#include <Register/TcoRegs.h>
+#include <Register/RtcRegs.h>
+
+#define PROGRESS_CODE_S3_SUSPEND_START  PcdGet32 (PcdProgressCodeS3SuspendStart)
+//
+// MODULE / GLOBAL DATA
+//
+// Module variables used by the both the main dispatcher and the source dispatchers
+// Declared in PchSmm.h
+//
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16                mAcpiBaseAddr;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16                mTcoBaseAddr;
+GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN               mReadyToLock;
+GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN               mS3SusStart;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT32                mNumOfRootPorts;
+
+GLOBAL_REMOVE_IF_UNREFERENCED PRIVATE_DATA          mPrivateData = {
+  {
+    NULL,
+    NULL
+  },                                    // CallbackDataBase linked list head
+  NULL,                                 // EFI handle returned when calling InstallMultipleProtocolInterfaces
+  NULL,                                 //
+  {                                     // protocol arrays
+    //
+    // elements within the array
+    //
+    {
+      PROTOCOL_SIGNATURE,
+      UsbType,
+      &gEfiSmmUsbDispatch2ProtocolGuid,
+      {{
+        (PCH_SMM_GENERIC_REGISTER) PchPiSmmCoreRegister,
+        (PCH_SMM_GENERIC_UNREGISTER) PchPiSmmCoreUnRegister
+      }}
+    },
+    {
+      PROTOCOL_SIGNATURE,
+      SxType,
+      &gEfiSmmSxDispatch2ProtocolGuid,
+      {{
+        (PCH_SMM_GENERIC_REGISTER) PchPiSmmCoreRegister,
+        (PCH_SMM_GENERIC_UNREGISTER) PchPiSmmCoreUnRegister
+      }}
+    },
+    {
+      PROTOCOL_SIGNATURE,
+      SwType,
+      &gEfiSmmSwDispatch2ProtocolGuid,
+      {{
+        (PCH_SMM_GENERIC_REGISTER) PchSwSmiRegister,
+        (PCH_SMM_GENERIC_UNREGISTER) PchSwSmiUnRegister,
+        (UINTN) MAXIMUM_SWI_VALUE
+      }}
+    },
+    {
+      PROTOCOL_SIGNATURE,
+      GpiType,
+      &gEfiSmmGpiDispatch2ProtocolGuid,
+      {{
+        (PCH_SMM_GENERIC_REGISTER) PchGpiSmiRegister,
+        (PCH_SMM_GENERIC_UNREGISTER) PchGpiSmiUnRegister,
+        (UINTN) PCH_GPIO_NUM_SUPPORTED_GPIS
+      }}
+    },
+    {
+      PROTOCOL_SIGNATURE,
+      PowerButtonType,
+      &gEfiSmmPowerButtonDispatch2ProtocolGuid,
+      {{
+        (PCH_SMM_GENERIC_REGISTER) PchPiSmmCoreRegister,
+        (PCH_SMM_GENERIC_UNREGISTER) PchPiSmmCoreUnRegister
+      }}
+    },
+    {
+      PROTOCOL_SIGNATURE,
+      PeriodicTimerType,
+      &gEfiSmmPeriodicTimerDispatch2ProtocolGuid,
+      {{
+        (PCH_SMM_GENERIC_REGISTER) PchPiSmmCoreRegister,
+        (PCH_SMM_GENERIC_UNREGISTER) PchPiSmmCoreUnRegister,
+        (UINTN) PchSmmPeriodicTimerDispatchGetNextShorterInterval
+      }}
+    },
+  }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONTEXT_FUNCTIONS     mContextFunctions[PCH_SMM_PROTOCOL_TYPE_MAX] = {
+  {
+    NULL,
+    NULL,
+    NULL
+  },
+  {
+    SxGetContext,
+    SxCmpContext,
+    NULL
+  },
+  {
+    NULL,
+    NULL,
+    NULL
+  },
+  {
+    NULL,
+    NULL,
+    NULL
+  },
+  {
+    PowerButtonGetContext,
+    PowerButtonCmpContext,
+    NULL
+  },
+  {
+    PeriodicTimerGetContext,
+    PeriodicTimerCmpContext,
+    PeriodicTimerGetCommBuffer
+  },
+};
+
+//
+// PROTOTYPES
+//
+// Functions use only in this file
+//
+EFI_STATUS
+EFIAPI
+PchSmmCoreDispatcher (
+  IN       EFI_HANDLE         SmmImageHandle,
+  IN CONST VOID               *PchSmmCore,     OPTIONAL
+  IN OUT   VOID               *CommunicationBuffer,
+  IN OUT   UINTN              *SourceSize
+  );
+
+//
+// FUNCTIONS
+//
+/**
+  SMM ready to lock notification event handler.
+
+  @param  Protocol   Points to the protocol's unique identifier
+  @param  Interface  Points to the interface instance
+  @param  Handle     The handle on which the interface was installed
+
+  @retval EFI_SUCCESS   SmmReadyToLockCallback runs successfully
+
+**/
+EFI_STATUS
+EFIAPI
+SmmReadyToLockCallback (
+  IN CONST EFI_GUID                       *Protocol,
+  IN VOID                                 *Interface,
+  IN EFI_HANDLE                           Handle
+  )
+{
+  mReadyToLock = TRUE;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  <b>PchSmiDispatcher SMM Module Entry Point</b>\n
+  - <b>Introduction</b>\n
+    The PchSmiDispatcher module is an SMM driver which  provides SMI handler registration
+    services for PCH generated SMIs.
+
+  - <b>Details</b>\n
+    This module provides SMI handler registration servicies for PCH SMIs.
+    NOTE: All the register/unregister functions will be locked after SMM ready to boot signal event.
+    Please make sure no handler is installed after that.
+
+  - @pre
+    - EFI_SMM_BASE2_PROTOCOL
+      - Documented in the System Management Mode Core Interface Specification
+    - EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+      - Documented in the UEFI 2.0 Specification and above
+    - EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+      - This is to ensure that PCI MMIO and IO resource has been prepared and available for this driver to allocate.
+    - EFI_SMM_CPU_PROTOCOL
+
+  - @result
+    The PchSmiDispatcher driver produces:
+    - EFI_SMM_USB_DISPATCH2_PROTOCOL
+    - EFI_SMM_SX_DISPATCH2_PROTOCOL
+    - EFI_SMM_SW_DISPATCH2_PROTOCOL
+    - EFI_SMM_GPI_DISPATCH2_PROTOCOL
+    - EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL
+    - EFI_SMM_POWER_BUTTON_DISPATCH2_PROTOCOL
+    - EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL
+    - @link _PCH_SMM_IO_TRAP_CONTROL_PROTOCOL PCH_SMM_IO_TRAP_CONTROL_PROTOCOL @endlink
+    - @link _PCH_PCIE_SMI_DISPATCH_PROTOCOL PCH_PCIE_SMI_DISPATCH_PROTOCOL @endlink
+    - @link _PCH_TCO_SMI_DISPATCH_PROTOCOL PCH_TCO_SMI_DISPATCH_PROTOCOL @endlink
+    - @link _PCH_ACPI_SMI_DISPATCH_PROTOCOL PCH_ACPI_SMI_DISPATCH_PROTOCOL @endlink
+    - @link _PCH_SMI_DISPATCH_PROTOCOL PCH_SMI_DISPATCH_PROTOCOL @endlink
+
+  @param[in] ImageHandle          Pointer to the loaded image protocol for this driver
+  @param[in] SystemTable          Pointer to the EFI System Table
+
+  @retval EFI_SUCCESS             PchSmmDispatcher Initialization completed.
+**/
+EFI_STATUS
+EFIAPI
+InitializePchSmmDispatcher (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS           Status;
+  VOID                 *SmmReadyToLockRegistration;
+
+  mS3SusStart = FALSE;
+
+  PchSmiDispatchUpdateDescriptors ();
+
+  //
+  // Access ACPI Base Addresses Register
+  //
+  mAcpiBaseAddr = PmcGetAcpiBase ();
+  ASSERT (mAcpiBaseAddr != 0);
+
+  //
+  // Access TCO Base Addresses Register
+  //
+  PchTcoBaseGet (&mTcoBaseAddr);
+  ASSERT (mTcoBaseAddr != 0);
+
+  mNumOfRootPorts = GetPchMaxPciePortNum ();
+
+  //
+  // Register a callback function to handle subsequent SMIs.  This callback
+  // will be called by SmmCoreDispatcher.
+  //
+  Status = gSmst->SmiHandlerRegister (PchSmmCoreDispatcher, NULL, &mPrivateData.SmiHandle);
+  ASSERT_EFI_ERROR (Status);
+  //
+  // Initialize Callback DataBase
+  //
+  InitializeListHead (&mPrivateData.CallbackDataBase);
+
+  //
+  // Enable SMIs on the PCH now that we have a callback
+  //
+  PchSmmInitHardware ();
+
+  //
+  // Install and initialize all the needed protocols
+  //
+  PchSwDispatchInit ();
+  PchSmmPublishDispatchProtocols ();
+  InstallPchSmiDispatchProtocols ();
+  InstallPchSmmPeriodicTimerControlProtocol (mPrivateData.InstallMultProtHandle);
+
+  //
+  // Register EFI_SMM_READY_TO_LOCK_PROTOCOL_GUID notify function.
+  //
+  Status = gSmst->SmmRegisterProtocolNotify (
+                    &gEfiSmmReadyToLockProtocolGuid,
+                    SmmReadyToLockCallback,
+                    &SmmReadyToLockRegistration
+                    );
+  ASSERT_EFI_ERROR (Status);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  The internal function used to create and insert a database record
+
+  @param[in]  InsertRecord              Record to insert to database.
+  @param[out] DispatchHandle            Handle of dispatch function to register.
+
+  @retval EFI_INVALID_PARAMETER         Error with NULL SMI source description
+  @retval EFI_OUT_OF_RESOURCES          Fail to allocate pool for database record
+  @retval EFI_SUCCESS                   The database record is created successfully.
+**/
+EFI_STATUS
+SmmCoreInsertRecord (
+  IN  DATABASE_RECORD                   *NewRecord,
+  OUT EFI_HANDLE                        *DispatchHandle
+  )
+{
+  EFI_STATUS                            Status;
+  DATABASE_RECORD                       *Record;
+
+  if ((NewRecord == NULL) ||
+      (NewRecord->Signature != DATABASE_RECORD_SIGNATURE))
+  {
+    ASSERT (FALSE);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = gSmst->SmmAllocatePool (EfiRuntimeServicesData, sizeof (DATABASE_RECORD), (VOID **) &Record);
+  if (EFI_ERROR (Status)) {
+    ASSERT (FALSE);
+    return EFI_OUT_OF_RESOURCES;
+  }
+  CopyMem (Record, NewRecord, sizeof (DATABASE_RECORD));
+
+  //
+  // After ensuring the source of event is not null, we will insert the record into the database
+  //
+  InsertTailList (&mPrivateData.CallbackDataBase, &Record->Link);
+
+  //
+  // Child's handle will be the address linked list link in the record
+  //
+  *DispatchHandle = (EFI_HANDLE) (&Record->Link);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Unregister a child SMI source dispatch function with a parent SMM driver
+
+  @param[in] This                       Protocol instance pointer.
+  @param[in] DispatchHandle             Handle of dispatch function to deregister.
+
+  @retval EFI_SUCCESS                   The dispatch function has been successfully
+                                        unregistered and the SMI source has been disabled
+                                        if there are no other registered child dispatch
+                                        functions for this SMI source.
+  @retval EFI_INVALID_PARAMETER         Handle is invalid.
+  @retval EFI_ACCESS_DENIED             Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchPiSmmCoreUnRegister (
+  IN PCH_SMM_GENERIC_PROTOCOL                           *This,
+  IN EFI_HANDLE                                         *DispatchHandle
+  )
+{
+  DATABASE_RECORD                   *RecordToDelete;
+  EFI_STATUS                        Status;
+  PCH_SMM_QUALIFIED_PROTOCOL        *Qualified;
+
+  Qualified      = QUALIFIED_PROTOCOL_FROM_GENERIC (This);
+  RecordToDelete = DATABASE_RECORD_FROM_LINK (DispatchHandle);
+  Status         = PchSmmCoreUnRegister (NULL, DispatchHandle);
+  if (!EFI_ERROR (Status)) {
+    SmiHandlerProfileUnregisterHandler (
+      Qualified->Guid,
+      RecordToDelete->Callback,
+      &RecordToDelete->ChildContext,
+      RecordToDelete->ContextSize
+      );
+  }
+  return Status;
+}
+
+/**
+  Register a child SMI dispatch function with a parent SMM driver.
+
+  @param[in] This                 Pointer to the PCH_SMM_GENERIC_PROTOCOL instance.
+  @param[in] DispatchFunction     Pointer to dispatch function to be invoked for this SMI source.
+  @param[in] DispatchContext      Pointer to the dispatch function's context.
+  @param[out] DispatchHandle      Handle of dispatch function, for when interfacing
+                                  with the parent SMM driver, will be the address of linked
+                                  list link in the call back record.
+
+  @retval EFI_OUT_OF_RESOURCES    Insufficient resources to create database record
+  @retval EFI_INVALID_PARAMETER   The input parameter is invalid
+  @retval EFI_SUCCESS             The dispatch function has been successfully
+                                  registered and the SMI source has been enabled.
+**/
+EFI_STATUS
+EFIAPI
+PchPiSmmCoreRegister (
+  IN  PCH_SMM_GENERIC_PROTOCOL                          *This,
+  IN  EFI_SMM_HANDLER_ENTRY_POINT2                      DispatchFunction,
+  IN  PCH_SMM_CONTEXT                                   *DispatchContext,
+  OUT EFI_HANDLE                                        *DispatchHandle
+  )
+{
+  EFI_STATUS                  Status;
+  DATABASE_RECORD             Record;
+  PCH_SMM_QUALIFIED_PROTOCOL  *Qualified;
+  PCH_SMM_SOURCE_DESC         NullSourceDesc;
+
+  //
+  // Initialize NullSourceDesc
+  //
+  NullInitSourceDesc (&NullSourceDesc);
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "Register is not allowed if the EndOfDxe event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  ZeroMem (&Record, sizeof (DATABASE_RECORD));
+
+  //
+  // Gather information about the registration request
+  //
+  Record.Callback          = DispatchFunction;
+
+  Qualified                = QUALIFIED_PROTOCOL_FROM_GENERIC (This);
+
+  Record.ProtocolType      = Qualified->Type;
+
+  Record.ContextFunctions  = mContextFunctions[Qualified->Type];
+  //
+  // Perform linked list housekeeping
+  //
+  Record.Signature         = DATABASE_RECORD_SIGNATURE;
+
+  switch (Qualified->Type) {
+    //
+    // By the end of this switch statement, we'll know the
+    // source description the child is registering for
+    //
+    case UsbType:
+      Record.ContextSize = sizeof (EFI_SMM_USB_REGISTER_CONTEXT);
+      CopyMem (&Record.ChildContext, DispatchContext, Record.ContextSize);
+      //
+      // Check the validity of Context Type
+      //
+      if ((Record.ChildContext.Usb.Type < UsbLegacy) || (Record.ChildContext.Usb.Type > UsbWake)) {
+        return EFI_INVALID_PARAMETER;
+      }
+
+      PchSmmUsbUpdateDescriptors ();
+      MapUsbToSrcDesc (DispatchContext, &Record.SrcDesc);
+      Record.ClearSource = NULL;
+      //
+      // use default clear source function
+      //
+      break;
+
+    case SxType:
+      Record.ContextSize = sizeof (EFI_SMM_SX_REGISTER_CONTEXT);
+      CopyMem (&Record.ChildContext, DispatchContext, Record.ContextSize);
+      //
+      // Check the validity of Context Type and Phase
+      //
+      if ((Record.ChildContext.Sx.Type < SxS0) ||
+          (Record.ChildContext.Sx.Type >= EfiMaximumSleepType) ||
+          (Record.ChildContext.Sx.Phase < SxEntry) ||
+          (Record.ChildContext.Sx.Phase >= EfiMaximumPhase)
+          ) {
+        return EFI_INVALID_PARAMETER;
+      }
+
+      CopyMem (&Record.SrcDesc, &mSxSourceDesc, sizeof (PCH_SMM_SOURCE_DESC));
+      Record.ClearSource = NULL;
+      //
+      // use default clear source function
+      //
+      break;
+
+    case PowerButtonType:
+      Record.ContextSize = sizeof (EFI_SMM_POWER_BUTTON_REGISTER_CONTEXT);
+      CopyMem (&Record.ChildContext, DispatchContext, Record.ContextSize);
+      //
+      // Check the validity of Context Phase
+      //
+      if ((Record.ChildContext.PowerButton.Phase < EfiPowerButtonEntry) ||
+          (Record.ChildContext.PowerButton.Phase > EfiPowerButtonExit))
+      {
+        return EFI_INVALID_PARAMETER;
+      }
+
+      CopyMem (&Record.SrcDesc, &mPowerButtonSourceDesc, sizeof (PCH_SMM_SOURCE_DESC));
+      Record.ClearSource = NULL;
+      //
+      // use default clear source function
+      //
+      break;
+
+    case PeriodicTimerType:
+      Record.ContextSize = sizeof (EFI_SMM_PERIODIC_TIMER_REGISTER_CONTEXT);
+      CopyMem (&Record.ChildContext, DispatchContext, Record.ContextSize);
+      //
+      // Check the validity of timer value
+      //
+      if (DispatchContext->PeriodicTimer.SmiTickInterval <= 0) {
+        return EFI_INVALID_PARAMETER;
+      }
+
+      MapPeriodicTimerToSrcDesc (DispatchContext, &Record.SrcDesc);
+      Record.MiscData.TimerSmiEnabled = TRUE;
+      Record.ClearSource = PchSmmPeriodicTimerClearSource;
+      break;
+
+    default:
+      return EFI_INVALID_PARAMETER;
+      break;
+  }
+
+  if (CompareSources (&Record.SrcDesc, &NullSourceDesc)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // After ensuring the source of event is not null, we will insert the record into the database
+  // Child's handle will be the address linked list link in the record
+  //
+  Status = SmmCoreInsertRecord (
+             &Record,
+             DispatchHandle
+             );
+  ASSERT_EFI_ERROR (Status);
+
+  if (Record.ClearSource == NULL) {
+    //
+    // Clear the SMI associated w/ the source using the default function
+    //
+    PchSmmClearSource (&Record.SrcDesc);
+  } else {
+    //
+    // This source requires special handling to clear
+    //
+    Record.ClearSource (&Record.SrcDesc);
+  }
+
+  PchSmmEnableSource (&Record.SrcDesc);
+  SmiHandlerProfileRegisterHandler (
+    Qualified->Guid,
+    DispatchFunction,
+    (UINTN)RETURN_ADDRESS (0),
+    DispatchContext,
+    Record.ContextSize
+    );
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Unregister a child SMI source dispatch function with a parent SMM driver.
+
+  @param[in] This                 Pointer to the PCH_SMM_GENERIC_PROTOCOL instance.
+  @param[in] DispatchHandle       Handle of dispatch function to deregister.
+
+  @retval EFI_SUCCESS             The dispatch function has been successfully
+                                  unregistered and the SMI source has been disabled
+                                  if there are no other registered child dispatch
+                                  functions for this SMI source.
+  @retval EFI_INVALID_PARAMETER   Handle is invalid.
+**/
+EFI_STATUS
+EFIAPI
+PchSmmCoreUnRegister (
+  IN PCH_SMM_GENERIC_PROTOCOL                           *This,
+  IN EFI_HANDLE                                         *DispatchHandle
+  )
+{
+  EFI_STATUS                   Status;
+  BOOLEAN                      NeedClearEnable;
+  UINTN                        DescIndex;
+  DATABASE_RECORD              *RecordToDelete;
+  DATABASE_RECORD              *RecordInDb;
+  LIST_ENTRY                   *LinkInDb;
+
+  if (DispatchHandle == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "UnRegister is not allowed if the SmmReadyToLock event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  RecordToDelete = DATABASE_RECORD_FROM_LINK (DispatchHandle);
+
+  //
+  // Take the entry out of the linked list
+  //
+  if (RecordToDelete->Link.ForwardLink == (LIST_ENTRY *) EFI_BAD_POINTER) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  RemoveEntryList (&RecordToDelete->Link);
+
+  //
+  // Loop through all the souces in record linked list to see if any source enable is equal.
+  // If any source enable is equal, we do not want to disable it.
+  //
+  for (DescIndex = 0; DescIndex < NUM_EN_BITS; ++DescIndex) {
+    if (IS_BIT_DESC_NULL (RecordToDelete->SrcDesc.En[DescIndex])) {
+      continue;
+    }
+    NeedClearEnable = TRUE;
+    LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);
+    while (!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {
+      RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);
+      if (IsBitEqualToAnySourceEn (&RecordToDelete->SrcDesc.En[DescIndex], &RecordInDb->SrcDesc)) {
+        NeedClearEnable = FALSE;
+        break;
+      }
+      LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, &RecordInDb->Link);
+    }
+    if (NeedClearEnable == FALSE) {
+      continue;
+    }
+    WriteBitDesc (&RecordToDelete->SrcDesc.En[DescIndex], 0, FALSE);
+  }
+  Status = gSmst->SmmFreePool (RecordToDelete);
+  if (EFI_ERROR (Status)) {
+    ASSERT (FALSE);
+    return Status;
+  }
+  return EFI_SUCCESS;
+}
+
+/**
+  This function clears the pending SMI status before set EOS.
+  NOTE: This only clears the pending SMI with known reason.
+        Please do not clear unknown pending SMI status since that will hide potential issues.
+
+  @param[in] SmiStsValue                SMI status
+  @param[in] SciEn                      Sci Enable status
+**/
+STATIC
+VOID
+ClearPendingSmiStatus (
+  UINT32  SmiStsValue,
+  BOOLEAN SciEn
+  )
+{
+  //
+  // Clear NewCentury status if it's not handled.
+  //
+  if (SmiStsValue & B_ACPI_IO_SMI_STS_TCO) {
+    if (IoRead16 (mTcoBaseAddr + R_TCO_IO_TCO1_STS) & B_TCO_IO_TCO1_STS_NEWCENTURY) {
+      PchTcoSmiClearSourceAndBlock (&mSrcDescNewCentury);
+    }
+  }
+  // Clear PWRBTNOR_STS if it's not handled.
+  //
+  if (IoRead16 (mAcpiBaseAddr + R_ACPI_IO_PM1_STS) & B_ACPI_IO_PM1_STS_PRBTNOR) {
+    IoWrite16 (mAcpiBaseAddr + R_ACPI_IO_PM1_STS, B_ACPI_IO_PM1_STS_PRBTNOR);
+  }
+  //
+  // Clear WADT_STS if this is triggered by WADT timer.
+  //
+  if (!SciEn) {
+    if ((IoRead32 (mAcpiBaseAddr + R_ACPI_IO_GPE0_EN_127_96) & B_ACPI_IO_GPE0_EN_127_96_WADT) &&
+        (IoRead32 (mAcpiBaseAddr + R_ACPI_IO_GPE0_STS_127_96) & B_ACPI_IO_GPE0_STS_127_96_WADT)) {
+      IoWrite32 (mAcpiBaseAddr + R_ACPI_IO_GPE0_STS_127_96, B_ACPI_IO_GPE0_STS_127_96_WADT);
+    }
+  }
+  //
+  // Clear GPIO_UNLOCK_SMI_STS in case it is set as GPIO Unlock SMI is not supported
+  //
+  if (SmiStsValue & B_ACPI_IO_SMI_STS_GPIO_UNLOCK) {
+    IoWrite32 (mAcpiBaseAddr + R_ACPI_IO_SMI_STS, B_ACPI_IO_SMI_STS_GPIO_UNLOCK);
+  }
+}
+
+/**
+  The callback function to handle subsequent SMIs.  This callback will be called by SmmCoreDispatcher.
+
+  @param[in] SmmImageHandle             Not used
+  @param[in] PchSmmCore                 Not used
+  @param[in, out] CommunicationBuffer   Not used
+  @param[in, out] SourceSize            Not used
+
+  @retval EFI_SUCCESS                   Function successfully completed
+**/
+EFI_STATUS
+EFIAPI
+PchSmmCoreDispatcher (
+  IN       EFI_HANDLE         SmmImageHandle,
+  IN CONST VOID               *PchSmmCore,
+  IN OUT   VOID               *CommunicationBuffer,
+  IN OUT   UINTN              *SourceSize
+  )
+{
+  //
+  // Used to prevent infinite loops
+  //
+  UINTN               EscapeCount;
+
+  BOOLEAN             ContextsMatch;
+  BOOLEAN             EosSet;
+  BOOLEAN             SxChildWasDispatched;
+
+  DATABASE_RECORD     *RecordInDb;
+  LIST_ENTRY          *LinkInDb;
+  DATABASE_RECORD     *RecordToExhaust;
+  LIST_ENTRY          *LinkToExhaust;
+
+  PCH_SMM_CONTEXT     Context;
+  VOID                *CommBuffer;
+  UINTN               CommBufferSize;
+
+  EFI_STATUS          Status;
+  BOOLEAN             SciEn;
+  UINT32              SmiEnValue;
+  UINT32              SmiStsValue;
+  UINT8               Port74Save;
+  UINT8               Port76Save;
+
+  PCH_SMM_SOURCE_DESC ActiveSource;
+
+  //
+  // Initialize ActiveSource
+  //
+  NullInitSourceDesc (&ActiveSource);
+
+  EscapeCount           = 3;
+  ContextsMatch         = FALSE;
+  EosSet                = FALSE;
+  SxChildWasDispatched  = FALSE;
+  Status                = EFI_SUCCESS;
+
+  //
+  // Save IO index registers
+  // @note: Save/Restore port 70h directly might break NMI_EN# setting,
+  //       then save/restore 74h/76h instead.
+  // @note: CF8 is not saved. Prefer method is to use MMIO instead of CF8
+  //
+  Port76Save = IoRead8 (R_RTC_IO_EXT_INDEX_ALT);
+  Port74Save = IoRead8 (R_RTC_IO_INDEX_ALT);
+
+  if (!IsListEmpty (&mPrivateData.CallbackDataBase)) {
+    //
+    // We have children registered w/ us -- continue
+    //
+    while ((!EosSet) && (EscapeCount > 0)) {
+      EscapeCount--;
+
+      LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);
+
+      //
+      // Cache SciEn, SmiEnValue and SmiStsValue to determine if source is active
+      //
+      SciEn       = PchSmmGetSciEn ();
+      SmiEnValue  = IoRead32 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_SMI_EN));
+      SmiStsValue = IoRead32 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_SMI_STS));
+
+      while (!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {
+        RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);
+
+        //
+        // look for the first active source
+        //
+        if (!SourceIsActive (&RecordInDb->SrcDesc, SciEn, SmiEnValue, SmiStsValue)) {
+          //
+          // Didn't find the source yet, keep looking
+          //
+          LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, &RecordInDb->Link);
+
+          //
+          // if it's the last one, try to clear EOS
+          //
+          if (IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {
+            //
+            // Clear pending SMI status before EOS
+            //
+            ClearPendingSmiStatus (SmiStsValue, SciEn);
+            EosSet = PchSmmSetAndCheckEos ();
+          }
+        } else {
+          //
+          // We found a source. If this is a sleep type, we have to go to
+          // appropriate sleep state anyway.No matter there is sleep child or not
+          //
+          if (RecordInDb->ProtocolType == SxType) {
+            SxChildWasDispatched = TRUE;
+          }
+          //
+          // "cache" the source description and don't query I/O anymore
+          //
+          CopyMem ((VOID *) &ActiveSource, (VOID *) &(RecordInDb->SrcDesc), sizeof (PCH_SMM_SOURCE_DESC));
+          LinkToExhaust = LinkInDb;
+
+          //
+          // exhaust the rest of the queue looking for the same source
+          //
+          while (!IsNull (&mPrivateData.CallbackDataBase, LinkToExhaust)) {
+            RecordToExhaust = DATABASE_RECORD_FROM_LINK (LinkToExhaust);
+            //
+            // RecordToExhaust->Link might be removed (unregistered) by Callback function, and then the
+            // system will hang in ASSERT() while calling GetNextNode().
+            // To prevent the issue, we need to get next record in DB here (before Callback function).
+            //
+            LinkToExhaust = GetNextNode (&mPrivateData.CallbackDataBase, &RecordToExhaust->Link);
+
+            if (CompareSources (&RecordToExhaust->SrcDesc, &ActiveSource)) {
+              //
+              // These source descriptions are equal, so this callback should be
+              // dispatched.
+              //
+              if (RecordToExhaust->ContextFunctions.GetContext != NULL) {
+                //
+                // This child requires that we get a calling context from
+                // hardware and compare that context to the one supplied
+                // by the child.
+                //
+                ASSERT (RecordToExhaust->ContextFunctions.CmpContext != NULL);
+
+                //
+                // Make sure contexts match before dispatching event to child
+                //
+                RecordToExhaust->ContextFunctions.GetContext (RecordToExhaust, &Context);
+                ContextsMatch = RecordToExhaust->ContextFunctions.CmpContext (&Context, &RecordToExhaust->ChildContext);
+
+              } else {
+                //
+                // This child doesn't require any more calling context beyond what
+                // it supplied in registration.  Simply pass back what it gave us.
+                //
+                Context       = RecordToExhaust->ChildContext;
+                ContextsMatch = TRUE;
+              }
+
+              if (ContextsMatch) {
+                if (RecordToExhaust->ProtocolType == PchSmiDispatchType) {
+                  //
+                  // For PCH SMI dispatch protocols
+                  //
+                  PchSmiTypeCallbackDispatcher (RecordToExhaust);
+                } else {
+                  if ((RecordToExhaust->ProtocolType == SxType) && (Context.Sx.Type == SxS3) && (Context.Sx.Phase == SxEntry) && !mS3SusStart) {
+                    REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PROGRESS_CODE_S3_SUSPEND_START);
+                    mS3SusStart = TRUE;
+                  }
+                  //
+                  // For EFI standard SMI dispatch protocols
+                  //
+                  if (RecordToExhaust->Callback != NULL) {
+                    if (RecordToExhaust->ContextFunctions.GetCommBuffer != NULL) {
+                      //
+                      // This callback function needs CommBuffer and CommBufferSize.
+                      // Get those from child and then pass to callback function.
+                      //
+                      RecordToExhaust->ContextFunctions.GetCommBuffer (RecordToExhaust, &CommBuffer, &CommBufferSize);
+                    } else {
+                      //
+                      // Child doesn't support the CommBuffer and CommBufferSize.
+                      // Just pass NULL value to callback function.
+                      //
+                      CommBuffer     = NULL;
+                      CommBufferSize = 0;
+                    }
+
+                    PERF_START_EX (NULL, "SmmFunction", NULL, AsmReadTsc (), RecordToExhaust->ProtocolType);
+                    RecordToExhaust->Callback ((EFI_HANDLE) & RecordToExhaust->Link, &Context, CommBuffer, &CommBufferSize);
+                    PERF_END_EX (NULL, "SmmFunction", NULL, AsmReadTsc (), RecordToExhaust->ProtocolType);
+                    if (RecordToExhaust->ProtocolType == SxType) {
+                      SxChildWasDispatched = TRUE;
+                    }
+                  } else {
+                    ASSERT (FALSE);
+                  }
+                }
+              }
+            }
+          }
+
+          if (RecordInDb->ClearSource == NULL) {
+            //
+            // Clear the SMI associated w/ the source using the default function
+            //
+            PchSmmClearSource (&ActiveSource);
+          } else {
+            //
+            // This source requires special handling to clear
+            //
+            RecordInDb->ClearSource (&ActiveSource);
+          }
+          //
+          // Clear pending SMI status before EOS
+          //
+          ClearPendingSmiStatus (SmiStsValue, SciEn);
+          //
+          // Also, try to clear EOS
+          //
+          EosSet = PchSmmSetAndCheckEos ();
+          //
+          // Queue is empty, reset the search
+          //
+          break;
+        }
+      }
+    }
+  }
+  //
+  // Restore IO index registers
+  // @note: Save/Restore port 70h directly might break NMI_EN# setting,
+  //       then save/restore 74h/76h instead.
+  //
+  IoWrite8 (R_RTC_IO_EXT_INDEX_ALT, Port76Save);
+  IoWrite8 (R_RTC_IO_INDEX_ALT, Port74Save);
+
+  return Status;
+}
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmGpi.c b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmGpi.c
new file mode 100644
index 0000000000..4c59c07bac
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmGpi.c
@@ -0,0 +1,255 @@
+/** @file
+  File to contain all the hardware specific stuff for the Smm Gpi dispatch protocol.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "PchSmm.h"
+#include "PchSmmHelpers.h"
+#include <Library/SmiHandlerProfileLib.h>
+#include <Register/GpioRegs.h>
+#include <Register/PmcRegs.h>
+
+//
+// Structure for GPI SMI is a template which needs to have
+// GPI Smi bit offset and Smi Status & Enable registers updated (accordingly
+// to choosen group and pad number) after adding it to SMM Callback database
+//
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mPchGpiSourceDescTemplate = {
+  PCH_SMM_NO_FLAGS,
+  {
+    NULL_BIT_DESC_INITIALIZER,
+    NULL_BIT_DESC_INITIALIZER
+  },
+  {
+    {
+      {
+        GPIO_ADDR_TYPE, {0x0}
+      },
+      S_GPIO_PCR_GP_SMI_STS, 0x0,
+    }
+  },
+  {
+    {
+      ACPI_ADDR_TYPE,
+      {R_ACPI_IO_SMI_STS}
+    },
+    S_ACPI_IO_SMI_STS,
+    N_ACPI_IO_SMI_STS_GPIO_SMI
+  }
+};
+
+/**
+  The register function used to register SMI handler of GPI SMI event.
+
+  @param[in]  This               Pointer to the EFI_SMM_GPI_DISPATCH2_PROTOCOL instance.
+  @param[in]  DispatchFunction   Function to register for handler when the specified GPI causes an SMI.
+  @param[in]  RegisterContext    Pointer to the dispatch function's context.
+                                 The caller fills this context in before calling
+                                 the register function to indicate to the register
+                                 function the GPI(s) for which the dispatch function
+                                 should be invoked.
+  @param[out] DispatchHandle     Handle generated by the dispatcher to track the
+                                 function instance.
+
+  @retval EFI_SUCCESS            The dispatch function has been successfully
+                                 registered and the SMI source has been enabled.
+  @retval EFI_ACCESS_DENIED      Register is not allowed
+  @retval EFI_INVALID_PARAMETER  RegisterContext is invalid. The GPI input value
+                                 is not within valid range.
+  @retval EFI_OUT_OF_RESOURCES   There is not enough memory (system or SMM) to manage this child.
+**/
+EFI_STATUS
+EFIAPI
+PchGpiSmiRegister (
+  IN CONST EFI_SMM_GPI_DISPATCH2_PROTOCOL  *This,
+  IN       EFI_SMM_HANDLER_ENTRY_POINT2    DispatchFunction,
+  IN       EFI_SMM_GPI_REGISTER_CONTEXT    *RegisterContext,
+  OUT      EFI_HANDLE                      *DispatchHandle
+  )
+{
+  EFI_STATUS                  Status;
+  DATABASE_RECORD             Record;
+  GPIO_PAD                    GpioPad;
+  UINT8                       GpiSmiBitOffset;
+  UINT32                      GpiHostSwOwnRegAddress;
+  UINT32                      GpiSmiStsRegAddress;
+  UINT32                      Data32And;
+
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "Register is not allowed if the EndOfDxe event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  Status = GpioGetPadAndSmiRegs (
+             (UINT32) RegisterContext->GpiNum,
+             &GpioPad,
+             &GpiSmiBitOffset,
+             &GpiHostSwOwnRegAddress,
+             &GpiSmiStsRegAddress
+             );
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  ZeroMem (&Record, sizeof (DATABASE_RECORD));
+
+  //
+  // Gather information about the registration request
+  //
+  Record.Callback          = DispatchFunction;
+  Record.ChildContext.Gpi  = *RegisterContext;
+  Record.ProtocolType      = GpiType;
+  Record.Signature         = DATABASE_RECORD_SIGNATURE;
+
+  CopyMem (&Record.SrcDesc, &mPchGpiSourceDescTemplate, sizeof (PCH_SMM_SOURCE_DESC) );
+
+  Record.SrcDesc.Sts[0].Reg.Data.raw = GpiSmiStsRegAddress;  // GPI SMI Status register
+  Record.SrcDesc.Sts[0].Bit = GpiSmiBitOffset;               // Bit position for selected pad
+
+  //
+  // Insert GpiSmi handler to PchSmmCore database
+  //
+  *DispatchHandle = NULL;
+
+  Status = SmmCoreInsertRecord (
+             &Record,
+             DispatchHandle
+             );
+  ASSERT_EFI_ERROR (Status);
+
+  SmiHandlerProfileRegisterHandler (
+    &gEfiSmmGpiDispatch2ProtocolGuid,
+    (EFI_SMM_HANDLER_ENTRY_POINT2) DispatchFunction,
+    (UINTN)RETURN_ADDRESS (0),
+    RegisterContext,
+    sizeof(*RegisterContext)
+    );
+
+  //
+  // Enable GPI SMI
+  // HOSTSW_OWN with respect to generating GPI SMI has negative logic:
+  //  - 0 (ACPI mode) - GPIO pad will be capable of generating SMI/NMI/SCI
+  //  - 1 (GPIO mode) - GPIO pad will not generate SMI/NMI/SCI
+  //
+  Data32And  = (UINT32)~(1u << GpiSmiBitOffset);
+  MmioAnd32 (GpiHostSwOwnRegAddress, Data32And);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Unregister a GPI SMI source dispatch function with a parent SMM driver
+
+  @param[in] This                 Pointer to the EFI_SMM_GPI_DISPATCH2_PROTOCOL instance.
+  @param[in] DispatchHandle       Handle of dispatch function to deregister.
+
+  @retval EFI_SUCCESS             The dispatch function has been successfully
+                                  unregistered and the SMI source has been disabled
+                                  if there are no other registered child dispatch
+                                  functions for this SMI source.
+  @retval EFI_INVALID_PARAMETER   Handle is invalid.
+**/
+EFI_STATUS
+EFIAPI
+PchGpiSmiUnRegister (
+  IN CONST EFI_SMM_GPI_DISPATCH2_PROTOCOL  *This,
+  IN       EFI_HANDLE                      DispatchHandle
+  )
+{
+  EFI_STATUS      Status;
+  DATABASE_RECORD *RecordToDelete;
+  DATABASE_RECORD *RecordInDb;
+  LIST_ENTRY      *LinkInDb;
+  GPIO_PAD        GpioPad;
+  UINT8           GpiSmiBitOffset;
+  UINT32          GpiHostSwOwnRegAddress;
+  UINT32          GpiSmiStsRegAddress;
+  UINT32          Data32Or;
+  UINT32          Data32And;
+  BOOLEAN         DisableGpiSmiSource;
+
+
+  if (DispatchHandle == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  RecordToDelete = DATABASE_RECORD_FROM_LINK (DispatchHandle);
+  if ((RecordToDelete->Signature != DATABASE_RECORD_SIGNATURE) ||
+      (RecordToDelete->ProtocolType != GpiType)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "UnRegister is not allowed if the SmmReadyToLock event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  DisableGpiSmiSource = TRUE;
+  //
+  // Loop through all sources in record linked list to see if any other GPI SMI
+  // is installed on the same pin. If no then disable GPI SMI capability on this pad
+  //
+  LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);
+  while (!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {
+    RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);
+    LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, &RecordInDb->Link);
+    //
+    // If this is the record to delete skip it
+    //
+    if (RecordInDb == RecordToDelete) {
+      continue;
+    }
+    //
+    // Check if record is GPI SMI type
+    //
+    if (RecordInDb->ProtocolType == GpiType) {
+      //
+      // Check if same GPIO pad is the source of this SMI
+      //
+      if (RecordInDb->ChildContext.Gpi.GpiNum == RecordToDelete->ChildContext.Gpi.GpiNum) {
+        DisableGpiSmiSource = FALSE;
+        break;
+      }
+    }
+  }
+
+  if (DisableGpiSmiSource) {
+    GpioGetPadAndSmiRegs (
+      (UINT32) RecordToDelete->ChildContext.Gpi.GpiNum,
+      &GpioPad,
+      &GpiSmiBitOffset,
+      &GpiHostSwOwnRegAddress,
+      &GpiSmiStsRegAddress
+      );
+
+    Data32Or = 1u << GpiSmiBitOffset;
+    Data32And = 0xFFFFFFFF;
+    MmioOr32 (GpiHostSwOwnRegAddress, Data32Or);
+  }
+
+
+  RemoveEntryList (&RecordToDelete->Link);
+  ZeroMem (RecordToDelete, sizeof (DATABASE_RECORD));
+  Status = gSmst->SmmFreePool (RecordToDelete);
+
+  if (EFI_ERROR (Status)) {
+    ASSERT (FALSE);
+    return Status;
+  }
+  SmiHandlerProfileUnregisterHandler (
+    &gEfiSmmGpiDispatch2ProtocolGuid,
+    RecordToDelete->Callback,
+    &RecordToDelete->ChildContext,
+    RecordToDelete->ContextSize
+    );
+  return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmHelpers.c b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmHelpers.c
new file mode 100644
index 0000000000..724a383855
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmHelpers.c
@@ -0,0 +1,332 @@
+/** @file
+  Helper functions for PCH SMM dispatcher.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "PchSmmHelpers.h"
+#include <Register/PmcRegs.h>
+
+///
+/// #define BIT_ZERO 0x00000001
+///
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32  BIT_ZERO = 0x00000001;
+
+///
+/// SUPPORT / HELPER FUNCTIONS (PCH version-independent)
+///
+
+/**
+  Compare 2 SMM source descriptors' enable settings.
+
+  @param[in] Src1                 Pointer to the PCH SMI source description table 1
+  @param[in] Src2                 Pointer to the PCH SMI source description table 2
+
+  @retval TRUE                    The enable settings of the 2 SMM source descriptors are identical.
+  @retval FALSE                   The enable settings of the 2 SMM source descriptors are not identical.
+**/
+BOOLEAN
+CompareEnables (
+  CONST IN PCH_SMM_SOURCE_DESC *Src1,
+  CONST IN PCH_SMM_SOURCE_DESC *Src2
+  )
+{
+  BOOLEAN IsEqual;
+  UINTN   DescIndex;
+
+  IsEqual = TRUE;
+  for (DescIndex = 0; DescIndex < NUM_EN_BITS; DescIndex++) {
+    ///
+    /// It's okay to compare a NULL bit description to a non-NULL bit description.
+    /// They are unequal and these tests will generate the correct result.
+    ///
+    if (Src1->En[DescIndex].Bit != Src2->En[DescIndex].Bit ||
+        Src1->En[DescIndex].Reg.Type != Src2->En[DescIndex].Reg.Type ||
+        Src1->En[DescIndex].Reg.Data.raw != Src2->En[DescIndex].Reg.Data.raw
+        ) {
+      IsEqual = FALSE;
+      break;
+      ///
+      /// out of for loop
+      ///
+    }
+  }
+
+  return IsEqual;
+}
+
+/**
+  Compare a bit descriptor to the enables of source descriptor. Includes null address type.
+
+  @param[in] BitDesc              Pointer to the PCH SMI bit descriptor
+  @param[in] Src                  Pointer to the PCH SMI source description table 2
+
+  @retval TRUE                    The bit desc is equal to any of the enables in source descriptor
+  @retval FALSE                   The bid desc is not equal to all of the enables in source descriptor
+**/
+BOOLEAN
+IsBitEqualToAnySourceEn (
+  CONST IN PCH_SMM_BIT_DESC    *BitDesc,
+  CONST IN PCH_SMM_SOURCE_DESC *Src
+  )
+{
+  BOOLEAN IsEqual;
+  UINTN   DescIndex;
+
+  IsEqual = FALSE;
+
+  for (DescIndex = 0; DescIndex < NUM_EN_BITS; ++DescIndex) {
+    if ((BitDesc->Reg.Type == Src->En[DescIndex].Reg.Type) &&
+        (BitDesc->Reg.Data.raw == Src->En[DescIndex].Reg.Data.raw) &&
+        (BitDesc->Bit == Src->En[DescIndex].Bit)) {
+      IsEqual = TRUE;
+      break;
+    }
+  }
+  return IsEqual;
+}
+
+/**
+  Compare 2 SMM source descriptors' statuses.
+
+  @param[in] Src1                 Pointer to the PCH SMI source description table 1
+  @param[in] Src2                 Pointer to the PCH SMI source description table 2
+
+  @retval TRUE                    The statuses of the 2 SMM source descriptors are identical.
+  @retval FALSE                   The statuses of the 2 SMM source descriptors are not identical.
+**/
+BOOLEAN
+CompareStatuses (
+  CONST IN PCH_SMM_SOURCE_DESC *Src1,
+  CONST IN PCH_SMM_SOURCE_DESC *Src2
+  )
+{
+  BOOLEAN IsEqual;
+  UINTN   DescIndex;
+
+  IsEqual = TRUE;
+
+  for (DescIndex = 0; DescIndex < NUM_STS_BITS; DescIndex++) {
+    ///
+    /// It's okay to compare a NULL bit description to a non-NULL bit description.
+    /// They are unequal and these tests will generate the correct result.
+    ///
+    if (Src1->Sts[DescIndex].Bit != Src2->Sts[DescIndex].Bit ||
+        Src1->Sts[DescIndex].Reg.Type != Src2->Sts[DescIndex].Reg.Type ||
+        Src1->Sts[DescIndex].Reg.Data.raw != Src2->Sts[DescIndex].Reg.Data.raw
+        ) {
+      IsEqual = FALSE;
+      break;
+      ///
+      /// out of for loop
+      ///
+    }
+  }
+
+  return IsEqual;
+}
+
+/**
+  Compare 2 SMM source descriptors, based on Enable settings and Status settings of them.
+
+  @param[in] Src1                 Pointer to the PCH SMI source description table 1
+  @param[in] Src2                 Pointer to the PCH SMI source description table 2
+
+  @retval TRUE                    The 2 SMM source descriptors are identical.
+  @retval FALSE                   The 2 SMM source descriptors are not identical.
+**/
+BOOLEAN
+CompareSources (
+  CONST IN PCH_SMM_SOURCE_DESC *Src1,
+  CONST IN PCH_SMM_SOURCE_DESC *Src2
+  )
+{
+  return (BOOLEAN) (CompareEnables (Src1, Src2) && CompareStatuses (Src1, Src2));
+}
+
+/**
+  Check if an SMM source is active.
+
+  @param[in] Src                  Pointer to the PCH SMI source description table
+  @param[in] SciEn                Indicate if SCI is enabled or not
+  @param[in] SmiEnValue           Value from R_ACPI_IO_SMI_EN
+  @param[in] SmiStsValue          Value from R_ACPI_IO_SMI_STS
+
+  @retval TRUE                    It is active.
+  @retval FALSE                   It is inactive.
+**/
+BOOLEAN
+SourceIsActive (
+  CONST IN PCH_SMM_SOURCE_DESC  *Src,
+  CONST IN BOOLEAN              SciEn,
+  CONST IN UINT32               SmiEnValue,
+  CONST IN UINT32               SmiStsValue
+  )
+{
+  UINTN   DescIndex;
+
+  ///
+  /// This source is dependent on SciEn, and SciEn == 1.  An ACPI OS is present,
+  /// so we shouldn't do anything w/ this source until SciEn == 0.
+  ///
+  if ((Src->Flags == PCH_SMM_SCI_EN_DEPENDENT) && (SciEn)) {
+    return FALSE;
+  }
+
+  ///
+  /// Checking top level SMI status. If the status is not active, return false immediately
+  ///
+  if (!IS_BIT_DESC_NULL (Src->PmcSmiSts)) {
+    if ((Src->PmcSmiSts.Reg.Type == ACPI_ADDR_TYPE) &&
+        (Src->PmcSmiSts.Reg.Data.acpi == R_ACPI_IO_SMI_STS) &&
+        ((SmiStsValue & (1u << Src->PmcSmiSts.Bit)) == 0)) {
+      return FALSE;
+    }
+  }
+
+  ///
+  /// Read each bit desc from hardware and make sure it's a one
+  ///
+  for (DescIndex = 0; DescIndex < NUM_EN_BITS; DescIndex++) {
+    if (!IS_BIT_DESC_NULL (Src->En[DescIndex])) {
+      if ((Src->En[DescIndex].Reg.Type == ACPI_ADDR_TYPE) &&
+          (Src->En[DescIndex].Reg.Data.acpi == R_ACPI_IO_SMI_EN) &&
+          ((SmiEnValue & (1u << Src->En[DescIndex].Bit)) == 0)) {
+        return FALSE;
+      } else if (ReadBitDesc (&Src->En[DescIndex]) == 0) {
+        return FALSE;
+      }
+    }
+  }
+
+  ///
+  /// Read each bit desc from hardware and make sure it's a one
+  ///
+  for (DescIndex = 0; DescIndex < NUM_STS_BITS; DescIndex++) {
+    if (!IS_BIT_DESC_NULL (Src->Sts[DescIndex])) {
+      if ((Src->Sts[DescIndex].Reg.Type == ACPI_ADDR_TYPE) &&
+          (Src->Sts[DescIndex].Reg.Data.acpi == R_ACPI_IO_SMI_STS) &&
+          ((SmiStsValue & (1u << Src->Sts[DescIndex].Bit)) == 0)) {
+        return FALSE;
+      } else if (ReadBitDesc (&Src->Sts[DescIndex]) == 0) {
+        return FALSE;
+      }
+    }
+  }
+
+  return TRUE;
+}
+
+/**
+  Enable the SMI source event by set the SMI enable bit, this function would also clear SMI
+  status bit to make initial state is correct
+
+  @param[in] SrcDesc              Pointer to the PCH SMI source description table
+
+**/
+VOID
+PchSmmEnableSource (
+  CONST PCH_SMM_SOURCE_DESC *SrcDesc
+  )
+{
+  UINTN DescIndex;
+
+  ///
+  /// Set enables to 1 by writing a 1
+  ///
+  for (DescIndex = 0; DescIndex < NUM_EN_BITS; DescIndex++) {
+    if (!IS_BIT_DESC_NULL (SrcDesc->En[DescIndex])) {
+      WriteBitDesc (&SrcDesc->En[DescIndex], 1, FALSE);
+    }
+  }
+  ///
+  /// Clear statuses to 0 by writing a 1
+  ///
+  for (DescIndex = 0; DescIndex < NUM_STS_BITS; DescIndex++) {
+    if (!IS_BIT_DESC_NULL (SrcDesc->Sts[DescIndex])) {
+      WriteBitDesc (&SrcDesc->Sts[DescIndex], 1, TRUE);
+    }
+  }
+}
+
+/**
+  Disable the SMI source event by clear the SMI enable bit
+
+  @param[in] SrcDesc              Pointer to the PCH SMI source description table
+
+**/
+VOID
+PchSmmDisableSource (
+  CONST PCH_SMM_SOURCE_DESC *SrcDesc
+  )
+{
+  UINTN DescIndex;
+
+  for (DescIndex = 0; DescIndex < NUM_EN_BITS; DescIndex++) {
+    if (!IS_BIT_DESC_NULL (SrcDesc->En[DescIndex])) {
+      WriteBitDesc (&SrcDesc->En[DescIndex], 0, FALSE);
+    }
+  }
+}
+
+/**
+  Clear the SMI status bit by set the source bit of SMI status register
+
+  @param[in] SrcDesc              Pointer to the PCH SMI source description table
+
+**/
+VOID
+PchSmmClearSource (
+  CONST PCH_SMM_SOURCE_DESC *SrcDesc
+  )
+{
+  UINTN DescIndex;
+
+  for (DescIndex = 0; DescIndex < NUM_STS_BITS; DescIndex++) {
+    if (!IS_BIT_DESC_NULL (SrcDesc->Sts[DescIndex])) {
+      WriteBitDesc (&SrcDesc->Sts[DescIndex], 1, TRUE);
+    }
+  }
+}
+
+/**
+  Sets the source to a 1 and then waits for it to clear.
+  Be very careful when calling this function -- it will not
+  ASSERT.  An acceptable case to call the function is when
+  waiting for the NEWCENTURY_STS bit to clear (which takes
+  3 RTCCLKs).
+
+  @param[in] SrcDesc              Pointer to the PCH SMI source description table
+
+**/
+VOID
+PchSmmClearSourceAndBlock (
+  CONST PCH_SMM_SOURCE_DESC *SrcDesc
+  )
+{
+  UINTN   DescIndex;
+  BOOLEAN IsSet;
+
+  for (DescIndex = 0; DescIndex < NUM_STS_BITS; DescIndex++) {
+
+    if (!IS_BIT_DESC_NULL (SrcDesc->Sts[DescIndex])) {
+      ///
+      /// Write the bit
+      ///
+      WriteBitDesc (&SrcDesc->Sts[DescIndex], 1, TRUE);
+
+      ///
+      /// Don't return until the bit actually clears.
+      ///
+      IsSet = TRUE;
+      while (IsSet) {
+        IsSet = ReadBitDesc (&SrcDesc->Sts[DescIndex]);
+        ///
+        /// IsSet will eventually clear -- or else we'll have
+        /// an infinite loop.
+        ///
+      }
+    }
+  }
+}
+
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmHelpers.h b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmHelpers.h
new file mode 100644
index 0000000000..93ab8564ff
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmHelpers.h
@@ -0,0 +1,163 @@
+/** @file
+  Helper functions for PCH SMM
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef PCH_SMM_HELPERS_H
+#define PCH_SMM_HELPERS_H
+
+#include "PchSmm.h"
+#include "PchxSmmHelpers.h"
+//
+// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// SUPPORT / HELPER FUNCTIONS (PCH version-independent)
+//
+
+/**
+  Publish SMI Dispatch protocols.
+
+
+**/
+VOID
+PchSmmPublishDispatchProtocols (
+  VOID
+  );
+
+/**
+  Compare 2 SMM source descriptors' enable settings.
+
+  @param[in] Src1                 Pointer to the PCH SMI source description table 1
+  @param[in] Src2                 Pointer to the PCH SMI source description table 2
+
+  @retval TRUE                    The enable settings of the 2 SMM source descriptors are identical.
+  @retval FALSE                   The enable settings of the 2 SMM source descriptors are not identical.
+**/
+BOOLEAN
+CompareEnables (
+  CONST IN PCH_SMM_SOURCE_DESC *Src1,
+  CONST IN PCH_SMM_SOURCE_DESC *Src2
+  );
+
+/**
+  Compare a bit descriptor to the enables of source descriptor. Includes null address type.
+
+  @param[in] BitDesc              Pointer to the PCH SMI bit descriptor
+  @param[in] Src                  Pointer to the PCH SMI source description table 2
+
+  @retval TRUE                    The bit desc is equal to any of the enables in source descriptor
+  @retval FALSE                   The bid desc is not equal to all of the enables in source descriptor
+**/
+BOOLEAN
+IsBitEqualToAnySourceEn (
+  CONST IN PCH_SMM_BIT_DESC    *BitDesc,
+  CONST IN PCH_SMM_SOURCE_DESC *Src
+  );
+
+/**
+  Compare 2 SMM source descriptors' statuses.
+
+  @param[in] Src1                 Pointer to the PCH SMI source description table 1
+  @param[in] Src2                 Pointer to the PCH SMI source description table 2
+
+  @retval TRUE                    The statuses of the 2 SMM source descriptors are identical.
+  @retval FALSE                   The statuses of the 2 SMM source descriptors are not identical.
+**/
+BOOLEAN
+CompareStatuses (
+  CONST IN PCH_SMM_SOURCE_DESC *Src1,
+  CONST IN PCH_SMM_SOURCE_DESC *Src2
+  );
+
+/**
+  Compare 2 SMM source descriptors, based on Enable settings and Status settings of them.
+
+  @param[in] Src1                 Pointer to the PCH SMI source description table 1
+  @param[in] Src2                 Pointer to the PCH SMI source description table 2
+
+  @retval TRUE                    The 2 SMM source descriptors are identical.
+  @retval FALSE                   The 2 SMM source descriptors are not identical.
+**/
+BOOLEAN
+CompareSources (
+  CONST IN PCH_SMM_SOURCE_DESC *Src1,
+  CONST IN PCH_SMM_SOURCE_DESC *Src2
+  );
+
+/**
+  Check if an SMM source is active.
+
+  @param[in] Src                  Pointer to the PCH SMI source description table
+  @param[in] SciEn                Indicate if SCI is enabled or not
+  @param[in] SmiEnValue           Value from R_PCH_SMI_EN
+  @param[in] SmiStsValue          Value from R_PCH_SMI_STS
+
+  @retval TRUE                    It is active.
+  @retval FALSE                   It is inactive.
+**/
+BOOLEAN
+SourceIsActive (
+  CONST IN PCH_SMM_SOURCE_DESC  *Src,
+  CONST IN BOOLEAN              SciEn,
+  CONST IN UINT32               SmiEnValue,
+  CONST IN UINT32               SmiStsValue
+  );
+
+/**
+  Enable the SMI source event by set the SMI enable bit, this function would also clear SMI
+  status bit to make initial state is correct
+
+  @param[in] SrcDesc              Pointer to the PCH SMI source description table
+
+**/
+VOID
+PchSmmEnableSource (
+  CONST PCH_SMM_SOURCE_DESC *SrcDesc
+  );
+
+/**
+  Disable the SMI source event by clear the SMI enable bit
+
+  @param[in] SrcDesc              Pointer to the PCH SMI source description table
+
+**/
+VOID
+PchSmmDisableSource (
+  CONST PCH_SMM_SOURCE_DESC *SrcDesc
+  );
+
+/**
+  Clear the SMI status bit by set the source bit of SMI status register
+
+  @param[in] SrcDesc              Pointer to the PCH SMI source description table
+
+**/
+VOID
+PchSmmClearSource (
+  CONST PCH_SMM_SOURCE_DESC *SrcDesc
+  );
+
+/**
+  Sets the source to a 1 and then waits for it to clear.
+  Be very careful when calling this function -- it will not
+  ASSERT.  An acceptable case to call the function is when
+  waiting for the NEWCENTURY_STS bit to clear (which takes
+  3 RTCCLKs).
+
+  @param[in] SrcDesc              Pointer to the PCH SMI source description table
+
+**/
+VOID
+PchSmmClearSourceAndBlock (
+  CONST PCH_SMM_SOURCE_DESC *SrcDesc
+  );
+
+/**
+  Performs update of SmmUsb descriptors with values that have to be evaluated during runtime.
+**/
+VOID
+PchSmmUsbUpdateDescriptors (
+  VOID
+  );
+
+#endif
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmPeriodicTimer.c b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmPeriodicTimer.c
new file mode 100644
index 0000000000..3078d0c696
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmPeriodicTimer.c
@@ -0,0 +1,670 @@
+/** @file
+  File to contain all the hardware specific stuff for the Periodical Timer dispatch protocol.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "PchSmmHelpers.h"
+#include <Protocol/PchSmmPeriodicTimerControl.h>
+#include <Library/PmcPrivateLib.h>
+
+//
+// There is only one instance for PeriodicTimerCommBuffer.
+// It's safe in SMM since there is no re-entry for the function.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_PERIODIC_TIMER_CONTEXT          mPchPeriodicTimerCommBuffer;
+
+typedef enum {
+  PERIODIC_TIMER= 0,
+  SWSMI_TIMER,
+  NUM_TIMERS
+} SUPPORTED_TIMER;
+
+typedef struct _TIMER_INTERVAL {
+  UINT64  Interval;
+  UINT8   AssociatedTimer;
+} TIMER_INTERVAL;
+
+#define NUM_INTERVALS 8
+
+//
+// Time constants, in 100 nano-second units
+//
+#define TIME_64s    640000000 ///< 64   s
+#define TIME_32s    320000000 ///< 32   s
+#define TIME_16s    160000000 ///< 16   s
+#define TIME_8s     80000000  ///<  8   s
+#define TIME_64ms   640000    ///< 64   ms
+#define TIME_32ms   320000    ///< 32   ms
+#define TIME_16ms   160000    ///< 16   ms
+#define TIME_1_5ms  15000     ///< 1.5  ms
+
+typedef enum {
+  INDEX_TIME_64s  = 0,
+  INDEX_TIME_32s,
+  INDEX_TIME_16s,
+  INDEX_TIME_8s,
+  INDEX_TIME_64ms,
+  INDEX_TIME_32ms,
+  INDEX_TIME_16ms,
+  INDEX_TIME_1_5ms,
+  INDEX_TIME_MAX
+} TIMER_INTERVAL_INDEX;
+
+static TIMER_INTERVAL mSmmPeriodicTimerIntervals[NUM_INTERVALS] = {
+  {
+    TIME_64s,
+    PERIODIC_TIMER
+  },
+  {
+    TIME_32s,
+    PERIODIC_TIMER
+  },
+  {
+    TIME_16s,
+    PERIODIC_TIMER
+  },
+  {
+    TIME_8s,
+    PERIODIC_TIMER
+  },
+  {
+    TIME_64ms,
+    SWSMI_TIMER
+  },
+  {
+    TIME_32ms,
+    SWSMI_TIMER
+  },
+  {
+    TIME_16ms,
+    SWSMI_TIMER
+  },
+  {
+    TIME_1_5ms,
+    SWSMI_TIMER
+  },
+};
+
+typedef struct _TIMER_INFO {
+  UINTN   NumChildren;        ///< number of children using this timer
+  UINT64  MinReqInterval;     ///< minimum interval required by children
+  UINTN   CurrentSetting;     ///< interval this timer is set at right now (index into interval table)
+} TIMER_INFO;
+
+GLOBAL_REMOVE_IF_UNREFERENCED TIMER_INFO          mTimers[NUM_TIMERS];
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mTimerSourceDesc[NUM_TIMERS] = {
+  {
+    PCH_SMM_NO_FLAGS,
+    {
+      {
+        {
+          ACPI_ADDR_TYPE,
+          {R_ACPI_IO_SMI_EN}
+        },
+        S_ACPI_IO_SMI_EN,
+        N_ACPI_IO_SMI_EN_PERIODIC
+      },
+      NULL_BIT_DESC_INITIALIZER
+    },
+    {
+      {
+        {
+          ACPI_ADDR_TYPE,
+          {R_ACPI_IO_SMI_STS}
+        },
+        S_ACPI_IO_SMI_STS,
+        N_ACPI_IO_SMI_STS_PERIODIC
+      }
+    },
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_STS}
+      },
+      S_ACPI_IO_SMI_STS,
+      N_ACPI_IO_SMI_STS_PERIODIC
+    }
+  },
+  {
+    PCH_SMM_NO_FLAGS,
+    {
+      {
+        {
+          ACPI_ADDR_TYPE,
+          {R_ACPI_IO_SMI_EN}
+        },
+        S_ACPI_IO_SMI_EN,
+        N_ACPI_IO_SMI_EN_SWSMI_TMR
+      },
+      NULL_BIT_DESC_INITIALIZER
+    },
+    {
+      {
+        {
+          ACPI_ADDR_TYPE,
+          {R_ACPI_IO_SMI_STS}
+        },
+        S_ACPI_IO_SMI_STS,
+        N_ACPI_IO_SMI_STS_SWSMI_TMR
+      }
+    },
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_STS}
+      },
+      S_ACPI_IO_SMI_STS,
+      N_ACPI_IO_SMI_STS_SWSMI_TMR
+    }
+  }
+};
+
+/**
+  Program Smm Periodic Timer
+
+  @param[in] SrcDesc              Pointer to the PCH_SMM_SOURCE_DESC instance.
+**/
+VOID
+PchSmmPeriodicTimerProgramTimers (
+  IN CONST PCH_SMM_SOURCE_DESC    *SrcDesc
+  );
+
+/**
+  Convert the dispatch context to the timer interval, this function will assert if then either:
+  (1) The context contains an invalid interval
+  (2) The timer interval table is corrupt
+
+  @param[in] DispatchContext      The pointer to the Dispatch Context
+
+  @retval TIMER_INTERVAL          The timer interval of input dispatch context
+**/
+TIMER_INTERVAL *
+ContextToTimerInterval (
+  IN  PCH_SMM_CONTEXT     *DispatchContext
+  )
+{
+  UINTN loopvar;
+
+  ///
+  /// Determine which timer this child is using
+  ///
+  for (loopvar = 0; loopvar < NUM_INTERVALS; loopvar++) {
+    if (((DispatchContext->PeriodicTimer.SmiTickInterval == 0) &&
+         (DispatchContext->PeriodicTimer.Period >= mSmmPeriodicTimerIntervals[loopvar].Interval)) ||
+        (DispatchContext->PeriodicTimer.SmiTickInterval == mSmmPeriodicTimerIntervals[loopvar].Interval)) {
+      return &mSmmPeriodicTimerIntervals[loopvar];
+    }
+  }
+  ///
+  /// If this assertion fires, then either:
+  ///    (1) the context contains an invalid interval
+  ///    (2) the timer interval table is corrupt
+  ///
+  ASSERT (FALSE);
+
+  return NULL;
+}
+
+/**
+  Figure out which timer the child is requesting and
+  send back the source description
+
+  @param[in] DispatchContext      The pointer to the Dispatch Context instances
+  @param[out] SrcDesc             The pointer to the source description
+
+**/
+VOID
+MapPeriodicTimerToSrcDesc (
+  IN  PCH_SMM_CONTEXT             *DispatchContext,
+  OUT PCH_SMM_SOURCE_DESC         *SrcDesc
+  )
+{
+  TIMER_INTERVAL  *TimerInterval;
+
+  ///
+  /// Figure out which timer the child is requesting and
+  /// send back the source description
+  ///
+  TimerInterval = ContextToTimerInterval (DispatchContext);
+  if (TimerInterval == NULL) {
+    return;
+  }
+
+  CopyMem (
+    (VOID *) SrcDesc,
+    (VOID *) (&mTimerSourceDesc[TimerInterval->AssociatedTimer]),
+    sizeof (PCH_SMM_SOURCE_DESC)
+    );
+
+  ///
+  /// Program the value of the interval into hardware
+  ///
+  PchSmmPeriodicTimerProgramTimers (SrcDesc);
+}
+
+/**
+  Update the elapsed time from the Interval data of DATABASE_RECORD
+
+  @param[in] Record               The pointer to the DATABASE_RECORD.
+  @param[out] HwContext           The Context to be updated.
+
+**/
+VOID
+EFIAPI
+PeriodicTimerGetContext (
+  IN  DATABASE_RECORD    *Record,
+  OUT PCH_SMM_CONTEXT    *HwContext
+  )
+{
+  TIMER_INTERVAL  *TimerInterval;
+
+  ASSERT (Record->ProtocolType == PeriodicTimerType);
+
+  TimerInterval = ContextToTimerInterval (&Record->ChildContext);
+  if (TimerInterval == NULL) {
+    return;
+  }
+  ///
+  /// Ignore the hardware context. It's not required for this protocol.
+  /// Instead, just increment the child's context.
+  /// Update the elapsed time w/ the data from our tables
+  ///
+  Record->MiscData.ElapsedTime += mTimers[TimerInterval->AssociatedTimer].MinReqInterval;
+  *HwContext = Record->ChildContext;
+}
+
+/**
+  Check whether Periodic Timer of two contexts match
+
+  @param[in] Context1             Context 1 that includes Periodic Timer  1
+  @param[in] Context2             Context 2 that includes Periodic Timer  2
+
+  @retval FALSE                   Periodic Timer match
+  @retval TRUE                    Periodic Timer don't match
+**/
+BOOLEAN
+EFIAPI
+PeriodicTimerCmpContext (
+  IN PCH_SMM_CONTEXT     *HwContext,
+  IN PCH_SMM_CONTEXT     *ChildContext
+  )
+{
+  DATABASE_RECORD        *Record;
+  Record = DATABASE_RECORD_FROM_CHILDCONTEXT (ChildContext);
+
+  if (!Record->MiscData.TimerSmiEnabled) {
+    return FALSE;
+  }
+  if (Record->MiscData.ElapsedTime >= ChildContext->PeriodicTimer.Period) {
+    ///
+    /// For EDKII, the ElapsedTime is reset when PeriodicTimerGetCommBuffer
+    ///
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+/**
+  Gather the CommBuffer information of SmmPeriodicTimerDispatch2.
+
+  @param[in]  Record              No use
+  @param[out] CommBuffer          Point to the CommBuffer structure
+  @param[out] CommBufferSize      Point to the Size of CommBuffer structure
+
+**/
+VOID
+EFIAPI
+PeriodicTimerGetCommBuffer (
+  IN  DATABASE_RECORD    *Record,
+  OUT VOID               **CommBuffer,
+  OUT UINTN              *CommBufferSize
+  )
+{
+  ASSERT (Record->ProtocolType == PeriodicTimerType);
+
+  mPchPeriodicTimerCommBuffer.ElapsedTime = Record->MiscData.ElapsedTime;
+
+  ///
+  /// For EDKII, the ElapsedTime is reset here
+  ///
+  Record->MiscData.ElapsedTime = 0;
+
+  ///
+  /// Return the CommBuffer
+  ///
+  *CommBuffer = (VOID *) &mPchPeriodicTimerCommBuffer;
+  *CommBufferSize = sizeof (EFI_SMM_PERIODIC_TIMER_CONTEXT);
+}
+
+/**
+  Program Smm Periodic Timer
+
+  @param[in] SrcDesc              Pointer to the PCH_SMM_SOURCE_DESC instance.
+**/
+VOID
+PchSmmPeriodicTimerProgramTimers (
+  IN CONST PCH_SMM_SOURCE_DESC    *SrcDesc
+  )
+{
+  SUPPORTED_TIMER Timer;
+  DATABASE_RECORD *RecordInDb;
+  LIST_ENTRY      *LinkInDb;
+  TIMER_INTERVAL  *TimerInterval;
+
+  ///
+  /// Find the minimum required interval for each timer
+  ///
+  for (Timer = 0; Timer < NUM_TIMERS; Timer++) {
+    mTimers[Timer].MinReqInterval = ~ (UINT64) 0x0;
+    mTimers[Timer].NumChildren    = 0;
+  }
+
+  LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);
+  while (!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {
+    RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);
+    if (RecordInDb->ProtocolType == PeriodicTimerType) {
+      if (RecordInDb->MiscData.TimerSmiEnabled) {
+        ///
+        /// This child is registerd with the PeriodicTimer protocol
+        ///
+        TimerInterval = ContextToTimerInterval (&RecordInDb->ChildContext);
+        if (TimerInterval == NULL) {
+          return;
+        }
+
+        Timer = TimerInterval->AssociatedTimer;
+        if (Timer < 0 || Timer >= NUM_TIMERS) {
+          ASSERT (FALSE);
+          CpuDeadLoop ();
+          return;
+        }
+        if (mTimers[Timer].MinReqInterval > RecordInDb->ChildContext.PeriodicTimer.SmiTickInterval) {
+          mTimers[Timer].MinReqInterval = RecordInDb->ChildContext.PeriodicTimer.SmiTickInterval;
+        }
+        mTimers[Timer].NumChildren++;
+      }
+    }
+    LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, &RecordInDb->Link);
+  }
+  ///
+  /// Program the hardware
+  ///
+  if (mTimers[PERIODIC_TIMER].NumChildren > 0) {
+    switch (mTimers[PERIODIC_TIMER].MinReqInterval) {
+      case TIME_64s:
+        PmcSetPeriodicSmiRate (PmcPeriodicSmiRate64s);
+        mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_64s;
+        break;
+
+      case TIME_32s:
+        PmcSetPeriodicSmiRate (PmcPeriodicSmiRate32s);
+        mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_32s;
+        break;
+
+      case TIME_16s:
+        PmcSetPeriodicSmiRate (PmcPeriodicSmiRate16s);
+        mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_16s;
+        break;
+
+      case TIME_8s:
+        PmcSetPeriodicSmiRate (PmcPeriodicSmiRate8s);
+        mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_8s;
+        break;
+
+      default:
+        ASSERT (FALSE);
+        break;
+    }
+
+    ///
+    /// Restart the timer here, just need to clear the SMI
+    ///
+    if (SrcDesc->Sts[0].Bit == N_ACPI_IO_SMI_STS_PERIODIC) {
+      PchSmmClearSource (&mTimerSourceDesc[PERIODIC_TIMER]);
+    }
+  } else {
+    PchSmmDisableSource (&mTimerSourceDesc[PERIODIC_TIMER]);
+  }
+
+  if (mTimers[SWSMI_TIMER].NumChildren > 0) {
+    switch (mTimers[SWSMI_TIMER].MinReqInterval) {
+      case TIME_64ms:
+        PmcSetSwSmiRate (PmcSwSmiRate64ms);
+        mTimers[SWSMI_TIMER].CurrentSetting = INDEX_TIME_64ms;
+        break;
+
+      case TIME_32ms:
+        PmcSetSwSmiRate (PmcSwSmiRate32ms);
+        mTimers[SWSMI_TIMER].CurrentSetting = INDEX_TIME_32ms;
+        break;
+
+      case TIME_16ms:
+        PmcSetSwSmiRate (PmcSwSmiRate16ms);
+        mTimers[SWSMI_TIMER].CurrentSetting = INDEX_TIME_16ms;
+        break;
+
+      case TIME_1_5ms:
+        PmcSetSwSmiRate (PmcSwSmiRate1p5ms);
+        mTimers[SWSMI_TIMER].CurrentSetting = INDEX_TIME_1_5ms;
+        break;
+
+      default:
+        ASSERT (FALSE);
+        break;
+    }
+
+    ///
+    /// Restart the timer here, need to disable, clear, then enable to restart this timer
+    ///
+    if (SrcDesc->Sts[0].Bit == N_ACPI_IO_SMI_STS_SWSMI_TMR) {
+      PchSmmDisableSource (&mTimerSourceDesc[SWSMI_TIMER]);
+      PchSmmClearSource (&mTimerSourceDesc[SWSMI_TIMER]);
+      PchSmmEnableSource (&mTimerSourceDesc[SWSMI_TIMER]);
+    }
+  } else {
+    PchSmmDisableSource (&mTimerSourceDesc[SWSMI_TIMER]);
+  }
+}
+
+/**
+  This services returns the next SMI tick period that is supported by the chipset.
+  The order returned is from longest to shortest interval period.
+
+  @param[in] This                 Pointer to the EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL instance.
+  @param[in, out] SmiTickInterval Pointer to pointer of the next shorter SMI interval period that is supported by the child.
+
+  @retval EFI_SUCCESS             The service returned successfully.
+  @retval EFI_INVALID_PARAMETER   The parameter SmiTickInterval is invalid.
+**/
+EFI_STATUS
+PchSmmPeriodicTimerDispatchGetNextShorterInterval (
+  IN CONST EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL  *This,
+  IN OUT   UINT64                                     **SmiTickInterval
+  )
+{
+  TIMER_INTERVAL  *IntervalPointer;
+
+  ASSERT (SmiTickInterval != NULL);
+  if (SmiTickInterval == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  IntervalPointer = (TIMER_INTERVAL *) *SmiTickInterval;
+
+  if (IntervalPointer == NULL) {
+    ///
+    /// The first time child requesting an interval
+    ///
+    IntervalPointer = &mSmmPeriodicTimerIntervals[0];
+  } else if (IntervalPointer == &mSmmPeriodicTimerIntervals[NUM_INTERVALS - 1]) {
+    ///
+    /// At end of the list
+    ///
+    IntervalPointer = NULL;
+  } else {
+    if ((IntervalPointer >= &mSmmPeriodicTimerIntervals[0]) &&
+        (IntervalPointer < &mSmmPeriodicTimerIntervals[NUM_INTERVALS - 1])
+        ) {
+      ///
+      /// Get the next interval in the list
+      ///
+      IntervalPointer++;
+    } else {
+      ///
+      /// Input is out of range
+      ///
+      return EFI_INVALID_PARAMETER;
+    }
+  }
+
+  if (IntervalPointer != NULL) {
+    *SmiTickInterval = &IntervalPointer->Interval;
+  } else {
+    *SmiTickInterval = NULL;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  This function is responsible for calculating and enabling any timers that are required
+  to dispatch messages to children. The SrcDesc argument isn't acutally used.
+
+  @param[in] SrcDesc              Pointer to the PCH_SMM_SOURCE_DESC instance.
+
+**/
+VOID
+EFIAPI
+PchSmmPeriodicTimerClearSource (
+  IN CONST PCH_SMM_SOURCE_DESC    *SrcDesc
+  )
+{
+  PchSmmPeriodicTimerProgramTimers (SrcDesc);
+}
+
+
+/**
+  Check if the handle is in type of PeriodicTimer
+
+  @retval TRUE                          The handle is in type of PeriodicTimer.
+  @retval FALSE                         The handle is not in type of PeriodicTimer.
+**/
+BOOLEAN
+IsSmmPeriodicTimerHandle (
+  IN EFI_HANDLE                         DispatchHandle
+  )
+{
+  DATABASE_RECORD                       *RecordInDb;
+  LIST_ENTRY                            *LinkInDb;
+
+  LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);
+  while (!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {
+    if (DispatchHandle == (EFI_HANDLE) LinkInDb) {
+      RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);
+      if (RecordInDb->ProtocolType == PeriodicTimerType) {
+        return TRUE;
+      }
+    }
+    LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, LinkInDb);
+  }
+  return FALSE;
+}
+
+/**
+  Pause SMM periodic timer callback function.
+
+  This function disable the SMI enable of SMI timer according to the DispatchHandle,
+  which is returned by SMM periodic timer callback registration.
+
+  @retval EFI_SUCCESS                   This operation is complete.
+  @retval EFI_INVALID_PARAMETER         The DispatchHandle is invalid.
+**/
+EFI_STATUS
+EFIAPI
+PchSmmPeriodicTimerControlPause (
+  IN PCH_SMM_PERIODIC_TIMER_CONTROL_PROTOCOL      *This,
+  IN EFI_HANDLE                                   DispatchHandle
+  )
+{
+  DATABASE_RECORD                       *RecordInDb;
+
+  if (IsSmmPeriodicTimerHandle (DispatchHandle) == FALSE) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  RecordInDb = DATABASE_RECORD_FROM_LINK (DispatchHandle);
+  RecordInDb->MiscData.TimerSmiEnabled = FALSE;
+  //
+  // reset the timer interval per SMI trigger due to stop a periodic timer SMI
+  //
+  PchSmmPeriodicTimerProgramTimers (&RecordInDb->SrcDesc);
+  return EFI_SUCCESS;
+}
+
+/**
+  Resume SMM periodic timer callback function.
+
+  This function enable the SMI enable of SMI timer according to the DispatchHandle,
+  which is returned by SMM periodic timer callback registration.
+
+  @retval EFI_SUCCESS                   This operation is complete.
+  @retval EFI_INVALID_PARAMETER         The DispatchHandle is invalid.
+**/
+EFI_STATUS
+EFIAPI
+PchSmmPeriodicTimerControlResume (
+  IN PCH_SMM_PERIODIC_TIMER_CONTROL_PROTOCOL      *This,
+  IN EFI_HANDLE                                   DispatchHandle
+  )
+{
+  DATABASE_RECORD                       *RecordInDb;
+
+  if (IsSmmPeriodicTimerHandle (DispatchHandle) == FALSE) {
+    return EFI_INVALID_PARAMETER;
+  }
+  RecordInDb = DATABASE_RECORD_FROM_LINK (DispatchHandle);
+  RecordInDb->MiscData.TimerSmiEnabled = TRUE;
+  //
+  // reset the timer interval per SMI trigger due to resume a periodic timer SMI
+  //
+  PchSmmPeriodicTimerProgramTimers (&RecordInDb->SrcDesc);
+  return EFI_SUCCESS;
+}
+
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_SMM_PERIODIC_TIMER_CONTROL_PROTOCOL mPchSmmPeriodicTimerControlProtocol = {
+  PchSmmPeriodicTimerControlPause,
+  PchSmmPeriodicTimerControlResume
+};
+
+/**
+  Install PCH SMM periodic timer control protocol
+
+  @param[in] Handle                     handle for this driver
+
+  @retval EFI_SUCCESS                   Driver initialization completed successfully
+**/
+EFI_STATUS
+EFIAPI
+InstallPchSmmPeriodicTimerControlProtocol (
+  IN EFI_HANDLE                         Handle
+  )
+{
+  EFI_STATUS                            Status;
+
+  //
+  // Install protocol interface
+  //
+  Status = gSmst->SmmInstallProtocolInterface (
+                    &Handle,
+                    &gPchSmmPeriodicTimerControlGuid,
+                    EFI_NATIVE_INTERFACE,
+                    &mPchSmmPeriodicTimerControlProtocol
+                    );
+  ASSERT_EFI_ERROR (Status);
+
+  return EFI_SUCCESS;
+}
+
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmPowerButton.c b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmPowerButton.c
new file mode 100644
index 0000000000..e6d3bf012f
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmPowerButton.c
@@ -0,0 +1,77 @@
+/** @file
+  File to contain all the hardware specific stuff for the Smm Power Button dispatch protocol.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <PchSmmHelpers.h>
+#include <Library/PmcPrivateLib.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mPowerButtonSourceDesc = {
+  PCH_SMM_SCI_EN_DEPENDENT,
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_PM1_EN}
+      },
+      S_ACPI_IO_PM1_EN,
+      N_ACPI_IO_PM1_EN_PWRBTN
+    },
+    NULL_BIT_DESC_INITIALIZER
+  },
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_PM1_STS}
+      },
+      S_ACPI_IO_PM1_STS,
+      N_ACPI_IO_PM1_STS_PWRBTN
+    }
+  },
+  {
+    {
+      ACPI_ADDR_TYPE,
+      {R_ACPI_IO_SMI_STS}
+    },
+    S_ACPI_IO_SMI_STS,
+    N_ACPI_IO_SMI_STS_PM1_STS_REG
+  }
+};
+
+/**
+  Get the power button status.
+
+  @param[in] Record               The pointer to the DATABASE_RECORD.
+  @param[out] Context             Calling context from the hardware, will be updated with the current power button status.
+
+**/
+VOID
+EFIAPI
+PowerButtonGetContext (
+  IN  DATABASE_RECORD    *Record,
+  OUT PCH_SMM_CONTEXT    *Context
+  )
+{
+  return;
+}
+
+/**
+  Check whether Power Button status of two contexts match
+
+  @param[in] Context1             Context 1 that includes Power Button status 1
+  @param[in] Context2             Context 2 that includes Power Button status 2
+
+  @retval FALSE                   Power Button status match
+  @retval TRUE                    Power Button status don't match
+**/
+BOOLEAN
+EFIAPI
+PowerButtonCmpContext (
+  IN PCH_SMM_CONTEXT     *Context1,
+  IN PCH_SMM_CONTEXT     *Context2
+  )
+{
+ return TRUE;
+}
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmSw.c b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmSw.c
new file mode 100644
index 0000000000..311a21820c
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmSw.c
@@ -0,0 +1,381 @@
+/** @file
+  File to contain all the hardware specific stuff for the Smm Sw dispatch protocol.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "PchSmmHelpers.h"
+#include <Protocol/SmmCpu.h>
+#include <Register/PchRegsLpc.h>
+#include <Register/PmcRegs.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_CPU_PROTOCOL          *mSmmCpuProtocol;
+
+STATIC LIST_ENTRY                       mSwSmiCallbackDataBase;
+
+//
+// "SWSMI" RECORD
+// Linked list data structures
+//
+#define SW_SMI_RECORD_SIGNATURE         SIGNATURE_32 ('S', 'W', 'S', 'M')
+
+#define SW_SMI_RECORD_FROM_LINK(_record)  CR (_record, SW_SMI_RECORD, Link, SW_SMI_RECORD_SIGNATURE)
+
+typedef struct {
+  UINT32                                Signature;
+  LIST_ENTRY                            Link;
+  EFI_SMM_SW_REGISTER_CONTEXT           Context;
+  EFI_SMM_HANDLER_ENTRY_POINT2          Callback;
+} SW_SMI_RECORD;
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSwSourceDesc = {
+  PCH_SMM_NO_FLAGS,
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_EN}
+      },
+      S_ACPI_IO_SMI_EN,
+      N_ACPI_IO_SMI_EN_APMC
+    },
+    NULL_BIT_DESC_INITIALIZER
+  },
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_STS}
+      },
+      S_ACPI_IO_SMI_STS,
+      N_ACPI_IO_SMI_STS_APM
+    }
+  },
+  {
+    {
+      ACPI_ADDR_TYPE,
+      {R_ACPI_IO_SMI_STS}
+    },
+    S_ACPI_IO_SMI_STS,
+    N_ACPI_IO_SMI_STS_APM
+  }
+};
+
+/**
+  Check the SwSmiInputValue to see if there is a duplicated one in the database
+
+  @param[in] SwSmiInputValue      SwSmiInputValue
+
+  @retval EFI_SUCCESS             There is no duplicated SwSmiInputValue
+  @retval EFI_INVALID_PARAMETER   There is a duplicated SwSmiInputValue
+**/
+EFI_STATUS
+SmiInputValueDuplicateCheck (
+  IN UINTN  SwSmiInputValue
+  )
+{
+  SW_SMI_RECORD   *SwSmiRecord;
+  LIST_ENTRY      *LinkInDb;
+
+  LinkInDb = GetFirstNode (&mSwSmiCallbackDataBase);
+  while (!IsNull (&mSwSmiCallbackDataBase, LinkInDb)) {
+    SwSmiRecord = SW_SMI_RECORD_FROM_LINK (LinkInDb);
+    if (SwSmiRecord->Context.SwSmiInputValue == SwSmiInputValue) {
+      return EFI_INVALID_PARAMETER;
+    }
+    LinkInDb = GetNextNode (&mSwSmiCallbackDataBase, &SwSmiRecord->Link);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Register a child SMI source dispatch function for the specified software SMI.
+
+  This service registers a function (DispatchFunction) which will be called when the software
+  SMI source specified by RegisterContext->SwSmiCpuIndex is detected. On return,
+  DispatchHandle contains a unique handle which may be used later to unregister the function
+  using UnRegister().
+
+  @param[in]  This                 Pointer to the EFI_SMM_SW_DISPATCH2_PROTOCOL instance.
+  @param[in]  DispatchFunction     Function to register for handler when the specified software
+                                   SMI is generated.
+  @param[in, out] RegisterContext  Pointer to the dispatch function's context.
+                                   The caller fills this context in before calling
+                                   the register function to indicate to the register
+                                   function which Software SMI input value the
+                                   dispatch function should be invoked for.
+  @param[out] DispatchHandle       Handle generated by the dispatcher to track the
+                                   function instance.
+
+  @retval EFI_SUCCESS            The dispatch function has been successfully
+                                 registered and the SMI source has been enabled.
+  @retval EFI_DEVICE_ERROR       The SW driver was unable to enable the SMI source.
+  @retval EFI_INVALID_PARAMETER  RegisterContext is invalid. The SW SMI input value
+                                 is not within a valid range or is already in use.
+  @retval EFI_OUT_OF_RESOURCES   There is not enough memory (system or SMM) to manage this
+                                 child.
+  @retval EFI_OUT_OF_RESOURCES   A unique software SMI value could not be assigned
+                                 for this dispatch.
+**/
+EFI_STATUS
+EFIAPI
+PchSwSmiRegister (
+  IN  EFI_SMM_SW_DISPATCH2_PROTOCOL       *This,
+  IN  EFI_SMM_HANDLER_ENTRY_POINT2        DispatchFunction,
+  IN  EFI_SMM_SW_REGISTER_CONTEXT         *DispatchContext,
+  OUT EFI_HANDLE                          *DispatchHandle
+  )
+{
+  EFI_STATUS       Status;
+  SW_SMI_RECORD    *SwSmiRecord;
+  UINTN            Index;
+
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  //
+  // Find available SW SMI value if the input is -1
+  //
+  if (DispatchContext->SwSmiInputValue == (UINTN) -1) {
+    for (Index = 1; Index < MAXIMUM_SWI_VALUE; Index++) {
+      if (!EFI_ERROR (SmiInputValueDuplicateCheck (Index))) {
+        DispatchContext->SwSmiInputValue = Index;
+        break;
+      }
+    }
+    if (DispatchContext->SwSmiInputValue == (UINTN) -1) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+  }
+  //
+  // Check if it's a valid SW SMI value.
+  // The value must not bigger than 0xFF.
+  // And the value must not be 0xFF sincie it's used for SmmControll protocol.
+  //
+  if (DispatchContext->SwSmiInputValue >= MAXIMUM_SWI_VALUE) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (EFI_ERROR (SmiInputValueDuplicateCheck (DispatchContext->SwSmiInputValue))) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Create database record and add to database
+  //
+  Status = gSmst->SmmAllocatePool (
+                    EfiRuntimeServicesData,
+                    sizeof (SW_SMI_RECORD),
+                    (VOID **) &SwSmiRecord
+                    );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Failed to allocate memory for SwSmiRecord! \n"));
+    return EFI_OUT_OF_RESOURCES;
+  }
+  //
+  // Gather information about the registration request
+  //
+  SwSmiRecord->Signature               = SW_SMI_RECORD_SIGNATURE;
+  SwSmiRecord->Context.SwSmiInputValue = DispatchContext->SwSmiInputValue;
+  SwSmiRecord->Callback                = DispatchFunction;
+  //
+  // Publish the S/W SMI numbers in Serial logs used for Debug build.
+  //
+  DEBUG ((DEBUG_INFO, "SW SMI NUM %x  Sw Record at Address 0x%X\n", SwSmiRecord->Context.SwSmiInputValue, SwSmiRecord));
+
+  InsertTailList (&mSwSmiCallbackDataBase, &SwSmiRecord->Link);
+
+  //
+  // Child's handle will be the address linked list link in the record
+  //
+  *DispatchHandle = (EFI_HANDLE) (&SwSmiRecord->Link);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Unregister a child SMI source dispatch function for the specified software SMI.
+
+  This service removes the handler associated with DispatchHandle so that it will no longer be
+  called in response to a software SMI.
+
+  @param[in] This                Pointer to the EFI_SMM_SW_DISPATCH2_PROTOCOL instance.
+  @param[in] DispatchHandle      Handle of dispatch function to deregister.
+
+  @retval EFI_SUCCESS            The dispatch function has been successfully unregistered.
+  @retval EFI_INVALID_PARAMETER  The DispatchHandle was not valid.
+**/
+EFI_STATUS
+EFIAPI
+PchSwSmiUnRegister (
+  IN CONST EFI_SMM_SW_DISPATCH2_PROTOCOL  *This,
+  IN       EFI_HANDLE                     DispatchHandle
+  )
+{
+  EFI_STATUS            Status;
+  SW_SMI_RECORD         *RecordToDelete;
+
+  if (DispatchHandle == 0) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "UnRegister is not allowed if the SmmReadyToLock event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  RecordToDelete = SW_SMI_RECORD_FROM_LINK (DispatchHandle);
+  //
+  // Take the entry out of the linked list
+  //
+  if (RecordToDelete->Signature != SW_SMI_RECORD_SIGNATURE) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  RemoveEntryList (&RecordToDelete->Link);
+  ZeroMem (RecordToDelete, sizeof (SW_SMI_RECORD));
+  Status = gSmst->SmmFreePool (RecordToDelete);
+  ASSERT_EFI_ERROR (Status);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Main entry point for an SMM handler dispatch or communicate-based callback.
+
+  @param[in]     DispatchHandle  The unique handle assigned to this handler by SmiHandlerRegister().
+  @param[in]     Context         Points to an optional handler context which was specified when the
+                                 handler was registered.
+  @param[in,out] CommBuffer      A pointer to a collection of data in memory that will
+                                 be conveyed from a non-SMM environment into an SMM environment.
+  @param[in,out] CommBufferSize  The size of the CommBuffer.
+
+  @retval EFI_SUCCESS                         The interrupt was handled and quiesced. No other handlers
+                                              should still be called.
+  @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED  The interrupt has been quiesced but other handlers should
+                                              still be called.
+  @retval EFI_WARN_INTERRUPT_SOURCE_PENDING   The interrupt is still pending and other handlers should still
+                                              be called.
+  @retval EFI_INTERRUPT_PENDING               The interrupt could not be quiesced.
+**/
+EFI_STATUS
+EFIAPI
+PchSwSmiDispatcher (
+  IN       EFI_HANDLE         DispatchHandle,
+  IN CONST VOID               *Context,
+  IN OUT   VOID               *CommBuffer,
+  IN OUT   UINTN              *CommBufferSize
+  )
+{
+  EFI_STATUS                            Status;
+  EFI_SMM_SAVE_STATE_IO_INFO            SmiIoInfo;
+  UINTN                                 CpuIndex;
+  SW_SMI_RECORD                         *SwSmiRecord;
+  LIST_ENTRY                            *LinkInDb;
+  EFI_SMM_SW_CONTEXT                    SwSmiCommBuffer;
+  UINTN                                 SwSmiCommBufferSize;
+
+  SwSmiCommBufferSize      = sizeof (EFI_SMM_SW_CONTEXT);
+  //
+  // The value in DataPort might not be accurate in multiple thread environment.
+  // There might be racing condition for R_PCH_IO_APM_STS port.
+  // Therefor, this is just for reference.
+  //
+  SwSmiCommBuffer.DataPort = IoRead8 (R_PCH_IO_APM_STS);
+
+  for (CpuIndex = 0; CpuIndex < gSmst->NumberOfCpus; CpuIndex++) {
+    Status = mSmmCpuProtocol->ReadSaveState (
+                                mSmmCpuProtocol,
+                                sizeof (EFI_SMM_SAVE_STATE_IO_INFO),
+                                EFI_SMM_SAVE_STATE_REGISTER_IO,
+                                CpuIndex,
+                                &SmiIoInfo
+                                );
+    //
+    // If this is not the SMI source, skip it.
+    //
+    if (EFI_ERROR (Status)) {
+      continue;
+    }
+    //
+    // If the IO address is not "BYTE" "WRITE" to "R_PCH_IO_APM_CNT (0xB2)", skip it.
+    //
+    if ((SmiIoInfo.IoPort != R_PCH_IO_APM_CNT) ||
+        (SmiIoInfo.IoType != EFI_SMM_SAVE_STATE_IO_TYPE_OUTPUT) ||
+        (SmiIoInfo.IoWidth != EFI_SMM_SAVE_STATE_IO_WIDTH_UINT8))
+    {
+      continue;
+    }
+    //
+    // If the IO data is used for SmmControl protocol, skip it.
+    //
+    if (SmiIoInfo.IoData == 0xFF) {
+      continue;
+    }
+
+    SwSmiCommBuffer.SwSmiCpuIndex = CpuIndex;
+    SwSmiCommBuffer.CommandPort   = (UINT8) SmiIoInfo.IoData;
+
+    LinkInDb = GetFirstNode (&mSwSmiCallbackDataBase);
+    while (!IsNull (&mSwSmiCallbackDataBase, LinkInDb)) {
+      SwSmiRecord = SW_SMI_RECORD_FROM_LINK (LinkInDb);
+      if (SwSmiRecord->Context.SwSmiInputValue == SmiIoInfo.IoData) {
+        SwSmiRecord->Callback ((EFI_HANDLE) &SwSmiRecord->Link, &SwSmiRecord->Context, &SwSmiCommBuffer, &SwSmiCommBufferSize);
+      }
+      LinkInDb = GetNextNode (&mSwSmiCallbackDataBase, &SwSmiRecord->Link);
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Init required protocol for Pch Sw Dispatch protocol.
+**/
+VOID
+PchSwDispatchInit (
+  VOID
+  )
+{
+  EFI_STATUS                            Status;
+  EFI_HANDLE                            DispatchHandle;
+  DATABASE_RECORD                       Record;
+
+  //
+  // Locate PI SMM CPU protocol
+  //
+  Status = gSmst->SmmLocateProtocol (&gEfiSmmCpuProtocolGuid, NULL, (VOID **)&mSmmCpuProtocol);
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Initialize SW SMI Callback DataBase
+  //
+  InitializeListHead (&mSwSmiCallbackDataBase);
+
+  //
+  // Insert SwSmi handler to PchSmmCore database
+  // There will always be one SwType record in PchSmmCore database
+  //
+  ZeroMem (&Record, sizeof (DATABASE_RECORD));
+  Record.Signature    = DATABASE_RECORD_SIGNATURE;
+  Record.Callback     = PchSwSmiDispatcher;
+  Record.ProtocolType = SwType;
+
+  CopyMem (&Record.SrcDesc, &mSwSourceDesc, sizeof (PCH_SMM_SOURCE_DESC));
+
+  DispatchHandle      = NULL;
+  Status = SmmCoreInsertRecord (
+             &Record,
+             &DispatchHandle
+             );
+  ASSERT_EFI_ERROR (Status);
+}
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmSx.c b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmSx.c
new file mode 100644
index 0000000000..798fb33347
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmSx.c
@@ -0,0 +1,117 @@
+/** @file
+  File to contain all the hardware specific stuff for the Smm Sx dispatch protocol.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "PchSmmHelpers.h"
+#include <Register/PmcRegs.h>
+#include "PchSmiHelper.h"
+
+extern BOOLEAN               mS3SusStart;
+#define PROGRESS_CODE_S3_SUSPEND_END  PcdGet32 (PcdProgressCodeS3SuspendEnd)
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSxSourceDesc = {
+  PCH_SMM_NO_FLAGS,
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_EN}
+      },
+      S_ACPI_IO_SMI_EN,
+      N_ACPI_IO_SMI_EN_ON_SLP_EN
+    },
+    NULL_BIT_DESC_INITIALIZER
+  },
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_STS}
+      },
+      S_ACPI_IO_SMI_STS,
+      N_ACPI_IO_SMI_STS_ON_SLP_EN
+    }
+  },
+  {
+    {
+      ACPI_ADDR_TYPE,
+      {R_ACPI_IO_SMI_STS}
+    },
+    S_ACPI_IO_SMI_STS,
+    N_ACPI_IO_SMI_STS_ON_SLP_EN
+  }
+};
+
+/**
+  Get the Sleep type
+
+  @param[in] Record               No use
+  @param[out] Context             The context that includes SLP_TYP bits to be filled
+
+**/
+VOID
+EFIAPI
+SxGetContext (
+  IN  DATABASE_RECORD    *Record,
+  OUT PCH_SMM_CONTEXT    *Context
+  )
+{
+  UINT32  Pm1Cnt;
+
+  Pm1Cnt = IoRead32 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_PM1_CNT));
+
+  ///
+  /// By design, the context phase will always be ENTRY
+  ///
+  Context->Sx.Phase = SxEntry;
+
+  ///
+  /// Map the PM1_CNT register's SLP_TYP bits to the context type
+  ///
+  switch (Pm1Cnt & B_ACPI_IO_PM1_CNT_SLP_TYP) {
+    case V_ACPI_IO_PM1_CNT_S0:
+      Context->Sx.Type = SxS0;
+      break;
+
+    case V_ACPI_IO_PM1_CNT_S1:
+      Context->Sx.Type = SxS1;
+      break;
+
+    case V_ACPI_IO_PM1_CNT_S3:
+      Context->Sx.Type = SxS3;
+      break;
+
+    case V_ACPI_IO_PM1_CNT_S4:
+      Context->Sx.Type = SxS4;
+      break;
+
+    case V_ACPI_IO_PM1_CNT_S5:
+      Context->Sx.Type = SxS5;
+      break;
+
+    default:
+      ASSERT (FALSE);
+      break;
+  }
+}
+
+/**
+  Check whether sleep type of two contexts match
+
+  @param[in] Context1             Context 1 that includes sleep type 1
+  @param[in] Context2             Context 2 that includes sleep type 2
+
+  @retval FALSE                   Sleep types match
+  @retval TRUE                    Sleep types don't match
+**/
+BOOLEAN
+EFIAPI
+SxCmpContext (
+  IN PCH_SMM_CONTEXT     *Context1,
+  IN PCH_SMM_CONTEXT     *Context2
+  )
+{
+  return (BOOLEAN) (Context1->Sx.Type == Context2->Sx.Type);
+}
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmUsb.c b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmUsb.c
new file mode 100644
index 0000000000..6b23956c4a
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmUsb.c
@@ -0,0 +1,244 @@
+/** @file
+  File to contain all the hardware specific stuff for the Smm USB dispatch protocol.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "PchSmmHelpers.h"
+#include <Register/PmcRegs.h>
+#include <Library/PchPciBdfLib.h>
+
+typedef enum {
+  PchUsbControllerLpc0 = 0,
+  PchUsbControllerXhci,
+  PchUsbControllerTypeMax
+} PCH_USB_CONTROLLER_TYPE;
+
+typedef struct {
+  UINT8                   Function;
+  UINT8                   Device;
+  PCH_USB_CONTROLLER_TYPE UsbConType;
+} PCH_USB_CONTROLLER;
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mUsb1Legacy = {
+  PCH_SMM_NO_FLAGS,
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_EN}
+      },
+      S_ACPI_IO_SMI_EN,
+      N_ACPI_IO_SMI_EN_LEGACY_USB
+    },
+    NULL_BIT_DESC_INITIALIZER
+  },
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_STS}
+      },
+      S_ACPI_IO_SMI_STS,
+      N_ACPI_IO_SMI_STS_LEGACY_USB
+    }
+  },
+  {
+    {
+      ACPI_ADDR_TYPE,
+      {R_ACPI_IO_SMI_STS}
+    },
+    S_ACPI_IO_SMI_STS,
+    N_ACPI_IO_SMI_STS_LEGACY_USB
+  }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mUsb3Legacy = {
+  PCH_SMM_NO_FLAGS,
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_EN}
+      },
+      S_ACPI_IO_SMI_EN,
+      N_ACPI_IO_SMI_EN_LEGACY_USB3
+    },
+    NULL_BIT_DESC_INITIALIZER
+  },
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_STS}
+      },
+      S_ACPI_IO_SMI_STS,
+      N_ACPI_IO_SMI_STS_LEGACY_USB3
+    }
+  },
+  {
+    {
+      ACPI_ADDR_TYPE,
+      {R_ACPI_IO_SMI_STS}
+    },
+    S_ACPI_IO_SMI_STS,
+    N_ACPI_IO_SMI_STS_LEGACY_USB3
+  }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_USB_CONTROLLER  mUsbControllersMap[] = {
+  {
+    0xFF, // to be updated in PchSmmUsbUpdateDescriptors
+    0xFF, // to be updated in PchSmmUsbUpdateDescriptors
+    PchUsbControllerLpc0
+  },
+  {
+    0xFF, // to be updated in PchSmmUsbUpdateDescriptors
+    0xFF, // to be updated in PchSmmUsbUpdateDescriptors
+    PchUsbControllerXhci
+  }
+};
+
+/**
+  Performs update of SmmUsb descriptors with values that have to be evaluated during runtime.
+**/
+VOID
+PchSmmUsbUpdateDescriptors (
+  VOID
+  )
+{
+  //
+  // mUsbControllersMap
+  //
+  mUsbControllersMap[0].Function  = LpcFuncNumber ();
+  mUsbControllersMap[0].Device    = LpcDevNumber ();
+  mUsbControllersMap[1].Function  = PchXhciFuncNumber ();
+  mUsbControllersMap[1].Device    = PchXhciDevNumber ();
+}
+
+/**
+  Find the handle that best matches the input Device Path and return the USB controller type
+
+  @param[in] DevicePath           Pointer to the device Path table
+  @param[out] Controller          Returned with the USB controller type of the input device path
+
+  @retval EFI_SUCCESS             Find the handle that best matches the input Device Path
+  @exception EFI_UNSUPPORTED      Invalid device Path table or can't find any match USB device path
+                                  PCH_USB_CONTROLLER_TYPE The USB controller type of the input
+                                  device path
+**/
+EFI_STATUS
+DevicePathToSupportedController (
+  IN  EFI_DEVICE_PATH_PROTOCOL   *DevicePath,
+  OUT PCH_USB_CONTROLLER_TYPE    *Controller
+  )
+{
+  EFI_STATUS                Status;
+  EFI_HANDLE                DeviceHandle;
+  ACPI_HID_DEVICE_PATH      *AcpiNode;
+  PCI_DEVICE_PATH           *PciNode;
+  EFI_DEVICE_PATH_PROTOCOL  *RemaingDevicePath;
+  UINT8                     UsbIndex;
+  ///
+  /// Find the handle that best matches the Device Path. If it is only a
+  /// partial match the remaining part of the device path is returned in
+  /// RemainingDevicePath.
+  ///
+  RemaingDevicePath = DevicePath;
+  Status = gBS->LocateDevicePath (
+                  &gEfiPciRootBridgeIoProtocolGuid,
+                  &DevicePath,
+                  &DeviceHandle
+                  );
+  if (EFI_ERROR (Status)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  DevicePath = RemaingDevicePath;
+
+  ///
+  /// Get first node: Acpi Node
+  ///
+  AcpiNode = (ACPI_HID_DEVICE_PATH *) RemaingDevicePath;
+
+  if (AcpiNode->Header.Type != ACPI_DEVICE_PATH ||
+      AcpiNode->Header.SubType != ACPI_DP ||
+      DevicePathNodeLength (&AcpiNode->Header) != sizeof (ACPI_HID_DEVICE_PATH) ||
+      AcpiNode->HID != EISA_PNP_ID (0x0A03) ||
+      AcpiNode->UID != 0
+      ) {
+    return EFI_UNSUPPORTED;
+  } else {
+    ///
+    /// Get the next node: Pci Node
+    ///
+    RemaingDevicePath = NextDevicePathNode (RemaingDevicePath);
+    PciNode           = (PCI_DEVICE_PATH *) RemaingDevicePath;
+    if (PciNode->Header.Type != HARDWARE_DEVICE_PATH ||
+        PciNode->Header.SubType != HW_PCI_DP ||
+        DevicePathNodeLength (&PciNode->Header) != sizeof (PCI_DEVICE_PATH)
+        ) {
+      return EFI_UNSUPPORTED;
+    }
+
+    for (UsbIndex = 0; UsbIndex < sizeof (mUsbControllersMap) / sizeof (PCH_USB_CONTROLLER); UsbIndex++) {
+      if ((PciNode->Device == mUsbControllersMap[UsbIndex].Device) &&
+          (PciNode->Function == mUsbControllersMap[UsbIndex].Function)) {
+        *Controller = mUsbControllersMap[UsbIndex].UsbConType;
+        return EFI_SUCCESS;
+      }
+    }
+
+    return EFI_UNSUPPORTED;
+  }
+}
+
+/**
+  Maps a USB context to a source description.
+
+  @param[in] Context              The context we need to map.  Type must be USB.
+  @param[in] SrcDesc              The source description that corresponds to the given context.
+
+**/
+VOID
+MapUsbToSrcDesc (
+  IN  PCH_SMM_CONTEXT         *Context,
+  OUT PCH_SMM_SOURCE_DESC     *SrcDesc
+  )
+{
+  PCH_USB_CONTROLLER_TYPE Controller;
+  EFI_STATUS              Status;
+
+  Status = DevicePathToSupportedController (Context->Usb.Device, &Controller);
+  ///
+  /// Either the device path passed in by the child is incorrect or
+  /// the ones stored here internally are incorrect.
+  ///
+  ASSERT_EFI_ERROR (Status);
+
+  switch (Context->Usb.Type) {
+    case UsbLegacy:
+      switch (Controller) {
+        case PchUsbControllerLpc0:
+          CopyMem ((VOID *) SrcDesc, (VOID *) (&mUsb1Legacy), sizeof (PCH_SMM_SOURCE_DESC));
+          break;
+
+        case PchUsbControllerXhci:
+          CopyMem ((VOID *) SrcDesc, (VOID *) (&mUsb3Legacy), sizeof (PCH_SMM_SOURCE_DESC));
+          break;
+
+        default:
+          ASSERT (FALSE);
+          break;
+      }
+      break;
+
+    case UsbWake:
+      ASSERT (FALSE);
+      break;
+
+    default:
+      ASSERT (FALSE);
+      break;
+  }
+}
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.c b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.c
new file mode 100644
index 0000000000..c0ce5785fd
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.c
@@ -0,0 +1,682 @@
+/** @file
+  This driver is responsible for the registration of child drivers
+  and the abstraction of the PCH SMI sources.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "PchSmmHelpers.h"
+#include <Register/PchRegs.h>
+#include <Register/PmcRegs.h>
+#include <Register/TcoRegs.h>
+
+extern UINT32 mTco1StsClear;
+//
+// Help handle porting bit shifts to IA-64.
+//
+#define BIT_ZERO  0x00000001
+
+/**
+  Publish SMI Dispatch protocols.
+
+
+**/
+VOID
+PchSmmPublishDispatchProtocols (
+  VOID
+  )
+{
+  EFI_STATUS Status = EFI_SUCCESS;
+  UINTN      Index;
+  //
+  // Install protocol interfaces.
+  //
+  for (Index = 0; Index < PCH_SMM_PROTOCOL_TYPE_MAX; Index++) {
+    Status = gSmst->SmmInstallProtocolInterface (
+                      &mPrivateData.InstallMultProtHandle,
+                      mPrivateData.Protocols[Index].Guid,
+                      EFI_NATIVE_INTERFACE,
+                      &mPrivateData.Protocols[Index].Protocols.Generic
+                      );
+  }
+  ASSERT_EFI_ERROR (Status);
+}
+
+/**
+  Initialize bits that aren't necessarily related to an SMI source.
+
+
+  @retval EFI_SUCCESS             SMI source initialization completed.
+  @retval Asserts                 Global Smi Bit is not enabled successfully.
+**/
+EFI_STATUS
+PchSmmInitHardware (
+  VOID
+  )
+{
+  EFI_STATUS  Status;
+
+  //
+  // Clear all SMIs
+  //
+  PchSmmClearSmi ();
+
+  Status = PchSmmEnableGlobalSmiBit ();
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Be *really* sure to clear all SMIs
+  //
+  PchSmmClearSmi ();
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Enables the PCH to generate SMIs. Note that no SMIs will be generated
+  if no SMI sources are enabled. Conversely, no enabled SMI source will
+  generate SMIs if SMIs are not globally enabled. This is the main
+  switchbox for SMI generation.
+
+
+  @retval EFI_SUCCESS             Enable Global Smi Bit completed
+**/
+EFI_STATUS
+PchSmmEnableGlobalSmiBit (
+  VOID
+  )
+{
+  UINT32  SmiEn;
+
+  SmiEn = IoRead32 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_SMI_EN));
+
+  //
+  // Set the "global smi enable" bit
+  //
+  SmiEn |= B_ACPI_IO_SMI_EN_GBL_SMI;
+
+  IoWrite32 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_SMI_EN), SmiEn);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Clears the SMI after all SMI source have been processed.
+  Note that this function will not work correctly (as it is
+  written) unless all SMI sources have been processed.
+  A revision of this function could manually clear all SMI
+  status bits to guarantee success.
+
+
+  @retval EFI_SUCCESS             Clears the SMIs completed
+  @retval Asserts                 EOS was not set to a 1
+**/
+EFI_STATUS
+PchSmmClearSmi (
+  VOID
+  )
+{
+  return EFI_SUCCESS;
+}
+
+/**
+  Set the SMI EOS bit after all SMI source have been processed.
+
+
+  @retval FALSE                   EOS was not set to a 1; this is an error
+  @retval TRUE                    EOS was correctly set to a 1
+**/
+BOOLEAN
+PchSmmSetAndCheckEos (
+  VOID
+  )
+{
+  UINT32  SmiEn;
+
+  SmiEn = IoRead32 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_SMI_EN));
+
+  //
+  // Reset the PCH to generate subsequent SMIs
+  //
+  SmiEn |= B_ACPI_IO_SMI_EN_EOS;
+
+  IoWrite32 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_SMI_EN), SmiEn);
+
+  //
+  // Double check that the assert worked
+  //
+  SmiEn = IoRead32 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_SMI_EN));
+
+  //
+  // Return TRUE if EOS is set correctly
+  //
+  if ((SmiEn & B_ACPI_IO_SMI_EN_EOS) == 0) {
+    //
+    // EOS was not set to a 1; this is an error
+    //
+    return FALSE;
+  } else {
+    //
+    // EOS was correctly set to a 1
+    //
+    return TRUE;
+  }
+}
+
+/**
+  Determine whether an ACPI OS is present (via the SCI_EN bit)
+
+
+  @retval TRUE                    ACPI OS is present
+  @retval FALSE                   ACPI OS is not present
+**/
+BOOLEAN
+PchSmmGetSciEn (
+  VOID
+  )
+{
+  BOOLEAN SciEn;
+  UINT32  Pm1Cnt;
+
+  //
+  // Determine whether an ACPI OS is present (via the SCI_EN bit)
+  //
+  Pm1Cnt  = IoRead32 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_PM1_CNT));
+  SciEn   = (BOOLEAN) ((Pm1Cnt & B_ACPI_IO_PM1_CNT_SCI_EN) == B_ACPI_IO_PM1_CNT_SCI_EN);
+
+  return SciEn;
+}
+
+/**
+  Read a specifying bit with the register
+  These may or may not need to change w/ the PCH version; they're highly IA-32 dependent, though.
+
+  @param[in] BitDesc              The struct that includes register address, size in byte and bit number
+
+  @retval TRUE                    The bit is enabled
+  @retval FALSE                   The bit is disabled
+**/
+BOOLEAN
+ReadBitDesc (
+  CONST PCH_SMM_BIT_DESC  *BitDesc
+  )
+{
+  EFI_STATUS  Status;
+  UINT64      Register;
+  UINT32      PciBus;
+  UINT32      PciDev;
+  UINT32      PciFun;
+  UINT32      PciReg;
+  UINTN       RegSize;
+  BOOLEAN     BitWasOne;
+  UINTN       ShiftCount;
+  UINTN       RegisterOffset;
+  UINT32      BaseAddr;
+  UINT64      PciBaseAddress;
+
+  ASSERT (BitDesc != NULL);
+  if (BitDesc == NULL) {
+    return FALSE;
+  }
+  ASSERT (!IS_BIT_DESC_NULL (*BitDesc));
+
+  RegSize     = 0;
+  Register    = 0;
+  ShiftCount  = 0;
+  BitWasOne   = FALSE;
+
+  switch (BitDesc->Reg.Type) {
+
+    case ACPI_ADDR_TYPE:
+    case TCO_ADDR_TYPE:
+      if (BitDesc->Reg.Type == ACPI_ADDR_TYPE) {
+        RegisterOffset  = BitDesc->Reg.Data.acpi;
+        BaseAddr        = mAcpiBaseAddr;
+      } else {
+        RegisterOffset  = BitDesc->Reg.Data.tco;
+        BaseAddr        = mTcoBaseAddr;
+      }
+      switch (BitDesc->SizeInBytes) {
+
+        case 0:
+          //
+          // Chances are that this field didn't get initialized.
+          // Check your assignments to bit descriptions.
+          //
+          ASSERT (FALSE);
+          break;
+
+        case 1:
+          RegSize = SMM_IO_UINT8;
+          break;
+
+        case 2:
+          RegSize = SMM_IO_UINT16;
+          break;
+
+        case 4:
+          RegSize = SMM_IO_UINT32;
+          break;
+
+        case 8:
+          RegSize = SMM_IO_UINT64;
+          break;
+
+        default:
+          //
+          // Unsupported or invalid register size
+          //
+          ASSERT (FALSE);
+          break;
+      }
+      //
+      // Double check that we correctly read in the acpi base address
+      //
+      ASSERT ((BaseAddr != 0x0) && ((BaseAddr & 0x1) != 0x1));
+
+      ShiftCount      = BitDesc->Bit;
+      //
+      // As current CPU Smm Io can only support at most
+      // 32-bit read/write,if Operation is 64 bit,
+      // we do a 32 bit operation according to BitDesc->Bit
+      //
+      if (RegSize == SMM_IO_UINT64) {
+        RegSize = SMM_IO_UINT32;
+        //
+        // If the operation is for high 32 bits
+        //
+        if (BitDesc->Bit >= 32) {
+          RegisterOffset += 4;
+          ShiftCount -= 32;
+        }
+      }
+
+      Status = gSmst->SmmIo.Io.Read (
+                                 &gSmst->SmmIo,
+                                 RegSize,
+                                 BaseAddr + RegisterOffset,
+                                 1,
+                                 &Register
+                                 );
+      ASSERT_EFI_ERROR (Status);
+
+      if ((Register & (LShiftU64 (BIT_ZERO, ShiftCount))) != 0) {
+        BitWasOne = TRUE;
+      } else {
+        BitWasOne = FALSE;
+      }
+      break;
+
+    case GPIO_ADDR_TYPE:
+    case MEMORY_MAPPED_IO_ADDRESS_TYPE:
+      //
+      // Read the register, and it with the bit to read
+      //
+      switch (BitDesc->SizeInBytes) {
+        case 1:
+          Register = (UINT64) MmioRead8 ((UINTN) BitDesc->Reg.Data.Mmio);
+          break;
+
+        case 2:
+          Register = (UINT64) MmioRead16 ((UINTN) BitDesc->Reg.Data.Mmio);
+          break;
+
+        case 4:
+          Register = (UINT64) MmioRead32 ((UINTN) BitDesc->Reg.Data.Mmio);
+          break;
+
+        case 8:
+          Register                      = (UINT64) MmioRead32 ((UINTN) BitDesc->Reg.Data.Mmio);
+          *((UINT32 *) (&Register) + 1) = MmioRead32 ((UINTN) BitDesc->Reg.Data.Mmio + 4);
+          break;
+
+        default:
+          //
+          // Unsupported or invalid register size
+          //
+          ASSERT (FALSE);
+          break;
+      }
+
+      Register = Register & (LShiftU64 (BIT0, BitDesc->Bit));
+      if (Register) {
+        BitWasOne = TRUE;
+      } else {
+        BitWasOne = FALSE;
+      }
+      break;
+
+    case PCIE_ADDR_TYPE:
+      PciBus  = BitDesc->Reg.Data.pcie.Fields.Bus;
+      PciDev  = BitDesc->Reg.Data.pcie.Fields.Dev;
+      PciFun  = BitDesc->Reg.Data.pcie.Fields.Fnc;
+      PciReg  = BitDesc->Reg.Data.pcie.Fields.Reg;
+      PciBaseAddress = PCI_SEGMENT_LIB_ADDRESS (DEFAULT_PCI_SEGMENT_NUMBER_PCH, PciBus, PciDev, PciFun, 0);
+      switch (BitDesc->SizeInBytes) {
+
+        case 0:
+          //
+          // Chances are that this field didn't get initialized.
+          // Check your assignments to bit descriptions.
+          //
+          ASSERT (FALSE);
+          break;
+
+        case 1:
+          Register = (UINT64) PciSegmentRead8 (PciBaseAddress + PciReg);
+          break;
+
+        case 2:
+          Register = (UINT64) PciSegmentRead16 (PciBaseAddress + PciReg);
+          break;
+
+        case 4:
+          Register = (UINT64) PciSegmentRead32 (PciBaseAddress + PciReg);
+          break;
+
+        default:
+          //
+          // Unsupported or invalid register size
+          //
+          ASSERT (FALSE);
+          break;
+      }
+
+      if ((Register & (LShiftU64 (BIT_ZERO, BitDesc->Bit))) != 0) {
+        BitWasOne = TRUE;
+      } else {
+        BitWasOne = FALSE;
+      }
+      break;
+
+    case PCR_ADDR_TYPE:
+      //
+      // Read the register, and it with the bit to read
+      //
+      switch (BitDesc->SizeInBytes) {
+        case 1:
+          Register = PchPcrRead8  (BitDesc->Reg.Data.Pcr.Fields.Pid, BitDesc->Reg.Data.Pcr.Fields.Offset);
+          break;
+
+        case 2:
+          Register = PchPcrRead16 (BitDesc->Reg.Data.Pcr.Fields.Pid, BitDesc->Reg.Data.Pcr.Fields.Offset);
+          break;
+
+        case 4:
+          Register = PchPcrRead32 (BitDesc->Reg.Data.Pcr.Fields.Pid, BitDesc->Reg.Data.Pcr.Fields.Offset);
+          break;
+
+        default:
+          //
+          // Unsupported or invalid register size
+          //
+          ASSERT (FALSE);
+          break;
+      }
+
+      Register = Register & (LShiftU64 (BIT0, BitDesc->Bit));
+      if (Register) {
+        BitWasOne = TRUE;
+      } else {
+        BitWasOne = FALSE;
+      }
+      break;
+
+    default:
+      //
+      // This address type is not yet implemented
+      //
+      ASSERT (FALSE);
+      break;
+  }
+
+  return BitWasOne;
+}
+
+/**
+  Write a specifying bit with the register
+
+  @param[in] BitDesc              The struct that includes register address, size in byte and bit number
+  @param[in] ValueToWrite         The value to be wrote
+  @param[in] WriteClear           If the rest bits of the register is write clear
+
+**/
+VOID
+WriteBitDesc (
+  CONST PCH_SMM_BIT_DESC  *BitDesc,
+  CONST BOOLEAN           ValueToWrite,
+  CONST BOOLEAN           WriteClear
+  )
+{
+  EFI_STATUS  Status;
+  UINT64      Register;
+  UINT64      AndVal;
+  UINT64      OrVal;
+  UINT32      RegSize;
+  UINT32      PciBus;
+  UINT32      PciDev;
+  UINT32      PciFun;
+  UINT32      PciReg;
+  UINTN       RegisterOffset;
+  UINT32      BaseAddr;
+  UINT64      PciBaseAddress;
+
+  ASSERT (BitDesc != NULL);
+  if (BitDesc == NULL) {
+    return;
+  }
+  ASSERT (!IS_BIT_DESC_NULL (*BitDesc));
+
+  RegSize   = 0;
+  Register  = 0;
+
+  if (WriteClear) {
+    AndVal = LShiftU64 (BIT_ZERO, BitDesc->Bit);
+  } else {
+    AndVal = ~(LShiftU64 (BIT_ZERO, BitDesc->Bit));
+  }
+
+  OrVal = (LShiftU64 ((UINT32) ValueToWrite, BitDesc->Bit));
+
+  switch (BitDesc->Reg.Type) {
+
+    case ACPI_ADDR_TYPE:
+    case TCO_ADDR_TYPE:
+      if (BitDesc->Reg.Type == ACPI_ADDR_TYPE) {
+        RegisterOffset  = BitDesc->Reg.Data.acpi;
+        BaseAddr        = mAcpiBaseAddr;
+      } else {
+        RegisterOffset  = BitDesc->Reg.Data.tco;
+        BaseAddr        = mTcoBaseAddr;
+      }
+
+      switch (BitDesc->SizeInBytes) {
+
+        case 0:
+          //
+          // Chances are that this field didn't get initialized.
+          // Check your assignments to bit descriptions.
+          //
+          ASSERT (FALSE);
+          break;
+
+        case 1:
+          RegSize = SMM_IO_UINT8;
+          break;
+
+        case 2:
+          RegSize = SMM_IO_UINT16;
+          break;
+
+        case 4:
+          RegSize = SMM_IO_UINT32;
+          break;
+
+        case 8:
+          RegSize = SMM_IO_UINT64;
+          break;
+
+        default:
+          //
+          // Unsupported or invalid register size
+          //
+          ASSERT (FALSE);
+          break;
+      }
+      //
+      // Double check that we correctly read in the acpi base address
+      //
+      ASSERT ((BaseAddr != 0x0) && ((BaseAddr & 0x1) != 0x1));
+
+      //
+      // As current CPU Smm Io can only support at most
+      // 32-bit read/write,if Operation is 64 bit,
+      // we do a 32 bit operation according to BitDesc->Bit
+      //
+      if (RegSize == SMM_IO_UINT64) {
+        RegSize = SMM_IO_UINT32;
+        //
+        // If the operation is for high 32 bits
+        //
+        if (BitDesc->Bit >= 32) {
+          RegisterOffset += 4;
+
+          if (WriteClear) {
+            AndVal = LShiftU64 (BIT_ZERO, BitDesc->Bit - 32);
+          } else {
+            AndVal = ~(LShiftU64 (BIT_ZERO, BitDesc->Bit - 32));
+          }
+
+          OrVal = LShiftU64 ((UINT32) ValueToWrite, BitDesc->Bit - 32);
+        }
+      }
+
+      Status = gSmst->SmmIo.Io.Read (
+                                 &gSmst->SmmIo,
+                                 RegSize,
+                                 BaseAddr + RegisterOffset,
+                                 1,
+                                 &Register
+                                 );
+      ASSERT_EFI_ERROR (Status);
+
+      Register &= AndVal;
+      Register |= OrVal;
+
+      Status = gSmst->SmmIo.Io.Write (
+                                 &gSmst->SmmIo,
+                                 RegSize,
+                                 BaseAddr + RegisterOffset,
+                                 1,
+                                 &Register
+                                 );
+      ASSERT_EFI_ERROR (Status);
+      break;
+
+    case GPIO_ADDR_TYPE:
+    case MEMORY_MAPPED_IO_ADDRESS_TYPE:
+      //
+      // Read the register, or it with the bit to set, then write it back.
+      //
+      switch (BitDesc->SizeInBytes) {
+        case 1:
+          MmioAndThenOr8  ((UINTN) BitDesc->Reg.Data.Mmio, (UINT8)  AndVal, (UINT8)  OrVal);
+          break;
+
+        case 2:
+          MmioAndThenOr16 ((UINTN) BitDesc->Reg.Data.Mmio, (UINT16) AndVal, (UINT16) OrVal);
+          break;
+
+        case 4:
+          MmioAndThenOr32 ((UINTN) BitDesc->Reg.Data.Mmio, (UINT32) AndVal, (UINT32) OrVal);
+          break;
+
+        case 8:
+          Register                      = (UINT64) MmioRead32 ((UINTN) BitDesc->Reg.Data.Mmio);
+          *((UINT32 *) (&Register) + 1) = MmioRead32 ((UINTN) BitDesc->Reg.Data.Mmio + 4);
+          Register &= AndVal;
+          Register |= OrVal;
+          MmioWrite32 ((UINTN) BitDesc->Reg.Data.Mmio, (UINT32) Register);
+          MmioWrite32 ((UINTN) BitDesc->Reg.Data.Mmio + 4, *((UINT32 *) (&Register) + 1));
+          break;
+
+        default:
+          //
+          // Unsupported or invalid register size
+          //
+          ASSERT (FALSE);
+          break;
+      }
+      break;
+
+    case PCIE_ADDR_TYPE:
+      PciBus  = BitDesc->Reg.Data.pcie.Fields.Bus;
+      PciDev  = BitDesc->Reg.Data.pcie.Fields.Dev;
+      PciFun  = BitDesc->Reg.Data.pcie.Fields.Fnc;
+      PciReg  = BitDesc->Reg.Data.pcie.Fields.Reg;
+      PciBaseAddress = PCI_SEGMENT_LIB_ADDRESS (DEFAULT_PCI_SEGMENT_NUMBER_PCH, PciBus, PciDev, PciFun, 0);
+      switch (BitDesc->SizeInBytes) {
+
+        case 0:
+          //
+          // Chances are that this field didn't get initialized -- check your assignments
+          // to bit descriptions.
+          //
+          ASSERT (FALSE);
+          break;
+
+        case 1:
+          PciSegmentAndThenOr8 (PciBaseAddress + PciReg, (UINT8) AndVal, (UINT8) OrVal);
+          break;
+
+        case 2:
+          PciSegmentAndThenOr16 (PciBaseAddress + PciReg, (UINT16) AndVal, (UINT16) OrVal);
+          break;
+
+        case 4:
+          PciSegmentAndThenOr32 (PciBaseAddress + PciReg, (UINT32) AndVal, (UINT32) OrVal);
+          break;
+
+        default:
+          //
+          // Unsupported or invalid register size
+          //
+          ASSERT (FALSE);
+          break;
+      }
+      break;
+
+    case PCR_ADDR_TYPE:
+      //
+      // Read the register, or it with the bit to set, then write it back.
+      //
+      switch (BitDesc->SizeInBytes) {
+        case 1:
+          PchPcrAndThenOr8  ((PCH_SBI_PID) BitDesc->Reg.Data.Pcr.Fields.Pid, (UINT16) BitDesc->Reg.Data.Pcr.Fields.Offset, (UINT8)  AndVal, (UINT8)  OrVal);
+          break;
+
+        case 2:
+          PchPcrAndThenOr16 ((PCH_SBI_PID) BitDesc->Reg.Data.Pcr.Fields.Pid, (UINT16) BitDesc->Reg.Data.Pcr.Fields.Offset, (UINT16) AndVal, (UINT16) OrVal);
+          break;
+
+        case 4:
+          PchPcrAndThenOr32 ((PCH_SBI_PID) BitDesc->Reg.Data.Pcr.Fields.Pid, (UINT16) BitDesc->Reg.Data.Pcr.Fields.Offset, (UINT32) AndVal, (UINT32) OrVal);
+          break;
+
+        default:
+          //
+          // Unsupported or invalid register size
+          //
+          ASSERT (FALSE);
+          break;
+      }
+      break;
+
+    default:
+      //
+      // This address type is not yet implemented
+      //
+      ASSERT (FALSE);
+      break;
+  }
+}
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.h b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.h
new file mode 100644
index 0000000000..998b38e159
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.h
@@ -0,0 +1,107 @@
+/** @file
+  This driver is responsible for the registration of child drivers
+  and the abstraction of the PCH SMI sources.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCHX_SMM_HELPERS_H_
+#define _PCHX_SMM_HELPERS_H_
+
+#include "PchSmm.h"
+
+/**
+  Initialize bits that aren't necessarily related to an SMI source.
+
+
+  @retval EFI_SUCCESS             SMI source initialization completed.
+  @retval Asserts                 Global Smi Bit is not enabled successfully.
+**/
+EFI_STATUS
+PchSmmInitHardware (
+  VOID
+  );
+
+/**
+  Enables the PCH to generate SMIs. Note that no SMIs will be generated
+  if no SMI sources are enabled. Conversely, no enabled SMI source will
+  generate SMIs if SMIs are not globally enabled. This is the main
+  switchbox for SMI generation.
+
+
+  @retval EFI_SUCCESS             Enable Global Smi Bit completed
+**/
+EFI_STATUS
+PchSmmEnableGlobalSmiBit (
+  VOID
+  );
+
+/**
+  Clears the SMI after all SMI source have been processed.
+  Note that this function will not work correctly (as it is
+  written) unless all SMI sources have been processed.
+  A revision of this function could manually clear all SMI
+  status bits to guarantee success.
+
+
+  @retval EFI_SUCCESS             Clears the SMIs completed
+  @retval Asserts                 EOS was not set to a 1
+**/
+EFI_STATUS
+PchSmmClearSmi (
+  VOID
+  );
+
+/**
+  Set the SMI EOS bit after all SMI source have been processed.
+
+
+  @retval FALSE                   EOS was not set to a 1; this is an error
+  @retval TRUE                    EOS was correctly set to a 1
+**/
+BOOLEAN
+PchSmmSetAndCheckEos (
+  VOID
+  );
+
+/**
+  Determine whether an ACPI OS is present (via the SCI_EN bit)
+
+
+  @retval TRUE                    ACPI OS is present
+  @retval FALSE                   ACPI OS is not present
+**/
+BOOLEAN
+PchSmmGetSciEn (
+  VOID
+  );
+
+/**
+  Read a specifying bit with the register
+
+  @param[in] BitDesc              The struct that includes register address, size in byte and bit number
+
+  @retval TRUE                    The bit is enabled
+  @retval FALSE                   The bit is disabled
+**/
+BOOLEAN
+ReadBitDesc (
+  CONST PCH_SMM_BIT_DESC *BitDesc
+  );
+
+/**
+  Write a specifying bit with the register
+
+  @param[in] BitDesc              The struct that includes register address, size in byte and bit number
+  @param[in] ValueToWrite         The value to be wrote
+  @param[in] WriteClear           If the rest bits of the register is write clear
+
+**/
+VOID
+WriteBitDesc (
+  CONST PCH_SMM_BIT_DESC  *BitDesc,
+  CONST BOOLEAN           ValueToWrite,
+  CONST BOOLEAN           WriteClear
+  );
+
+#endif
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PcieSmmClient.c b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PcieSmmClient.c
new file mode 100644
index 0000000000..6d210f671b
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PcieSmmClient.c
@@ -0,0 +1,38 @@
+/** @file
+  This function handle the register/unregister of PCH PCIe specific SMI events.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "PchSmmHelpers.h"
+#include <Register/PmcRegs.h>
+#include <Register/PchPcieRpRegs.h>
+#include <Library/CpuPcieInfoFruLib.h>
+#include <CpuPcieInfo.h>
+#include <Library/PchPcieRpLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchPciBdfLib.h>
+
+extern UINT32  mNumOfRootPorts;
+
+/**
+  Get CPU or PCH Pcie Root Port Device and Function Number by Root Port physical Number
+
+  @param[in]  RpNumber              Root port physical number. (0-based)
+  @param[out] RpDev                 Return corresponding root port device number.
+  @param[out] RpFun                 Return corresponding root port function number.
+**/
+VOID
+GetPcieRpDevFun (
+  IN  UINTN   RpIndex,
+  OUT UINTN   *RpDev,
+  OUT UINTN   *RpFun
+  )
+{
+  if (RpIndex >= CpuRpIndex0 && RpIndex <= CpuRpIndex3) {
+    GetCpuPcieRpDevFun ((RpIndex - CpuRpIndex0), RpDev, RpFun);
+  } else {
+    *RpDev = PchPcieRpDevNumber (RpIndex);
+    *RpFun = PchPcieRpFuncNumber (RpIndex);
+  }
+}
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/SmmGlobalsPch.c b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/SmmGlobalsPch.c
new file mode 100644
index 0000000000..f66079884f
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/SmmGlobalsPch.c
@@ -0,0 +1,20 @@
+/** @file
+  This driver is responsible for the registration of child drivers
+  and the abstraction of the PCH SMI sources.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Register/TcoRegs.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mTco1StsClear =
+  (
+    B_TCO_IO_TCO1_STS_DMISERR |
+    B_TCO_IO_TCO1_STS_DMISMI |
+    B_TCO_IO_TCO1_STS_DMISCI |
+    B_TCO_IO_TCO1_STS_BIOSWR |
+    B_TCO_IO_TCO1_STS_NEWCENTURY |
+    B_TCO_IO_TCO1_STS_TIMEOUT |
+    B_TCO_IO_TCO1_STS_TCO_INT |
+    B_TCO_IO_TCO1_STS_SW_TCO_SMI
+    );
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControl.inf b/Silicon/Intel/AlderlakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControl.inf
new file mode 100644
index 0000000000..d73c12f964
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControl.inf
@@ -0,0 +1,53 @@
+## @file
+# Component description file for SmmControl module
+#
+#   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+#   SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = SmmControl
+FILE_GUID = A0BAD9F7-AB78-491b-B583-C52B7F84B9E0
+VERSION_STRING = 1.0
+MODULE_TYPE = DXE_RUNTIME_DRIVER
+ENTRY_POINT = SmmControlDriverEntryInit
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+
+
+[LibraryClasses]
+IoLib
+UefiDriverEntryPoint
+DebugLib
+UefiBootServicesTableLib
+UefiRuntimeServicesTableLib
+PmcLib
+GpioLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+AlderlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+SmmControlDriver.h
+SmmControlDriver.c
+
+
+[Protocols]
+gEfiSmmControl2ProtocolGuid ## PRODUCES
+
+
+[Guids]
+gEfiEventVirtualAddressChangeGuid
+
+
+[Depex]
+TRUE
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.c b/Silicon/Intel/AlderlakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.c
new file mode 100644
index 0000000000..8864d18787
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.c
@@ -0,0 +1,338 @@
+/** @file
+  This is the driver that publishes the SMM Control Protocol.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Guid/EventGroup.h>
+#include <Library/PmcLib.h>
+#include <Library/GpioLib.h>
+#include <IndustryStandard/Pci30.h>
+#include <Register/PchRegsLpc.h>
+#include <Register/SpiRegs.h>
+#include <Register/PmcRegs.h>
+#include "SmmControlDriver.h"
+
+STATIC SMM_CONTROL_PRIVATE_DATA mSmmControl;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16                          mABase;
+
+/**
+  Fixup internal data pointers so that the services can be called in virtual mode.
+
+  @param[in] Event                The event registered.
+  @param[in] Context              Event context.
+
+**/
+VOID
+EFIAPI
+SmmControlVirtualAddressChangeEvent (
+  IN EFI_EVENT                  Event,
+  IN VOID                       *Context
+  )
+{
+  gRT->ConvertPointer (0, (VOID *) &(mSmmControl.SmmControl.Trigger));
+  gRT->ConvertPointer (0, (VOID *) &(mSmmControl.SmmControl.Clear));
+}
+
+/**
+  <b>SmmControl DXE RUNTIME Module Entry Point</b>\n
+  - <b>Introduction</b>\n
+    The SmmControl module is a DXE RUNTIME driver that provides a standard way
+    for other drivers to trigger software SMIs.
+
+  - @pre
+    - PCH Power Management I/O space base address has already been programmed.
+      If SmmControl Runtime DXE driver is run before Status Code Runtime Protocol
+      is installed and there is the need to use Status code in the driver, it will
+      be necessary to add EFI_STATUS_CODE_RUNTIME_PROTOCOL_GUID to the dependency file.
+    - EFI_SMM_BASE2_PROTOCOL
+      - Documented in the System Management Mode Core Interface Specification.
+
+  - @result
+    The SmmControl driver produces the EFI_SMM_CONTROL_PROTOCOL documented in
+    System Management Mode Core Interface Specification.
+
+  @param[in] ImageHandle          Handle for the image of this driver
+  @param[in] SystemTable          Pointer to the EFI System Table
+
+  @retval EFI_STATUS              Results of the installation of the SMM Control Protocol
+**/
+EFI_STATUS
+EFIAPI
+SmmControlDriverEntryInit (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  )
+{
+  EFI_STATUS  Status;
+  EFI_EVENT   Event;
+
+  DEBUG ((DEBUG_INFO, "SmmControlDriverEntryInit() Start\n"));
+
+  //
+  // Get the Power Management I/O space base address. We assume that
+  // this base address has already been programmed if this driver is
+  // being run.
+  //
+  mABase = PmcGetAcpiBase ();
+
+  Status = EFI_SUCCESS;
+  if (mABase != 0) {
+    //
+    // Install the instance of the protocol
+    //
+    mSmmControl.Signature                       = SMM_CONTROL_PRIVATE_DATA_SIGNATURE;
+    mSmmControl.Handle                          = ImageHandle;
+
+    mSmmControl.SmmControl.Trigger              = Activate;
+    mSmmControl.SmmControl.Clear                = Deactivate;
+    mSmmControl.SmmControl.MinimumTriggerPeriod = 0;
+
+    //
+    // Install our protocol interfaces on the device's handle
+    //
+    Status = gBS->InstallMultipleProtocolInterfaces (
+                    &mSmmControl.Handle,
+                    &gEfiSmmControl2ProtocolGuid,
+                    &mSmmControl.SmmControl,
+                    NULL
+                    );
+  } else {
+    Status = EFI_DEVICE_ERROR;
+    return Status;
+  }
+
+  Status = gBS->CreateEventEx (
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_NOTIFY,
+                  SmmControlVirtualAddressChangeEvent,
+                  NULL,
+                  &gEfiEventVirtualAddressChangeGuid,
+                  &Event
+                  );
+
+  DEBUG ((DEBUG_INFO, "SmmControlDriverEntryInit() End\n"));
+
+  return Status;
+}
+
+/**
+  Trigger the software SMI
+
+  @param[in] Command              The value to be set on the software SMI command port
+  @param[in] Data                 The value to be set on the software SMI data port
+
+  @retval EFI_SUCCESS             Function completes successfully
+**/
+EFI_STATUS
+EFIAPI
+SmmTrigger (
+  IN UINT8   Command,
+  IN UINT8   Data
+  )
+{
+  UINT32  OutputData;
+  UINT32  OutputPort;
+
+  //
+  // Enable the APMC SMI
+  //
+  OutputPort  = mABase + R_ACPI_IO_SMI_EN;
+  OutputData  = IoRead32 ((UINTN) OutputPort);
+  OutputData |= (B_ACPI_IO_SMI_EN_APMC | B_ACPI_IO_SMI_EN_GBL_SMI);
+  DEBUG (
+    (DEBUG_VERBOSE,
+     "The SMI Control Port at address %x will be written to %x.\n",
+     OutputPort,
+     OutputData)
+    );
+  IoWrite32 (
+    (UINTN) OutputPort,
+    (UINT32) (OutputData)
+    );
+
+  OutputPort  = R_PCH_IO_APM_STS;
+  OutputData  = Data;
+
+  //
+  // Write data to APM DATA PORT
+  //
+  IoWrite8 (
+    (UINTN) OutputPort,
+    (UINT8) (OutputData)
+    );
+  OutputPort  = R_PCH_IO_APM_CNT;
+  OutputData  = Command;
+
+  //
+  // Generate the APMC SMI
+  //
+  IoWrite8 (
+    (UINTN) OutputPort,
+    (UINT8) (OutputData)
+    );
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Clear the SMI status
+
+
+  @retval EFI_SUCCESS             The function completes successfully
+  @retval EFI_DEVICE_ERROR        Something error occurred
+**/
+EFI_STATUS
+EFIAPI
+SmmClear (
+  VOID
+  )
+{
+  EFI_STATUS  Status;
+  UINT32      OutputData;
+  UINT32      OutputPort;
+
+  Status = EFI_SUCCESS;
+
+  //
+  // Clear the Power Button Override Status Bit, it gates EOS from being set.
+  //
+  OutputPort  = mABase + R_ACPI_IO_PM1_STS;
+  OutputData  = B_ACPI_IO_PM1_STS_PRBTNOR;
+  DEBUG (
+    (DEBUG_VERBOSE,
+     "The PM1 Status Port at address %x will be written to %x.\n",
+     OutputPort,
+     OutputData)
+    );
+  IoWrite16 (
+    (UINTN) OutputPort,
+    (UINT16) (OutputData)
+    );
+
+  //
+  // Clear the APM SMI Status Bit
+  //
+  OutputPort  = mABase + R_ACPI_IO_SMI_STS;
+  OutputData  = B_ACPI_IO_SMI_STS_APM;
+  DEBUG (
+    (DEBUG_VERBOSE,
+     "The SMI Status Port at address %x will be written to %x.\n",
+     OutputPort,
+     OutputData)
+    );
+  IoWrite32 (
+    (UINTN) OutputPort,
+    (UINT32) (OutputData)
+    );
+
+  //
+  // Set the EOS Bit
+  //
+  OutputPort  = mABase + R_ACPI_IO_SMI_EN;
+  OutputData  = IoRead32 ((UINTN) OutputPort);
+  OutputData |= B_ACPI_IO_SMI_EN_EOS;
+  DEBUG (
+    (DEBUG_VERBOSE,
+     "The SMI Control Port at address %x will be written to %x.\n",
+     OutputPort,
+     OutputData)
+    );
+  IoWrite32 (
+    (UINTN) OutputPort,
+    (UINT32) (OutputData)
+    );
+
+  //
+  // There is no need to read EOS back and check if it is set.
+  // This can lead to a reading of zero if an SMI occurs right after the SMI_EN port read
+  // but before the data is returned to the CPU.
+  // SMM Dispatcher should make sure that EOS is set after all SMI sources are processed.
+  //
+  return Status;
+}
+
+/**
+  This routine generates an SMI
+
+  @param[in] This                       The EFI SMM Control protocol instance
+  @param[in, out] CommandPort           The buffer contains data to the command port
+  @param[in, out] DataPort              The buffer contains data to the data port
+  @param[in] Periodic                   Periodic or not
+  @param[in] ActivationInterval         Interval of periodic SMI
+
+  @retval EFI Status                    Describing the result of the operation
+  @retval EFI_INVALID_PARAMETER         Some parameter value passed is not supported
+**/
+EFI_STATUS
+EFIAPI
+Activate (
+  IN CONST EFI_SMM_CONTROL2_PROTOCOL                    * This,
+  IN OUT  UINT8                                         *CommandPort       OPTIONAL,
+  IN OUT  UINT8                                         *DataPort          OPTIONAL,
+  IN      BOOLEAN                                       Periodic           OPTIONAL,
+  IN      UINTN                                         ActivationInterval OPTIONAL
+  )
+{
+  EFI_STATUS  Status;
+  UINT8       Command;
+  UINT8       Data;
+
+  if (Periodic) {
+    DEBUG ((DEBUG_WARN, "Invalid parameter\n"));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Extract the values from CommandPort and DataPort
+  //
+  if (CommandPort == NULL) {
+    Command = 0xFF;
+  } else {
+    Command = *CommandPort;
+  }
+
+  if (DataPort == NULL) {
+    Data = 0x00;
+  } else {
+    Data = *DataPort;
+  }
+
+  //
+  // Clear any pending the APM SMI
+  //
+  Status = SmmClear ();
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  return SmmTrigger (Command, Data);
+}
+
+/**
+  This routine clears an SMI
+
+  @param[in] This                 The EFI SMM Control protocol instance
+  @param[in] Periodic             Periodic or not
+
+  @retval EFI Status              Describing the result of the operation
+  @retval EFI_INVALID_PARAMETER   Some parameter value passed is not supported
+**/
+EFI_STATUS
+EFIAPI
+Deactivate (
+  IN CONST EFI_SMM_CONTROL2_PROTOCOL       *This,
+  IN  BOOLEAN                              Periodic OPTIONAL
+  )
+{
+  if (Periodic) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return SmmClear ();
+}
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.h b/Silicon/Intel/AlderlakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.h
new file mode 100644
index 0000000000..a366de7d5e
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.h
@@ -0,0 +1,122 @@
+/** @file
+  Header file for SMM Control Driver.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _SMM_CONTROL_DRIVER_H_
+#define _SMM_CONTROL_DRIVER_H_
+
+#include <Protocol/SmmControl2.h>
+
+
+#define SMM_CONTROL_PRIVATE_DATA_SIGNATURE  SIGNATURE_32 ('i', '4', 's', 'c')
+
+typedef struct {
+  UINTN                           Signature;
+  EFI_HANDLE                      Handle;
+  EFI_SMM_CONTROL2_PROTOCOL       SmmControl;
+} SMM_CONTROL_PRIVATE_DATA;
+
+#define SMM_CONTROL_PRIVATE_DATA_FROM_THIS(a) CR (a, SMM_CONTROL_PRIVATE_DATA, SmmControl, SMM_CONTROL_DEV_SIGNATURE)
+
+//
+// Prototypes
+//
+
+/**
+  <b>SmmControl DXE RUNTIME Module Entry Point</b>\n
+  - <b>Introduction</b>\n
+    The SmmControl module is a DXE RUNTIME driver that provides a standard way
+    for other drivers to trigger software SMIs.
+
+  - @pre
+    - PCH Power Management I/O space base address has already been programmed.
+      If SmmControl Runtime DXE driver is run before Status Code Runtime Protocol
+      is installed and there is the need to use Status code in the driver, it will
+      be necessary to add EFI_STATUS_CODE_RUNTIME_PROTOCOL_GUID to the dependency file.
+    - EFI_SMM_BASE2_PROTOCOL
+      - Documented in the System Management Mode Core Interface Specification.
+
+  - @result
+    The SmmControl driver produces the EFI_SMM_CONTROL_PROTOCOL documented in
+    System Management Mode Core Interface Specification.
+
+  @param[in] ImageHandle          Handle for the image of this driver
+  @param[in] SystemTable          Pointer to the EFI System Table
+
+  @retval EFI_STATUS              Results of the installation of the SMM Control Protocol
+**/
+EFI_STATUS
+EFIAPI
+SmmControlDriverEntryInit (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  );
+
+/**
+  Trigger the software SMI
+
+  @param[in] Command              The value to be set on the software SMI command port
+  @param[in] Data                 The value to be set on the software SMI data port
+
+  @retval EFI_SUCCESS             Function completes successfully
+**/
+EFI_STATUS
+EFIAPI
+SmmTrigger (
+  IN UINT8   Command,
+  IN UINT8   Data
+  );
+
+/**
+  Clear the SMI status
+
+
+  @retval EFI_SUCCESS             The function completes successfully
+  @retval EFI_DEVICE_ERROR        Something error occurred
+**/
+EFI_STATUS
+EFIAPI
+SmmClear (
+  VOID
+  );
+
+/**
+  This routine generates an SMI
+
+  @param[in] This                       The EFI SMM Control protocol instance
+  @param[in, out] ArgumentBuffer        The buffer of argument
+  @param[in, out] ArgumentBufferSize    The size of the argument buffer
+  @param[in] Periodic                   Periodic or not
+  @param[in] ActivationInterval         Interval of periodic SMI
+
+  @retval EFI Status                    Describing the result of the operation
+  @retval EFI_INVALID_PARAMETER         Some parameter value passed is not supported
+**/
+EFI_STATUS
+EFIAPI
+Activate (
+  IN CONST EFI_SMM_CONTROL2_PROTOCOL    *This,
+  IN OUT  UINT8                         *ArgumentBuffer OPTIONAL,
+  IN OUT  UINT8                         *ArgumentBufferSize OPTIONAL,
+  IN      BOOLEAN                       Periodic OPTIONAL,
+  IN      UINTN                         ActivationInterval OPTIONAL
+  );
+
+/**
+  This routine clears an SMI
+
+  @param[in] This                 The EFI SMM Control protocol instance
+  @param[in] Periodic             Periodic or not
+
+  @retval EFI Status              Describing the result of the operation
+  @retval EFI_INVALID_PARAMETER   Some parameter value passed is not supported
+**/
+EFI_STATUS
+EFIAPI
+Deactivate (
+  IN CONST EFI_SMM_CONTROL2_PROTOCOL    *This,
+  IN       BOOLEAN                      Periodic OPTIONAL
+  );
+#endif
-- 
2.36.1.windows.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 6/8] AlderlakeSiliconPkg/SystemAgent: Add NVS support
  2023-06-15 17:52 [PATCH 1/8] AlderlakeSiliconPkg: Add package and library instances Saloni Kasbekar
                   ` (3 preceding siblings ...)
  2023-06-15 17:53 ` [PATCH 5/8] AlderlakeSiliconPkg/Pch: Add drivers Saloni Kasbekar
@ 2023-06-15 17:53 ` Saloni Kasbekar
  2023-07-24  7:58   ` [edk2-devel] " Chaganty, Rangasai V
  2023-06-15 17:53 ` [PATCH 7/8] AlderlakeSiliconPkg/SystemAgent: Add include headers Saloni Kasbekar
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 15+ messages in thread
From: Saloni Kasbekar @ 2023-06-15 17:53 UTC (permalink / raw)
  To: devel
  Cc: Saloni Kasbekar, Sai Chaganty, Nate DeSimone, Isaac Oram,
	Rosen Chuang

Adds the System Agent NVS ACPI table and structures

Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Isaac Oram <isaac.w.oram@intel.com>
Cc: Rosen Chuang <rosen.chuang@intel.com>
Signed-off-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
---
 .../SystemAgent/AcpiTables/SaSsdt/SaNvs.asl   | 18 +++++++++++
 .../IncludePrivate/Protocol/SaNvsArea.h       | 30 +++++++++++++++++++
 .../SystemAgent/IncludePrivate/SaNvsAreaDef.h | 22 ++++++++++++++
 3 files changed, 70 insertions(+)
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/SaNvs.asl
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/IncludePrivate/Protocol/SaNvsArea.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/IncludePrivate/SaNvsAreaDef.h

diff --git a/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/SaNvs.asl b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/SaNvs.asl
new file mode 100644
index 0000000000..e9785873d2
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/SaNvs.asl
@@ -0,0 +1,18 @@
+/**@file
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+  //
+  // Define SA NVS Area operation region.
+  //
+
+
+  OperationRegion(SANV,SystemMemory,SANB,SANL)
+  Field(SANV,AnyAcc,Lock,Preserve)
+  {  Offset(0),      M64B, 64, // Offset(0),   Base of above 4GB MMIO resource
+  Offset(8),    M64L, 64, // Offset(8),   Length of above 4GB MMIO resource
+  Offset(16),    M32B, 32, // Offset(16),   Base of below 4GB MMIO resource
+  Offset(20),    M32L, 32, // Offset(20),   Length of below 4GB MMIO resource
+  }
\ No newline at end of file
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/IncludePrivate/Protocol/SaNvsArea.h b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/IncludePrivate/Protocol/SaNvsArea.h
new file mode 100644
index 0000000000..3a75465843
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/IncludePrivate/Protocol/SaNvsArea.h
@@ -0,0 +1,30 @@
+/** @file
+  Definition of the System Agent global NVS area protocol.
+  This protocol publishes the address and format of a global ACPI NVS buffer
+  used as a communications buffer between SMM/DXE/PEI code and ASL code.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _SYSTEM_AGENT_NVS_AREA_H_
+#define _SYSTEM_AGENT_NVS_AREA_H_
+
+//
+// SA NVS Area definition
+//
+#include <SaNvsAreaDef.h>
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gSaNvsAreaProtocolGuid;
+
+///
+/// System Agent Global NVS Area Protocol
+///
+typedef struct {
+  SYSTEM_AGENT_NVS_AREA *Area;        ///< System Agent Global NVS Area Structure
+} SYSTEM_AGENT_NVS_AREA_PROTOCOL;
+
+#endif // _SYSTEM_AGENT_NVS_AREA_H_
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/IncludePrivate/SaNvsAreaDef.h b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/IncludePrivate/SaNvsAreaDef.h
new file mode 100644
index 0000000000..5b8136866a
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/IncludePrivate/SaNvsAreaDef.h
@@ -0,0 +1,22 @@
+/**@file
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+  //
+  // Define SA NVS Area operation region.
+  //
+#ifndef _SA_NVS_AREA_DEF_H_
+#define _SA_NVS_AREA_DEF_H_
+
+#pragma pack (push,1)
+typedef struct {
+  UINT64   Mmio64Base;                              ///< Offset 0     Base of above 4GB MMIO resource
+  UINT64   Mmio64Length;                            ///< Offset 8     Length of above 4GB MMIO resource
+  UINT32   Mmio32Base;                              ///< Offset 16     Base of below 4GB MMIO resource
+  UINT32   Mmio32Length;                            ///< Offset 20     Length of below 4GB MMIO resource
+} SYSTEM_AGENT_NVS_AREA;
+
+#pragma pack(pop)
+#endif
-- 
2.36.1.windows.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 7/8] AlderlakeSiliconPkg/SystemAgent: Add include headers
  2023-06-15 17:52 [PATCH 1/8] AlderlakeSiliconPkg: Add package and library instances Saloni Kasbekar
                   ` (4 preceding siblings ...)
  2023-06-15 17:53 ` [PATCH 6/8] AlderlakeSiliconPkg/SystemAgent: Add NVS support Saloni Kasbekar
@ 2023-06-15 17:53 ` Saloni Kasbekar
  2023-07-24  8:03   ` [edk2-devel] " Chaganty, Rangasai V
  2023-06-15 17:53 ` [PATCH 8/8] AlderlakeSiliconPkg/SystemAgent: Add library and driver modules Saloni Kasbekar
  2023-07-23  0:04 ` [edk2-devel] [PATCH 1/8] AlderlakeSiliconPkg: Add package and library instances Chaganty, Rangasai V
  7 siblings, 1 reply; 15+ messages in thread
From: Saloni Kasbekar @ 2023-06-15 17:53 UTC (permalink / raw)
  To: devel
  Cc: Saloni Kasbekar, Sai Chaganty, Nate DeSimone, Isaac Oram,
	Rosen Chuang

Adds the following header files:
* SystemAgent/Include

Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Isaac Oram <isaac.w.oram@intel.com>
Cc: Rosen Chuang <rosen.chuang@intel.com>
Signed-off-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
---
 .../Include/ConfigBlock/MemoryDxeConfig.h     | 126 ++++++++++
 .../ConfigBlock/SaMiscPeiPreMemConfig.h       | 112 +++++++++
 .../Include/Library/DxeSaPolicyLib.h          |  58 +++++
 .../Include/Library/PeiSaPolicyLib.h          |  13 ++
 .../SystemAgent/Include/MemInfoHob.h          | 220 ++++++++++++++++++
 .../SystemAgent/Include/Protocol/SaPolicy.h   |  54 +++++
 .../SystemAgent/Include/SaDataHob.h           |  28 +++
 7 files changed, 611 insertions(+)
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/ConfigBlock/MemoryDxeConfig.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/ConfigBlock/SaMiscPeiPreMemConfig.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/Library/DxeSaPolicyLib.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/Library/PeiSaPolicyLib.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/MemInfoHob.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/Protocol/SaPolicy.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/SaDataHob.h

diff --git a/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/ConfigBlock/MemoryDxeConfig.h b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/ConfigBlock/MemoryDxeConfig.h
new file mode 100644
index 0000000000..eca0c2f1ba
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/ConfigBlock/MemoryDxeConfig.h
@@ -0,0 +1,126 @@
+/** @file
+  Memory DXE Policy definitions
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _MEMORY_DXE_CONFIG_H_
+#define _MEMORY_DXE_CONFIG_H_
+
+#pragma pack(push, 1)
+
+/**
+ Making any setup structure change after code frozen
+ will need to maintain backward compatibility, bump up
+ structure revision and update below history table\n
+  <b>Revision 1</b>:  - Initial version.
+**/
+#define MEMORY_DXE_CONFIG_REVISION 2
+
+typedef struct _MEMORY_DXE_CONFIG  MEMORY_DXE_CONFIG;
+
+/**
+  Retrieves the OEM custom string for the SMBIOS Type 17 Table DeviceLocator field.
+  Implementation of this function is optional, if this function pointer is NULL then
+  the reference implementation of DeviceLocator will be used.
+
+  @param[in]  This                          A pointer to this instance of MEMORY_DXE_CONFIG.
+  @param[in]  Controller                    Desired Controller to get a DeviceLocator string for.
+  @param[in]  Dimm                          Desired DIMM to get a DeviceLocator string for.
+  @param[in]  MdSocket                      0 = Memory Down, 1 = Socketed.
+
+  @retval                                   The DeviceLocator string
+  @retval     NULL                          If the return value is NULL, the default value will be used.
+**/
+typedef
+CHAR8*
+(EFIAPI *MEMORY_DXE_CONFIG_GET_DEVICE_LOCATOR_STRING)(
+  IN CONST    MEMORY_DXE_CONFIG   *This,
+  IN          UINT8               Controller,
+  IN          UINT8               Dimm,
+  IN          UINT8               MdSocket
+  );
+
+/**
+  Retrieves the OEM custom string for the SMBIOS Type 17 Table BankLocator field.
+  Implementation of this function is optional, if this function pointer is NULL then
+  the reference implementation of DeviceLocator will be used.
+
+  @param[in]  This                          A pointer to this instance of MEMORY_DXE_CONFIG.
+  @param[in]  Controller                    Desired Controller to get a BankLocator string for.
+  @param[in]  Dimm                          Desired DIMM to get a BankLocator string for.
+  @param[in]  MdSocket                      0 = Memory Down, 1 = Socketed.
+
+  @retval                                   The BankLocator string
+  @retval     NULL                          If the return value is NULL, the default value will be used.
+**/
+typedef
+CHAR8*
+(EFIAPI *MEMORY_DXE_CONFIG_GET_BANK_LOCATOR_STRING)(
+  IN CONST    MEMORY_DXE_CONFIG   *This,
+  IN          UINT8               Controller,
+  IN          UINT8               Dimm,
+  IN          UINT8               MdSocket
+  );
+
+/**
+  The Memory Configuration includes DIMM SPD address Map and DIMM Slot Mechanical present bit map.
+  The data elements should be initialized by a Platform Module.\n
+  <b>Revision 1</b>:
+  - Initial version.
+**/
+struct _MEMORY_DXE_CONFIG {
+  CONFIG_BLOCK_HEADER   Header;                   ///< Offset 0-27: Config Block Header
+/**
+  Offset 28:
+  Dimm SPD address
+  Only Server support 2 channels * 3 slots per channel = 6 sockets totally
+  The Desktop and mobile only support 2 channels * 2 slots per channel = 4 sockets totally
+  So there is mapping rule here for Desktop and mobile that there are no more 4 DIMMS totally in a system:
+    Channel A/ Slot 0 --> Dimm 0 --> SpdAddressTable[0]
+    Channel A/ Slot 1 --> Dimm 1 --> SpdAddressTable[1]
+    Channel B/ Slot 0 --> Dimm 2 --> SpdAddressTable[2]
+    Channel B/ Slot 1 --> Dimm 3 --> SpdAddressTable[3]
+  Refer to SmbiosMemory.c for use
+  If change the mapping rule, please update the Revision number.
+**/
+  UINT8                                           *SpdAddressTable;
+/**
+  Offset 36:
+  ChannelASlotMap and ChannelBSlotMap change to use SlotMap as the DIMM slot map solution.
+  Reserve 2-bytes in order to comply with 4-bytes alignment and keep the offset of other members.
+**/
+  UINT8                                           ChannelASlotMap;
+  UINT8                                           ChannelBSlotMap;
+/**
+  Offset 38:
+  MRC execution time measurement: <b>0=Disable</b>, 1=Enable
+**/
+  UINT8                                           MrcTimeMeasure;
+/**
+  Offset 39:
+  Fast boot: 0=Disable, <b>1=Enable</b>
+**/
+  UINT8                                           MrcFastBoot;
+/**
+  Offset 40:
+  Retrieves the OEM custom string for the SMBIOS Type 17 Table DeviceLocator field.
+**/
+  MEMORY_DXE_CONFIG_GET_DEVICE_LOCATOR_STRING     GetDeviceLocatorString;
+/**
+  Offset 48:
+  Retrieves the OEM custom string for the SMBIOS Type 17 Table BankLocator field.
+**/
+  MEMORY_DXE_CONFIG_GET_BANK_LOCATOR_STRING       GetBankLocatorString;
+/**
+  Offset 56:
+  Each DIMM Slot Mechanical present bit map, bit 0 -> DIMM 0, bit 1 -> DIMM1, ...
+  if the bit is 1, the related DIMM slot is present.
+  E.g. if memory controller 0 channel 3 has 2 DIMMs,  SlotMap[0][3] = 0x03;
+  E.g. if memory controller 1 channel 2 has only 1 DIMMs,  SlotMap[1][2] = 0x0;
+**/
+  UINT8                                           **SlotMap;
+};
+#pragma pack(pop)
+
+#endif // _MEMORY_DXE_CONFIG_H_
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/ConfigBlock/SaMiscPeiPreMemConfig.h b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/ConfigBlock/SaMiscPeiPreMemConfig.h
new file mode 100644
index 0000000000..cb75696b61
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/ConfigBlock/SaMiscPeiPreMemConfig.h
@@ -0,0 +1,112 @@
+/** @file
+  Policy details for miscellaneous configuration in System Agent
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _SA_MISC_PEI_PREMEM_CONFIG_H_
+#define _SA_MISC_PEI_PREMEM_CONFIG_H_
+
+#pragma pack(push, 1)
+
+#ifndef MEM_CFG_MAX_SOCKETS
+#define MEM_CFG_MAX_SOCKETS 16
+#endif
+
+#define SA_MISC_PEI_PREMEM_CONFIG_REVISION 1
+
+/**
+  This configuration block is to configure SA Miscellaneous variables during PEI Pre-Mem phase like programming
+  different System Agent BARs, TsegSize, MmioSize required etc.
+  <b>Revision 1</b>:
+  - Initial version.
+**/
+typedef struct {
+  CONFIG_BLOCK_HEADER  Header;               ///< Offset 0-27 Config Block Header
+  /**
+    Offset 28 Memory DIMMs' SPD address for reading SPD data.
+    TGL Mapping
+      0 - Controller 0 Channel 0 Dimm 0 - DDR4 - DDR5 - LPDDR4 - LPDDR5
+      1 - Controller 0 Channel 0 Dimm 1 - DDR4
+      2 - Controller 0 Channel 1 Dimm 0 -------- DDR5 - LPDDR4 - LPDDR5
+      3 - Controller 0 Channel 1 Dimm 1 -------- DDR5 2DPC
+      4 - Controller 0 Channel 2 Dimm 0 --------------- LPDDR4 - LPDDR5
+      6 - Controller 0 Channel 3 Dimm 0 --------------- LPDDR4 - LPDDR5
+      8 - Controller 1 Channel 0 Dimm 0 - DDR4 - DDR5 - LPDDR4 - LPDDR5
+      9 - Controller 1 Channel 0 Dimm 1 - DDR4
+     10 - Controller 1 Channel 1 Dimm 0 -------- DDR5 - LPDDR4 - LPDDR5
+     11 - Controller 1 Channel 1 Dimm 1 -------- DDR5 2DPC
+     12 - Controller 1 Channel 2 Dimm 0 --------------- LPDDR4 - LPDDR5
+     14 - Controller 1 Channel 3 Dimm 0 --------------- LPDDR4 - LPDDR5
+  **/
+  UINT8   SpdAddressTable[MEM_CFG_MAX_SOCKETS];
+  VOID    *S3DataPtr;                        ///< Offset 44 Memory data save pointer for S3 resume. The memory space should be allocated and filled with proper S3 resume data on a resume path
+  UINT32  SmbusBar;                          ///< Offset 48 Address of System Agent SMBUS BAR: <b>0xEFA0</b>
+  /**
+    Offset 52 Size of TSEG in bytes. (Must be power of 2)
+    <b>0x400000</b>: 4MB for Release build (When IED enabled, it will be 8MB)
+    0x1000000      : 16MB for Debug build (Regardless IED enabled or disabled)
+  **/
+  UINT32  TsegSize;
+  /**
+    Offset 56
+    <b>(Test)</b> Size of IED region in bytes.
+    <b>0</b> : IED Disabled (no memory occupied)
+    0x400000 : 4MB SMM memory occupied by IED (Part of TSEG)
+    <b>Note: Enabling IED may also enlarge TsegSize together.</b>
+    @deprecated
+  **/
+  UINT32  IedSize;
+  UINT32  SkipExtGfxScan:1;                  ///< <b>(Test)</b> OFfset 60:0 :1=Skip External Gfx Device Scan; <b>0=Scan for external graphics devices</b>. Set this policy to skip External Graphics card scanning if the platform uses Internal Graphics only.
+  UINT32  BdatEnable:1;                      ///< Offset 60:1 :This field enables the generation of the BIOS DATA ACPI Tables: <b>0=FALSE</b>, 1=TRUE.
+  UINT32  TxtImplemented:1;                  ///< OFfset 60:2 :This field currently is used to tell MRC if it should run after TXT initializatoin completed: <b>0=Run without waiting for TXT</b>, 1=Run after TXT initialization by callback
+  /**
+   Offset 60:3 :
+   <b>(Test)</b> Scan External Discrete Graphics Devices for Legacy Only VGA OpROMs
+
+   When enabled, if the primary graphics device is an external discrete graphics device, Si will scan the
+   graphics device for legacy only VGA OpROMs.
+
+   This is intended to ease the implementation of a BIOS feature to automatically enable CSM if the Primary Gfx device
+   only supports Legacy VBIOS (No UEFI GOP Present).  Otherwise disabling CSM won't result in no video being displayed.
+   This is useful for platforms that implement PCIe slots that allow the end user to install an arbitrary Gfx device.
+
+   This setting will only take effect if SkipExtGfxScan == 0.  It is ignored otherwise.
+
+  - Disabled (0x0)         : Don't Scan for Legacy Only VGA OpROMs (Default)
+  - <b>Enabled</b>  (0x1)  : Scan External Gfx for Legacy Only VGA OpROM
+  **/
+  UINT32  ScanExtGfxForLegacyOpRom:1;
+  UINT32  RsvdBits0  :28;                    ///< Offset 60:4 :Reserved for future use
+  UINT8   UserBd;                            ///< Offset 64 <b>0=Mobile/Mobile Halo</b>, 1=Desktop/DT Halo, 2=Desktop 2DPC DDR5, 5=ULT/ULX/Mobile Halo Type3, 6=ULT/ULX/Mobile Halo Type4, 8=UP Server
+  UINT8   LockPTMregs;                       ///< <b>(Test)</b> Offset 65 Lock PCU Thermal Management registers: 0=FALSE, <b>1=TRUE</b>
+  UINT8   BdatTestType;                      ///< Offset 66 When BdatEnable is set to TRUE, this option selects the type of data which will be populated in the BIOS Data ACPI Tables: <b>0=RMT</b>, 1=RMT Per Bit, 2=Margin 2D.
+  UINT8   CridEnable;                        ///< Offset 67 For Platforms supporting Intel(R) SIPP, this policy is use control enable/disable Compatibility Revision ID (CRID) feature: <b>0=FALSE</b>, 1=TRUE
+  UINT32  AcpiReservedMemorySize;            ///< Offset 68 The Size of a Reserved memory buffer allocated in previous boot for S3 resume used. Originally it is retrieved from AcpiVariableCompatibility variable.
+  UINT64  AcpiReservedMemoryBase;            ///< Offset 80 The Base address of a Reserved memory buffer allocated in previous boot for S3 resume used. Originally it is retrieved from AcpiVariableCompatibility variable.
+  UINT64  SystemMemoryLength;                ///< Offset 88 Total system memory length from previous boot, this is required for S3 resume. Originally it is retrieved from AcpiVariableCompatibility variable.
+
+  UINT8   WrcFeatureEnable;                   ///< Offset 96: Enable/Disable WRC (Write Cache) feature of IOP. When enabled, supports IO devices allocating onto the ring and into LLC.
+  UINT8   FirstDimmBitMask;                   ///< Offset 97: Defines which DIMM should be populated first on a 2DPC board.
+                                              ///<            4 bit mask: Bit[0]: MC0 DIMM0, Bit[1]: MC0 DIMM1, Bit[2]: MC1 DIMM0, Bit[3]: MC1 DIMM1.
+                                              ///<            For each MC, the first DIMM to be populated should be set to '1'.
+                                              ///<            Note: this mask is only for non-ECC DIMM.
+  UINT8   FirstDimmBitMaskEcc;                ///< Offset 98: Defines which ECC DIMM should be populated first on a 2DPC board.
+                                              ///<            4 bit mask: Bit[0]: MC0 DIMM0, Bit[1]: MC0 DIMM1, Bit[2]: MC1 DIMM0, Bit[3]: MC1 DIMM1.
+                                              ///<            For each MC, the first DIMM to be populated should be set to '1'.
+                                              ///<            For example, if one MC is T-topology, there is no special population rule, can put it as 11 for this MC and it means either D0 or D1 can be
+                                              ///<            be populated firstly.
+                                              ///<            Note: this mask is only for ECC DIMM, not for non-ECC DIMM.
+
+  UINT8   DisableMrcRetrainingOnRtcPowerLoss; ///< Offset 99: Enable/Disable DisableMrcRetrainingOnRtcPowerLoss.
+
+
+  // Since the biggest element is UINT64, this structure should be aligned with 64 bits.
+  UINT8   Rsvd[4];                           ///< Reserved for config block alignment.
+  UINT8  ResizableBarSupport;
+
+  UINT8  Rsrvd1[7];
+} SA_MISC_PEI_PREMEM_CONFIG;
+#pragma pack(pop)
+
+#endif // _SA_MISC_PEI_PREMEM_CONFIG_H_
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/Library/DxeSaPolicyLib.h b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/Library/DxeSaPolicyLib.h
new file mode 100644
index 0000000000..5f5eeeeb63
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/Library/DxeSaPolicyLib.h
@@ -0,0 +1,58 @@
+/** @file
+  Prototype of the DxeSaPolicyLib library.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _DXE_SA_POLICY_LIB_H_
+#define _DXE_SA_POLICY_LIB_H_
+
+#include <Protocol/SaPolicy.h>
+
+/**
+  This function prints the DXE phase policy.
+
+  @param[in] SaPolicy    - SA DXE Policy protocol
+**/
+VOID
+SaPrintPolicyProtocol (
+  IN  SA_POLICY_PROTOCOL         *SaPolicy
+  )
+;
+
+/**
+  CreateSaDxeConfigBlocks generates the config blocksg of SA DXE Policy.
+  It allocates and zero out buffer, and fills in the Intel default settings.
+
+  @param[out] SaPolicy                  The pointer to get SA Policy Protocol instance
+
+  @retval EFI_SUCCESS                   The policy default is initialized.
+  @retval EFI_OUT_OF_RESOURCES          Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+CreateSaDxeConfigBlocks(
+  IN OUT  SA_POLICY_PROTOCOL      **SaPolicy
+);
+
+/**
+  SaInstallPolicyProtocol installs SA Policy.
+  While installed, RC assumes the Policy is ready and finalized. So please update and override
+  any setting before calling this function.
+
+  @param[in] ImageHandle                Image handle of this driver.
+  @param[in] SaPolicy                   The pointer to SA Policy Protocol instance
+
+  @retval EFI_SUCCESS                   The policy is installed.
+  @retval EFI_OUT_OF_RESOURCES          Insufficient resources to create buffer
+
+**/
+EFI_STATUS
+EFIAPI
+SaInstallPolicyProtocol (
+  IN  EFI_HANDLE                  ImageHandle,
+  IN  SA_POLICY_PROTOCOL         *SaPolicy
+  )
+;
+
+#endif // _DXE_SA_POLICY_LIB_H_
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/Library/PeiSaPolicyLib.h b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/Library/PeiSaPolicyLib.h
new file mode 100644
index 0000000000..8b941b4420
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/Library/PeiSaPolicyLib.h
@@ -0,0 +1,13 @@
+/** @file
+  Prototype of the PeiSaPolicy library.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PEI_SA_POLICY_LIB_H_
+#define _PEI_SA_POLICY_LIB_H_
+
+#include <Ppi/SiPolicy.h>
+#include <Library/ConfigBlockLib.h>
+
+#endif // _PEI_SA_POLICY_LIBRARY_H_
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/MemInfoHob.h b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/MemInfoHob.h
new file mode 100644
index 0000000000..d6c670d4ce
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/MemInfoHob.h
@@ -0,0 +1,220 @@
+/** @file
+  This file contains definitions required for creation of
+  Memory S3 Save data, Memory Info data and Memory Platform
+  data hobs.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _MEM_INFO_HOB_H_
+#define _MEM_INFO_HOB_H_
+
+
+#pragma pack (push, 1)
+
+extern EFI_GUID gSiMemoryS3DataGuid;
+extern EFI_GUID gSiMemoryInfoDataGuid;
+extern EFI_GUID gSiMemoryPlatformDataGuid;
+
+#define MAX_NODE        2
+#define MAX_CH          4
+#define MAX_DIMM        2
+#define HOB_MAX_SAGV_POINTS 4
+
+///
+/// Defines taken from MRC so avoid having to include MrcInterface.h
+///
+
+//
+// Matches MAX_SPD_SAVE define in MRC
+//
+#ifndef MAX_SPD_SAVE
+#define MAX_SPD_SAVE 29
+#endif
+
+//
+// MRC version description.
+//
+typedef struct {
+  UINT8  Major;     ///< Major version number
+  UINT8  Minor;     ///< Minor version number
+  UINT8  Rev;       ///< Revision number
+  UINT8  Build;     ///< Build number
+} SiMrcVersion;
+
+//
+// Matches MrcChannelSts enum in MRC
+//
+#ifndef CHANNEL_NOT_PRESENT
+#define CHANNEL_NOT_PRESENT     0  // There is no channel present on the controller.
+#endif
+#ifndef CHANNEL_DISABLED
+#define CHANNEL_DISABLED        1  // There is a channel present but it is disabled.
+#endif
+#ifndef CHANNEL_PRESENT
+#define CHANNEL_PRESENT         2  // There is a channel present and it is enabled.
+#endif
+
+//
+// Matches MrcDimmSts enum in MRC
+//
+#ifndef DIMM_ENABLED
+#define DIMM_ENABLED     0  // DIMM/rank Pair is enabled, presence will be detected.
+#endif
+#ifndef DIMM_DISABLED
+#define DIMM_DISABLED    1  // DIMM/rank Pair is disabled, regardless of presence.
+#endif
+#ifndef DIMM_PRESENT
+#define DIMM_PRESENT     2  // There is a DIMM present in the slot/rank pair and it will be used.
+#endif
+#ifndef DIMM_NOT_PRESENT
+#define DIMM_NOT_PRESENT 3  // There is no DIMM present in the slot/rank pair.
+#endif
+
+//
+// Matches MrcDdrType enum in MRC
+//
+#ifndef MRC_DDR_TYPE_DDR5
+#define MRC_DDR_TYPE_DDR5     1
+#endif
+#ifndef MRC_DDR_TYPE_LPDDR5
+#define MRC_DDR_TYPE_LPDDR5   2
+#endif
+#ifndef MRC_DDR_TYPE_LPDDR4
+#define MRC_DDR_TYPE_LPDDR4   3
+#endif
+#ifndef MRC_DDR_TYPE_UNKNOWN
+#define MRC_DDR_TYPE_UNKNOWN  4
+#endif
+
+#define MAX_PROFILE_NUM     7 // number of memory profiles supported
+#define MAX_XMP_PROFILE_NUM 5 // number of XMP profiles supported
+
+//
+// DIMM timings
+//
+typedef struct {
+  UINT32 tCK;       ///< Memory cycle time, in femtoseconds.
+  UINT16 NMode;     ///< Number of tCK cycles for the channel DIMM's command rate mode.
+  UINT16 tCL;       ///< Number of tCK cycles for the channel DIMM's CAS latency.
+  UINT16 tCWL;      ///< Number of tCK cycles for the channel DIMM's minimum CAS write latency time.
+  UINT16 tFAW;      ///< Number of tCK cycles for the channel DIMM's minimum four activate window delay time.
+  UINT16 tRAS;      ///< Number of tCK cycles for the channel DIMM's minimum active to precharge delay time.
+  UINT16 tRCDtRP;   ///< Number of tCK cycles for the channel DIMM's minimum RAS# to CAS# delay time and Row Precharge delay time.
+  UINT16 tREFI;     ///< Number of tCK cycles for the channel DIMM's minimum Average Periodic Refresh Interval.
+  UINT16 tRFC;      ///< Number of tCK cycles for the channel DIMM's minimum refresh recovery delay time.
+  UINT16 tRFCpb;    ///< Number of tCK cycles for the channel DIMM's minimum per bank refresh recovery delay time.
+  UINT16 tRFC2;     ///< Number of tCK cycles for the channel DIMM's minimum refresh recovery delay time.
+  UINT16 tRFC4;     ///< Number of tCK cycles for the channel DIMM's minimum refresh recovery delay time.
+  UINT16 tRPab;     ///< Number of tCK cycles for the channel DIMM's minimum row precharge delay time for all banks.
+  UINT16 tRRD;      ///< Number of tCK cycles for the channel DIMM's minimum row active to row active delay time.
+  UINT16 tRRD_L;    ///< Number of tCK cycles for the channel DIMM's minimum row active to row active delay time for same bank groups.
+  UINT16 tRRD_S;    ///< Number of tCK cycles for the channel DIMM's minimum row active to row active delay time for different bank groups.
+  UINT16 tRTP;      ///< Number of tCK cycles for the channel DIMM's minimum internal read to precharge command delay time.
+  UINT16 tWR;       ///< Number of tCK cycles for the channel DIMM's minimum write recovery time.
+  UINT16 tWTR;      ///< Number of tCK cycles for the channel DIMM's minimum internal write to read command delay time.
+  UINT16 tWTR_L;    ///< Number of tCK cycles for the channel DIMM's minimum internal write to read command delay time for same bank groups.
+  UINT16 tWTR_S;    ///< Number of tCK cycles for the channel DIMM's minimum internal write to read command delay time for different bank groups.
+  UINT16 tCCD_L;  ///< Number of tCK cycles for the channel DIMM's minimum CAS-to-CAS delay for same bank group.
+} MRC_CH_TIMING;
+
+typedef struct {
+  UINT16 tRDPRE;     ///< Read CAS to Precharge cmd delay
+} MRC_IP_TIMING;
+
+///
+/// Memory SMBIOS & OC Memory Data Hob
+///
+typedef struct {
+  UINT8            Status;                  ///< See MrcDimmStatus for the definition of this field.
+  UINT8            DimmId;
+  UINT32           DimmCapacity;            ///< DIMM size in MBytes.
+  UINT16           MfgId;
+  UINT8            ModulePartNum[20];       ///< Module part number for DDR3 is 18 bytes however for DRR4 20 bytes as per JEDEC Spec, so reserving 20 bytes
+  UINT8            RankInDimm;              ///< The number of ranks in this DIMM.
+  UINT8            SpdDramDeviceType;       ///< Save SPD DramDeviceType information needed for SMBIOS structure creation.
+  UINT8            SpdModuleType;           ///< Save SPD ModuleType information needed for SMBIOS structure creation.
+  UINT8            SpdModuleMemoryBusWidth; ///< Save SPD ModuleMemoryBusWidth information needed for SMBIOS structure creation.
+  UINT8            SpdSave[MAX_SPD_SAVE];   ///< Save SPD Manufacturing information needed for SMBIOS structure creation.
+  UINT16           Speed;                   ///< The maximum capable speed of the device, in MHz
+  UINT8            MdSocket;                ///< MdSocket: 0 = Memory Down, 1 = Socketed. Needed for SMBIOS structure creation.
+} DIMM_INFO;
+
+typedef struct {
+  UINT8            Status;                  ///< Indicates whether this channel should be used.
+  UINT8            ChannelId;
+  UINT8            DimmCount;               ///< Number of valid DIMMs that exist in the channel.
+  MRC_CH_TIMING    Timing[MAX_PROFILE_NUM]; ///< The channel timing values.
+  DIMM_INFO        DimmInfo[MAX_DIMM];      ///< Save the DIMM output characteristics.
+} CHANNEL_INFO;
+
+typedef struct {
+  UINT8            Status;                  ///< Indicates whether this controller should be used.
+  UINT16           DeviceId;                ///< The PCI device id of this memory controller.
+  UINT8            RevisionId;              ///< The PCI revision id of this memory controller.
+  UINT8            ChannelCount;            ///< Number of valid channels that exist on the controller.
+  CHANNEL_INFO     ChannelInfo[MAX_CH];     ///< The following are channel level definitions.
+} CONTROLLER_INFO;
+
+/// This data structure contains per-SaGv timing values that are considered output by the MRC.
+typedef struct {
+  UINT32        DataRate;    ///< The memory rate for the current SaGv Point in units of MT/s
+  MRC_CH_TIMING JedecTiming; ///< Timings used for this entry's corresponding SaGv Point - derived from JEDEC SPD spec
+  MRC_IP_TIMING IpTiming;    ///< Timings used for this entry's corresponding SaGv Point - IP specific
+} HOB_SAGV_TIMING_OUT;
+
+/// This data structure contains SAGV config values that are considered output by the MRC.
+typedef struct {
+  UINT32              NumSaGvPointsEnabled; ///< Count of the total number of SAGV Points enabled.
+  UINT32              SaGvPointMask;        ///< Bit mask where each bit indicates an enabled SAGV point.
+  HOB_SAGV_TIMING_OUT SaGvTiming[HOB_MAX_SAGV_POINTS];
+} HOB_SAGV_INFO;
+
+typedef struct {
+  UINT8             Revision;
+  UINT16            DataWidth;              ///< Data width, in bits, of this memory device
+  /** As defined in SMBIOS 3.0 spec
+    Section 7.18.2 and Table 75
+  **/
+  UINT8             MemoryType;             ///< DDR type: DDR3, DDR4, or LPDDR3
+  UINT16            MaximumMemoryClockSpeed;///< The maximum capable speed of the device, in megahertz (MHz)
+  UINT16            ConfiguredMemoryClockSpeed; ///< The configured clock speed to the memory device, in megahertz (MHz)
+  /** As defined in SMBIOS 3.0 spec
+    Section 7.17.3 and Table 72
+  **/
+  UINT8             ErrorCorrectionType;
+
+  SiMrcVersion      Version;
+  BOOLEAN           EccSupport;
+  UINT8             MemoryProfile;
+  UINT8             IsDMBRunning;                      ///< Deprecated.
+  UINT32            TotalPhysicalMemorySize;
+  UINT32            DefaultXmptCK[MAX_XMP_PROFILE_NUM];///< Stores the tCK value read from SPD XMP profiles if they exist.
+  ///
+  /// Set of bit flags showing XMP and User Profile capability status for the DIMMs detected in system. For each bit, 1 is supported, 0 is unsupported.
+  /// Bit 0: XMP Profile 1 capability status
+  /// Bit 1: XMP Profile 2 capability status
+  /// Bit 2: XMP Profile 3 capability status
+  /// Bit 3: User Profile 4 capability status
+  /// Bit 4: User Profile 5 capability status
+  ///
+  UINT8             XmpProfileEnable;
+  UINT8             XmpConfigWarning;                  ///< If XMP capable DIMMs config support only 1DPC, but 2DPC is installed
+  UINT8             Ratio;                             ///< DDR Frequency Ratio, Max Value 255
+  UINT8             RefClk;
+  UINT32            VddVoltage[MAX_PROFILE_NUM];
+  UINT32            VddqVoltage[MAX_PROFILE_NUM];
+  UINT32            VppVoltage[MAX_PROFILE_NUM];
+  CONTROLLER_INFO   Controller[MAX_NODE];
+  UINT16            Ratio_UINT16;                      ///< DDR Frequency Ratio, used for programs that require ratios higher then 255
+  UINT32            NumPopulatedChannels;              ///< Total number of memory channels populated
+  HOB_SAGV_INFO     SagvConfigInfo;                    ///< This data structure contains SAGV config values that are considered output by the MRC.
+  UINT16            TotalMemWidth;                     ///< Total Memory Width in bits from all populated channels
+  BOOLEAN           MemorySpeedReducedWrongDimmSlot;   ///< Can be used by OEM BIOS to display a warning on the screen that DDR speed was reduced due to wrong DIMM population
+  BOOLEAN           MemorySpeedReducedMixedConfig;     ///< Can be used by OEM BIOS to display a warning on the screen that DDR speed was reduced due to mixed DIMM config
+  BOOLEAN           DynamicMemoryBoostTrainingFailed;  ///< TRUE if Dynamic Memory Boost failed to train and was force disabled on the last full training boot. FALSE otherwise.
+} MEMORY_INFO_DATA_HOB;
+
+#pragma pack (pop)
+
+#endif // _MEM_INFO_HOB_H_
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/Protocol/SaPolicy.h b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/Protocol/SaPolicy.h
new file mode 100644
index 0000000000..cc258debe1
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/Protocol/SaPolicy.h
@@ -0,0 +1,54 @@
+/** @file
+  Interface definition details between System Agent and platform drivers during DXE phase.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _SA_POLICY_H_
+#define _SA_POLICY_H_
+
+#include <ConfigBlock.h>
+#include <Library/ConfigBlockLib.h>
+#include <GraphicsConfig.h>
+#include <ConfigBlock/MemoryDxeConfig.h>
+
+///
+/// Extern the GUID for protocol users.
+///
+extern EFI_GUID gSaPolicyProtocolGuid;
+extern EFI_GUID gGraphicsDxeConfigGuid;
+extern EFI_GUID gMemoryDxeConfigGuid;
+
+/**
+  Don't change the original SA_POLICY_PROTOCOL_REVISION macro, external
+  modules maybe have consumed this macro in their source code.  Directly
+  update the SA_POLICY_PROTOCOL_REVISION version number may cause those
+  external modules to auto mark themselves wrong version info.
+  Always create new version macro for new Policy protocol interface.
+**/
+#define SA_POLICY_PROTOCOL_REVISION  1
+
+
+
+
+/**
+  SA DXE Policy
+
+ The SA_POLICY_PROTOCOL producer drvier is recommended to
+ set all the SA_POLICY_PROTOCOL size buffer zero before init any member parameter,
+ this clear step can make sure no random value for those unknow new version parameters.
+
+ Make sure to update the Revision if any change to the protocol, including the existing
+ internal structure definations.\n
+  Note: Here revision will be bumped up when adding/removing any config block under this structure.\n
+  <b>Revision 1</b>:
+  - Initial version.
+**/
+typedef struct {
+  CONFIG_BLOCK_TABLE_HEADER      TableHeader;    ///< Offset 0-31
+/*
+  Individual Config Block Structures are added here in memory as part of AddConfigBlock()
+*/
+} SA_POLICY_PROTOCOL;
+
+#endif
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/SaDataHob.h b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/SaDataHob.h
new file mode 100644
index 0000000000..bded1851f4
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/SaDataHob.h
@@ -0,0 +1,28 @@
+/** @file
+  The GUID definition for SaDataHob
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _SA_DATA_HOB_H_
+#define _SA_DATA_HOB_H_
+
+#include <Base.h>
+#include <CpuPcieInfo.h>
+#include <Library/PcdLib.h>
+
+extern EFI_GUID gSaDataHobGuid;
+#pragma pack (push,1)
+
+///
+/// System Agent Data Hob
+///
+typedef struct {
+  EFI_HOB_GUID_TYPE        EfiHobGuidType;                       ///< GUID Hob type structure for gSaDataHobGuid
+  UINT8                    PrimaryDisplay;
+  BOOLEAN                  ResizableBarSupport;                  ///< Resizable BAR Support
+  UINT8                    Rsvd1[2];                             ///< Reserved for future use
+} SA_DATA_HOB;
+
+#pragma pack (pop)
+#endif
-- 
2.36.1.windows.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 8/8] AlderlakeSiliconPkg/SystemAgent: Add library and driver modules
  2023-06-15 17:52 [PATCH 1/8] AlderlakeSiliconPkg: Add package and library instances Saloni Kasbekar
                   ` (5 preceding siblings ...)
  2023-06-15 17:53 ` [PATCH 7/8] AlderlakeSiliconPkg/SystemAgent: Add include headers Saloni Kasbekar
@ 2023-06-15 17:53 ` Saloni Kasbekar
  2023-07-24  8:07   ` [edk2-devel] " Chaganty, Rangasai V
  2023-07-23  0:04 ` [edk2-devel] [PATCH 1/8] AlderlakeSiliconPkg: Add package and library instances Chaganty, Rangasai V
  7 siblings, 1 reply; 15+ messages in thread
From: Saloni Kasbekar @ 2023-06-15 17:53 UTC (permalink / raw)
  To: devel
  Cc: Saloni Kasbekar, Sai Chaganty, Nate DeSimone, Isaac Oram,
	Rosen Chuang

Adds the following modules:
- Library/DxeSaPolicyLib
- SaInit

Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Isaac Oram <isaac.w.oram@intel.com>
Cc: Rosen Chuang <rosen.chuang@intel.com>
Signed-off-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
---
 .../Library/DxeSaPolicyLib/DxeSaPolicyLib.c   | 225 ++++++++++++++++++
 .../Library/DxeSaPolicyLib/DxeSaPolicyLib.inf |  46 ++++
 .../DxeSaPolicyLib/DxeSaPolicyLibrary.h       |  30 +++
 .../SystemAgent/SaInit/Dxe/SaAcpi.c           | 193 +++++++++++++++
 .../SystemAgent/SaInit/Dxe/SaInit.c           |  97 ++++++++
 .../SystemAgent/SaInit/Dxe/SaInit.h           |  42 ++++
 .../SystemAgent/SaInit/Dxe/SaInitDxe.c        |  90 +++++++
 .../SystemAgent/SaInit/Dxe/SaInitDxe.h        | 119 +++++++++
 .../SystemAgent/SaInit/Dxe/SaInitDxe.inf      |  98 ++++++++
 9 files changed, 940 insertions(+)
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLib.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLib.inf
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLibrary.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaAcpi.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInit.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInit.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.inf

diff --git a/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLib.c b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLib.c
new file mode 100644
index 0000000000..d812f300c1
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLib.c
@@ -0,0 +1,225 @@
+/** @file
+  This file provide services for DXE phase policy default initialization
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "DxeSaPolicyLibrary.h"
+#include <Library/DxeGraphicsPolicyLib.h>
+#include <Register/SaRegsHostBridge.h>
+#include "MemoryConfig.h"
+
+extern EFI_GUID gMemoryDxeConfigGuid;
+
+/**
+  This function prints the SA DXE phase policy.
+
+  @param[in] SaPolicy - SA DXE Policy protocol
+**/
+VOID
+SaPrintPolicyProtocol (
+  IN  SA_POLICY_PROTOCOL      *SaPolicy
+  )
+{
+  UINT8                       ControllerIndex;
+  UINT8                       ChannelIndex;
+  EFI_STATUS                  Status;
+  MEMORY_DXE_CONFIG           *MemoryDxeConfig;
+
+  Status = GetConfigBlock ((VOID *) SaPolicy, &gMemoryDxeConfigGuid, (VOID *)&MemoryDxeConfig);
+  ASSERT_EFI_ERROR (Status);
+
+
+  DEBUG_CODE_BEGIN ();
+  INTN  i;
+
+  DEBUG ((DEBUG_INFO, "\n------------------------ SA Policy (DXE) print BEGIN -----------------\n"));
+  DEBUG ((DEBUG_INFO, "Revision : %x\n", SaPolicy->TableHeader.Header.Revision));
+  ASSERT (SaPolicy->TableHeader.Header.Revision == SA_POLICY_PROTOCOL_REVISION);
+
+  DEBUG ((DEBUG_INFO, "------------------------ SA_MEMORY_CONFIGURATION -----------------\n"));
+
+  DEBUG ((DEBUG_INFO, " SpdAddressTable[%d] :", 4));
+  for (i = 0; i < 4; i++) {
+    DEBUG ((DEBUG_INFO, " %x", MemoryDxeConfig->SpdAddressTable[i]));
+  }
+  DEBUG ((DEBUG_INFO, "\n"));
+
+  for (ControllerIndex = 0; ControllerIndex < MEM_CFG_MAX_CONTROLLERS; ControllerIndex++) {
+    for (ChannelIndex = 0; ChannelIndex < MEM_CFG_MAX_CHANNELS; ChannelIndex++) {
+      DEBUG ((DEBUG_INFO, " SlotMap[%d][%d] : 0x%x\n", ControllerIndex, ChannelIndex, MemoryDxeConfig->SlotMap[ControllerIndex][ChannelIndex]));
+    }
+  }
+  DEBUG ((DEBUG_INFO, " MrcTimeMeasure  : %x\n", MemoryDxeConfig->MrcTimeMeasure));
+  DEBUG ((DEBUG_INFO, " MrcFastBoot     : %x\n", MemoryDxeConfig->MrcFastBoot));
+
+  DEBUG ((DEBUG_INFO, "------------------------ CPU_PCIE_CONFIGURATION -----------------\n"));
+  DEBUG ((DEBUG_INFO, " PegAspm[%d] :", SA_PEG_MAX_FUN));
+  DEBUG ((DEBUG_INFO, " PegRootPortHPE[%d] :", SA_PEG_MAX_FUN));
+  DEBUG ((DEBUG_INFO, "\n"));
+
+
+  DEBUG ((DEBUG_INFO, "\n------------------------ SA Policy (DXE) print END -----------------\n"));
+  DEBUG_CODE_END ();
+
+  return;
+}
+
+/**
+  Load DXE Config block default
+
+  @param[in] ConfigBlockPointer         Pointer to config block
+**/
+VOID
+LoadMemoryDxeDefault (
+  IN VOID    *ConfigBlockPointer
+  )
+{
+  UINT8                    ControllerIndex;
+  UINT8                    ChannelIndex;
+  MEMORY_DXE_CONFIG        *MemoryDxeConfig;
+
+  MemoryDxeConfig = ConfigBlockPointer;
+  ///
+  /// Initialize the Memory Configuration
+  ///
+  ///
+  /// DIMM SMBus addresses info
+  /// Refer to the SpdAddressTable[] mapping rule in DxeSaPolicyLibrary.h
+  ///
+  MemoryDxeConfig->SpdAddressTable = AllocateZeroPool (sizeof (UINT8) * 4);
+  ASSERT (MemoryDxeConfig->SpdAddressTable != NULL);
+  if (MemoryDxeConfig->SpdAddressTable != NULL) {
+    MemoryDxeConfig->SpdAddressTable[0] = DIMM_SMB_SPD_P0C0D0;
+    MemoryDxeConfig->SpdAddressTable[1] = DIMM_SMB_SPD_P0C0D1;
+    MemoryDxeConfig->SpdAddressTable[2] = DIMM_SMB_SPD_P0C1D0;
+    MemoryDxeConfig->SpdAddressTable[3] = DIMM_SMB_SPD_P0C1D1;
+  }
+  MemoryDxeConfig->SlotMap = (UINT8**)AllocateZeroPool (sizeof (UINT8*) * MEM_CFG_MAX_CONTROLLERS);
+  ASSERT (MemoryDxeConfig->SlotMap != NULL);
+  if (MemoryDxeConfig->SlotMap != NULL) {
+    for (ControllerIndex = 0; ControllerIndex < MEM_CFG_MAX_CONTROLLERS; ControllerIndex++) {
+      MemoryDxeConfig->SlotMap[ControllerIndex] = (UINT8*)AllocateZeroPool (sizeof (UINT8) * MEM_CFG_MAX_CHANNELS);
+      ASSERT (MemoryDxeConfig->SlotMap[ControllerIndex] != NULL);
+      if (MemoryDxeConfig->SlotMap[ControllerIndex] != NULL) {
+        for (ChannelIndex = 0; ChannelIndex < MEM_CFG_MAX_CHANNELS; ChannelIndex++) {
+          MemoryDxeConfig->SlotMap[ControllerIndex][ChannelIndex] = 0x01;
+        }
+      }
+    }
+  }
+}
+
+/**
+  LoadSaDxeConfigBlockDefault - Initialize default settings for each SA Config block
+
+  @param[in] ConfigBlockPointer         The buffer pointer that will be initialized as specific config block
+  @param[in] BlockId                    Request to initialize defaults of specified config block by given Block ID
+
+  @retval EFI_SUCCESS                   The given buffer has contained the defaults of requested config block
+  @retval EFI_NOT_FOUND                 Block ID is not defined so no default Config block will be initialized
+**/
+
+GLOBAL_REMOVE_IF_UNREFERENCED COMPONENT_BLOCK_ENTRY  mSaDxeIpBlocks [] = {
+  {&gMemoryDxeConfigGuid,   sizeof (MEMORY_DXE_CONFIG),   MEMORY_DXE_CONFIG_REVISION,    LoadMemoryDxeDefault}
+};
+
+
+/**
+  CreateSaDxeConfigBlocks generates the config blocksg of SA DXE Policy.
+  It allocates and zero out buffer, and fills in the Intel default settings.
+
+  @param[out] SaPolicy               The pointer to get SA  DXE Protocol instance
+
+  @retval EFI_SUCCESS                   The policy default is initialized.
+  @retval EFI_OUT_OF_RESOURCES          Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+CreateSaDxeConfigBlocks (
+  IN OUT  SA_POLICY_PROTOCOL      **SaPolicy
+  )
+{
+  UINT16              TotalBlockSize;
+  EFI_STATUS          Status;
+  SA_POLICY_PROTOCOL  *SaInitPolicy;
+  UINT16              RequiredSize;
+
+  DEBUG ((DEBUG_INFO, "SA Create Dxe Config Blocks\n"));
+
+  SaInitPolicy = NULL;
+
+  TotalBlockSize = GetComponentConfigBlockTotalSize (&mSaDxeIpBlocks[0], sizeof (mSaDxeIpBlocks) / sizeof (COMPONENT_BLOCK_ENTRY));
+  TotalBlockSize += GraphicsGetConfigBlockTotalSizeDxe ();
+  DEBUG ((DEBUG_INFO, "TotalBlockSize = 0x%x\n", TotalBlockSize));
+
+  RequiredSize = sizeof (CONFIG_BLOCK_TABLE_HEADER) + TotalBlockSize;
+
+  Status = CreateConfigBlockTable (RequiredSize, (VOID *) &SaInitPolicy);
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Initialize Policy Revision
+  //
+  SaInitPolicy->TableHeader.Header.Revision = SA_POLICY_PROTOCOL_REVISION;
+  //
+  // Add config blocks.
+  //
+  Status =  AddComponentConfigBlocks ((VOID *) SaInitPolicy, &mSaDxeIpBlocks[0], sizeof (mSaDxeIpBlocks) / sizeof (COMPONENT_BLOCK_ENTRY));
+  ASSERT_EFI_ERROR (Status);
+
+
+  // Gfx
+  Status = GraphicsAddConfigBlocksDxe ((VOID *) SaInitPolicy);
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Assignment for returning SaInitPolicy config block base address
+  //
+  *SaPolicy = SaInitPolicy;
+  return Status;
+}
+
+
+/**
+  SaInstallPolicyProtocol installs SA Policy.
+  While installed, RC assumes the Policy is ready and finalized. So please update and override
+  any setting before calling this function.
+
+  @param[in] ImageHandle                Image handle of this driver.
+  @param[in] SaPolicy                   The pointer to SA Policy Protocol instance
+
+  @retval EFI_SUCCESS                   The policy is installed.
+  @retval EFI_OUT_OF_RESOURCES          Insufficient resources to create buffer
+
+**/
+EFI_STATUS
+EFIAPI
+SaInstallPolicyProtocol (
+  IN  EFI_HANDLE                  ImageHandle,
+  IN  SA_POLICY_PROTOCOL         *SaPolicy
+  )
+{
+  EFI_STATUS            Status;
+
+  ///
+  /// Print SA DXE Policy
+  ///
+  SaPrintPolicyProtocol (SaPolicy);
+  GraphicsDxePolicyPrint (SaPolicy);
+
+  ///
+  /// Install protocol to to allow access to this Policy.
+  ///
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &ImageHandle,
+                  &gSaPolicyProtocolGuid,
+                  SaPolicy,
+                  NULL
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}
+
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLib.inf b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLib.inf
new file mode 100644
index 0000000000..02d52b6e6b
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLib.inf
@@ -0,0 +1,46 @@
+## @file
+# Component description file for the PeiSaPolicy library.
+#
+#   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+#   SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = DxeSaPolicyLib
+FILE_GUID = B402A3A4-4B82-410E-B79C-5914880A05E7
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = DxeSaPolicyLib
+
+
+[LibraryClasses]
+BaseMemoryLib
+UefiRuntimeServicesTableLib
+UefiBootServicesTableLib
+DebugLib
+PostCodeLib
+ConfigBlockLib
+HobLib
+DxeGraphicsPolicyLib
+CpuPlatformLib
+
+[Packages]
+MdePkg/MdePkg.dec
+AlderlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+DxeSaPolicyLib.c
+DxeSaPolicyLibrary.h
+
+
+[Guids]
+gMemoryDxeConfigGuid
+
+
+[Protocols]
+gSaPolicyProtocolGuid ## PRODUCES
+
+[Pcd]
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLibrary.h b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLibrary.h
new file mode 100644
index 0000000000..14fc02512e
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLibrary.h
@@ -0,0 +1,30 @@
+/** @file
+  Header file for the DxeSaPolicy library.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _DXE_SA_POLICY_LIBRARY_H_
+#define _DXE_SA_POLICY_LIBRARY_H_
+
+#include <Uefi.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/ConfigBlockLib.h>
+#include <CpuPcieConfigGen3.h>
+#include <CpuPcieConfig.h>
+#include <Protocol/SaPolicy.h>
+
+#define WORD_FIELD_VALID_BIT  BIT15
+///
+/// DIMM SMBus addresses
+///
+#define DIMM_SMB_SPD_P0C0D0 0xA0
+#define DIMM_SMB_SPD_P0C0D1 0xA2
+#define DIMM_SMB_SPD_P0C1D0 0xA4
+#define DIMM_SMB_SPD_P0C1D1 0xA6
+
+#endif // _DXE_SA_POLICY_LIBRARY_H_
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaAcpi.c b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaAcpi.c
new file mode 100644
index 0000000000..f73995be0c
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaAcpi.c
@@ -0,0 +1,193 @@
+/** @file
+  This is the driver that initializes the Intel System Agent.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "SaInitDxe.h"
+#include "SaInit.h"
+#include <Protocol/SaNvsArea.h>
+#include <Library/PchInfoLib.h>
+#include <CpuPcieInfo.h>
+#include <Library/AslUpdateLib.h>
+#include <HostBridgeDataHob.h>
+#include <Library/CpuPlatformLib.h>
+#include <Library/PeiDxeSmmReserveMmio64SizeLib.h>
+#include <Register/Cpuid.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <Pi/PiFirmwareFile.h>
+
+///
+/// Global Variables
+///
+GLOBAL_REMOVE_IF_UNREFERENCED SYSTEM_AGENT_NVS_AREA_PROTOCOL  mSaNvsAreaProtocol;
+
+/**
+  A protocol callback which updates 64bits MMIO Base and Length in SA GNVS area
+**/
+VOID
+UpdateSaGnvsForMmioResourceBaseLength (
+  VOID
+  )
+{
+  EFI_PHYSICAL_ADDRESS      PciBaseAddress;
+  UINT32                    Tolud;
+  UINT64                    Length;
+  UINT64                    McD0BaseAddress;
+  UINTN                     ResMemLimit1;
+  BOOLEAN                   EnableAbove4GBMmioBiosAssignemnt;
+  VOID                      *CpuHob;
+  UINT8                     PhysicalAddressBits;
+  UINT64                    PhysicalAddressLimit;
+
+  PciBaseAddress                   = 0;
+  Tolud                            = 0;
+  Length                           = 0;
+  ResMemLimit1                     = 0;
+  EnableAbove4GBMmioBiosAssignemnt = TRUE;
+  CpuHob                           = NULL;
+  PhysicalAddressBits              = 0;
+  PhysicalAddressLimit             = 0;
+  //
+  // Read memory map registers
+  //
+  McD0BaseAddress        = PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, SA_MC_BUS, 0, 0, 0);
+  Tolud                  = PciSegmentRead32 (McD0BaseAddress + R_SA_TOLUD) & B_SA_TOLUD_TOLUD_MASK;
+  PciBaseAddress         = Tolud;
+
+  ResMemLimit1 = (UINTN) PcdGet64 (PcdSiPciExpressBaseAddress);
+
+  Length = ResMemLimit1 - PciBaseAddress;
+
+  CpuHob = GetFirstHob (EFI_HOB_TYPE_CPU);
+  if (CpuHob != NULL) {
+    PhysicalAddressBits  = ((EFI_HOB_CPU *) CpuHob)->SizeOfMemorySpace;
+    PhysicalAddressLimit = LShiftU64 (1, PhysicalAddressBits);
+  }
+  //
+  // Check Enable Above 4GB MMIO or not
+  //
+
+  DEBUG ((DEBUG_INFO, "Update SA GNVS Area.\n"));
+  mSaNvsAreaProtocol.Area->Mmio32Base   = (UINT32) PciBaseAddress;
+  mSaNvsAreaProtocol.Area->Mmio32Length = (UINT32) Length;
+  if (EnableAbove4GBMmioBiosAssignemnt == TRUE) {
+    if (PhysicalAddressBits != 0 && ( PhysicalAddressLimit % 0x4000000000) == 0) { // Checking Memory Size multiples of 256GB
+      mSaNvsAreaProtocol.Area->Mmio64Base   = BASE_256GB;
+      //
+      // Some platforms need to reserve MMIO space from PhysicalAddressLimit for P2SB usage.
+      //
+      mSaNvsAreaProtocol.Area->Mmio64Length = PhysicalAddressLimit - mSaNvsAreaProtocol.Area->Mmio64Base - ReserveMmio64Size ();
+    } else {
+      mSaNvsAreaProtocol.Area->Mmio64Base   = BASE_256GB;
+      mSaNvsAreaProtocol.Area->Mmio64Length = SIZE_256GB;
+    }
+  }
+  DEBUG ((DEBUG_INFO, "SaNvsAreaProtocol.Area->Mmio64Base = %lx\n", mSaNvsAreaProtocol.Area->Mmio64Base));
+  DEBUG ((DEBUG_INFO, "SaNvsAreaProtocol.Area->Mmio64Length = %lx\n", mSaNvsAreaProtocol.Area->Mmio64Length));
+  DEBUG ((DEBUG_INFO, "SaNvsAreaProtocol.Area->Mmio32Base = %lx\n", mSaNvsAreaProtocol.Area->Mmio32Base));
+  DEBUG ((DEBUG_INFO, "SaNvsAreaProtocol.Area->Mmio32Length = %lx\n", mSaNvsAreaProtocol.Area->Mmio32Length));
+}
+
+/**
+  Initialize SA Nvs Area operation region.
+
+  @retval EFI_SUCCESS    initialized successfully
+  @retval EFI_NOT_FOUND  Nvs Area operation region is not found
+**/
+EFI_STATUS
+PatchSaNvsAreaAddress (
+  VOID
+  )
+{
+  EFI_STATUS                            Status;
+  UINT32                                Address;
+  UINT16                                Length;
+
+  Address = (UINT32) (UINTN) mSaNvsAreaProtocol.Area;
+  Length  = (UINT16) sizeof (SYSTEM_AGENT_NVS_AREA);
+  DEBUG ((DEBUG_INFO, "PatchSaNvsAreaAddress: SA NVS Address %x Length %x\n", Address, Length));
+
+  Status  = UpdateNameAslCode (SIGNATURE_32 ('S','A','N','B'), &Address, sizeof (Address));
+  ASSERT_EFI_ERROR (Status);
+  Status  = UpdateNameAslCode (SIGNATURE_32 ('S','A','N','L'), &Length, sizeof (Length));
+  ASSERT_EFI_ERROR (Status);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  This function gets registered as a callback to perform Dmar Igd
+
+  @param[in] Event     - A pointer to the Event that triggered the callback.
+  @param[in] Context   - A pointer to private data registered with the callback function.
+**/
+VOID
+EFIAPI
+SaAcpiEndOfDxeCallback (
+  IN EFI_EVENT    Event,
+  IN VOID         *Context
+  )
+{
+
+  DEBUG ((DEBUG_INFO, "%a - Start\n", __FUNCTION__));
+
+  PatchSaNvsAreaAddress();
+
+  DEBUG ((DEBUG_INFO, "%a - End\n", __FUNCTION__));
+  return;
+}
+
+
+/**
+  SystemAgent Acpi Initialization.
+
+  @param[in] ImageHandle             Handle for the image of this driver
+
+  @retval EFI_SUCCESS             The function completed successfully
+  @retval EFI_OUT_OF_RESOURCES    No enough buffer to allocate
+**/
+EFI_STATUS
+EFIAPI
+SaAcpiInit (
+  IN EFI_HANDLE         ImageHandle
+  )
+{
+  EFI_STATUS                Status;
+  EFI_EVENT                 EndOfDxeEvent;
+
+  ///
+  /// Install System Agent Global NVS protocol
+  ///
+  DEBUG ((DEBUG_INFO, "Install SA GNVS protocol\n"));
+  Status = (gBS->AllocatePool) (EfiACPIMemoryNVS, sizeof (SYSTEM_AGENT_NVS_AREA), (VOID **) &mSaNvsAreaProtocol.Area);
+  ASSERT_EFI_ERROR (Status);
+  ZeroMem ((VOID *) mSaNvsAreaProtocol.Area, sizeof (SYSTEM_AGENT_NVS_AREA));
+
+
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &ImageHandle,
+                  &gSaNvsAreaProtocolGuid,
+                  &mSaNvsAreaProtocol,
+                  NULL
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+
+  ///
+  /// Register an end of DXE event for SA ACPI to do tasks before invoking any UEFI drivers,
+  /// applications, or connecting consoles,...
+  ///
+  
+  Status = gBS->CreateEventEx (
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_CALLBACK,
+                  SaAcpiEndOfDxeCallback,
+                  NULL,
+                  &gEfiEndOfDxeEventGroupGuid,
+                  &EndOfDxeEvent
+                  );
+
+  return EFI_SUCCESS;
+}
+
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInit.c b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInit.c
new file mode 100644
index 0000000000..5e472b0f60
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInit.c
@@ -0,0 +1,97 @@
+/** @file
+  This is the Common driver that initializes the Intel System Agent.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "SaInit.h"
+#include <Library/PciSegmentLib.h>
+#include <HostBridgeDataHob.h>
+#include <Protocol/PciEnumerationComplete.h>
+#include <Library/CpuPlatformLib.h>
+#include <Register/SaRegsHostBridge.h>
+
+///
+/// Global Variables
+///
+BOOLEAN                                                              mSkipPamLock = FALSE;
+
+/*
+  Intel(R) Core Processor Skylake BWG version 0.4.0
+
+  18.6 System Agent Configuration Locking
+   For reliable operation and security, System BIOS must set the following bits:
+   1. For all modern Intel processors, Intel strongly recommends that BIOS should set
+       the D_LCK bit. Set B0:D0:F0.R088h [4] = 1b to lock down SMRAM space.
+  BaseAddr values for mSaSecurityRegisters that uses PciExpressBaseAddress will be initialized at
+  Runtime inside function CpuPcieInitPolicy().
+*/
+GLOBAL_REMOVE_IF_UNREFERENCED BOOT_SCRIPT_REGISTER_SETTING mSaSecurityRegisters[] = {
+  {0,  R_SA_SMRAMC,  0xFFFFFFFF,  BIT4}
+};
+
+/**
+  SystemAgent Initialization Common Function.
+
+  @retval EFI_SUCCESS   - Always.
+**/
+
+VOID
+SaInitEntryPoint (
+  VOID
+  )
+{
+  HOST_BRIDGE_DATA_HOB        *HostBridgeDataHob;
+
+  ///
+  /// Get Host Bridge Data HOB
+  ///
+  HostBridgeDataHob = NULL;
+  HostBridgeDataHob = (HOST_BRIDGE_DATA_HOB *) GetFirstGuidHob (&gHostBridgeDataHobGuid);
+  if (HostBridgeDataHob != NULL) {
+    mSkipPamLock = HostBridgeDataHob->SkipPamLock;
+  }
+  return;
+}
+
+/**
+  This function does SA security lock
+**/
+VOID
+SaSecurityLock (
+  VOID
+  )
+{
+  UINT8           Index;
+  UINT64          BaseAddress;
+  UINT32          RegOffset;
+  UINT32          Data32And;
+  UINT32          Data32Or;
+
+  ///
+  /// 17.2 System Agent Security Lock configuration
+  ///
+  DEBUG ((DEBUG_INFO, "DXE SaSecurityLock\n"));
+  for (Index = 0; Index < (sizeof (mSaSecurityRegisters) / sizeof (BOOT_SCRIPT_REGISTER_SETTING)); Index++) {
+    BaseAddress = mSaSecurityRegisters[Index].BaseAddr;
+    RegOffset   = mSaSecurityRegisters[Index].Offset;
+    Data32And   = mSaSecurityRegisters[Index].AndMask;
+    Data32Or    = mSaSecurityRegisters[Index].OrMask;
+
+    if (RegOffset == R_SA_SMRAMC) {
+      ///
+      /// SMRAMC LOCK must use CF8/CFC access
+      ///
+      PciCf8Or8 (PCI_CF8_LIB_ADDRESS (SA_MC_BUS, SA_MC_DEV, SA_MC_FUN, R_SA_SMRAMC), (UINT8) Data32Or);
+      BaseAddress = S3_BOOT_SCRIPT_LIB_PCI_ADDRESS (SA_MC_BUS, SA_MC_DEV, SA_MC_FUN, R_SA_SMRAMC);
+      S3BootScriptSavePciCfgReadWrite (
+        S3BootScriptWidthUint8,
+        (UINTN) BaseAddress,
+        &Data32Or,
+        &Data32And
+        );
+    }
+  }
+
+}
+
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInit.h b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInit.h
new file mode 100644
index 0000000000..14e48a3eb4
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInit.h
@@ -0,0 +1,42 @@
+/** @file
+  Header file for SA Common Initialization Driver.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _SA_INITIALIZATION_DRIVER_H_
+#define _SA_INITIALIZATION_DRIVER_H_
+
+#include <Uefi.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Pci.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/UefiLib.h>
+#include <Library/IoLib.h>
+#include <Library/PciCf8Lib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Guid/EventGroup.h>
+#include <CpuRegs.h>
+#include <Library/CpuPlatformLib.h>
+#include <Protocol/SaPolicy.h>
+
+typedef struct {
+  UINT64  BaseAddr;
+  UINT32  Offset;
+  UINT32  AndMask;
+  UINT32  OrMask;
+} BOOT_SCRIPT_REGISTER_SETTING;
+
+/**
+  SystemAgent Initialization Common Function.
+
+  @retval EFI_SUCCESS   - Always.
+**/
+VOID
+SaInitEntryPoint (
+  VOID
+  );
+#endif
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.c b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.c
new file mode 100644
index 0000000000..0e613fce3a
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.c
@@ -0,0 +1,90 @@
+/** @file
+  This is the driver that initializes the Intel System Agent.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "SaInitDxe.h"
+#include "SaInit.h"
+#include <MemInfoHob.h>
+#include <Protocol/PciEnumerationComplete.h>
+#include <Library/CpuPlatformLib.h>
+#include <Library/CpuPcieInfoFruLib.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16                   mPcieIoTrapAddress;
+
+/**
+  SystemAgent Dxe Initialization.
+
+  @param[in] ImageHandle             Handle for the image of this driver
+  @param[in] SystemTable             Pointer to the EFI System Table
+
+  @retval EFI_SUCCESS             The function completed successfully
+  @retval EFI_OUT_OF_RESOURCES    No enough buffer to allocate
+**/
+EFI_STATUS
+EFIAPI
+SaInitEntryPointDxe (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  )
+{
+  EFI_STATUS                Status;
+  VOID                      *Registration;
+#if FixedPcdGetBool(PcdFspWrapperEnable) == 0
+  EFI_EVENT                 Event;
+#endif
+
+  DEBUG ((DEBUG_INFO, "SaInitDxe Start\n"));
+
+  SaInitEntryPoint ();
+
+  Status = SaAcpiInit (ImageHandle);
+  ///
+  /// Create PCI Enumeration Completed callback for CPU PCIe
+  ///
+  EfiCreateProtocolNotifyEvent (
+    &gEfiPciEnumerationCompleteProtocolGuid,
+    TPL_CALLBACK,
+    CpuPciEnumCompleteCallback,
+    NULL,
+    &Registration
+    );
+
+  DEBUG ((DEBUG_INFO, "SaInitDxe End\n"));
+
+  return EFI_SUCCESS;
+}
+
+/**
+  This function gets registered as a callback to perform CPU PCIe initialization before EndOfDxe
+
+  @param[in] Event     - A pointer to the Event that triggered the callback.
+  @param[in] Context   - A pointer to private data registered with the callback function.
+**/
+VOID
+EFIAPI
+CpuPciEnumCompleteCallback (
+  IN EFI_EVENT    Event,
+  IN VOID         *Context
+  )
+{
+  EFI_STATUS          Status;
+  VOID                *ProtocolPointer;
+
+  DEBUG ((DEBUG_INFO, "CpuPciEnumCompleteCallback Start\n"));
+  ///
+  /// Check if this is first time called by EfiCreateProtocolNotifyEvent() or not,
+  /// if it is, we will skip it until real event is triggered
+  ///
+  Status = gBS->LocateProtocol (&gEfiPciEnumerationCompleteProtocolGuid, NULL, (VOID **) &ProtocolPointer);
+  if (EFI_SUCCESS != Status) {
+    return;
+  }
+
+  gBS->CloseEvent (Event);
+
+  UpdateSaGnvsForMmioResourceBaseLength ();
+  DEBUG ((DEBUG_INFO, "CpuPciEnumCompleteCallback End\n"));
+  return;
+}
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.h b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.h
new file mode 100644
index 0000000000..72c0a25493
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.h
@@ -0,0 +1,119 @@
+/** @file
+  Header file for SA Initialization Driver.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _SA_INIT_DXE_DRIVER_H_
+#define _SA_INIT_DXE_DRIVER_H_
+
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/AcpiTable.h>
+#include <Library/DxeIgdOpRegionInitLib.h>
+#include <Library/CpuPlatformLib.h>
+#include <Register/SaRegsHostBridge.h>
+
+///
+/// Driver Consumed Protocol Prototypes
+///
+#include <Protocol/SaPolicy.h>
+
+typedef struct {
+  UINT64                Address;
+  EFI_BOOT_SCRIPT_WIDTH Width;
+  UINT32                Value;
+} BOOT_SCRIPT_PCI_REGISTER_SAVE;
+
+///
+/// Function Prototype
+///
+/**
+  This function gets registered as a callback to perform CPU PCIe initialization before ExitPmAuth
+
+  @param[in] Event     - A pointer to the Event that triggered the callback.
+  @param[in] Context   - A pointer to private data registered with the callback function.
+
+**/
+VOID
+EFIAPI
+CpuPciEnumCompleteCallback (
+  IN EFI_EVENT Event,
+  IN VOID      *Context
+  );
+
+/**
+  <b>System Agent Initialization DXE Driver Entry Point</b>
+  - <b>Introduction</b> \n
+    Based on the information/data in SA_POLICY_PROTOCOL, this module performs further SA initialization in DXE phase,
+    e.g. internal devices enable/disable, SSVID/SID programming, graphic power-management, VT-d, IGD OpRegion initialization.
+    From the perspective of a PCI Express hierarchy, the Broadwell System Agent and PCH together appear as a Root Complex with root ports the number of which depends on how the 8 PCH ports and 4 System Agent PCIe ports are configured [4x1, 2x8, 1x16].
+    There is an internal link (DMI or OPI) that connects the System Agent to the PCH component. This driver includes initialization of SA DMI, PCI Express, SA & PCH Root Complex Topology.
+    For iGFX, this module implements the initialization of the Graphics Technology Power Management from the Broadwell System Agent BIOS Specification and the initialization of the IGD OpRegion/Software SCI - BIOS Specification.
+    The ASL files that go along with the driver define the IGD OpRegion mailboxes in ACPI space and implement the software SCI interrupt mechanism.
+    The IGD OpRegion/Software SCI code serves as a communication interface between system BIOS, ASL, and Intel graphics driver including making a block of customizable data (VBT) from the Intel video BIOS available.
+    Reference Code for the SCI service functions "Get BIOS Data" and "System BIOS Callback" can be found in the ASL files, those functions can be platform specific, the sample provided in the reference code are implemented for Intel CRB.
+    This module implements the VT-d functionality described in the Broadwell System Agent BIOS Specification.
+    This module publishes the LegacyRegion protocol to control the read and write accesses to the Legacy BIOS ranges.
+    E000 and F000 segments are the legacy BIOS ranges and contain pointers to the ACPI regions, SMBIOS tables and so on. This is a private protocol used by Intel Framework.
+    This module registers CallBack function that performs SA security registers lockdown at end of post as required from Broadwell Bios Spec.
+    In addition, this module publishes the SaInfo Protocol with information such as current System Agent reference code version#.
+
+  - @pre
+    - EFI_FIRMWARE_VOLUME_PROTOCOL: Documented in Firmware Volume Specification, available at the URL: http://www.intel.com/technology/framework/spec.htm
+    - SA_POLICY_PROTOCOL: A protocol published by a platform DXE module executed earlier; this is documented in this document as well.
+    - EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL: Documented in the Unified Extensible Firmware Interface Specification, version 2.0, available at the URL: http://www.uefi.org/specs/
+    - EFI_BOOT_SCRIPT_SAVE_PROTOCOL: A protocol published by a platform DXE module executed earlier; refer to the Sample Code section of the Framework PCH Reference Code.
+    - EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL: Documented in the Unified Extensible Firmware Interface Specification, version 2.0, available at the URL: http://www.uefi.org/specs/
+    - EFI_ACPI_TABLE_PROTOCOL : Documented in PI Specification 1.2
+    - EFI_CPU_IO_PROTOCOL: Documented in CPU I/O Protocol Specification, available at the URL: http://www.intel.com/technology/framework/spec.htm
+    - EFI_DATA_HUB_PROTOCOL: Documented in EFI Data Hub Infrastructure Specification, available at the URL: http://www.intel.com/technology/framework/spec.htm
+    - EFI_HII_PROTOCOL (or EFI_HII_DATABASE_PROTOCOL for UEFI 2.1): Documented in Human Interface Infrastructure Specification, available at the URL: http://www.intel.com/technology/framework/spec.htm
+    (For EFI_HII_DATABASE_PROTOCOL, refer to UEFI Specification Version 2.1 available at the URL: http://www.uefi.org/)
+
+  - @result
+    IGD power-management functionality is initialized;  VT-d is initialized (meanwhile, the DMAR table is updated); IGD OpRegion is initialized - IGD_OPREGION_PROTOCOL installed, IGD OpRegion allocated and mailboxes initialized, chipset initialized and ready to generate Software SCI for Internal graphics events. Publishes the SA_INFO_PROTOCOL with current SA reference code version #. Publishes the EFI_LEGACY_REGION_PROTOCOL documented in the Compatibility Support Module Specification, version 0.9, available at the URL: http://www.intel.com/technology/framework/spec.htm
+
+  - <b>References</b> \n
+    IGD OpRegion/Software SCI for Broadwell
+    Advanced Configuration and Power Interface Specification Revision 4.0a.
+
+  - <b>Porting Recommendations</b> \n
+    No modification of the DXE driver should be typically necessary.
+    This driver should be executed after all related devices (audio, video, ME, etc.) are initialized to ensure correct data in DMAR table and DMA-remapping registers.
+
+  @param[in] ImageHandle             Handle for the image of this driver
+  @param[in] SystemTable             Pointer to the EFI System Table
+
+  @retval EFI_SUCCESS             The function completed successfully
+  @retval EFI_OUT_OF_RESOURCES    No enough buffer to allocate
+**/
+EFI_STATUS
+EFIAPI
+SaInitEntryPointDxe (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  );
+
+/**
+  SystemAgent Acpi Initialization.
+
+  @param[in] ImageHandle             Handle for the image of this driver
+
+  @retval EFI_SUCCESS             The function completed successfully
+  @retval EFI_OUT_OF_RESOURCES    No enough buffer to allocate
+**/
+EFI_STATUS
+EFIAPI
+SaAcpiInit (
+  IN EFI_HANDLE         ImageHandle
+  );
+
+/**
+  A protocol callback which updates 64bits MMIO Base and Length in SA GNVS area
+**/
+VOID
+UpdateSaGnvsForMmioResourceBaseLength (
+  VOID
+  );
+
+#endif
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.inf b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.inf
new file mode 100644
index 0000000000..b434ce9027
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.inf
@@ -0,0 +1,98 @@
+## @file
+# Component description file for SystemAgent Initialization driver
+#
+#   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+#   SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = SaInitDxe
+FILE_GUID = DE23ACEE-CF55-4fb6-AA77-984AB53DE811
+VERSION_STRING = 1.0
+MODULE_TYPE = DXE_DRIVER
+ENTRY_POINT = SaInitEntryPointDxe
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC
+#
+
+
+
+[LibraryClasses]
+UefiDriverEntryPoint
+UefiLib
+UefiBootServicesTableLib
+DxeServicesTableLib
+DebugLib
+TimerLib
+PciCf8Lib
+PciSegmentLib
+BaseMemoryLib
+MemoryAllocationLib
+CpuPlatformLib
+IoLib
+S3BootScriptLib
+PmcLib
+PchCycleDecodingLib
+PchInfoLib
+GpioLib
+ConfigBlockLib
+PchPcieRpLib
+DxeIgdOpRegionInitLib
+AslUpdateLib
+PeiDxeSmmReserveMmio64SizeLib
+CpuPcieInfoFruLib
+
+[Packages]
+MdePkg/MdePkg.dec
+UefiCpuPkg/UefiCpuPkg.dec
+IntelSiliconPkg/IntelSiliconPkg.dec
+AlderlakeSiliconPkg/SiPkg.dec
+
+[Pcd]
+gSiPkgTokenSpaceGuid.PcdSiPciExpressBaseAddress
+gSiPkgTokenSpaceGuid.PcdMchBaseAddress
+gSiPkgTokenSpaceGuid.PcdSiIoApicBaseAddress
+gSiPkgTokenSpaceGuid.PcdFspWrapperEnable
+gSiPkgTokenSpaceGuid.PcdCpuPcieEnable                  ## CONSUMES
+
+[FixedPcd]
+gSiPkgTokenSpaceGuid.PcdAdlLpSupport               ## CONSUMES
+gSiPkgTokenSpaceGuid.PcdAdlSSupport
+
+[Sources]
+SaInitDxe.h
+SaInitDxe.c
+SaInit.h
+SaInit.c
+SaAcpi.c
+
+[Protocols]
+gEfiAcpiTableProtocolGuid              ## CONSUMES
+gSaNvsAreaProtocolGuid                 ## PRODUCES
+gSaPolicyProtocolGuid                  ## CONSUMES
+gEfiCpuArchProtocolGuid                ## CONSUMES
+gEfiPciEnumerationCompleteProtocolGuid ## CONSUMES
+gEfiPciRootBridgeIoProtocolGuid        ## CONSUMES
+gIgdOpRegionProtocolGuid               ## PRODUCES
+gEfiFirmwareVolume2ProtocolGuid        ## CONSUMES
+gGopComponentName2ProtocolGuid         ## CONSUMES
+
+[Guids]
+gEfiEndOfDxeEventGroupGuid
+gSiConfigHobGuid        ## CONSUMES
+gGraphicsDxeConfigGuid
+gMemoryDxeConfigGuid
+gSaDataHobGuid
+gHostBridgeDataHobGuid
+
+[Depex]
+gEfiAcpiTableProtocolGuid AND
+gEfiFirmwareVolume2ProtocolGuid AND
+gSaPolicyProtocolGuid AND
+gEfiPciRootBridgeIoProtocolGuid AND
+gEfiPciHostBridgeResourceAllocationProtocolGuid AND # This is to ensure that PCI MMIO resource has been prepared and available for this driver to allocate.
+gEfiHiiDatabaseProtocolGuid
-- 
2.36.1.windows.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [edk2-devel] [PATCH 1/8] AlderlakeSiliconPkg: Add package and library instances
  2023-06-15 17:52 [PATCH 1/8] AlderlakeSiliconPkg: Add package and library instances Saloni Kasbekar
                   ` (6 preceding siblings ...)
  2023-06-15 17:53 ` [PATCH 8/8] AlderlakeSiliconPkg/SystemAgent: Add library and driver modules Saloni Kasbekar
@ 2023-07-23  0:04 ` Chaganty, Rangasai V
  7 siblings, 0 replies; 15+ messages in thread
From: Chaganty, Rangasai V @ 2023-07-23  0:04 UTC (permalink / raw)
  To: Kasbekar, Saloni, devel@edk2.groups.io
  Cc: Desimone, Nathaniel L, Oram, Isaac W, Chuang, Rosen

Looks good. One feedback though, in PeiDxeSmmReserveMmioSizeLib.inf.
The file comments states that the functions in the library are available for PEI, DXE and SMM only. 
Yet, MODULE_TYPE is set to BASE, which contradicts the above the line. 
From the .inf specification, we have the following guideline around MODULE_TYPE

MODULE_TYPE	
This is the type of module. One of the EDK II Module Types. For Library Modules, the MODULE_TYPE must specify the MODULE_TYPE of the module that will typically use the library. 

As such, I think MODULE_TYPE for the library .inf should be set to PEIM, instead of BASE.

With that, Reviewed-by: Sai Chaganty <rangasai.v.chaganty@intel.com>

Regards,
Sai

-----Original Message-----
From: Kasbekar, Saloni <saloni.kasbekar@intel.com> 
Sent: Thursday, June 15, 2023 10:53 AM
To: devel@edk2.groups.io
Cc: Kasbekar, Saloni <saloni.kasbekar@intel.com>; Chaganty, Rangasai V <rangasai.v.chaganty@intel.com>; Desimone, Nathaniel L <nathaniel.l.desimone@intel.com>; Oram, Isaac W <isaac.w.oram@intel.com>; Chuang, Rosen <rosen.chuang@intel.com>
Subject: [PATCH 1/8] AlderlakeSiliconPkg: Add package and library instances

Create the AlderlakeSiliconPkg to provide an initial package for silicon initialization code for Alder Lake (ADL) products. Add the following libraries -
- BasePciSegmentMultiSegLibPci
- BaseSiConfigBlockLib
- PeiDxeSmmReserveMmio64SizeLib
- PeiPostMemSiliconPolicyInitLib

Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Isaac Oram <isaac.w.oram@intel.com>
Cc: Rosen Chuang <rosen.chuang@intel.com>
Signed-off-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
---
 .../BasePciSegmentMultiSegLibPci.inf          |  37 ++
 .../BasePciSegmentMultiSegLibPci.uni          |  14 +
 .../PciSegmentLib.c                           | 597 ++++++++++++++++++
 .../BaseSiConfigBlockLib.c                    |  87 +++
 .../BaseSiConfigBlockLib.inf                  |  32 +
 .../PeiDxeSmmReserveMmio64SizeLib.c           |  22 +
 .../PeiDxeSmmReserveMmio64SizeLib.inf         |  28 +
 .../PeiPostMemSiliconPolicyInitLib.c          |  94 +++
 .../PeiPostMemSiliconPolicyInitLib.inf        |  39 ++
 .../PeiPreMemSiliconPolicyInitLib.c           |  98 +++
 .../PeiPreMemSiliconPolicyInitLib.inf         |  36 ++
 11 files changed, 1084 insertions(+)
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Library/BasePciSegmentMultiSegLibPci/BasePciSegmentMultiSegLibPci.inf
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Library/BasePciSegmentMultiSegLibPci/BasePciSegmentMultiSegLibPci.uni
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Library/BasePciSegmentMultiSegLibPci/PciSegmentLib.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Library/BaseSiConfigBlockLib/BaseSiConfigBlockLib.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Library/BaseSiConfigBlockLib/BaseSiConfigBlockLib.inf
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Library/PeiDxeSmmReserveMmio64SizeLib/PeiDxeSmmReserveMmio64SizeLib.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Library/PeiDxeSmmReserveMmio64SizeLib/PeiDxeSmmReserveMmio64SizeLib.inf
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Library/PeiPostMemSiliconPolicyInitLib/PeiPostMemSiliconPolicyInitLib.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Library/PeiPostMemSiliconPolicyInitLib/PeiPostMemSiliconPolicyInitLib.inf
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Library/PeiPreMemSiliconPolicyInitLib/PeiPreMemSiliconPolicyInitLib.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Library/PeiPreMemSiliconPolicyInitLib/PeiPreMemSiliconPolicyInitLib.inf

diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Library/BasePciSegmentMultiSegLibPci/BasePciSegmentMultiSegLibPci.inf b/Silicon/Intel/AlderlakeSiliconPkg/Library/BasePciSegmentMultiSegLibPci/BasePciSegmentMultiSegLibPci.inf
new file mode 100644
index 0000000000..f3764d0187
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Library/BasePciSegmentMultiSegLi
+++ bPci/BasePciSegmentMultiSegLibPci.inf
@@ -0,0 +1,37 @@
+## @file
+# Instance of PCI Segment Library based on PCI Library.
+#
+# PCI Segment Library that layers on top of the PCI Library which only 
+#  supports segment 0 and segment 1 PCI configuration access.
+#
+#   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+#   SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = BasePciSegmentMultiSegLibPci
+  MODULE_UNI_FILE                = BasePciSegmentMultiSegLibPci.uni
+  FILE_GUID                      = AC65B409-DF03-466e-8D2B-6FCE1079F0B2
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = PciSegmentLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
+#
+
+[Sources]
+  PciSegmentLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  AlderlakeSiliconPkg/SiPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  PciLib
+  DebugLib
+  PcdLib
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Library/BasePciSegmentMultiSegLibPci/BasePciSegmentMultiSegLibPci.uni b/Silicon/Intel/AlderlakeSiliconPkg/Library/BasePciSegmentMultiSegLibPci/BasePciSegmentMultiSegLibPci.uni
new file mode 100644
index 0000000000..dd8d74bee8
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Library/BasePciSegmentMultiSegLi
+++ bPci/BasePciSegmentMultiSegLibPci.uni
@@ -0,0 +1,14 @@
+// /** @file
+// Instance of PCI Segment Library based on PCI Library.
+//
+// PCI Segment Library that layers on top of the PCI Library which only 
+//  supports segment 0 and segment 1 PCI configuration access.
+//
+//   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+//   SPDX-License-Identifier: BSD-2-Clause-Patent
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "Instance of PCI Segment Library based on PCI Library."
+
+#string STR_MODULE_DESCRIPTION          #language en-US "PCI Segment Library that layers on top of the PCI Library which only supports segment 0 and segment 1 PCI configuration access."
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Library/BasePciSegmentMultiSegLibPci/PciSegmentLib.c b/Silicon/Intel/AlderlakeSiliconPkg/Library/BasePciSegmentMultiSegLibPci/PciSegmentLib.c
new file mode 100644
index 0000000000..9bcb388016
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Library/BasePciSegmentMultiSegLi
+++ bPci/PciSegmentLib.c
@@ -0,0 +1,597 @@
+/** @file
+  PCI Segment Library that layers on top of the PCI Library which only
+   supports segment 0 and segment 1 PCI configuration access.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent **/
+
+#include <Base.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PciLib.h>
+#include <Library/PciSegmentLib.h>
+
+/**
+  Assert the validity of a PCI Segment address.
+  A valid PCI Segment address should not contain 1's in bits 28..31 and 
+33..63
+  and the segment should be 0 or 1.
+
+  @param  A The address to validate.
+  @param  M Additional bits to assert to be zero.
+
+**/
+#define ASSERT_INVALID_PCI_SEGMENT_ADDRESS(A,M) \
+  ASSERT (((A) & (0xfffffffef0000000ULL | (M))) == 0)
+
+/**
+  Convert the PCI Segment library address to PCI library address.
+  From ICL generation support the multiple segment, and the segment 
+number start from BIT28,
+  So we convert the Segment Number offset from BIT32 to BIT28
+
+  @param A The address to convert.
+**/
+#define PCI_SEGMENT_TO_PCI_ADDRESS(A) ((UINTN) (UINT32) ((A) | 
+((RShiftU64 ((A) & BIT32, 4)))))
+
+
+
+/**
+  Reads an 8-bit PCI configuration register.
+
+  Reads and returns the 8-bit PCI configuration register specified by Address.
+  This function must guarantee that all PCI read and write operations are serialized.
+
+  If any reserved bits in Address are set, then ASSERT().
+
+  @param  Address   The address that encodes the PCI Segment, Bus, Device, Function, and Register.
+
+  @return The 8-bit PCI configuration register specified by Address.
+
+**/
+UINT8
+EFIAPI
+PciSegmentRead8 (
+  IN UINT64                    Address
+  )
+{
+  ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 0);
+
+  return PciRead8 (PCI_SEGMENT_TO_PCI_ADDRESS (Address)); }
+
+/**
+  Writes an 8-bit PCI configuration register.
+
+  Writes the 8-bit PCI configuration register specified by Address with the value specified by Value.
+  Value is returned.  This function must guarantee that all PCI read and write operations are serialized.
+
+  If any reserved bits in Address are set, then ASSERT().
+
+  @param  Address     The address that encodes the PCI Segment, Bus, Device, Function, and Register.
+  @param  Value       The value to write.
+
+  @return The value written to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciSegmentWrite8 (
+  IN UINT64                    Address,
+  IN UINT8                     Value
+  )
+{
+  ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 0);
+
+  return PciWrite8 (PCI_SEGMENT_TO_PCI_ADDRESS (Address), Value); }
+
+/**
+  Performs a bitwise OR of an 8-bit PCI configuration register with an 8-bit value.
+
+  Reads the 8-bit PCI configuration register specified by Address,  
+ performs a bitwise OR between the read result and the value specified 
+ by OrData,  and writes the result to the 8-bit PCI configuration register specified by Address.
+  The value written to the PCI configuration register is returned.
+  This function must guarantee that all PCI read and write operations are serialized.
+
+  If any reserved bits in Address are set, then ASSERT().
+
+  @param  Address   The address that encodes the PCI Segment, Bus, Device, Function, and Register.
+  @param  OrData    The value to OR with the PCI configuration register.
+
+  @return The value written to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciSegmentOr8 (
+  IN UINT64                    Address,
+  IN UINT8                     OrData
+  )
+{
+  return PciWrite8 (PCI_SEGMENT_TO_PCI_ADDRESS (Address), (UINT8) 
+(PciSegmentRead8 (Address) | OrData)); }
+
+/**
+  Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit value.
+
+  Reads the 8-bit PCI configuration register specified by Address,  
+ performs a bitwise AND between the read result and the value specified 
+ by AndData,  and writes the result to the 8-bit PCI configuration register specified by Address.
+  The value written to the PCI configuration register is returned.
+  This function must guarantee that all PCI read and write operations are serialized.
+  If any reserved bits in Address are set, then ASSERT().
+
+  @param  Address   The address that encodes the PCI Segment, Bus, Device, Function, and Register.
+  @param  AndData   The value to AND with the PCI configuration register.
+
+  @return The value written to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciSegmentAnd8 (
+  IN UINT64                    Address,
+  IN UINT8                     AndData
+  )
+{
+  return PciSegmentWrite8 (Address, (UINT8) (PciSegmentRead8 (Address) 
+& AndData)); }
+
+/**
+  Performs a bitwise AND of an 8-bit PCI configuration register with an 
+8-bit value,
+  followed a  bitwise OR with another 8-bit value.
+
+  Reads the 8-bit PCI configuration register specified by Address,  
+ performs a bitwise AND between the read result and the value specified 
+ by AndData,  performs a bitwise OR between the result of the AND 
+ operation and the value specified by OrData,  and writes the result to the 8-bit PCI configuration register specified by Address.
+  The value written to the PCI configuration register is returned.
+  This function must guarantee that all PCI read and write operations are serialized.
+
+  If any reserved bits in Address are set, then ASSERT().
+
+  @param  Address   The address that encodes the PCI Segment, Bus, Device, Function, and Register.
+  @param  AndData    The value to AND with the PCI configuration register.
+  @param  OrData    The value to OR with the PCI configuration register.
+
+  @return The value written to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciSegmentAndThenOr8 (
+  IN UINT64                    Address,
+  IN UINT8                     AndData,
+  IN UINT8                     OrData
+  )
+{
+  return PciSegmentWrite8 (Address, (UINT8) ((PciSegmentRead8 (Address) 
+& AndData) | OrData)); }
+
+/**
+  Reads a 16-bit PCI configuration register.
+
+  Reads and returns the 16-bit PCI configuration register specified by Address.
+  This function must guarantee that all PCI read and write operations are serialized.
+
+  If any reserved bits in Address are set, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+  @param  Address   The address that encodes the PCI Segment, Bus, Device, Function, and Register.
+
+  @return The 16-bit PCI configuration register specified by Address.
+
+**/
+UINT16
+EFIAPI
+PciSegmentRead16 (
+  IN UINT64                    Address
+  )
+{
+  ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 1);
+
+  return PciRead16 (PCI_SEGMENT_TO_PCI_ADDRESS (Address)); }
+
+/**
+  Writes a 16-bit PCI configuration register.
+
+  Writes the 16-bit PCI configuration register specified by Address with the value specified by Value.
+  Value is returned.  This function must guarantee that all PCI read and write operations are serialized.
+
+  If any reserved bits in Address are set, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+  @param  Address     The address that encodes the PCI Segment, Bus, Device, Function, and Register.
+  @param  Value       The value to write.
+
+  @return The parameter of Value.
+
+**/
+UINT16
+EFIAPI
+PciSegmentWrite16 (
+  IN UINT64                    Address,
+  IN UINT16                    Value
+  )
+{
+  ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 1);
+
+  return PciWrite16 (PCI_SEGMENT_TO_PCI_ADDRESS (Address), Value); }
+
+/**
+  Performs a bitwise OR of a 16-bit PCI configuration register with
+  a 16-bit value.
+
+  Reads the 16-bit PCI configuration register specified by Address, 
+ performs a  bitwise OR between the read result and the value specified 
+ by  OrData, and writes the result to the 16-bit PCI configuration 
+ register  specified by Address. The value written to the PCI 
+ configuration register is  returned. This function must guarantee that 
+ all PCI read and write operations  are serialized.
+
+  If any reserved bits in Address are set, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+  @param  Address The address that encodes the PCI Segment, Bus, Device, Function and
+                  Register.
+  @param  OrData  The value to OR with the PCI configuration register.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciSegmentOr16 (
+  IN UINT64                    Address,
+  IN UINT16                    OrData
+  )
+{
+  return PciSegmentWrite16 (Address, (UINT16) (PciSegmentRead16 
+(Address) | OrData)); }
+
+/**
+  Performs a bitwise AND of a 16-bit PCI configuration register with a 
+16-bit value,
+  followed a  bitwise OR with another 16-bit value.
+
+  Reads the 16-bit PCI configuration register specified by Address,  
+ performs a bitwise AND between the read result and the value specified 
+ by AndData,  performs a bitwise OR between the result of the AND 
+ operation and the value specified by OrData,  and writes the result to the 16-bit PCI configuration register specified by Address.
+  The value written to the PCI configuration register is returned.
+  This function must guarantee that all PCI read and write operations are serialized.
+
+  If any reserved bits in Address are set, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+  @param  Address   The address that encodes the PCI Segment, Bus, Device, Function, and Register.
+  @param  AndData    The value to AND with the PCI configuration register.
+  @param  OrData    The value to OR with the PCI configuration register.
+
+  @return The value written to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciSegmentAndThenOr16 (
+  IN UINT64                    Address,
+  IN UINT16                    AndData,
+  IN UINT16                    OrData
+  )
+{
+  return PciSegmentWrite16 (Address, (UINT16) ((PciSegmentRead16 
+(Address) & AndData) | OrData)); }
+
+/**
+  Reads a 32-bit PCI configuration register.
+
+  Reads and returns the 32-bit PCI configuration register specified by Address.
+  This function must guarantee that all PCI read and write operations are serialized.
+
+  If any reserved bits in Address are set, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+  @param  Address   The address that encodes the PCI Segment, Bus, Device, Function, and Register.
+
+  @return The 32-bit PCI configuration register specified by Address.
+
+**/
+UINT32
+EFIAPI
+PciSegmentRead32 (
+  IN UINT64                    Address
+  )
+{
+  ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 3);
+
+  return PciRead32 (PCI_SEGMENT_TO_PCI_ADDRESS (Address)); }
+
+/**
+  Writes a 32-bit PCI configuration register.
+
+  Writes the 32-bit PCI configuration register specified by Address with the value specified by Value.
+  Value is returned.  This function must guarantee that all PCI read and write operations are serialized.
+
+  If any reserved bits in Address are set, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+  @param  Address     The address that encodes the PCI Segment, Bus, Device, Function, and Register.
+  @param  Value       The value to write.
+
+  @return The parameter of Value.
+
+**/
+UINT32
+EFIAPI
+PciSegmentWrite32 (
+  IN UINT64                    Address,
+  IN UINT32                    Value
+  )
+{
+  ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 3);
+
+  return PciWrite32 (PCI_SEGMENT_TO_PCI_ADDRESS (Address), Value); }
+
+/**
+  Performs a bitwise OR of a 32-bit PCI configuration register with a 32-bit value.
+
+  Reads the 32-bit PCI configuration register specified by Address,  
+ performs a bitwise OR between the read result and the value specified 
+ by OrData,  and writes the result to the 32-bit PCI configuration register specified by Address.
+  The value written to the PCI configuration register is returned.
+  This function must guarantee that all PCI read and write operations are serialized.
+
+  If any reserved bits in Address are set, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+  @param  Address   The address that encodes the PCI Segment, Bus, Device, Function, and Register.
+  @param  OrData    The value to OR with the PCI configuration register.
+
+  @return The value written to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciSegmentOr32 (
+  IN UINT64                    Address,
+  IN UINT32                    OrData
+  )
+{
+  return PciSegmentWrite32 (Address, PciSegmentRead32 (Address) | 
+OrData); }
+
+/**
+  Performs a bitwise AND of a 32-bit PCI configuration register with a 
+32-bit value,
+  followed a  bitwise OR with another 32-bit value.
+
+  Reads the 32-bit PCI configuration register specified by Address,  
+ performs a bitwise AND between the read result and the value specified 
+ by AndData,  performs a bitwise OR between the result of the AND 
+ operation and the value specified by OrData,  and writes the result to the 32-bit PCI configuration register specified by Address.
+  The value written to the PCI configuration register is returned.
+  This function must guarantee that all PCI read and write operations are serialized.
+
+  If any reserved bits in Address are set, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+  @param  Address   The address that encodes the PCI Segment, Bus, Device, Function, and Register.
+  @param  AndData   The value to AND with the PCI configuration register.
+  @param  OrData    The value to OR with the PCI configuration register.
+
+  @return The value written to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciSegmentAndThenOr32 (
+  IN UINT64                    Address,
+  IN UINT32                    AndData,
+  IN UINT32                    OrData
+  )
+{
+  return PciSegmentWrite32 (Address, (PciSegmentRead32 (Address) & 
+AndData) | OrData); }
+/**
+  Reads a range of PCI configuration registers into a caller supplied buffer.
+
+  Reads the range of PCI configuration registers specified by 
+ StartAddress and  Size into the buffer specified by Buffer. This 
+ function only allows the PCI  configuration registers from a single 
+ PCI function to be read. Size is  returned. When possible 32-bit PCI 
+ configuration read cycles are used to read  from StartAdress to 
+ StartAddress + Size. Due to alignment restrictions, 8-bit  and 16-bit 
+ PCI configuration read cycles may be used at the beginning and the  end of the range.
+
+  If any reserved bits in StartAddress are set, then ASSERT().
+  If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
+  If Size > 0 and Buffer is NULL, then ASSERT().
+
+  @param  StartAddress  The starting address that encodes the PCI Segment, Bus, Device,
+                        Function and Register.
+  @param  Size          The size in bytes of the transfer.
+  @param  Buffer        The pointer to a buffer receiving the data read.
+
+  @return Size
+
+**/
+UINTN
+EFIAPI
+PciSegmentReadBuffer (
+  IN  UINT64                   StartAddress,
+  IN  UINTN                    Size,
+  OUT VOID                     *Buffer
+  )
+{
+  UINTN                                ReturnValue;
+
+  ASSERT_INVALID_PCI_SEGMENT_ADDRESS (StartAddress, 0);  ASSERT 
+ (((StartAddress & 0xFFF) + Size) <= 0x1000);
+
+  if (Size == 0) {
+    return Size;
+  }
+
+  ASSERT (Buffer != NULL);
+  if (Buffer == NULL) {
+    return 0;
+  }
+
+  //
+  // Save Size for return
+  //
+  ReturnValue = Size;
+
+  if ((StartAddress & BIT0) != 0) {
+    //
+    // Read a byte if StartAddress is byte aligned
+    //
+    *(volatile UINT8 *)Buffer = PciSegmentRead8 (StartAddress);
+    StartAddress += sizeof (UINT8);
+    Size -= sizeof (UINT8);
+    Buffer = (UINT8*)Buffer + 1;
+  }
+
+  if (Size >= sizeof (UINT16) && (StartAddress & BIT1) != 0) {
+    //
+    // Read a word if StartAddress is word aligned
+    //
+    WriteUnaligned16 (Buffer, PciSegmentRead16 (StartAddress));
+    StartAddress += sizeof (UINT16);
+    Size -= sizeof (UINT16);
+    Buffer = (UINT16*)Buffer + 1;
+  }
+
+  while (Size >= sizeof (UINT32)) {
+    //
+    // Read as many double words as possible
+    //
+    WriteUnaligned32 (Buffer, PciSegmentRead32 (StartAddress));
+    StartAddress += sizeof (UINT32);
+    Size -= sizeof (UINT32);
+    Buffer = (UINT32*)Buffer + 1;
+  }
+
+  if (Size >= sizeof (UINT16)) {
+    //
+    // Read the last remaining word if exist
+    //
+    WriteUnaligned16 (Buffer, PciSegmentRead16 (StartAddress));
+    StartAddress += sizeof (UINT16);
+    Size -= sizeof (UINT16);
+    Buffer = (UINT16*)Buffer + 1;
+  }
+
+  if (Size >= sizeof (UINT8)) {
+    //
+    // Read the last remaining byte if exist
+    //
+    *(volatile UINT8 *)Buffer = PciSegmentRead8 (StartAddress);  }
+
+  return ReturnValue;
+}
+
+/**
+  Copies the data in a caller supplied buffer to a specified range of 
+PCI
+  configuration space.
+
+  Writes the range of PCI configuration registers specified by 
+ StartAddress and  Size from the buffer specified by Buffer. This 
+ function only allows the PCI  configuration registers from a single 
+ PCI function to be written. Size is  returned. When possible 32-bit 
+ PCI configuration write cycles are used to  write from StartAdress to 
+ StartAddress + Size. Due to alignment restrictions,  8-bit and 16-bit 
+ PCI configuration write cycles may be used at the beginning  and the end of the range.
+
+  If any reserved bits in StartAddress are set, then ASSERT().
+  If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
+  If Size > 0 and Buffer is NULL, then ASSERT().
+
+  @param  StartAddress  The starting address that encodes the PCI Segment, Bus, Device,
+                        Function and Register.
+  @param  Size          The size in bytes of the transfer.
+  @param  Buffer        The pointer to a buffer containing the data to write.
+
+  @return The parameter of Size.
+
+**/
+UINTN
+EFIAPI
+PciSegmentWriteBuffer (
+  IN UINT64                    StartAddress,
+  IN UINTN                     Size,
+  IN VOID                      *Buffer
+  )
+{
+  UINTN                                ReturnValue;
+
+  ASSERT_INVALID_PCI_SEGMENT_ADDRESS (StartAddress, 0);  ASSERT 
+ (((StartAddress & 0xFFF) + Size) <= 0x1000);
+
+  if (Size == 0) {
+    return 0;
+  }
+
+  ASSERT (Buffer != NULL);
+  if (Buffer == NULL) {
+    return 0;
+  }
+
+  //
+  // Save Size for return
+  //
+  ReturnValue = Size;
+
+  if ((StartAddress & BIT0) != 0) {
+    //
+    // Write a byte if StartAddress is byte aligned
+    //
+    PciSegmentWrite8 (StartAddress, *(UINT8*) Buffer);
+    StartAddress += sizeof (UINT8);
+    Size -= sizeof (UINT8);
+    Buffer = (UINT8*) Buffer + 1;
+  }
+
+  if (Size >= sizeof (UINT16) && (StartAddress & BIT1) != 0) {
+    //
+    // Write a word if StartAddress is word aligned
+    //
+    PciSegmentWrite16 (StartAddress, ReadUnaligned16 (Buffer));
+    StartAddress += sizeof (UINT16);
+    Size -= sizeof (UINT16);
+    Buffer = (UINT16*) Buffer + 1;
+  }
+
+  while (Size >= sizeof (UINT32)) {
+    //
+    // Write as many double words as possible
+    //
+    PciSegmentWrite32 (StartAddress, ReadUnaligned32 (Buffer));
+    StartAddress += sizeof (UINT32);
+    Size -= sizeof (UINT32);
+    Buffer = (UINT32*) Buffer + 1;
+  }
+
+  if (Size >= sizeof (UINT16)) {
+    //
+    // Write the last remaining word if exist
+    //
+    PciSegmentWrite16 (StartAddress, ReadUnaligned16 (Buffer));
+    StartAddress += sizeof (UINT16);
+    Size -= sizeof (UINT16);
+    Buffer = (UINT16*) Buffer + 1;
+  }
+
+  if (Size >= sizeof (UINT8)) {
+    //
+    // Write the last remaining byte if exist
+    //
+    PciSegmentWrite8 (StartAddress, *(UINT8*) Buffer);  }
+
+  return ReturnValue;
+}
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Library/BaseSiConfigBlockLib/BaseSiConfigBlockLib.c b/Silicon/Intel/AlderlakeSiliconPkg/Library/BaseSiConfigBlockLib/BaseSiConfigBlockLib.c
new file mode 100644
index 0000000000..93290d8371
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Library/BaseSiConfigBlockLib/Bas
+++ eSiConfigBlockLib.c
@@ -0,0 +1,87 @@
+/** @file
+  This file is BaseSiConfigBlockLib library is used to add config 
+blocks
+  to config block header.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include 
+<ConfigBlock.h> #include <Library/DebugLib.h> #include 
+<Library/IoLib.h> #include <Library/BaseMemoryLib.h> #include 
+<Library/ConfigBlockLib.h> #include <Library/SiConfigBlockLib.h>
+
+
+/**
+  GetComponentConfigBlockTotalSize get config block table total size.
+
+  @param[in] ComponentBlocks    Component blocks array
+  @param[in] TotalBlockCount    Number of blocks
+
+  @retval                       Size of config block table
+**/
+UINT16
+EFIAPI
+GetComponentConfigBlockTotalSize (
+  IN COMPONENT_BLOCK_ENTRY *ComponentBlocks,
+  IN UINT16                TotalBlockCount
+  )
+{
+  UINT16            TotalBlockSize;
+  UINT16            BlockCount;
+
+  TotalBlockSize = 0;
+  for (BlockCount = 0 ; BlockCount < TotalBlockCount; BlockCount++) {
+    TotalBlockSize += (UINT32) ComponentBlocks[BlockCount].Size;  }
+
+  return TotalBlockSize;
+}
+
+/**
+  AddComponentConfigBlocks add all config blocks.
+
+  @param[in] ConfigBlockTableAddress    The pointer to add config blocks
+  @param[in] ComponentBlocks            Config blocks array
+  @param[in] TotalBlockCount            Number of blocks
+
+  @retval EFI_SUCCESS                   The policy default is initialized.
+  @retval EFI_OUT_OF_RESOURCES          Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+AddComponentConfigBlocks (
+  IN VOID                  *ConfigBlockTableAddress,
+  IN COMPONENT_BLOCK_ENTRY *ComponentBlocks,
+  IN UINT16                TotalBlockCount
+  )
+{
+  UINT16            BlockCount;
+  VOID              *ConfigBlockPointer;
+  CONFIG_BLOCK      ConfigBlockBuf;
+  EFI_STATUS        Status;
+
+  Status = EFI_SUCCESS;
+
+  //
+  // Initialize ConfigBlockPointer to NULL
+  //
+  ConfigBlockPointer = NULL;
+  //
+  // Loop to identify each config block from ComponentBlocks[] Table 
+and add each of them
+  //
+  for (BlockCount = 0; BlockCount < TotalBlockCount; BlockCount++) {
+    ZeroMem (&ConfigBlockBuf, sizeof (CONFIG_BLOCK));
+    CopyMem (&(ConfigBlockBuf.Header.GuidHob.Name), ComponentBlocks[BlockCount].Guid, sizeof (EFI_GUID));
+    ConfigBlockBuf.Header.GuidHob.Header.HobLength = ComponentBlocks[BlockCount].Size;
+    ConfigBlockBuf.Header.Revision                 = ComponentBlocks[BlockCount].Revision;
+    ConfigBlockPointer = (VOID *)&ConfigBlockBuf;
+    Status = AddConfigBlock ((VOID *)ConfigBlockTableAddress, (VOID *)&ConfigBlockPointer);
+    ASSERT_EFI_ERROR (Status);
+    if (ComponentBlocks[BlockCount].LoadDefault != NULL) {
+      ComponentBlocks[BlockCount].LoadDefault (ConfigBlockPointer);
+    }
+  }
+  return Status;
+}
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Library/BaseSiConfigBlockLib/BaseSiConfigBlockLib.inf b/Silicon/Intel/AlderlakeSiliconPkg/Library/BaseSiConfigBlockLib/BaseSiConfigBlockLib.inf
new file mode 100644
index 0000000000..097095ef0d
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Library/BaseSiConfigBlockLib/Bas
+++ eSiConfigBlockLib.inf
@@ -0,0 +1,32 @@
+## @file
+# Component description file for the BaseSiConfigBlockLib library.
+#
+#   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+#   SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = BaseSiConfigBlockLib
+FILE_GUID = 6C068D0F-F48E-48CB-B369-433E507AF4A2
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = SiConfigBlockLib
+
+
+[LibraryClasses]
+DebugLib
+IoLib
+ConfigBlockLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+AlderlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+BaseSiConfigBlockLib.c
+
+
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Library/PeiDxeSmmReserveMmio64SizeLib/PeiDxeSmmReserveMmio64SizeLib.c b/Silicon/Intel/AlderlakeSiliconPkg/Library/PeiDxeSmmReserveMmio64SizeLib/PeiDxeSmmReserveMmio64SizeLib.c
new file mode 100644
index 0000000000..90d6be2feb
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Library/PeiDxeSmmReserveMmio64Si
+++ zeLib/PeiDxeSmmReserveMmio64SizeLib.c
@@ -0,0 +1,22 @@
+/** @file
+  PEI/DXE/SMM library for reserved 64-bit MMIO space.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent **/
+
+#include <Base.h>
+#include <Library/PeiDxeSmmReserveMmio64SizeLib.h>
+
+/**
+  The function return the 64 bit MMIO size to reserve.
+
+  @retval The 64-bit MMIO size
+**/
+UINT64
+ReserveMmio64Size (
+  VOID
+  )
+{
+  return 0;
+}
\ No newline at end of file
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Library/PeiDxeSmmReserveMmio64SizeLib/PeiDxeSmmReserveMmio64SizeLib.inf b/Silicon/Intel/AlderlakeSiliconPkg/Library/PeiDxeSmmReserveMmio64SizeLib/PeiDxeSmmReserveMmio64SizeLib.inf
new file mode 100644
index 0000000000..ed2b7d6d50
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Library/PeiDxeSmmReserveMmio64Si
+++ zeLib/PeiDxeSmmReserveMmio64SizeLib.inf
@@ -0,0 +1,28 @@
+## @file
+# PEI/DXE/SMM library for reserved 64-bit MMIO space.
+#
+# All function in this library is available for PEI, DXE, and SMM, # 
+But do not support UEFI RUNTIME environment call.
+#
+#   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+#   SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmReserveMmio64Size
+FILE_GUID = 4CF5E3F4-025A-48CA-8E97-7B2BD5D4391F
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PeiDxeSmmReserveMmio64Size
+
+[LibraryClasses]
+
+[Packages]
+MdePkg/MdePkg.dec
+AlderlakeSiliconPkg/SiPkg.dec
+
+[Sources]
+PeiDxeSmmReserveMmio64SizeLib.c
+
+[Pcd]
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Library/PeiPostMemSiliconPolicyInitLib/PeiPostMemSiliconPolicyInitLib.c b/Silicon/Intel/AlderlakeSiliconPkg/Library/PeiPostMemSiliconPolicyInitLib/PeiPostMemSiliconPolicyInitLib.c
new file mode 100644
index 0000000000..a9d6c7e265
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Library/PeiPostMemSiliconPolicyI
+++ nitLib/PeiPostMemSiliconPolicyInitLib.c
@@ -0,0 +1,94 @@
+/** @file
+  This library initialize Silicon Policy for PostMemory.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include 
+<Ppi/SiPolicy.h> #include <Ppi/PeiSiDefaultPolicy.h> #include 
+<Library/PcdLib.h> #include <Library/DebugLib.h> #include 
+<Library/PeiServicesLib.h> #include <Library/SiPolicyLib.h>
+
+/**
+  Performs silicon post-mem policy initialization.
+
+  The returned data must be used as input data for 
+ SiliconPolicyDonePostMem (),  and SiliconPolicyUpdateLib.SiliconPolicyUpdatePostMem ().
+
+  @param[in, out] Policy       Pointer to policy.
+  @return the initialized policy.
+**/
+VOID *
+EFIAPI
+SiliconPolicyInitPostMem (
+  IN OUT VOID *Policy
+  )
+{
+  EFI_STATUS                        Status;
+  SI_POLICY_PPI                     *SiPolicyPpi;
+  PEI_SI_DEFAULT_POLICY_INIT_PPI    *PeiSiDefaultPolicyInitPpi;
+
+  DEBUG ((DEBUG_INFO, "Silicon PEI Policy Initialization Start in 
+ Post-Memory...\n"));
+
+  ASSERT (Policy == NULL);
+  SiPolicyPpi = NULL;
+  PeiSiDefaultPolicyInitPpi = NULL;
+
+  //
+  // Locate Policy init PPI to install default silicon policy  //  
+ Status = PeiServicesLocatePpi (
+             &gSiDefaultPolicyInitPpiGuid,
+             0,
+             NULL,
+             (VOID **) &PeiSiDefaultPolicyInitPpi
+             );
+  ASSERT_EFI_ERROR (Status);
+  if (PeiSiDefaultPolicyInitPpi != NULL) {
+    Status = PeiSiDefaultPolicyInitPpi->PeiPolicyInit ();
+    ASSERT_EFI_ERROR (Status);
+    if (Status == EFI_SUCCESS) {
+      Status = PeiServicesLocatePpi (
+                 &gSiPolicyPpiGuid,
+                 0,
+                 NULL,
+                 (VOID **) &SiPolicyPpi
+                 );
+      ASSERT_EFI_ERROR (Status);
+    }
+  }
+
+  if (SiPolicyPpi == NULL) {
+    DEBUG ((DEBUG_ERROR, "Fail to create default policy!\n"));
+    return NULL;
+  }
+
+
+  return SiPolicyPpi;
+}
+
+/**
+  The silicon post-mem policy is finalized.
+  Silicon code can do initialization based upon the policy data.
+
+  The input Policy must be returned by SiliconPolicyInitPostMem().
+
+  @param[in] Policy       Pointer to policy.
+  @retval RETURN_SUCCESS The policy is handled consumed by silicon code.
+**/
+RETURN_STATUS
+EFIAPI
+SiliconPolicyDonePostMem (
+  IN VOID *Policy
+  )
+{
+  EFI_STATUS                   Status;
+
+  Status = SiInstallPolicyReadyPpi ();
+  ASSERT_EFI_ERROR (Status);
+  DEBUG ((DEBUG_INFO, "Silicon PEI Policy Initialization Done in 
+ Post-Memory\n"));
+
+  return Status;
+}
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Library/PeiPostMemSiliconPolicyInitLib/PeiPostMemSiliconPolicyInitLib.inf b/Silicon/Intel/AlderlakeSiliconPkg/Library/PeiPostMemSiliconPolicyInitLib/PeiPostMemSiliconPolicyInitLib.inf
new file mode 100644
index 0000000000..62184b39d2
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Library/PeiPostMemSiliconPolicyI
+++ nitLib/PeiPostMemSiliconPolicyInitLib.inf
@@ -0,0 +1,39 @@
+## @file
+# Component information file for Silicon Policy Init Library # This 
+library implements Silicon Policy Initialization for PostMemory.
+#
+#   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+#   SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PeiPostMemSiliconPolicyInitLib
+  FILE_GUID                      = 20B51FFB-93D3-4546-9F13-2C91AEEF9212
+  MODULE_TYPE                    = PEIM
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = SiliconPolicyInitLib
+
+[LibraryClasses]
+  BaseLib
+  PcdLib
+  PeiServicesLib
+  DebugLib
+  SiPolicyLib
+
+[Packages]
+  MdePkg/MdePkg.dec
+  AlderlakeSiliconPkg/SiPkg.dec
+
+[Sources]
+  PeiPostMemSiliconPolicyInitLib.c
+
+[Pcd]
+  gSiPkgTokenSpaceGuid.PcdDumpDefaultSiliconPolicy
+
+[Ppis]
+  gSiDefaultPolicyInitPpiGuid
+  gEfiPeiMpServicesPpiGuid
+
+[Depex]
+  gSiDefaultPolicyInitPpiGuid
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Library/PeiPreMemSiliconPolicyInitLib/PeiPreMemSiliconPolicyInitLib.c b/Silicon/Intel/AlderlakeSiliconPkg/Library/PeiPreMemSiliconPolicyInitLib/PeiPreMemSiliconPolicyInitLib.c
new file mode 100644
index 0000000000..74fb47a73d
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Library/PeiPreMemSiliconPolicyIn
+++ itLib/PeiPreMemSiliconPolicyInitLib.c
@@ -0,0 +1,98 @@
+/** @file
+  This library initialize Silicon Policy for PreMemory.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include 
+<Ppi/SiPolicy.h> #include <Ppi/PeiPreMemSiDefaultPolicy.h> #include 
+<Library/DebugLib.h> #include <Library/PeiServicesLib.h> #include 
+<Library/SiPolicyLib.h>
+
+
+/**
+  Performs silicon pre-mem policy initialization.
+
+  The returned data must be used as input data for 
+ SiliconPolicyDonePreMem (),  and SiliconPolicyUpdateLib.SiliconPolicyUpdatePreMem ().
+
+  @param[in, out] Policy       Pointer to policy.
+  @return the initialized policy.
+**/
+VOID *
+EFIAPI
+SiliconPolicyInitPreMem (
+  IN OUT VOID *Policy
+  )
+{
+  EFI_STATUS                             Status;
+  SI_PREMEM_POLICY_PPI                   *SiPreMemPolicyPpi;
+  PEI_PREMEM_SI_DEFAULT_POLICY_INIT_PPI  
+*PeiPreMemSiDefaultPolicyInitPpi;
+
+  DEBUG ((DEBUG_INFO, "Silicon PEI Policy Initialization Start in 
+ Pre-Memory...\n"));
+
+  ASSERT (Policy == NULL);
+  SiPreMemPolicyPpi = NULL;
+  PeiPreMemSiDefaultPolicyInitPpi = NULL;
+
+  //
+  // Locate Policy init PPI to install default silicon policy  //  
+ Status = PeiServicesLocatePpi (
+             &gSiPreMemDefaultPolicyInitPpiGuid,
+             0,
+             NULL,
+             (VOID **) &PeiPreMemSiDefaultPolicyInitPpi
+             );
+  ASSERT_EFI_ERROR (Status);
+  if (PeiPreMemSiDefaultPolicyInitPpi != NULL) {
+    Status = PeiPreMemSiDefaultPolicyInitPpi->PeiPreMemPolicyInit ();
+    ASSERT_EFI_ERROR (Status);
+    if (Status == EFI_SUCCESS) {
+      Status = PeiServicesLocatePpi (
+                 &gSiPreMemPolicyPpiGuid,
+                 0,
+                 NULL,
+                 (VOID **) &SiPreMemPolicyPpi
+                 );
+      ASSERT_EFI_ERROR (Status);
+    }
+  }
+
+  if (SiPreMemPolicyPpi == NULL) {
+    DEBUG ((DEBUG_ERROR, "Fail to create default policy!\n"));
+    return NULL;
+  }
+
+  return SiPreMemPolicyPpi;
+}
+
+/**
+  The silicon pre-mem policy is finalized.
+  Silicon code can do initialization based upon the policy data.
+
+  The input Policy must be returned by SiliconPolicyInitPreMem().
+
+  @param[in] Policy       Pointer to policy.
+  @retval RETURN_SUCCESS The policy is handled consumed by silicon code.
+**/
+RETURN_STATUS
+EFIAPI
+SiliconPolicyDonePreMem (
+  IN VOID *Policy
+  )
+{
+  EFI_STATUS                   Status;
+  //
+  // Install PreMem Policy Ready PPI
+  // While installs PreMemPolicyReadyPpi, RC assumes the Policy is 
+ready and finalized. So please
+  // update and override any setting before calling this function.
+  //
+  Status = SiPreMemInstallPolicyReadyPpi ();
+  ASSERT_EFI_ERROR (Status);
+
+  DEBUG ((DEBUG_INFO, "Silicon PEI Policy Initialization Done in 
+ Pre-Memory\n"));
+
+  return Status;
+}
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Library/PeiPreMemSiliconPolicyInitLib/PeiPreMemSiliconPolicyInitLib.inf b/Silicon/Intel/AlderlakeSiliconPkg/Library/PeiPreMemSiliconPolicyInitLib/PeiPreMemSiliconPolicyInitLib.inf
new file mode 100644
index 0000000000..d5ce714ce5
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Library/PeiPreMemSiliconPolicyIn
+++ itLib/PeiPreMemSiliconPolicyInitLib.inf
@@ -0,0 +1,36 @@
+## @file
+# Component information file for Silicon Policy Init Library # This 
+library implements Silicon Policy Initialization for PreMemory.
+#
+#   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+#   SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PeiPreMemSiliconPolicyInitLib
+  FILE_GUID                      = 1FB4B175-0BB6-4137-A4AC-EA48FCE83862
+  MODULE_TYPE                    = PEIM
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = SiliconPolicyInitLib
+
+[LibraryClasses]
+  BaseLib
+  PeiServicesLib
+  DebugLib
+  SiPolicyLib
+
+[Packages]
+  MdePkg/MdePkg.dec
+  AlderlakeSiliconPkg/SiPkg.dec
+
+[Sources]
+  PeiPreMemSiliconPolicyInitLib.c
+
+[Pcd]
+
+[Ppis]
+  gSiPreMemDefaultPolicyInitPpiGuid
+
+[Depex]
+  gSiPreMemDefaultPolicyInitPpiGuid
--
2.36.1.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#107144): https://edk2.groups.io/g/devel/message/107144
Mute This Topic: https://groups.io/mt/99554471/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [edk2-devel] [PATCH 3/8] AlderlakeSiliconPkg/Pch: Add include headers
  2023-06-15 17:53 ` [PATCH 3/8] AlderlakeSiliconPkg/Pch: Add include headers Saloni Kasbekar
@ 2023-07-24  7:38   ` Chaganty, Rangasai V
  0 siblings, 0 replies; 15+ messages in thread
From: Chaganty, Rangasai V @ 2023-07-24  7:38 UTC (permalink / raw)
  To: Kasbekar, Saloni, devel@edk2.groups.io
  Cc: Desimone, Nathaniel L, Oram, Isaac W, Chuang, Rosen

Reviewed-by: Sai Chaganty <rangasai.v.chaganty@intel.com>

-----Original Message-----
From: Kasbekar, Saloni <saloni.kasbekar@intel.com> 
Sent: Thursday, June 15, 2023 10:53 AM
To: devel@edk2.groups.io
Cc: Kasbekar, Saloni <saloni.kasbekar@intel.com>; Chaganty, Rangasai V <rangasai.v.chaganty@intel.com>; Desimone, Nathaniel L <nathaniel.l.desimone@intel.com>; Oram, Isaac W <isaac.w.oram@intel.com>; Chuang, Rosen <rosen.chuang@intel.com>
Subject: [PATCH 3/8] AlderlakeSiliconPkg/Pch: Add include headers

Adds the following header files:
* Pch/Include

Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Isaac Oram <isaac.w.oram@intel.com>
Cc: Rosen Chuang <rosen.chuang@intel.com>
Signed-off-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
---
 .../Include/ConfigBlock/PchGeneralConfig.h    |  86 ++++++++
 .../Pch/Include/Library/PchCycleDecodingLib.h |  59 ++++++
 .../Pch/Include/Library/PchInfoDefs.h         |  19 ++
 .../Pch/Include/Library/PchInfoLib.h          | 108 ++++++++++
 .../Pch/Include/Library/PchPciBdfLib.h        | 187 ++++++++++++++++++
 .../Pch/Include/PchPolicyCommon.h             |  30 +++
 .../Pch/Include/PchPreMemPolicyCommon.h       |  53 +++++
 .../Pch/Include/PchResetPlatformSpecific.h    |  21 ++
 .../Pch/Include/Protocol/PchAcpiSmiDispatch.h | 134 +++++++++++++  .../Pch/Include/Protocol/PchPcieSmiDispatch.h | 166 ++++++++++++++++
 .../Pch/Include/Protocol/PchSmiDispatch.h     | 132 +++++++++++++
 .../Include/Protocol/PchSmmIoTrapControl.h    |  65 ++++++
 .../Protocol/PchSmmPeriodicTimerControl.h     |  65 ++++++
 .../Pch/Include/Protocol/PchTcoSmiDispatch.h  | 150 ++++++++++++++
 .../Pch/Include/Protocol/SmmSmbus.h           |  13 ++
 .../Pch/Include/Register/PchRegs.h            |  45 +++++
 16 files changed, 1333 insertions(+)
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/ConfigBlock/PchGeneralConfig.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Library/PchCycleDecodingLib.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Library/PchInfoDefs.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Library/PchInfoLib.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Library/PchPciBdfLib.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/PchPolicyCommon.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/PchPreMemPolicyCommon.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/PchResetPlatformSpecific.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchAcpiSmiDispatch.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchPcieSmiDispatch.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchSmiDispatch.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchSmmIoTrapControl.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchSmmPeriodicTimerControl.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchTcoSmiDispatch.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/SmmSmbus.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Register/PchRegs.h

diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/ConfigBlock/PchGeneralConfig.h b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/ConfigBlock/PchGeneralConfig.h
new file mode 100644
index 0000000000..4501537fe2
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/ConfigBlock/PchGener
+++ alConfig.h
@@ -0,0 +1,86 @@
+/** @file
+  PCH General policy
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent **/ #ifndef 
+_PCH_GENERAL_CONFIG_H_ #define _PCH_GENERAL_CONFIG_H_
+
+
+extern EFI_GUID gPchGeneralConfigGuid;
+extern EFI_GUID gPchGeneralPreMemConfigGuid;
+
+#pragma pack (push,1)
+
+enum PCH_RESERVED_PAGE_ROUTE {
+  PchReservedPageToLpc,                   ///< Port 80h cycles are sent to LPC.
+  PchReservedPageToPcie                   ///< Port 80h cycles are sent to PCIe.
+};
+
+/**
+  PCH General Configuration
+  <b>Revision 1</b>:  - Initial version.
+  <b>Revision 2</b>:  - Added AcpiL6dPmeHandling **/ typedef struct {
+  CONFIG_BLOCK_HEADER   Header;                   ///< Config Block Header
+  /**
+    This member describes whether or not the Compatibility Revision ID (CRID) feature
+    of PCH should be enabled. <b>0: Disable</b>; 1: Enable
+  **/
+  UINT32    Crid            :  1;
+  /**
+    Set to enable low latency of legacy IO.
+    Some systems require lower IO latency irrespective of power.
+    This is a tradeoff between power and IO latency.
+    @note: Once this is enabled, DmiAspm, Pcie DmiAspm in SystemAgent
+    and ITSS Clock Gating are forced to disabled.
+    <b>0: Disable</b>, 1: Enable
+  **/
+  UINT32    LegacyIoLowLatency  :  1;
+  /**
+  Enables _L6D ACPI handler.
+  PME GPE is shared by multiple devices So BIOS must verify the same in 
+the ASL handler by reading offset for PMEENABLE and PMESTATUS bit
+  <b>0: Disable</b>, 1: Enable
+  **/
+  UINT32    AcpiL6dPmeHandling  :  1;
+  UINT32    RsvdBits0           : 29;       ///< Reserved bits
+} PCH_GENERAL_CONFIG;
+
+/**
+  PCH General Pre-Memory Configuration
+  <b>Revision 1</b>:  - Initial version.
+  <b>Revision 2</b>:  - Added GpioOverride.
+  <b>Revision 3</b>:  - Added IoeDebugEn, PmodeClkEn **/ typedef struct 
+{
+  CONFIG_BLOCK_HEADER   Header;                   ///< Config Block Header
+  /**
+    Control where the Port 80h cycles are sent, <b>0: LPC</b>; 1: PCI.
+  **/
+  UINT32    Port80Route     :  1;
+  UINT32    IotgPllSscEn    :  1;       ///< Need to disable CPU Side SSC for A0 PO
+  /**
+    Gpio override Level
+    -- <b>0: Disable</b>;
+    -  1: Override Level 1 - Skips GPIO configuration in PEI/FSPM/FSPT phase
+    -  2: Override Level 2 - Reserved for future use
+  **/
+  UINT32    GpioOverride    :  3;
+  /**
+    Enable/Disable IOE Debug. When enabled, IOE D2D Dfx link and clock will keep up for debug
+    <b>0: Disable</b>; 1: Enable
+  **/
+  UINT32    IoeDebugEn      :  1;
+  /**
+    Enable/Disable PMODE clock. When enabled, Pmode clock will toggle for XDP use
+    <b>0: Disable</b>; 1: Enable
+  **/
+  UINT32    PmodeClkEn      :  1;
+  UINT32    RsvdBits0       : 25;       ///< Reserved bits
+} PCH_GENERAL_PREMEM_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _PCH_GENERAL_CONFIG_H_
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Library/PchCycleDecodingLib.h b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Library/PchCycleDecodingLib.h
new file mode 100644
index 0000000000..65ecd58de1
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Library/PchCycleDeco
+++ dingLib.h
@@ -0,0 +1,59 @@
+/** @file
+  Header file for PchCycleDecodingLib.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent **/ #ifndef 
+_PCH_CYCLE_DECODING_LIB_H_ #define _PCH_CYCLE_DECODING_LIB_H_
+
+/**
+  Get PCH TCO base address.
+
+  @param[out] Address                   Address of TCO base address.
+
+  @retval EFI_SUCCESS                   Successfully completed.
+  @retval EFI_INVALID_PARAMETER         Invalid pointer passed.
+**/
+EFI_STATUS
+PchTcoBaseGet (
+  OUT UINT16                            *Address
+  );
+
+/**
+  Set PCH LPC IO decode ranges.
+  Program LPC I/O Decode Ranges, PCR[DMI] + 2770h[15:0] to the same value programmed in LPC offset 80h.
+  Please check EDS for detail of Lpc IO decode ranges bit definition.
+  Bit  12: FDD range
+  Bit 9:8: LPT range
+  Bit 6:4: ComB range
+  Bit 2:0: ComA range
+
+  @param[in] LpcIoDecodeRanges          Lpc IO decode ranges bit settings.
+
+  @retval EFI_SUCCESS                   Successfully completed.
+  @retval EFI_UNSUPPORTED               DMIC.SRL is set.
+**/
+EFI_STATUS
+PchLpcIoDecodeRangesSet (
+  IN  UINT16                            LpcIoDecodeRanges
+  );
+
+/**
+  Set PCH LPC and eSPI CS0# IO enable decoding.
+  Setup I/O Enables in DMI to the same value program in LPC/eSPI PCI offset 82h.
+  Note: Bit[15:10] of the source decode register is Read-Only. The IO 
+range indicated by the Enables field
+  in LPC/eSPI PCI offset 82h[13:10] is always forwarded by DMI to subtractive agent for handling.
+  Please check EDS for detail of LPC/eSPI IO decode ranges bit definition.
+
+  @param[in] LpcIoEnableDecoding        LPC IO enable decoding bit settings.
+
+  @retval EFI_SUCCESS                   Successfully completed.
+  @retval EFI_UNSUPPORTED               DMIC.SRL is set.
+**/
+EFI_STATUS
+PchLpcIoEnableDecodingSet (
+  IN  UINT16                            LpcIoEnableDecoding
+  );
+
+#endif // _PCH_CYCLE_DECODING_LIB_H_
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Library/PchInfoDefs.h b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Library/PchInfoDefs.h
new file mode 100644
index 0000000000..9328e1899c
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Library/PchInfoDefs.
+++ h
@@ -0,0 +1,19 @@
+/** @file
+  Header file for PchInfoDefs.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent **/ #ifndef 
+_PCH_INFO_DEFS_H_ #define _PCH_INFO_DEFS_H_
+
+#define PCH_STEPPING_MAX      0xFF
+
+#define PCH_LP                  2
+#define PCH_N                   3
+#define PCH_S                   4
+#define PCH_P                   5
+#define PCH_M                   6
+#define PCH_UNKNOWN_SERIES      0xFF
+
+#endif
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Library/PchInfoLib.h b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Library/PchInfoLib.h
new file mode 100644
index 0000000000..d5d412c9f2
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Library/PchInfoLib.h
@@ -0,0 +1,108 @@
+/** @file
+  Header file for PchInfoLib.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent **/ #ifndef 
+_PCH_INFO_LIB_H_ #define _PCH_INFO_LIB_H_
+
+#include <Uefi/UefiBaseType.h>
+#include "PchInfoDefs.h"
+
+typedef UINT8 PCH_STEPPING;
+typedef UINT8 PCH_SERIES;
+typedef UINT8 PCH_GENERATION;
+
+typedef enum {
+  RstUnsupported  = 0,
+  RstPremium,
+  RstOptane,
+  RstMaxMode
+} RST_MODE;
+
+/**
+  Return LPC Device Id
+
+  @retval PCH_LPC_DEVICE_ID         PCH Lpc Device ID
+**/
+UINT16
+PchGetLpcDid (
+  VOID
+  );
+
+/**
+  Return Pch stepping type
+
+  @retval PCH_STEPPING            Pch stepping type
+**/
+PCH_STEPPING
+PchStepping (
+  VOID
+  );
+
+/**
+  Return Pch Series
+
+  @retval PCH_SERIES                Pch Series
+**/
+PCH_SERIES
+PchSeries (
+  VOID
+  );
+
+/**
+  Check if this is PCH LP series
+
+  @retval TRUE                It's PCH LP series
+  @retval FALSE               It's not PCH LP series
+**/
+BOOLEAN
+IsPchLp (
+  VOID
+  );
+
+
+/**
+  Check if this is PCH P series
+
+  @retval TRUE                It's PCH P series
+  @retval FALSE               It's not PCH P series
+**/
+BOOLEAN
+IsPchP (
+  VOID
+  );
+
+/**
+  Get Pch Maximum Pcie Root Port Number
+
+  @retval PcieMaxRootPort         Pch Maximum Pcie Root Port Number
+**/
+UINT8
+GetPchMaxPciePortNum (
+  VOID
+  );
+
+/**
+  Get Pch Maximum Serial IO I2C controllers number
+
+  @retval Pch Maximum Serial IO I2C controllers number **/
+UINT8
+GetPchMaxSerialIoI2cControllersNum (
+  VOID
+  );
+
+/**
+  return support status for P2SB PCR 20-bit addressing
+
+  @retval    TRUE
+  @retval    FALSE
+**/
+BOOLEAN
+IsP2sb20bPcrSupported (
+  VOID
+  );
+
+#endif // _PCH_INFO_LIB_H_
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Library/PchPciBdfLib.h b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Library/PchPciBdfLib.h
new file mode 100644
index 0000000000..0c8e4d21a1
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Library/PchPciBdfLib
+++ .h
@@ -0,0 +1,187 @@
+/** @file
+  Header file for PchPciBdfLib.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent **/ #ifndef 
+_PCH_PCI_BDF_LIB_H_ #define _PCH_PCI_BDF_LIB_H_
+
+/**
+  Get P2SB controller address that can be passed to the PCI Segment Library functions.
+
+  @retval P2SB controller address in PCI Segment Library representation 
+**/
+UINT64
+P2sbPciCfgBase (
+  VOID
+  );
+
+/**
+  Get P2SB PCI device number
+
+  @retval PCI dev number
+**/
+UINT8
+P2sbDevNumber (
+  VOID
+  );
+
+/**
+  Get P2SB PCI function number
+
+  @retval PCI fun number
+**/
+UINT8
+P2sbFuncNumber (
+  VOID
+  );
+
+/**
+  Returns SPI PCI Config Space base address
+
+  @retval  UINT64  SPI Config Space base address **/
+UINT64
+SpiPciCfgBase (
+  VOID
+  );
+
+/**
+  Returns SPI Device number
+
+  @retval UINT8   PCH SPI Device number
+**/
+UINT8
+SpiDevNumber (
+  VOID
+  );
+
+/**
+  Returns SPI Function number
+
+  @retval UINT8   PCH SPI Function number
+**/
+UINT8
+SpiFuncNumber (
+  VOID
+  );
+
+/**
+  Get XHCI controller address that can be passed to the PCI Segment Library functions.
+
+  @retval XHCI controller address in PCI Segment Library representation 
+**/
+UINT64
+PchXhciPciCfgBase (
+  VOID
+  );
+
+/**
+  Get XHCI controller PCIe Device Number
+
+  @retval XHCI controller PCIe Device Number **/
+UINT8
+PchXhciDevNumber (
+  VOID
+  );
+
+/**
+  Get XHCI controller PCIe Function Number
+
+  @retval XHCI controller PCIe Function Number **/
+UINT8
+PchXhciFuncNumber (
+  VOID
+  );
+
+/**
+  Returns PCH LPC device PCI base address.
+
+  @retval                   PCH LPC PCI base address.
+**/
+UINT64
+LpcPciCfgBase (
+  VOID
+  );
+
+/**
+  Get LPC controller PCIe Device Number
+
+  @retval LPC controller PCIe Device Number **/
+UINT8
+LpcDevNumber (
+  VOID
+  );
+
+
+/**
+  Get LPC controller PCIe Function Number
+
+  @retval LPC controller PCIe Function Number **/
+UINT8
+LpcFuncNumber (
+  VOID
+  );
+
+
+/**
+  Get PCH PCIe controller PCIe Device Number
+
+  @param[in]  RpIndex       Root port physical number. (0-based)
+
+  @retval PCH PCIe controller PCIe Device Number **/
+UINT8
+PchPcieRpDevNumber (
+  IN  UINTN   RpIndex
+  );
+
+/**
+  Get PCH PCIe controller PCIe Function Number
+
+  @param[in]  RpIndex       Root port physical number. (0-based)
+
+  @retval PCH PCIe controller PCIe Function Number **/
+UINT8
+PchPcieRpFuncNumber (
+  IN  UINTN   RpIndex
+  );
+
+/**
+  Get HECI1 controller address that can be passed to the PCI Segment Library functions.
+
+  @retval HECI1 controller address in PCI Segment Library 
+representation **/
+UINT64
+PchHeci1PciCfgBase (
+  VOID
+  );
+
+/**
+  Get HECI3 PCI device number
+
+  @retval PCI dev number
+**/
+UINT8
+PchHeci3DevNumber (
+  VOID
+  );
+
+/**
+  Get HECI3 PCI function number
+
+  @retval PCI fun number
+**/
+UINT8
+PchHeci3FuncNumber (
+  VOID
+  );
+
+
+#endif //_PCH_PCI_BDF_LIB_H_
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/PchPolicyCommon.h b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/PchPolicyCommon.h
new file mode 100644
index 0000000000..f8a07098f0
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/PchPolicyCommon.h
@@ -0,0 +1,30 @@
+/** @file
+  PCH configuration based on PCH policy
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent **/ #ifndef 
+_PCH_POLICY_COMMON_H_ #define _PCH_POLICY_COMMON_H_
+
+#include <ConfigBlock.h>
+
+#include "PchLimits.h"
+#include "ConfigBlock/PchGeneralConfig.h"
+#include <PchPcieRpConfig.h>
+#include <PchDmiConfig.h>
+#include <PmConfig.h>
+#include <SerialIoConfig.h>
+
+#ifndef FORCE_ENABLE
+#define FORCE_ENABLE  1
+#endif
+#ifndef FORCE_DISABLE
+#define FORCE_DISABLE 2
+#endif
+#ifndef PLATFORM_POR
+#define PLATFORM_POR  0
+#endif
+
+
+#endif // _PCH_POLICY_COMMON_H_
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/PchPreMemPolicyCommon.h b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/PchPreMemPolicyCommon.h
new file mode 100644
index 0000000000..2100a01071
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/PchPreMemPolicyCommo
+++ n.h
@@ -0,0 +1,53 @@
+/** @file
+  PCH configuration based on PCH policy
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent **/ #ifndef 
+_PCH_PREMEM_POLICY_COMMON_H_ #define _PCH_PREMEM_POLICY_COMMON_H_
+
+#include <ConfigBlock.h>
+
+#include "PchLimits.h"
+#include "ConfigBlock/PchGeneralConfig.h"
+#include <WatchDogConfig.h>
+#include <SmbusConfig.h>
+#include <LpcConfig.h>
+#include <PchDmiConfig.h>
+
+#pragma pack (push,1)
+
+#ifndef FORCE_ENABLE
+#define FORCE_ENABLE  1
+#endif
+#ifndef FORCE_DISABLE
+#define FORCE_DISABLE 2
+#endif
+#ifndef PLATFORM_POR
+#define PLATFORM_POR  0
+#endif
+
+/**
+  PCH Policy revision number
+  Any backwards compatible changes to this structure will result in an 
+update in the revision number **/ #define PCH_PREMEM_POLICY_REVISION  1
+
+/**
+  PCH Policy PPI\n
+  All PCH config block change history will be listed here\n\n
+
+  - <b>Revision 1</b>:
+    - Initial version.\n
+**/
+typedef struct _PCH_PREMEM_POLICY {
+  CONFIG_BLOCK_TABLE_HEADER      TableHeader;
+/*
+  Individual Config Block Structures are added here in memory as part 
+of AddConfigBlock() */ } PCH_PREMEM_POLICY;
+
+#pragma pack (pop)
+
+#endif // _PCH_PREMEM_POLICY_COMMON_H_
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/PchResetPlatformSpecific.h b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/PchResetPlatformSpecific.h
new file mode 100644
index 0000000000..88884cac25
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/PchResetPlatformSpec
+++ ific.h
@@ -0,0 +1,21 @@
+/** @file
+  PCH Reset Platform Specific definitions.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent **/ #ifndef 
+_PCH_RESET_PLATFORM_SPECIFIC_H_ #define _PCH_RESET_PLATFORM_SPECIFIC_H_
+
+#define PCH_PLATFORM_SPECIFIC_RESET_STRING   L"PCH_RESET"
+#define PCH_RESET_DATA_STRING_MAX_LENGTH     (sizeof (PCH_PLATFORM_SPECIFIC_RESET_STRING) / sizeof (UINT16))
+
+extern EFI_GUID gPchGlobalResetGuid;
+
+typedef struct _RESET_DATA {
+  CHAR16   Description[PCH_RESET_DATA_STRING_MAX_LENGTH];
+  EFI_GUID Guid;
+} PCH_RESET_DATA;
+
+#endif // _PCH_RESET_PLATFORM_SPECIFIC_H_
+
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchAcpiSmiDispatch.h b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchAcpiSmiDispatch.h
new file mode 100644
index 0000000000..f22da50262
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchAcpiSmiD
+++ ispatch.h
@@ -0,0 +1,134 @@
+/** @file
+  APIs of PCH ACPI SMI Dispatch Protocol.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent **/ #ifndef 
+_PCH_ACPI_SMI_DISPATCH_PROTOCOL_H_
+#define _PCH_ACPI_SMI_DISPATCH_PROTOCOL_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID                         gPchAcpiSmiDispatchProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility //
+typedef struct _PCH_ACPI_SMI_DISPATCH_PROTOCOL    PCH_ACPI_SMI_DISPATCH_PROTOCOL;
+
+//
+// Member functions
+//
+
+/**
+  Callback function for an PCH ACPI SMI handler dispatch.
+
+  @param[in] DispatchHandle             The unique handle assigned to this handler by register function.
+
+**/
+typedef
+VOID
+(EFIAPI *PCH_ACPI_SMI_DISPATCH_CALLBACK) (
+  IN EFI_HANDLE                         DispatchHandle
+  );
+
+/**
+  Register a child SMI source dispatch function for PCH ACPI SMI events.
+
+  @param[in] This                       Protocol instance pointer.
+  @param[in] DispatchFunction           Pointer to dispatch function to be invoked for
+                                        this SMI source
+  @param[out] DispatchHandle            Handle of dispatch function, for when interfacing
+                                        with the parent SMM driver.
+
+  @retval EFI_SUCCESS                   The dispatch function has been successfully
+                                        registered and the SMI source has been enabled.
+  @retval EFI_DEVICE_ERROR              The driver was unable to enable the SMI source.
+  @retval EFI_OUT_OF_RESOURCES          Not enough memory (system or SMM) to manage this child.
+  @retval EFI_ACCESS_DENIED             Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_ACPI_SMI_DISPATCH_REGISTER) (
+  IN  PCH_ACPI_SMI_DISPATCH_PROTOCOL    *This,
+  IN  PCH_ACPI_SMI_DISPATCH_CALLBACK    DispatchFunction,
+  OUT EFI_HANDLE                        *DispatchHandle
+  );
+
+/**
+  Unregister a child SMI source dispatch function with a parent ACPI 
+SMM driver
+
+  @param[in] This                       Protocol instance pointer.
+  @param[in] DispatchHandle             Handle of dispatch function to deregister.
+
+  @retval EFI_SUCCESS                   The dispatch function has been successfully
+                                        unregistered and the SMI source has been disabled
+                                        if there are no other registered child dispatch
+                                        functions for this SMI source.
+  @retval EFI_INVALID_PARAMETER         Handle is invalid.
+  @retval EFI_ACCESS_DENIED             Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_ACPI_SMI_DISPATCH_UNREGISTER) (
+  IN  PCH_ACPI_SMI_DISPATCH_PROTOCOL    *This,
+  IN  EFI_HANDLE                        DispatchHandle
+  );
+
+/**
+  Interface structure for PCH ACPI SMIs Dispatch Protocol
+  The PCH ACPI SMI DISPATCH PROTOCOL provides the ability to dispatch function for PCH ACPI related SMIs.
+  It contains SMI types of Pme, RtcAlarm, PmeB0, and Time overflow.
+**/
+struct _PCH_ACPI_SMI_DISPATCH_PROTOCOL {
+  /**
+    This member specifies the revision of this structure. This field is used to
+    indicate backwards compatible changes to the protocol.
+  **/
+  UINT8                                 Revision;
+  /**
+    Smi unregister function for PCH ACPI SMI DISPATCH PROTOCOL.
+  **/
+  PCH_ACPI_SMI_DISPATCH_UNREGISTER      UnRegister;
+  /**
+    Pme
+    The event is triggered by hardware when the PME# signal goes active.
+    Additionally, the event is only triggered when SCI_EN is not set.
+  **/
+  PCH_ACPI_SMI_DISPATCH_REGISTER        PmeRegister;
+  /**
+    PmeB0
+    The event is triggered PCH when any internal device with PCI Power Management
+    capabilities on bus 0 asserts the equivalent of the PME# signal.
+    Additionally, the event is only triggered when SCI_EN is not set.
+    The following are internal devices which can set this bit:
+    Intel HD Audio, Intel Management Engine "maskable" wake events, Integrated LAN,
+    SATA, xHCI, Intel SST
+  **/
+  PCH_ACPI_SMI_DISPATCH_REGISTER        PmeB0Register;
+  /**
+    RtcAlarm
+    The event is triggered by hardware when the RTC generates an alarm
+    (assertion of the IRQ8# signal).
+  **/
+  PCH_ACPI_SMI_DISPATCH_REGISTER        RtcAlarmRegister;
+  /**
+    TmrOverflow
+    The event is triggered any time bit 22 of the 24-bit timer goes high
+    (bits are numbered from 0 to 23).
+    This will occur every 2.3435 seconds. When the TMROF_EN bit (ABASE + 02h, bit 0) is set,
+    then the setting of the TMROF_STS bit will additionally generate an SMI#
+    Additionally, the event is only triggered when SCI_EN is not set.
+  **/
+  PCH_ACPI_SMI_DISPATCH_REGISTER        TmrOverflowRegister;
+};
+
+/**
+  PCH ACPI SMI dispatch revision number
+
+  Revision 1:   Initial version
+**/
+#define PCH_ACPI_SMI_DISPATCH_REVISION            1
+
+#endif
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchPcieSmiDispatch.h b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchPcieSmiDispatch.h
new file mode 100644
index 0000000000..0c0f1ab962
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchPcieSmiD
+++ ispatch.h
@@ -0,0 +1,166 @@
+/** @file
+  APIs of PCH PCIE SMI Dispatch Protocol.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent **/ #ifndef 
+_PCH_PCIE_SMI_DISPATCH_PROTOCOL_H_
+#define _PCH_PCIE_SMI_DISPATCH_PROTOCOL_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID                         gPchPcieSmiDispatchProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility //
+typedef struct _PCH_PCIE_SMI_DISPATCH_PROTOCOL    PCH_PCIE_SMI_DISPATCH_PROTOCOL;
+
+typedef enum {
+  PchRpIndex0      = 0,
+  PchRpIndex1      = 1,
+  PchRpIndex2      = 2,
+  PchRpIndex3      = 3,
+  PchRpIndex4      = 4,
+  PchRpIndex5      = 5,
+  PchRpIndex6      = 6,
+  PchRpIndex7      = 7,
+  PchRpIndex8      = 8,
+  PchRpIndex9      = 9,
+  PchRpIndex10     = 10,
+  PchRpIndex11     = 11,
+  PchRpIndex12     = 12,
+  PchRpIndex13     = 13,
+  PchRpIndex14     = 14,
+  PchRpIndex15     = 15,
+  PchRpIndex16     = 16,
+  PchRpIndex17     = 17,
+  PchRpIndex18     = 18,
+  PchRpIndex19     = 19,
+  PchRpIndex20     = 20,
+  PchRpIndex21     = 21,
+  PchRpIndex22     = 22,
+  PchRpIndex23     = 23,
+  /**
+    Quantity of PCH and CPU PCIe ports, as well as their encoding in this enum, may change between
+    silicon generations and series. Do not assume that PCH port 0 will be always encoded by 0.
+    Instead, it is recommended to use (PchRpIndex0 + PchPortIndex) 
+style to be forward-compatible
+  **/
+  CpuRpIndex0      = 0x40,
+  CpuRpIndex1      = 0x41,
+  CpuRpIndex2      = 0x42,
+  CpuRpIndex3      = 0x43
+} PCIE_COMBINED_RPINDEX;
+
+//
+// Member functions
+//
+
+typedef struct {
+  UINT8                                 RpIndex; ///< Root port index (0-based), 0: RP1, 1: RP2, n: RP(N+1)
+  UINT8                                 BusNum;  ///< Root port pci bus number
+  UINT8                                 DevNum;  ///< Root port pci device number
+  UINT8                                 FuncNum; ///< Root port pci function number
+} PCH_PCIE_SMI_RP_CONTEXT;
+
+/**
+  Callback function for an PCH PCIE RP SMI handler dispatch.
+
+  @param[in] DispatchHandle             The unique handle assigned to this handler by register function.
+  @param[in] RpContext                  Pointer of PCH PCIE Root Port context.
+
+**/
+typedef
+VOID
+(EFIAPI *PCH_PCIE_SMI_RP_DISPATCH_CALLBACK) (
+  IN EFI_HANDLE                         DispatchHandle,
+  IN PCH_PCIE_SMI_RP_CONTEXT            *RpContext
+  );
+
+/**
+  Register a child SMI source dispatch function for PCH PCIERP SMI events.
+
+  @param[in] This                       Protocol instance pointer.
+  @param[in] DispatchFunction           Pointer to dispatch function to be invoked for
+                                        this SMI source
+  @param[in] RpIndex                    Refer PCIE_COMBINED_RPINDEX for PCH RP index and CPU RP index.
+                                        0: RP1, 1: RP2, n: RP(N+1)
+  @param[out] DispatchHandle            Handle of dispatch function, for when interfacing
+                                        with the parent SMM driver.
+
+  @retval EFI_SUCCESS                   The dispatch function has been successfully
+                                        registered and the SMI source has been enabled.
+  @retval EFI_DEVICE_ERROR              The driver was unable to enable the SMI source.
+  @retval EFI_OUT_OF_RESOURCES          Not enough memory (system or SMM) to manage this child.
+  @retval EFI_ACCESS_DENIED             Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_PCIE_SMI_RP_DISPATCH_REGISTER) (
+  IN  PCH_PCIE_SMI_DISPATCH_PROTOCOL    *This,
+  IN  PCH_PCIE_SMI_RP_DISPATCH_CALLBACK DispatchFunction,
+  IN  UINTN                             RpIndex,
+  OUT EFI_HANDLE                        *DispatchHandle
+  );
+
+/**
+  Unregister a child SMI source dispatch function with a parent PCIE 
+SMM driver
+
+  @param[in] This                       Protocol instance pointer.
+  @param[in] DispatchHandle             Handle of dispatch function to deregister.
+
+  @retval EFI_SUCCESS                   The dispatch function has been successfully
+                                        unregistered and the SMI source has been disabled
+                                        if there are no other registered child dispatch
+                                        functions for this SMI source.
+  @retval EFI_INVALID_PARAMETER         Handle is invalid.
+  @retval EFI_ACCESS_DENIED             Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_PCIE_SMI_DISPATCH_UNREGISTER) (
+  IN  PCH_PCIE_SMI_DISPATCH_PROTOCOL    *This,
+  IN  EFI_HANDLE                        DispatchHandle
+  );
+
+/**
+  Interface structure for PCH PCIE SMIs Dispatch Protocol
+  The PCH PCIE SMI DISPATCH PROTOCOL provides the ability to dispatch function for PCH PCIE related SMIs.
+  It contains SMI types of HotPlug, LinkActive, and Link EQ.
+**/
+struct _PCH_PCIE_SMI_DISPATCH_PROTOCOL {
+  /**
+    This member specifies the revision of this structure. This field is used to
+    indicate backwards compatible changes to the protocol.
+  **/
+  UINT8                                 Revision;
+  /**
+    Smi unregister function for PCH PCIE SMI DISPATCH PROTOCOL.
+  **/
+  PCH_PCIE_SMI_DISPATCH_UNREGISTER      UnRegister;
+  /**
+    PcieRpXHotPlug
+    The event is triggered when PCIE root port Hot-Plug Presence Detect.
+  **/
+  PCH_PCIE_SMI_RP_DISPATCH_REGISTER     HotPlugRegister;
+  /**
+    PcieRpXLinkActive
+    The event is triggered when Hot-Plug Link Active State Changed.
+  **/
+  PCH_PCIE_SMI_RP_DISPATCH_REGISTER     LinkActiveRegister;
+  /**
+    PcieRpXLinkEq
+    The event is triggered when Device Requests Software Link Equalization.
+  **/
+  PCH_PCIE_SMI_RP_DISPATCH_REGISTER     LinkEqRegister;
+};
+
+/**
+  PCH PCIE SMI dispatch revision number
+
+  Revision 1:   Initial version
+**/
+#define PCH_PCIE_SMI_DISPATCH_REVISION            1
+
+#endif
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchSmiDispatch.h b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchSmiDispatch.h
new file mode 100644
index 0000000000..fd270fe72a
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchSmiDispa
+++ tch.h
@@ -0,0 +1,132 @@
+/** @file
+  APIs of PCH SMI Dispatch Protocol.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent **/ #ifndef 
+_PCH_SMI_DISPATCH_PROTOCOL_H_ #define _PCH_SMI_DISPATCH_PROTOCOL_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID                         gPchSmiDispatchProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility //
+typedef struct _PCH_SMI_DISPATCH_PROTOCOL         PCH_SMI_DISPATCH_PROTOCOL;
+
+//
+// Member functions
+//
+
+/**
+  Callback function for an PCH SMI handler dispatch.
+
+  @param[in] DispatchHandle             The unique handle assigned to this handler by register function.
+
+**/
+typedef
+VOID
+(EFIAPI *PCH_SMI_DISPATCH_CALLBACK) (
+  IN EFI_HANDLE                         DispatchHandle
+  );
+
+/**
+  Register a child SMI source dispatch function for specific PCH SMI dispatch event.
+
+  @param[in] This                       Protocol instance pointer.
+  @param[in] DispatchFunction           Pointer to dispatch function to be invoked for
+                                        this SMI source
+  @param[out] DispatchHandle            Handle of dispatch function, for when interfacing
+                                        with the parent SMM driver.
+
+  @retval EFI_SUCCESS                   The dispatch function has been successfully
+                                        registered and the SMI source has been enabled.
+  @retval EFI_DEVICE_ERROR              The driver was unable to enable the SMI source.
+  @retval EFI_OUT_OF_RESOURCES          Not enough memory (system or SMM) to manage this child.
+  @retval EFI_ACCESS_DENIED             Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SMI_DISPATCH_REGISTER) (
+  IN  PCH_SMI_DISPATCH_PROTOCOL         *This,
+  IN  PCH_SMI_DISPATCH_CALLBACK         DispatchFunction,
+  OUT EFI_HANDLE                        *DispatchHandle
+  );
+
+/**
+  Unregister a child SMI source dispatch function with a parent SMM 
+driver
+
+  @param[in] This                       Protocol instance pointer.
+  @param[in] DispatchHandle             Handle of dispatch function to deregister.
+
+  @retval EFI_SUCCESS                   The dispatch function has been successfully
+                                        unregistered and the SMI source has been disabled
+                                        if there are no other registered child dispatch
+                                        functions for this SMI source.
+  @retval EFI_INVALID_PARAMETER         Handle is invalid.
+  @retval EFI_ACCESS_DENIED             Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SMI_DISPATCH_UNREGISTER) (
+  IN  PCH_SMI_DISPATCH_PROTOCOL         *This,
+  IN  EFI_HANDLE                        DispatchHandle
+  );
+
+/**
+  Interface structure for PCH specific SMIs Dispatch Protocol
+  The PCH SMI DISPATCH PROTOCOL provides the ability to dispatch function for PCH misc SMIs.
+  It contains legacy SMIs and new PCH SMI types like:
+  SerialIrq, McSmi, Smbus, ...
+**/
+struct _PCH_SMI_DISPATCH_PROTOCOL {
+  /**
+    This member specifies the revision of this structure. This field is used to
+    indicate backwards compatible changes to the protocol.
+  **/
+  UINT8                                 Revision;
+  /**
+    Smi unregister function for PCH SMI DISPATCH PROTOCOL.
+  **/
+  PCH_SMI_DISPATCH_UNREGISTER           UnRegister;
+  /**
+    SerialIrq
+    The event is triggered while the SMI# was caused by the SERIRQ decoder.
+  **/
+  PCH_SMI_DISPATCH_REGISTER             SerialIrqRegister;
+  /**
+    McSmi
+    The event is triggered if there has been an access to the power management
+    microcontroller range (62h or 66h) and the Microcontroller Decode Enable #1 bit
+    in the LPC Bridge I/O Enables configuration register is 1 .
+  **/
+  PCH_SMI_DISPATCH_REGISTER             McSmiRegister;
+  /**
+    SmBus
+    The event is triggered while the SMI# was caused by:
+    1. The SMBus target receiving a message that an SMI# should be caused, or
+    2. The SMBALERT# signal goes active and the SMB_SMI_EN bit is set and the
+       SMBALERT_DIS bit is cleared, or
+    3. The SMBus target receiving a Host Notify message and the HOST_NOTIFY_INTREN and
+       the SMB_SMI_EN bits are set, or
+    4. The PCH detecting the SMLINK_SLAVE_SMI command while in the S0 state.
+  **/
+  PCH_SMI_DISPATCH_REGISTER             SmbusRegister;
+  /**
+    SPI Asynchronous
+    When registered, the flash controller will generate an SMI when it blocks a BIOS write or erase.
+  **/
+  PCH_SMI_DISPATCH_REGISTER             SpiAsyncRegister;
+};
+
+/**
+  PCH SMI dispatch revision number
+
+  Revision 1:   Initial version
+**/
+#define PCH_SMI_DISPATCH_REVISION                 1
+
+#endif
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchSmmIoTrapControl.h b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchSmmIoTrapControl.h
new file mode 100644
index 0000000000..87c301901e
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchSmmIoTra
+++ pControl.h
@@ -0,0 +1,65 @@
+/** @file
+  PCH SMM IO Trap Control Protocol
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent **/ #ifndef 
+_PCH_SMM_IO_TRAP_CONTROL_H_ #define _PCH_SMM_IO_TRAP_CONTROL_H_
+
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID                                   gPchSmmIoTrapControlGuid;
+
+//
+// Forward reference for ANSI C compatibility // typedef struct 
+_PCH_SMM_IO_TRAP_CONTROL_PROTOCOL  PCH_SMM_IO_TRAP_CONTROL_PROTOCOL;
+
+//
+// Related Definitions
+//
+
+//
+// Member functions
+//
+
+/**
+  The Prototype of Pause and Resume IoTrap callback function.
+
+  @param[in] This                 Pointer to the PCH_SMM_IO_TRAP_CONTROL_PROTOCOL instance.
+  @param[in] DispatchHandle       Handle of the child service to change state.
+
+  @retval EFI_SUCCESS             This operation is complete.
+  @retval EFI_INVALID_PARAMETER   The DispatchHandle is invalid.
+  @retval EFI_ACCESS_DENIED       The SMI status is alrady PAUSED/RESUMED.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SMM_IO_TRAP_CONTROL_FUNCTION) (
+  IN PCH_SMM_IO_TRAP_CONTROL_PROTOCOL           * This,
+  IN EFI_HANDLE                                 DispatchHandle
+  );
+
+/**
+  Interface structure for the SMM IO trap pause and resume protocol
+  This protocol provides the functions to runtime control the IoTrap SMI enabled/disable.
+  This applys the capability to the DispatchHandle which returned by 
+IoTrap callback
+  registration, and the DispatchHandle which must be MergeDisable = TRUE and Address != 0.
+  Besides, when S3 resuem, it only restores the state of IoTrap callback registration.
+  The Paused/Resume state won't be restored after S3 resume.
+**/
+struct _PCH_SMM_IO_TRAP_CONTROL_PROTOCOL {
+  /**
+    This runtime pauses a registered IoTrap handler.
+  **/
+  PCH_SMM_IO_TRAP_CONTROL_FUNCTION      Pause;
+  /**
+    This runtime resumes a registered IoTrap handler.
+  **/
+  PCH_SMM_IO_TRAP_CONTROL_FUNCTION      Resume;
+};
+
+#endif
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchSmmPeriodicTimerControl.h b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchSmmPeriodicTimerControl.h
new file mode 100644
index 0000000000..f4773c3dd3
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchSmmPerio
+++ dicTimerControl.h
@@ -0,0 +1,65 @@
+/** @file
+  PCH SMM Periodic Timer Control Protocol
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent **/ #ifndef 
+_PCH_SMM_PERIODIC_TIMER_CONTROL_H_
+#define _PCH_SMM_PERIODIC_TIMER_CONTROL_H_
+
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID                                             gPchSmmPeriodicTimerControlGuid;
+
+//
+// Forward reference for ANSI C compatibility //
+typedef struct _PCH_SMM_PERIODIC_TIMER_CONTROL_PROTOCOL     PCH_SMM_PERIODIC_TIMER_CONTROL_PROTOCOL;
+
+//
+// Related Definitions
+//
+
+//
+// Member functions
+//
+
+/**
+  The Prototype of Pause and Resume SMM PERIODIC TIMER function.
+
+  @param[in] This                       Pointer to the PCH_SMM_PERIODIC_TIMER_CONTROL_PROTOCOL instance.
+  @param[in] DispatchHandle             Handle of the child service to change state.
+
+  @retval EFI_SUCCESS                   This operation is complete.
+  @retval EFI_INVALID_PARAMETER         The DispatchHandle is invalid.
+  @retval EFI_ACCESS_DENIED             The SMI status is alrady PAUSED/RESUMED.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SMM_PERIODIC_TIMER_CONTROL_FUNCTION) (
+  IN PCH_SMM_PERIODIC_TIMER_CONTROL_PROTOCOL      *This,
+  IN EFI_HANDLE                                   DispatchHandle
+  );
+
+/**
+  Interface structure for the SMM PERIODIC TIMER pause and resume 
+protocol
+  This protocol provides the functions to runtime control the SM periodic timer enabled/disable.
+  This applies the capability to the DispatchHandle which returned by 
+SMM periodic timer callback
+  registration.
+  Besides, when S3 resume, it only restores the state of callback registration.
+  The Paused/Resume state won't be restored after S3 resume.
+**/
+struct _PCH_SMM_PERIODIC_TIMER_CONTROL_PROTOCOL {
+  /**
+    This runtime pauses the registered periodic timer handler.
+  **/
+  PCH_SMM_PERIODIC_TIMER_CONTROL_FUNCTION         Pause;
+  /**
+    This runtime resumes the registered periodic timer handler.
+  **/
+  PCH_SMM_PERIODIC_TIMER_CONTROL_FUNCTION         Resume;
+};
+
+#endif // _PCH_SMM_PERIODIC_TIMER_CONTROL_H_
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchTcoSmiDispatch.h b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchTcoSmiDispatch.h
new file mode 100644
index 0000000000..f39773e420
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/PchTcoSmiDi
+++ spatch.h
@@ -0,0 +1,150 @@
+/** @file
+  APIs of PCH TCO SMI Dispatch Protocol.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent **/ #ifndef 
+_PCH_TCO_SMI_DISPATCH_PROTOCOL_H_
+#define _PCH_TCO_SMI_DISPATCH_PROTOCOL_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID                         gPchTcoSmiDispatchProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility //
+typedef struct _PCH_TCO_SMI_DISPATCH_PROTOCOL     PCH_TCO_SMI_DISPATCH_PROTOCOL;
+
+//
+// Member functions
+//
+
+/**
+  Callback function for an PCH TCO SMI handler dispatch.
+
+  @param[in] DispatchHandle             The unique handle assigned to this handler by register function.
+
+**/
+typedef
+VOID
+(EFIAPI *PCH_TCO_SMI_DISPATCH_CALLBACK) (
+  IN EFI_HANDLE                         DispatchHandle
+  );
+
+/**
+  Register a child SMI source dispatch function for PCH TCO SMI events.
+
+  @param[in] This                       Protocol instance pointer.
+  @param[in] DispatchFunction           Pointer to dispatch function to be invoked for
+                                        this SMI source
+  @param[out] DispatchHandle            Handle of dispatch function, for when interfacing
+                                        with the parent SMM driver.
+
+  @retval EFI_SUCCESS                   The dispatch function has been successfully
+                                        registered and the SMI source has been enabled.
+  @retval EFI_DEVICE_ERROR              The driver was unable to enable the SMI source.
+  @retval EFI_OUT_OF_RESOURCES          Not enough memory (system or SMM) to manage this child.
+  @retval EFI_ACCESS_DENIED             Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_TCO_SMI_DISPATCH_REGISTER) (
+  IN  PCH_TCO_SMI_DISPATCH_PROTOCOL     *This,
+  IN  PCH_TCO_SMI_DISPATCH_CALLBACK     DispatchFunction,
+  OUT EFI_HANDLE                        *DispatchHandle
+  );
+
+/**
+  Unregister a child SMI source dispatch function with a parent TCO SMM 
+driver
+
+  @param[in] This                       Protocol instance pointer.
+  @param[in] DispatchHandle             Handle of dispatch function to deregister.
+
+  @retval EFI_SUCCESS                   The dispatch function has been successfully
+                                        unregistered and the SMI source has been disabled
+                                        if there are no other registered child dispatch
+                                        functions for this SMI source.
+  @retval EFI_INVALID_PARAMETER         Handle is invalid.
+  @retval EFI_ACCESS_DENIED             Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_TCO_SMI_DISPATCH_UNREGISTER) (
+  IN  PCH_TCO_SMI_DISPATCH_PROTOCOL     *This,
+  IN  EFI_HANDLE                        DispatchHandle
+  );
+
+/**
+  Interface structure for PCH TCO SMIs Dispatch Protocol
+  The PCH TCO SMI DISPATCH PROTOCOL provides the ability to dispatch function for PCH TCO related SMIs.
+  It contains SMI types of Mch, TcoTimeout, OsTco, Nmi, IntruderDectect, and BiowWp.
+**/
+struct _PCH_TCO_SMI_DISPATCH_PROTOCOL {
+  /**
+    This member specifies the revision of this structure. This field is used to
+    indicate backwards compatible changes to the protocol.
+  **/
+  UINT8                                 Revision;
+  /**
+    Smi unregister function for PCH TCO SMI DISPATCH PROTOCOL.
+  **/
+  PCH_TCO_SMI_DISPATCH_UNREGISTER       UnRegister;
+  /**
+    Mch
+    The event is triggered when PCH received a DMI special cycle message using DMI indicating that
+    it wants to cause an SMI.
+    The software must read the processor to determine the reason for the SMI.
+  **/
+  PCH_TCO_SMI_DISPATCH_REGISTER         MchRegister;
+  /**
+    TcoTimeout
+    The event is triggered by PCH to indicate that the SMI was caused by the TCO timer reaching 0.
+  **/
+  PCH_TCO_SMI_DISPATCH_REGISTER         TcoTimeoutRegister;
+  /**
+    OsTco
+    The event is triggered when software caused an SMI# by writing to the TCO_DAT_IN register (TCOBASE + 02h).
+  **/
+  PCH_TCO_SMI_DISPATCH_REGISTER         OsTcoRegister;
+  /**
+    Nmi
+    The event is triggered by the PCH when an SMI# occurs because an event occurred that would otherwise have
+    caused an NMI (because NMI2SMI_EN is set)
+  **/
+  PCH_TCO_SMI_DISPATCH_REGISTER         NmiRegister;
+  /**
+    IntruderDectect
+    The event is triggered by PCH to indicate that an intrusion was detected.
+  **/
+  PCH_TCO_SMI_DISPATCH_REGISTER         IntruderDetRegister;
+  /**
+    SpiBiosWp
+    This event is triggered when SMI# was caused by the TCO logic and
+    SPI flash controller asserted Synchronous SMI by BIOS lock enable set.
+  **/
+  PCH_TCO_SMI_DISPATCH_REGISTER         SpiBiosWpRegister;
+  /**
+    LpcBiosWp
+    This event is triggered when SMI# was caused by the TCO logic and
+    LPC/eSPI BIOS lock enable set.
+  **/
+  PCH_TCO_SMI_DISPATCH_REGISTER         LpcBiosWpRegister;
+  /**
+    NewCentury
+    This event is triggered when SMI# was caused by the TCO logic and
+    year of RTC date rolls over a century (99 to 00).
+  **/
+  PCH_TCO_SMI_DISPATCH_REGISTER         NewCenturyRegister;
+};
+
+/**
+  PCH TCO SMI dispatch revision number
+
+  Revision 1:   Initial version
+  Revision 2:   Add NEWCENTURY support
+**/
+#define PCH_TCO_SMI_DISPATCH_REVISION             2
+
+#endif
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/SmmSmbus.h b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/SmmSmbus.h
new file mode 100644
index 0000000000..fa1a79ca84
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Protocol/SmmSmbus.h
@@ -0,0 +1,13 @@
+/** @file
+  SmmSmbus Protocol
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent **/ #ifndef 
+__EFI_SMM_SMBUS_PROTOCOL_H__ #define __EFI_SMM_SMBUS_PROTOCOL_H__
+
+extern EFI_GUID               gEfiSmmSmbusProtocolGuid;
+
+#endif
+
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Register/PchRegs.h b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Register/PchRegs.h
new file mode 100644
index 0000000000..33b75e82fd
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Include/Register/PchRegs.h
@@ -0,0 +1,45 @@
+/** @file
+  Generic register definitions for PCH.
+
+Conventions:
+
+  - Register definition format:
+    
+ Prefix_[GenerationName]_[ComponentName]_SubsystemName_RegisterSpace_Re
+ gisterName
+  - Prefix:
+    Definitions beginning with "R_" are registers
+    Definitions beginning with "B_" are bits within registers
+    Definitions beginning with "V_" are meaningful values within the bits
+    Definitions beginning with "S_" are register size
+    Definitions beginning with "N_" are the bit position
+  - [GenerationName]:
+    Three letter acronym of the generation is used (e.g. SKL,KBL,CNL etc.).
+    Register name without GenerationName applies to all generations.
+  - [ComponentName]:
+    This field indicates the component name that the register belongs to (e.g. PCH, SA etc.)
+    Register name without ComponentName applies to all components.
+    Register that is specific to -H denoted by "_PCH_H_" in component name.
+    Register that is specific to -LP denoted by "_PCH_LP_" in component name.
+  - SubsystemName:
+    This field indicates the subsystem name of the component that the register belongs to
+    (e.g. PCIE, USB, SATA, GPIO, PMC etc.).
+  - RegisterSpace:
+    MEM - MMIO space register of subsystem.
+    IO  - IO space register of subsystem.
+    PCR - Private configuration register of subsystem.
+    CFG - PCI configuration space register of subsystem.
+  - RegisterName:
+    Full register name.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent **/ #ifndef 
+_PCH_REGS_H_ #define _PCH_REGS_H_
+
+///
+/// The default PCH PCI segment and bus number /// #define 
+DEFAULT_PCI_SEGMENT_NUMBER_PCH  0
+#define DEFAULT_PCI_BUS_NUMBER_PCH      0
+
+#endif //_PCH_REGS_H_
--
2.36.1.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#107159): https://edk2.groups.io/g/devel/message/107159
Mute This Topic: https://groups.io/mt/99554474/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [edk2-devel] [PATCH 4/8] AlderlakeSiliconPkg/Pch: Add libraries
  2023-06-15 17:53 ` [PATCH 4/8] AlderlakeSiliconPkg/Pch: Add libraries Saloni Kasbekar
@ 2023-07-24  7:42   ` Chaganty, Rangasai V
  0 siblings, 0 replies; 15+ messages in thread
From: Chaganty, Rangasai V @ 2023-07-24  7:42 UTC (permalink / raw)
  To: Kasbekar, Saloni, devel@edk2.groups.io
  Cc: Desimone, Nathaniel L, Oram, Isaac W, Chuang, Rosen

Reviewed-by: Sai Chaganty <rangasai.v.chaganty@intel.com>

-----Original Message-----
From: Kasbekar, Saloni <saloni.kasbekar@intel.com> 
Sent: Thursday, June 15, 2023 10:53 AM
To: devel@edk2.groups.io
Cc: Kasbekar, Saloni <saloni.kasbekar@intel.com>; Chaganty, Rangasai V <rangasai.v.chaganty@intel.com>; Desimone, Nathaniel L <nathaniel.l.desimone@intel.com>; Oram, Isaac W <isaac.w.oram@intel.com>; Chuang, Rosen <rosen.chuang@intel.com>
Subject: [PATCH 4/8] AlderlakeSiliconPkg/Pch: Add libraries

Adds the following libraries:
- BasePchPciBdfLib
- BaseResetSystemLib
- PeiDxeSmmPchCycleDecodingLib

Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Isaac Oram <isaac.w.oram@intel.com>
Cc: Rosen Chuang <rosen.chuang@intel.com>
Signed-off-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
---
 .../BasePchPciBdfLib/BasePchPciBdfLib.inf     |  32 ++
 .../Library/BasePchPciBdfLib/PchPciBdfLib.c   | 308 ++++++++++++++++++
 .../BaseResetSystemLib/BaseResetSystemLib.c   | 114 +++++++
 .../BaseResetSystemLib/BaseResetSystemLib.inf |  37 +++
 .../PchCycleDecodingLib.c                     | 194 +++++++++++
 .../PeiDxeSmmPchCycleDecodingLib.inf          |  41 +++
 6 files changed, 726 insertions(+)
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/BasePchPciBdfLib/BasePchPciBdfLib.inf
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/BasePchPciBdfLib/PchPciBdfLib.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/BaseResetSystemLib/BaseResetSystemLib.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/BaseResetSystemLib/BaseResetSystemLib.inf
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PchCycleDecodingLib.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PeiDxeSmmPchCycleDecodingLib.inf

diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/BasePchPciBdfLib/BasePchPciBdfLib.inf b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/BasePchPciBdfLib/BasePchPciBdfLib.inf
new file mode 100644
index 0000000000..e65f564c1b
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/BasePchPciBdfLib/Bas
+++ ePchPciBdfLib.inf
@@ -0,0 +1,32 @@
+## @file
+# PCH PCIe Bus Device Function Library.
+#
+# All functions from this library are available in PEI, DXE, and SMM, # 
+But do not support UEFI RUNTIME environment call.
+#
+#   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+#   SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmPchPciBdfLib
+FILE_GUID = A36363FC-2951-4DCF-AC81-16F4ED3FDA47
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchPciBdfLib
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+PciSegmentLib
+PchInfoLib
+PchPcieRpLib
+
+[Packages]
+MdePkg/MdePkg.dec
+AlderlakeSiliconPkg/SiPkg.dec
+
+[Sources]
+PchPciBdfLib.c
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/BasePchPciBdfLib/PchPciBdfLib.c b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/BasePchPciBdfLib/PchPciBdfLib.c
new file mode 100644
index 0000000000..c26625e2eb
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/BasePchPciBdfLib/Pch
+++ PciBdfLib.c
@@ -0,0 +1,308 @@
+/** @file
+  PCH PCIe Bus Device Function Library.
+  All functions from this library are available in PEI, DXE, and SMM,
+  But do not support UEFI RUNTIME environment call.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent **/
+
+#include <Base.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchPcieRpLib.h>
+#include <Register/PchRegs.h>
+#include <PchBdfAssignment.h>
+
+/**
+  Check if a Device is present for PCH FRU
+  If the data is defined for PCH RFU return it
+  If the data is not defined (Device is NOT present) assert.
+
+  @param[in]  DataToCheck       Device or Function number to check
+
+  @retval Device or Function number value if defined for PCH FRU
+          0xFF if not present in PCH FRU **/
+UINT8
+CheckAndReturn (
+  UINT8 DataToCheck
+  )
+{
+  if (DataToCheck == NOT_PRESENT) {
+    ASSERT (FALSE);
+  }
+  return DataToCheck;
+}
+
+/**
+  Get P2SB PCI device number
+
+  @retval PCI dev number
+**/
+UINT8
+P2sbDevNumber (
+  VOID
+  )
+{
+  return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_P2SB); }
+
+/**
+  Get P2SB PCI function number
+
+  @retval PCI fun number
+**/
+UINT8
+P2sbFuncNumber (
+  VOID
+  )
+{
+  return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_P2SB); }
+
+/**
+  Get P2SB controller address that can be passed to the PCI Segment Library functions.
+
+  @retval P2SB controller address in PCI Segment Library representation 
+**/
+UINT64
+P2sbPciCfgBase (
+  VOID
+  )
+{
+  return PCI_SEGMENT_LIB_ADDRESS (
+           DEFAULT_PCI_SEGMENT_NUMBER_PCH,
+           DEFAULT_PCI_BUS_NUMBER_PCH,
+           P2sbDevNumber (),
+           P2sbFuncNumber (),
+           0
+           );
+}
+
+
+
+/**
+  Returns PCH SPI Device number
+
+  @retval UINT8   PCH SPI Device number
+**/
+UINT8
+SpiDevNumber (
+  VOID
+  )
+{
+  return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_SPI); }
+
+/**
+  Returns PCH SPI Function number
+
+  @retval UINT8   PCH SPI Function number
+**/
+UINT8
+SpiFuncNumber (
+  VOID
+  )
+{
+  return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_SPI); }
+
+/**
+  Returns PCH SPI PCI Config Space base address
+
+  @retval  UINT64  PCH SPI Config Space base address **/
+UINT64
+SpiPciCfgBase (
+  VOID
+  )
+{
+  return PCI_SEGMENT_LIB_ADDRESS (
+           DEFAULT_PCI_SEGMENT_NUMBER_PCH,
+           DEFAULT_PCI_BUS_NUMBER_PCH,
+           SpiDevNumber (),
+           SpiFuncNumber (),
+           0
+           );
+}
+
+/**
+  Get XHCI controller PCIe Device Number
+
+  @retval XHCI controller PCIe Device Number **/
+UINT8
+PchXhciDevNumber (
+  VOID
+  )
+{
+  return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_XHCI); }
+
+/**
+  Get XHCI controller PCIe Function Number
+
+  @retval XHCI controller PCIe Function Number **/
+UINT8
+PchXhciFuncNumber (
+  VOID
+  )
+{
+  return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_XHCI); }
+
+/**
+  Get LPC controller PCIe Device Number
+
+  @retval LPC controller PCIe Device Number **/
+UINT8
+LpcDevNumber (
+  VOID
+  )
+{
+  return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_LPC); }
+
+/**
+  Get LPC controller PCIe Function Number
+
+  @retval LPC controller PCIe Function Number **/
+UINT8
+LpcFuncNumber (
+  VOID
+  )
+{
+  return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_LPC); }
+
+/**
+  Returns PCH LPC device PCI base address.
+
+  @retval                   PCH LPC PCI base address.
+**/
+UINT64
+LpcPciCfgBase (
+  VOID
+  )
+{
+  return PCI_SEGMENT_LIB_ADDRESS (
+           DEFAULT_PCI_SEGMENT_NUMBER_PCH,
+           DEFAULT_PCI_BUS_NUMBER_PCH,
+           LpcDevNumber (),
+           LpcFuncNumber (),
+           0
+           );
+}
+
+
+
+/**
+  Get PCH PCIe controller PCIe Device Number
+
+  @param[in]  RpIndex       Root port physical number. (0-based)
+
+  @retval PCH PCIe controller PCIe Device Number **/
+UINT8
+PchPcieRpDevNumber (
+  IN  UINTN   RpIndex
+  )
+{
+  switch (RpIndex) {
+    case 0:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_1);
+    case 1:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_2);
+    case 2:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_3);
+    case 3:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_4);
+    case 4:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_5);
+    case 5:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_6);
+    case 6:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_7);
+    case 7:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_8);
+    case 8:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_9);
+    case 9:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_10);
+    case 10:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_11);
+    case 11:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_12);
+    case 12:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_13);
+    case 13:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_14);
+    case 14:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_15);
+    case 15:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_16);
+    case 16:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_17);
+    case 17:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_18);
+    case 18:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_19);
+    case 19:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_20);
+    case 20:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_21);
+    case 21:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_22);
+    case 22:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_23);
+    case 23:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_24);
+    case 24:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_25);
+    case 25:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_26);
+    case 26:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_27);
+    case 27:
+      return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_28);
+
+    default:
+      ASSERT (FALSE);
+      return 0xFF;
+  }
+}
+
+/**
+  Get PCH PCIe controller PCIe Function Number
+  Note:
+  For Client PCH generations Function Number can be various
+  depending on "Root Port Function Swapping". For such cases
+  Function Number  MUST be obtain from proper register.
+  For Server PCHs we have no "Root Port Function Swapping"
+  and we can return fixed Function Number.
+  To address this difference in this, PCH generation independent,
+  library we should call specific function in PchPcieRpLib.
+
+  @param[in]  RpIndex       Root port physical number. (0-based)
+
+  @retval PCH PCIe controller PCIe Function Number **/
+UINT8
+PchPcieRpFuncNumber (
+  IN  UINTN   RpIndex
+  )
+{
+  UINTN   Device;
+  UINTN   Function;
+
+  GetPchPcieRpDevFun (RpIndex, &Device, &Function);
+
+  return (UINT8)Function;
+}
+
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/BaseResetSystemLib/BaseResetSystemLib.c b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/BaseResetSystemLib/BaseResetSystemLib.c
new file mode 100644
index 0000000000..86eeff9407
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/BaseResetSystemLib/B
+++ aseResetSystemLib.c
@@ -0,0 +1,114 @@
+/** @file
+  System reset library services.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include <Uefi.h> 
+#include <Library/IoLib.h> #include <Library/DebugLib.h> #include 
+<Library/ResetSystemLib.h> #include <Library/PmcLib.h> #include 
+<Library/BaseLib.h> #include <Register/PchRegsLpc.h> #include 
+<Register/PmcRegs.h>
+
+/**
+  Calling this function causes a system-wide reset. This sets
+  all circuitry within the system to its initial state. This type of 
+reset
+  is asynchronous to system operation and operates without regard to
+  cycle boundaries.
+
+  System reset should not return, if it returns, it means the system 
+does
+  not support cold reset.
+**/
+VOID
+EFIAPI
+ResetCold (
+  VOID
+  )
+{
+  IoWrite8 (R_PCH_IO_RST_CNT, V_PCH_IO_RST_CNT_FULLRESET); }
+
+/**
+  Calling this function causes a system-wide initialization. The 
+processors
+  are set to their initial state, and pending cycles are not corrupted.
+
+  System reset should not return, if it returns, it means the system 
+does
+  not support warm reset.
+**/
+VOID
+EFIAPI
+ResetWarm (
+  VOID
+  )
+{
+  IoWrite8 (R_PCH_IO_RST_CNT, V_PCH_IO_RST_CNT_HARDRESET); }
+
+/**
+  Calling this function causes the system to enter a power state 
+equivalent
+  to the ACPI G2/S5 or G3 states.
+
+  System shutdown should not return, if it returns, it means the system 
+does
+  not support shut down reset.
+**/
+VOID
+EFIAPI
+ResetShutdown (
+  VOID
+  )
+{
+  UINT16         ABase;
+  UINT32         Data32;
+
+  ABase = PmcGetAcpiBase ();
+
+  ///
+  /// Firstly, GPE0_EN should be disabled to avoid any GPI waking up 
+ the system from S5  ///
+  IoWrite32 (ABase + R_ACPI_IO_GPE0_EN_127_96, 0);
+
+  ///
+  /// Secondly, PwrSts register must be cleared  ///  /// Write a "1" 
+ to bit[8] of power button status register at  /// (PM_BASE + 
+ PM1_STS_OFFSET) to clear this bit  ///
+  IoWrite16 (ABase + R_ACPI_IO_PM1_STS, B_ACPI_IO_PM1_STS_PWRBTN);
+
+  ///
+  /// Finally, transform system into S5 sleep state  ///
+  Data32 = IoRead32 (ABase + R_ACPI_IO_PM1_CNT);
+
+  Data32 = (UINT32) ((Data32 &~(B_ACPI_IO_PM1_CNT_SLP_TYP + 
+ B_ACPI_IO_PM1_CNT_SLP_EN)) | V_ACPI_IO_PM1_CNT_S5);
+
+  IoWrite32 (ABase + R_ACPI_IO_PM1_CNT, Data32);
+
+  Data32 = Data32 | B_ACPI_IO_PM1_CNT_SLP_EN;
+
+  IoWrite32 (ABase + R_ACPI_IO_PM1_CNT, Data32);
+
+  return;
+}
+
+/**
+  Calling this function causes the system to enter a power state for platform specific.
+
+  @param[in] DataSize             The size of ResetData in bytes.
+  @param[in] ResetData            Optional element used to introduce a platform specific reset.
+                                  The exact type of the reset is defined by the EFI_GUID that follows
+                                  the Null-terminated Unicode string.
+
+**/
+VOID
+EFIAPI
+ResetPlatformSpecific (
+  IN UINTN            DataSize,
+  IN VOID             *ResetData OPTIONAL
+  )
+{
+  IoWrite8 (R_PCH_IO_RST_CNT, V_PCH_IO_RST_CNT_FULLRESET); }
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/BaseResetSystemLib/BaseResetSystemLib.inf b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/BaseResetSystemLib/BaseResetSystemLib.inf
new file mode 100644
index 0000000000..f0a987d671
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/BaseResetSystemLib/B
+++ aseResetSystemLib.inf
@@ -0,0 +1,37 @@
+## @file
+# Component description file for Intel Ich7 Reset System Library.
+#
+#   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+#   SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = BaseResetSystemLib
+FILE_GUID = D4FF05AA-3C7D-4B8A-A1EE-AA5EFA0B1732
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+UEFI_SPECIFICATION_VERSION = 2.00
+LIBRARY_CLASS = ResetSystemLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF
+#
+
+[LibraryClasses]
+IoLib
+BaseLib
+DebugLib
+PmcLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+AlderlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+BaseResetSystemLib.c
+
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PchCycleDecodingLib.c b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PchCycleDecodingLib.c
new file mode 100644
index 0000000000..ccdac7c5ab
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDec
+++ odingLib/PchCycleDecodingLib.c
@@ -0,0 +1,194 @@
+/** @file
+  PCH cycle decoding configuration and query library.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include <Base.h> 
+#include <Uefi/UefiBaseType.h> #include <Library/IoLib.h> #include 
+<Library/DebugLib.h> #include <Library/BaseLib.h> #include 
+<Library/PciSegmentLib.h> #include <Library/PchInfoLib.h> #include 
+<Library/PchPcrLib.h> #include <Library/PchCycleDecodingLib.h> #include 
+<Library/PchDmiLib.h> #include <Library/BaseMemoryLib.h> #include 
+<Register/PchRegs.h> #include <Register/PchRegsLpc.h> #include 
+<Register/SpiRegs.h> #include <Library/EspiLib.h> #include 
+<Library/PchPciBdfLib.h>
+
+typedef enum {
+  SlaveLpcEspiCS0,
+  SlaveEspiCS1,
+  SlaveId_Max
+} SLAVE_ID_INDEX;
+
+/**
+  Get PCH TCO base address.
+
+  @param[out] Address                   Address of TCO base address.
+
+  @retval EFI_SUCCESS                   Successfully completed.
+  @retval EFI_INVALID_PARAMETER         Invalid pointer passed.
+**/
+EFI_STATUS
+PchTcoBaseGet (
+  OUT UINT16                            *Address
+  )
+{
+  if (Address == NULL) {
+    DEBUG ((DEBUG_ERROR, "PchTcoBaseGet Error. Invalid pointer.\n"));
+    ASSERT (FALSE);
+    return EFI_INVALID_PARAMETER;
+  }
+  //
+  // Read "TCO Base Address" from DMI
+  // Don't read TCO base address from SMBUS PCI register since SMBUS might be disabled.
+  //
+  *Address = PchDmiGetTcoBase ();
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Set PCH LPC/eSPI IO decode ranges.
+  Program LPC/eSPI I/O Decode Ranges in DMI to the same value programmed in LPC/eSPI PCI offset 80h.
+  Please check EDS for detail of LPC/eSPI IO decode ranges bit definition.
+  Bit  12: FDD range
+  Bit 9:8: LPT range
+  Bit 6:4: ComB range
+  Bit 2:0: ComA range
+
+  @param[in] LpcIoDecodeRanges          LPC/eSPI IO decode ranges bit settings.
+
+  @retval EFI_SUCCESS                   Successfully completed.
+  @retval EFI_UNSUPPORTED               DMIC.SRL is set.
+**/
+EFI_STATUS
+PchLpcIoDecodeRangesSet (
+  IN  UINT16                            LpcIoDecodeRanges
+  )
+{
+  UINT64                                LpcBaseAddr;
+  EFI_STATUS                            Status;
+
+  //
+  // Note: Inside this function, don't use debug print since it's could used before debug print ready.
+  //
+
+  LpcBaseAddr = LpcPciCfgBase ();
+
+  //
+  // check if setting is identical
+  //
+  if (LpcIoDecodeRanges == PciSegmentRead16 (LpcBaseAddr + R_LPC_CFG_IOD)) {
+    return EFI_SUCCESS;
+  }
+
+  Status = PchDmiSetLpcIoDecodeRanges (LpcIoDecodeRanges);  if 
+ (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    return Status;
+  }
+
+  //
+  // program LPC/eSPI PCI offset 80h.
+  //
+  PciSegmentWrite16 (LpcBaseAddr + R_LPC_CFG_IOD, LpcIoDecodeRanges);
+
+  return Status;
+}
+
+/**
+  Set PCH LPC/eSPI and eSPI CS1# IO enable decoding.
+  Setup I/O Enables in DMI to the same value program in LPC/eSPI PCI offset 82h (LPC, eSPI CS0#) or A0h (eSPI CS1#).
+  Note: Bit[15:10] of the source decode register is Read-Only. The IO 
+range indicated by the Enables field
+  in LPC/eSPI PCI offset 82h[13:10] or A0h[13:10] is always forwarded by DMI to subtractive agent for handling.
+  Please check EDS for detail of Lpc/eSPI IO decode ranges bit definition.
+
+  @param[in] IoEnableDecoding           LPC/eSPI IO enable decoding bit settings.
+  @param[in] SlaveId                    Target ID (refer to SLAVE_ID_INDEX)
+
+  @retval EFI_SUCCESS                   Successfully completed.
+  @retval EFI_UNSUPPORTED               DMI configuration is locked
+**/
+EFI_STATUS
+LpcEspiIoEnableDecodingSetHelper (
+  IN  UINT16                            IoEnableDecoding,
+  IN  SLAVE_ID_INDEX                    SlaveId
+  )
+{
+  UINT64      LpcBaseAddr;
+  EFI_STATUS  Status;
+  UINT16      Cs1IoEnableDecodingOrg;
+  UINT16      Cs0IoEnableDecodingOrg;
+  UINT16      IoEnableDecodingMerged;
+
+  LpcBaseAddr = LpcPciCfgBase ();
+
+  Cs0IoEnableDecodingOrg = PciSegmentRead16 (LpcBaseAddr + 
+ R_LPC_CFG_IOE);
+
+  if (IsEspiSecondSlaveSupported ()) {
+    Cs1IoEnableDecodingOrg = PciSegmentRead16 (LpcBaseAddr + 
+ R_ESPI_CFG_CS1IORE);  } else {
+    Cs1IoEnableDecodingOrg = 0;
+  }
+
+  if (SlaveId == SlaveEspiCS1) {
+    if (IoEnableDecoding == Cs1IoEnableDecodingOrg) {
+      return EFI_SUCCESS;
+    } else {
+      IoEnableDecodingMerged = (Cs0IoEnableDecodingOrg | IoEnableDecoding);
+    }
+  } else {
+    if ((IoEnableDecoding | Cs1IoEnableDecodingOrg) == Cs0IoEnableDecodingOrg) {
+      return EFI_SUCCESS;
+    } else {
+      IoEnableDecodingMerged = (Cs1IoEnableDecodingOrg | IoEnableDecoding);
+    }
+  }
+
+  Status = PchDmiSetLpcIoEnable (IoEnableDecodingMerged);  if 
+ (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    return Status;
+  }
+
+  //
+  // program PCI offset 82h for LPC/eSPI.
+  //
+  PciSegmentWrite16 (LpcBaseAddr + R_LPC_CFG_IOE, 
+ IoEnableDecodingMerged);
+
+  if (SlaveId == SlaveEspiCS1) {
+    //
+    // For eSPI CS1# device program eSPI PCI offset A0h.
+    //
+    PciSegmentWrite16 (LpcBaseAddr + R_ESPI_CFG_CS1IORE, 
+ IoEnableDecoding);  }
+
+  return Status;
+}
+
+/**
+  Set PCH LPC and eSPI CS0# IO enable decoding.
+  Setup I/O Enables in DMI to the same value program in LPC/eSPI PCI offset 82h.
+  Note: Bit[15:10] of the source decode register is Read-Only. The IO 
+range indicated by the Enables field
+  in LPC/eSPI PCI offset 82h[13:10] is always forwarded by DMI to subtractive agent for handling.
+  Please check EDS for detail of LPC/eSPI IO decode ranges bit definition.
+
+  @param[in] LpcIoEnableDecoding        LPC IO enable decoding bit settings.
+
+  @retval EFI_SUCCESS                   Successfully completed.
+  @retval EFI_UNSUPPORTED               DMIC.SRL is set.
+**/
+EFI_STATUS
+PchLpcIoEnableDecodingSet (
+  IN  UINT16                            LpcIoEnableDecoding
+  )
+{
+  return LpcEspiIoEnableDecodingSetHelper (LpcIoEnableDecoding, 
+SlaveLpcEspiCS0); }
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PeiDxeSmmPchCycleDecodingLib.inf b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PeiDxeSmmPchCycleDecodingLib.inf
new file mode 100644
index 0000000000..a381c0f0f7
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDec
+++ odingLib/PeiDxeSmmPchCycleDecodingLib.inf
@@ -0,0 +1,41 @@
+## @file
+# PCH cycle decoding Lib.
+#
+# All function in this library is available for PEI, DXE, and SMM, # 
+But do not support UEFI RUNTIME environment call.
+#
+#   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+#   SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmPchCycleDecodingLib FILE_GUID = 
+676C749F-9CD1-46B7-BAFD-4B1BC36B4C8E
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchCycleDecodingLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+PciSegmentLib
+PchInfoLib
+PchPcrLib
+PchDmiLib
+EspiLib
+PchPciBdfLib
+
+[Packages]
+MdePkg/MdePkg.dec
+AlderlakeSiliconPkg/SiPkg.dec
+
+[Sources]
+PchCycleDecodingLib.c
+
+[Pcd]
+gSiPkgTokenSpaceGuid.PcdSiHpetBaseAddress        ## CONSUMES
+gSiPkgTokenSpaceGuid.PcdSiIoApicBaseAddress      ## CONSUMES
--
2.36.1.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#107160): https://edk2.groups.io/g/devel/message/107160
Mute This Topic: https://groups.io/mt/99554476/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [edk2-devel] [PATCH 5/8] AlderlakeSiliconPkg/Pch: Add drivers
  2023-06-15 17:53 ` [PATCH 5/8] AlderlakeSiliconPkg/Pch: Add drivers Saloni Kasbekar
@ 2023-07-24  7:54   ` Chaganty, Rangasai V
  0 siblings, 0 replies; 15+ messages in thread
From: Chaganty, Rangasai V @ 2023-07-24  7:54 UTC (permalink / raw)
  To: Kasbekar, Saloni, devel@edk2.groups.io
  Cc: Desimone, Nathaniel L, Oram, Isaac W, Chuang, Rosen

Reviewed-by: Sai Chaganty <rangasai.v.chaganty@intel.com>

-----Original Message-----
From: Kasbekar, Saloni <saloni.kasbekar@intel.com> 
Sent: Thursday, June 15, 2023 10:53 AM
To: devel@edk2.groups.io
Cc: Kasbekar, Saloni <saloni.kasbekar@intel.com>; Chaganty, Rangasai V <rangasai.v.chaganty@intel.com>; Desimone, Nathaniel L <nathaniel.l.desimone@intel.com>; Oram, Isaac W <isaac.w.oram@intel.com>; Chuang, Rosen <rosen.chuang@intel.com>
Subject: [PATCH 5/8] AlderlakeSiliconPkg/Pch: Add drivers

Adds the following drivers:
- PchSmiDispatcher
- SmmControl

Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Isaac Oram <isaac.w.oram@intel.com>
Cc: Rosen Chuang <rosen.chuang@intel.com>
Signed-off-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
---
 .../Pch/PchSmiDispatcher/Smm/PchSmiDispatch.c | 1857 +++++++++++++++++
 .../PchSmiDispatcher/Smm/PchSmiDispatcher.inf |  106 +
 .../Pch/PchSmiDispatcher/Smm/PchSmiHelper.h   |   34 +
 .../Pch/PchSmiDispatcher/Smm/PchSmm.h         | 1028 +++++++++
 .../Pch/PchSmiDispatcher/Smm/PchSmmCore.c     |  905 ++++++++
 .../Pch/PchSmiDispatcher/Smm/PchSmmGpi.c      |  255 +++
 .../Pch/PchSmiDispatcher/Smm/PchSmmHelpers.c  |  332 +++
 .../Pch/PchSmiDispatcher/Smm/PchSmmHelpers.h  |  163 ++
 .../Smm/PchSmmPeriodicTimer.c                 |  670 ++++++
 .../PchSmiDispatcher/Smm/PchSmmPowerButton.c  |   77 +
 .../Pch/PchSmiDispatcher/Smm/PchSmmSw.c       |  381 ++++
 .../Pch/PchSmiDispatcher/Smm/PchSmmSx.c       |  117 ++
 .../Pch/PchSmiDispatcher/Smm/PchSmmUsb.c      |  244 +++
 .../Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.c |  682 ++++++
 .../Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.h |  107 +
 .../Pch/PchSmiDispatcher/Smm/PcieSmmClient.c  |   38 +
 .../Pch/PchSmiDispatcher/Smm/SmmGlobalsPch.c  |   20 +
 .../Pch/SmmControl/RuntimeDxe/SmmControl.inf  |   53 +
 .../SmmControl/RuntimeDxe/SmmControlDriver.c  |  338 +++
 .../SmmControl/RuntimeDxe/SmmControlDriver.h  |  122 ++
 20 files changed, 7529 insertions(+)
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiDispatch.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiDispatcher.inf
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiHelper.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmm.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmCore.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmGpi.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmHelpers.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmHelpers.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmPeriodicTimer.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmPowerButton.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmSw.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmSx.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmUsb.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PcieSmmClient.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/SmmGlobalsPch.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControl.inf
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.h

diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiDispatch.c b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiDispatch.c
new file mode 100644
index 0000000000..be81459009
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiDispatch.c
@@ -0,0 +1,1857 @@
+/** @file
+  This function handle the register/unregister of PCH specific SMI events.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "PchSmmHelpers.h"
+#include <Library/SmiHandlerProfileLib.h>
+#include <Register/PchRegs.h>
+#include <Register/PmcRegs.h>
+#include <Register/TcoRegs.h>
+#include <Register/PchRegsLpc.h>
+#include <Register/SpiRegs.h>
+#include <Library/PchPciBdfLib.h>
+#include <Library/S3BootScriptLib.h>
+#include "PchSmiHelper.h"
+
+
+/**
+  The internal function used to create and insert a database record
+  for SMI record of Pch Smi types.
+
+  @param[in]  SrcDesc                   The pointer to the SMI source description
+  @param[in]  DispatchFunction          Pointer to dispatch function to be invoked for this SMI source
+  @param[in]  PchSmiType                Specific SMI type of PCH SMI
+  @param[out] DispatchHandle            Handle of dispatch function to register.
+
+  @retval EFI_INVALID_PARAMETER         Error with NULL SMI source description
+  @retval EFI_OUT_OF_RESOURCES          Fail to allocate pool for database record
+  @retval EFI_SUCCESS                   The database record is created successfully.
+**/
+EFI_STATUS
+PchSmiRecordInsert (
+  IN  CONST PCH_SMM_SOURCE_DESC         *SrcDesc,
+  IN  PCH_SMI_CALLBACK_FUNCTIONS        DispatchFunction,
+  IN  PCH_SMI_TYPES                     PchSmiType,
+  OUT EFI_HANDLE                        *DispatchHandle
+  )
+{
+  EFI_STATUS                            Status;
+  DATABASE_RECORD                       Record;
+
+  if (SrcDesc == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  ZeroMem (&Record, sizeof (DATABASE_RECORD));
+  //
+  // Gather information about the registration request
+  //
+  Record.Signature                      = DATABASE_RECORD_SIGNATURE;
+  Record.PchSmiCallback                 = DispatchFunction;
+  Record.ProtocolType                   = PchSmiDispatchType;
+  Record.PchSmiType                     = PchSmiType;
+
+  CopyMem (&Record.SrcDesc, SrcDesc, sizeof (PCH_SMM_SOURCE_DESC));
+  Status = SmmCoreInsertRecord (
+             &Record,
+             DispatchHandle
+             );
+  ASSERT_EFI_ERROR (Status);
+
+  return EFI_SUCCESS;
+}
+
+
+//
+// TCO_STS bit that needs to be cleared
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mDescSrcTcoSts = {
+  PCH_SMM_NO_FLAGS,
+  {
+    NULL_BIT_DESC_INITIALIZER,
+    NULL_BIT_DESC_INITIALIZER
+  },
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_STS}
+      },
+      S_ACPI_IO_SMI_STS,
+      N_ACPI_IO_SMI_STS_TCO
+    }
+  },
+  NULL_BIT_DESC_INITIALIZER
+};
+
+/**
+  Clear the TCO SMI status bit and block after the SMI handling is done
+
+  @param[in] SrcDesc                    Pointer to the PCH SMI source description table
+
+**/
+VOID
+EFIAPI
+PchTcoSmiClearSourceAndBlock (
+  CONST PCH_SMM_SOURCE_DESC             *SrcDesc
+  )
+{
+  PchSmmClearSourceAndBlock (SrcDesc);
+  //
+  // Any TCO-based status bits require special handling.
+  // SMI_STS.TCO_STS must be cleared in addition to the status bit in the TCO registers
+  //
+  PchSmmClearSource (&mDescSrcTcoSts);
+}
+
+/**
+  Clear the TCO SMI status bit after the SMI handling is done
+
+  @param[in] SrcDesc                    Pointer to the PCH SMI source description table
+
+**/
+VOID
+EFIAPI
+PchTcoSmiClearSource (
+  CONST PCH_SMM_SOURCE_DESC             *SrcDesc
+  )
+{
+  PchSmmClearSource (SrcDesc);
+  //
+  // Any TCO-based status bits require special handling.
+  // SMI_STS.TCO_STS must be cleared in addition to the status bit in the TCO registers
+  //
+  PchSmmClearSource (&mDescSrcTcoSts);
+}
+
+/**
+  Initialize Source descriptor structure
+
+   @param[in] SrcDesc                    Pointer to the PCH SMI source description table
+
+**/
+VOID
+EFIAPI
+NullInitSourceDesc (
+   PCH_SMM_SOURCE_DESC                   *SrcDesc
+   )
+{
+  ZeroMem (SrcDesc, sizeof (PCH_SMM_SOURCE_DESC));
+  SrcDesc->En[0].Reg.Type = PCH_SMM_ADDR_TYPE_NULL;
+  SrcDesc->En[1].Reg.Type = PCH_SMM_ADDR_TYPE_NULL;
+  SrcDesc->Sts[0].Reg.Type = PCH_SMM_ADDR_TYPE_NULL;
+  SrcDesc->PmcSmiSts.Reg.Type = PCH_SMM_ADDR_TYPE_NULL;
+}
+
+//
+// Mch srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescMch = {
+  PCH_SMM_NO_FLAGS,
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_EN}
+      },
+      S_ACPI_IO_SMI_EN,
+      N_ACPI_IO_SMI_EN_TCO
+    },
+    NULL_BIT_DESC_INITIALIZER
+  },
+  {
+    {
+      {
+        TCO_ADDR_TYPE,
+        {R_TCO_IO_TCO1_STS}
+      },
+      S_TCO_IO_TCO1_STS,
+      N_TCO_IO_TCO1_STS_DMISMI
+    }
+  },
+  {
+    {
+      ACPI_ADDR_TYPE,
+      {R_ACPI_IO_SMI_STS}
+    },
+    S_ACPI_IO_SMI_STS,
+    N_ACPI_IO_SMI_STS_TCO
+  }
+};
+
+/**
+  The register function used to register SMI handler of MCH event.
+
+  @param[in]  This                      The pointer to the protocol itself
+  @param[in]  DispatchFunction          Pointer to dispatch function to be invoked for this SMI source
+  @param[out] DispatchHandle            Handle of dispatch function to register.
+
+  @retval EFI_INVALID_PARAMETER         Error with NULL SMI source description
+  @retval EFI_OUT_OF_RESOURCES          Fail to allocate pool for database record
+  @retval EFI_SUCCESS                   The database record is created successfully.
+  @retval EFI_ACCESS_DENIED             Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiMchRegister (
+  IN  PCH_TCO_SMI_DISPATCH_PROTOCOL     *This,
+  IN  PCH_TCO_SMI_DISPATCH_CALLBACK     DispatchFunction,
+  OUT EFI_HANDLE                        *DispatchHandle
+  )
+{
+  EFI_STATUS                            Status;
+  DATABASE_RECORD                       *Record;
+
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  Status = PchSmiRecordInsert (
+             &mSrcDescMch,
+             (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+             PchTcoSmiMchType,
+             DispatchHandle
+             );
+  if (!EFI_ERROR (Status)) {
+    Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+    Record->ClearSource = PchTcoSmiClearSource;
+    PchSmmClearSource (&Record->SrcDesc);
+    PchSmmEnableSource (&Record->SrcDesc);
+    SmiHandlerProfileRegisterHandler (&gPchTcoSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+  }
+  return Status;
+}
+
+//
+// TcoTimeout srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescTcoTimeout = {
+  PCH_SMM_NO_FLAGS,
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_EN}
+      },
+      S_ACPI_IO_SMI_EN,
+      N_ACPI_IO_SMI_EN_TCO
+    },
+    NULL_BIT_DESC_INITIALIZER
+  },
+  {
+    {
+      {
+        TCO_ADDR_TYPE,
+        {R_TCO_IO_TCO1_STS}
+      },
+      S_TCO_IO_TCO1_STS,
+      N_TCO_IO_TCO1_STS_TIMEOUT
+    }
+  },
+  {
+    {
+      ACPI_ADDR_TYPE,
+      {R_ACPI_IO_SMI_STS}
+    },
+    S_ACPI_IO_SMI_STS,
+    N_ACPI_IO_SMI_STS_TCO
+  }
+};
+
+/**
+  The register function used to register SMI handler of TcoTimeout event.
+
+  @param[in]  This                      The pointer to the protocol itself
+  @param[in]  DispatchFunction          Pointer to dispatch function to be invoked for this SMI source
+  @param[out] DispatchHandle            Handle of dispatch function to register.
+
+  @retval EFI_INVALID_PARAMETER         Error with NULL SMI source description
+  @retval EFI_OUT_OF_RESOURCES          Fail to allocate pool for database record
+  @retval EFI_SUCCESS                   The database record is created successfully.
+  @retval EFI_ACCESS_DENIED             Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiTcoTimeoutRegister (
+  IN  PCH_TCO_SMI_DISPATCH_PROTOCOL     *This,
+  IN  PCH_TCO_SMI_DISPATCH_CALLBACK     DispatchFunction,
+  OUT EFI_HANDLE                        *DispatchHandle
+  )
+{
+  EFI_STATUS                            Status;
+  DATABASE_RECORD                       *Record;
+
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  Status = PchSmiRecordInsert (
+             &mSrcDescTcoTimeout,
+             (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+             PchTcoSmiTcoTimeoutType,
+             DispatchHandle
+             );
+  if (!EFI_ERROR (Status)) {
+    Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+    Record->ClearSource = PchTcoSmiClearSource;
+    PchSmmClearSource (&Record->SrcDesc);
+    PchSmmEnableSource (&Record->SrcDesc);
+    SmiHandlerProfileRegisterHandler (&gPchTcoSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+  }
+  return Status;
+}
+
+//
+// OsTco srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescOsTco = {
+  PCH_SMM_NO_FLAGS,
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_EN}
+      },
+      S_ACPI_IO_SMI_EN,
+      N_ACPI_IO_SMI_EN_TCO
+    },
+    NULL_BIT_DESC_INITIALIZER
+  },
+  {
+    {
+      {
+        TCO_ADDR_TYPE,
+        {R_TCO_IO_TCO1_STS}
+      },
+      S_TCO_IO_TCO1_STS,
+      N_TCO_IO_TCO1_STS_SW_TCO_SMI
+    }
+  },
+  {
+    {
+      ACPI_ADDR_TYPE,
+      {R_ACPI_IO_SMI_STS}
+    },
+    S_ACPI_IO_SMI_STS,
+    N_ACPI_IO_SMI_STS_TCO
+  }
+};
+
+/**
+  The register function used to register SMI handler of OS TCO event.
+
+  @param[in]  This                      The pointer to the protocol itself
+  @param[in]  DispatchFunction          Pointer to dispatch function to be invoked for this SMI source
+  @param[out] DispatchHandle            Handle of dispatch function to register.
+
+  @retval EFI_INVALID_PARAMETER         Error with NULL SMI source description
+  @retval EFI_OUT_OF_RESOURCES          Fail to allocate pool for database record
+  @retval EFI_SUCCESS                   The database record is created successfully.
+  @retval EFI_ACCESS_DENIED             Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiOsTcoRegister (
+  IN  PCH_TCO_SMI_DISPATCH_PROTOCOL     *This,
+  IN  PCH_TCO_SMI_DISPATCH_CALLBACK     DispatchFunction,
+  OUT EFI_HANDLE                        *DispatchHandle
+  )
+{
+  EFI_STATUS                            Status;
+  DATABASE_RECORD                       *Record;
+
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  Status = PchSmiRecordInsert (
+             &mSrcDescOsTco,
+             (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+             PchTcoSmiOsTcoType,
+             DispatchHandle
+             );
+  if (!EFI_ERROR (Status)) {
+    Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+    Record->ClearSource = PchTcoSmiClearSource;
+    PchSmmClearSource (&Record->SrcDesc);
+    PchSmmEnableSource (&Record->SrcDesc);
+    SmiHandlerProfileRegisterHandler (&gPchTcoSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+  }
+  return Status;
+}
+
+//
+// Nmi
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescNmi = {
+  PCH_SMM_NO_FLAGS,
+  {
+    {
+      {
+        TCO_ADDR_TYPE,
+        {R_TCO_IO_TCO1_CNT}
+      },
+      S_TCO_IO_TCO1_CNT,
+      N_TCO_IO_TCO1_CNT_NMI2SMI_EN
+    },
+    NULL_BIT_DESC_INITIALIZER
+  },
+  {
+    {
+      {
+        TCO_ADDR_TYPE,
+        {R_TCO_IO_TCO1_STS}
+      },
+      S_TCO_IO_TCO1_STS,
+      N_TCO_IO_TCO1_STS_NMI2SMI
+    }
+  },
+  //
+  // NOTE: The status of NMI2SMI won't reflect to PMC SMI_STS.
+  //       So skip the top level status check and check the TCO1_STS directly.
+  //
+  NULL_BIT_DESC_INITIALIZER
+};
+
+/**
+  The register function used to register SMI handler of NMI event.
+
+  @param[in]  This                      The pointer to the protocol itself
+  @param[in]  DispatchFunction          Pointer to dispatch function to be invoked for this SMI source
+  @param[out] DispatchHandle            Handle of dispatch function to register.
+
+  @retval EFI_INVALID_PARAMETER         Error with NULL SMI source description
+  @retval EFI_OUT_OF_RESOURCES          Fail to allocate pool for database record
+  @retval EFI_SUCCESS                   The database record is created successfully.
+  @retval EFI_ACCESS_DENIED             Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiNmiRegister (
+  IN  PCH_TCO_SMI_DISPATCH_PROTOCOL     *This,
+  IN  PCH_TCO_SMI_DISPATCH_CALLBACK     DispatchFunction,
+  OUT EFI_HANDLE                        *DispatchHandle
+  )
+{
+  EFI_STATUS                            Status;
+  DATABASE_RECORD                       *Record;
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  Status = PchSmiRecordInsert (
+             &mSrcDescNmi,
+             (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+             PchTcoSmiNmiType,
+             DispatchHandle
+             );
+  if (!EFI_ERROR (Status)) {
+    Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+    Record->ClearSource = PchTcoSmiClearSource;
+    PchSmmClearSource (&Record->SrcDesc);
+    PchSmmEnableSource (&Record->SrcDesc);
+    SmiHandlerProfileRegisterHandler (&gPchTcoSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+  }
+  return Status;
+}
+
+//
+// IntruderDetect srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescIntruderDet = {
+  PCH_SMM_NO_FLAGS,
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_EN}
+      },
+      S_ACPI_IO_SMI_EN,
+      N_ACPI_IO_SMI_EN_TCO
+    },
+    {
+      {
+        TCO_ADDR_TYPE,
+        {R_TCO_IO_TCO2_CNT}
+      },
+      S_TCO_IO_TCO2_CNT,
+      N_TCO_IO_TCO2_CNT_INTRD_SEL
+    }
+  },
+  {
+    {
+      {
+        TCO_ADDR_TYPE,
+        {R_TCO_IO_TCO2_STS}
+      },
+      S_TCO_IO_TCO2_STS,
+      N_TCO_IO_TCO2_STS_INTRD_DET
+    }
+  },
+  {
+    {
+      ACPI_ADDR_TYPE,
+      {R_ACPI_IO_SMI_STS}
+    },
+    S_ACPI_IO_SMI_STS,
+    N_ACPI_IO_SMI_STS_TCO
+  }
+};
+
+/**
+  The register function used to register SMI handler of Intruder Detect event.
+
+  @param[in]  This                      The pointer to the protocol itself
+  @param[in]  DispatchFunction          Pointer to dispatch function to be invoked for this SMI source
+  @param[out] DispatchHandle            Handle of dispatch function to register.
+
+  @retval EFI_INVALID_PARAMETER         Error with NULL SMI source description
+  @retval EFI_OUT_OF_RESOURCES          Fail to allocate pool for database record
+  @retval EFI_SUCCESS                   The database record is created successfully.
+  @retval EFI_ACCESS_DENIED             Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiIntruderDetRegister (
+  IN  PCH_TCO_SMI_DISPATCH_PROTOCOL     *This,
+  IN  PCH_TCO_SMI_DISPATCH_CALLBACK     DispatchFunction,
+  OUT EFI_HANDLE                        *DispatchHandle
+  )
+{
+  EFI_STATUS                            Status;
+  DATABASE_RECORD                       *Record;
+
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  Status = PchSmiRecordInsert (
+             &mSrcDescIntruderDet,
+             (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+             PchTcoSmiIntruderDetectType,
+             DispatchHandle
+             );
+  if (!EFI_ERROR (Status)) {
+    Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+    Record->ClearSource = PchTcoSmiClearSourceAndBlock;
+    PchSmmClearSource (&Record->SrcDesc);
+    PchSmmEnableSource (&Record->SrcDesc);
+    SmiHandlerProfileRegisterHandler (&gPchTcoSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+  }
+  return Status;
+}
+
+//
+// SpiBiosWp srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_SMM_SOURCE_DESC mSrcDescSpiBiosWp = {
+  PCH_SMM_NO_FLAGS,
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_EN}
+      },
+      S_ACPI_IO_SMI_EN,
+      N_ACPI_IO_SMI_EN_TCO
+    },
+    {
+      {
+        PCIE_ADDR_TYPE,
+        { 0xFFFFFFFF } // to be updated in PchSmiDispatchUpdateDescriptors
+      },
+      S_SPI_CFG_BC,
+      N_SPI_CFG_BC_BLE
+    },
+  },
+  {
+    {
+      {
+        PCIE_ADDR_TYPE,
+        { 0xFFFFFFFF } // to be updated in PchSmiDispatchUpdateDescriptors
+      },
+      S_SPI_CFG_BC,
+      N_SPI_CFG_BC_SYNC_SS
+    }
+  },
+  {
+    {
+      ACPI_ADDR_TYPE,
+      {R_ACPI_IO_SMI_STS}
+    },
+    S_ACPI_IO_SMI_STS,
+    N_ACPI_IO_SMI_STS_TCO
+  }
+};
+
+/**
+  Special handling for SPI Write Protect
+
+  @param[in]  SrcDesc   Not used
+**/
+VOID
+EFIAPI
+PchTcoSpiWpClearSource (
+  CONST PCH_SMM_SOURCE_DESC             *SrcDesc
+  )
+{
+  UINT64 SpiRegBase;
+  UINT32 BiosControl;
+  UINT32 Timeout;
+
+  SpiRegBase = SpiPciCfgBase ();
+  PciSegmentAndThenOr32 (
+    SpiRegBase + R_SPI_CFG_BC,
+    (UINT32) ~B_SPI_CFG_BC_ASYNC_SS,
+    B_SPI_CFG_BC_SYNC_SS
+    );
+  //
+  // Ensure the SYNC is cleared
+  //
+  Timeout = 1000;
+  do {
+    BiosControl = PciSegmentRead32 (SpiRegBase + R_SPI_CFG_BC);
+    Timeout--;
+  } while ((BiosControl & B_SPI_CFG_BC_SYNC_SS) && (Timeout > 0));
+
+  //
+  // Any TCO-based status bits require special handling.
+  // SMI_STS.TCO_STS must be cleared in addition to the status bit in the TCO registers
+  //
+  PchSmmClearSource (&mDescSrcTcoSts);
+}
+
+/**
+  Set SMI_EN_TCO to enable TCO SMI.
+**/
+STATIC
+VOID
+PchSetSmiEnTco (
+  VOID
+  )
+{
+  IoOr32 (mAcpiBaseAddr + R_ACPI_IO_SMI_EN, B_ACPI_IO_SMI_EN_TCO);
+}
+
+/**
+  The register function used to register SMI handler of BIOS write protect event.
+
+  @param[in]  This                      The pointer to the protocol itself
+  @param[in]  DispatchFunction          Pointer to dispatch function to be invoked for this SMI source
+  @param[out] DispatchHandle            Handle of dispatch function to register.
+
+  @retval EFI_INVALID_PARAMETER         Error with NULL SMI source description
+  @retval EFI_OUT_OF_RESOURCES          Fail to allocate pool for database record
+  @retval EFI_SUCCESS                   The database record is created successfully.
+  @retval EFI_ACCESS_DENIED             Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiSpiBiosWpRegister (
+  IN  PCH_TCO_SMI_DISPATCH_PROTOCOL     *This,
+  IN  PCH_TCO_SMI_DISPATCH_CALLBACK     DispatchFunction,
+  OUT EFI_HANDLE                        *DispatchHandle
+  )
+{
+  EFI_STATUS                            Status;
+  DATABASE_RECORD                       *Record;
+
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  Status = PchSmiRecordInsert (
+             &mSrcDescSpiBiosWp,
+             (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+             PchTcoSmiSpiBiosWpType,
+             DispatchHandle
+             );
+  if (!EFI_ERROR (Status)) {
+    Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+    Record->ClearSource = PchTcoSpiWpClearSource;
+    PchTcoSpiWpClearSource (NULL);
+    //
+    // It doesn't enable the BIOSLOCK here. Enable it by policy in DXE.
+    // Only enable SMI_EN_TCO.
+    //
+    PchSetSmiEnTco ();
+    SmiHandlerProfileRegisterHandler (&gPchTcoSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+  }
+  return Status;
+}
+
+//
+// LpcBiosWp srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_SMM_SOURCE_DESC mSrcDescLpcBiosWp = {
+  PCH_SMM_NO_FLAGS,
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_EN}
+      },
+      S_ACPI_IO_SMI_EN,
+      N_ACPI_IO_SMI_EN_TCO
+    },
+    {
+      {
+        PCIE_ADDR_TYPE,
+        { 0xFFFFFFFF } // to be updated in PchSmiDispatchUpdateDescriptors
+      },
+      S_LPC_CFG_BC,
+      N_LPC_CFG_BC_LE
+    }
+  },
+  {
+    {
+      {
+        TCO_ADDR_TYPE,
+        {R_TCO_IO_TCO1_STS}
+      },
+      S_TCO_IO_TCO1_STS,
+      N_TCO_IO_TCO1_STS_BIOSWR
+    }
+  },
+  {
+    {
+      ACPI_ADDR_TYPE,
+      {R_ACPI_IO_SMI_STS}
+    },
+    S_ACPI_IO_SMI_STS,
+    N_ACPI_IO_SMI_STS_TCO
+  }
+};
+
+/**
+  The register function used to register SMI handler of LPC BIOS write protect event.
+
+  @param[in]  This                      The pointer to the protocol itself
+  @param[in]  DispatchFunction          Pointer to dispatch function to be invoked for this SMI source
+  @param[out] DispatchHandle            Handle of dispatch function to register.
+
+  @retval EFI_INVALID_PARAMETER         Error with NULL SMI source description
+  @retval EFI_OUT_OF_RESOURCES          Fail to allocate pool for database record
+  @retval EFI_SUCCESS                   The database record is created successfully.
+  @retval EFI_ACCESS_DENIED             Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiLpcBiosWpRegister (
+  IN  PCH_TCO_SMI_DISPATCH_PROTOCOL     *This,
+  IN  PCH_TCO_SMI_DISPATCH_CALLBACK     DispatchFunction,
+  OUT EFI_HANDLE                        *DispatchHandle
+  )
+{
+  EFI_STATUS                            Status;
+  DATABASE_RECORD                       *Record;
+
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  if (IsEspiEnabled ()) {
+    //
+    // Status is D31F0's PCBC.BWPDS
+    //
+    ASSERT (FALSE);
+    return EFI_UNSUPPORTED;
+  }
+
+  Status = PchSmiRecordInsert (
+             &mSrcDescLpcBiosWp,
+             (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+             PchTcoSmiLpcBiosWpType,
+             DispatchHandle
+             );
+  if (!EFI_ERROR (Status)) {
+    Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+    Record->ClearSource = PchTcoSmiClearSource;
+    PchSmmClearSource (&Record->SrcDesc);
+    //
+    // It doesn't enable the BIOSLOCK here. Enable it by policy in DXE.
+    // Only enable SMI_EN_TCO.
+    //
+    PchSetSmiEnTco ();
+    SmiHandlerProfileRegisterHandler (&gPchTcoSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+  }
+  return Status;
+}
+
+//
+// NEWCENTURY_STS bit that needs to be cleared
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescNewCentury = {
+  PCH_SMM_NO_FLAGS,
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_EN}
+      },
+      S_ACPI_IO_SMI_EN,
+      N_ACPI_IO_SMI_EN_TCO
+    },
+    NULL_BIT_DESC_INITIALIZER
+  },
+  {
+    {
+      {
+        TCO_ADDR_TYPE,
+        {R_TCO_IO_TCO1_STS}
+      },
+      S_TCO_IO_TCO1_STS,
+      N_TCO_IO_TCO1_STS_NEWCENTURY
+    }
+  },
+  {
+    {
+      ACPI_ADDR_TYPE,
+      {R_ACPI_IO_SMI_STS}
+    },
+    S_ACPI_IO_SMI_STS,
+    N_ACPI_IO_SMI_STS_TCO
+  }
+};
+
+/**
+  The register function used to register SMI handler of NEW CENTURY event.
+
+  @param[in]  This                      The pointer to the protocol itself
+  @param[in]  DispatchFunction          Pointer to dispatch function to be invoked for this SMI source
+  @param[out] DispatchHandle            Handle of dispatch function to register.
+
+  @retval EFI_INVALID_PARAMETER         Error with NULL SMI source description
+  @retval EFI_OUT_OF_RESOURCES          Fail to allocate pool for database record
+  @retval EFI_SUCCESS                   The database record is created successfully.
+  @retval EFI_ACCESS_DENIED             Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiNewCenturyRegister (
+  IN  PCH_TCO_SMI_DISPATCH_PROTOCOL     *This,
+  IN  PCH_TCO_SMI_DISPATCH_CALLBACK     DispatchFunction,
+  OUT EFI_HANDLE                        *DispatchHandle
+  )
+{
+  EFI_STATUS                            Status;
+  DATABASE_RECORD                       *Record;
+
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  Status = PchSmiRecordInsert (
+             &mSrcDescNewCentury,
+             (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+             PchTcoSmiNewCenturyType,
+             DispatchHandle
+             );
+  if (!EFI_ERROR (Status)) {
+    Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+    Record->ClearSource = PchTcoSmiClearSourceAndBlock;
+    PchSmmClearSource (&Record->SrcDesc);
+    PchSmmEnableSource (&Record->SrcDesc);
+    SmiHandlerProfileRegisterHandler (&gPchTcoSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+  }
+  return Status;
+}
+
+/**
+  Unregister a child SMI source dispatch function with a parent SMM driver
+
+  @param[in] This                       Protocol instance pointer.
+  @param[in] DispatchHandle             Handle of dispatch function to deregister.
+
+  @retval EFI_SUCCESS                   The dispatch function has been successfully
+                                        unregistered and the SMI source has been disabled
+                                        if there are no other registered child dispatch
+                                        functions for this SMI source.
+  @retval EFI_INVALID_PARAMETER         Handle is invalid.
+  @retval EFI_ACCESS_DENIED             Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiUnRegister (
+  IN  PCH_TCO_SMI_DISPATCH_PROTOCOL     *This,
+  IN  EFI_HANDLE                        DispatchHandle
+  )
+{
+  return EFI_SUCCESS;
+}
+
+//
+// Pme srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescPme = {
+  PCH_SMM_SCI_EN_DEPENDENT,
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_GPE0_EN_127_96}
+      },
+      S_ACPI_IO_GPE0_EN_127_96,
+      N_ACPI_IO_GPE0_EN_127_96_PME
+    },
+    NULL_BIT_DESC_INITIALIZER
+  },
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_GPE0_STS_127_96}
+      },
+      S_ACPI_IO_GPE0_STS_127_96,
+      N_ACPI_IO_GPE0_STS_127_96_PME
+    }
+  },
+  {
+    {
+      ACPI_ADDR_TYPE,
+      {R_ACPI_IO_SMI_STS}
+    },
+    S_ACPI_IO_SMI_STS,
+    N_ACPI_IO_SMI_STS_GPE0
+  }
+};
+
+/**
+  The register function used to register SMI handler of PME event.
+
+  @param[in]  This                      The pointer to the protocol itself
+  @param[in]  DispatchFunction          Pointer to dispatch function to be invoked for this SMI source
+  @param[out] DispatchHandle            Handle of dispatch function to register.
+
+  @retval EFI_INVALID_PARAMETER         Error with NULL SMI source description
+  @retval EFI_OUT_OF_RESOURCES          Fail to allocate pool for database record
+  @retval EFI_SUCCESS                   The database record is created successfully.
+  @retval EFI_ACCESS_DENIED             Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchAcpiSmiPmeRegister (
+  IN  PCH_ACPI_SMI_DISPATCH_PROTOCOL    *This,
+  IN  PCH_ACPI_SMI_DISPATCH_CALLBACK    DispatchFunction,
+  OUT EFI_HANDLE                        *DispatchHandle
+  )
+{
+  EFI_STATUS                            Status;
+
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  Status = PchSmiRecordInsert (
+             &mSrcDescPme,
+             (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+             PchAcpiSmiPmeType,
+             DispatchHandle
+             );
+  PchSmmClearSource (&mSrcDescPme);
+  PchSmmEnableSource (&mSrcDescPme);
+  if (!EFI_ERROR (Status)) {
+    SmiHandlerProfileRegisterHandler (&gPchAcpiSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+  }
+  return Status;
+}
+
+//
+// PmeB0 srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescPmeB0 = {
+  PCH_SMM_SCI_EN_DEPENDENT,
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_GPE0_EN_127_96}
+      },
+      S_ACPI_IO_GPE0_EN_127_96,
+      N_ACPI_IO_GPE0_EN_127_96_PME_B0
+    },
+    NULL_BIT_DESC_INITIALIZER
+  },
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_GPE0_STS_127_96}
+      },
+      S_ACPI_IO_GPE0_STS_127_96,
+      N_ACPI_IO_GPE0_STS_127_96_PME_B0
+    }
+  },
+  {
+    {
+      ACPI_ADDR_TYPE,
+      {R_ACPI_IO_SMI_STS}
+    },
+    S_ACPI_IO_SMI_STS,
+    N_ACPI_IO_SMI_STS_GPE0
+  }
+};
+/**
+  The register function used to register SMI handler of PME B0 event.
+
+  @param[in]  This                      The pointer to the protocol itself
+  @param[in]  DispatchFunction          Pointer to dispatch function to be invoked for this SMI source
+  @param[out] DispatchHandle            Handle of dispatch function to register.
+
+  @retval EFI_INVALID_PARAMETER         Error with NULL SMI source description
+  @retval EFI_OUT_OF_RESOURCES          Fail to allocate pool for database record
+  @retval EFI_SUCCESS                   The database record is created successfully.
+  @retval EFI_ACCESS_DENIED             Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchAcpiSmiPmeB0Register (
+  IN  PCH_ACPI_SMI_DISPATCH_PROTOCOL    *This,
+  IN  PCH_ACPI_SMI_DISPATCH_CALLBACK    DispatchFunction,
+  OUT EFI_HANDLE                        *DispatchHandle
+  )
+{
+  EFI_STATUS                            Status;
+
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  Status = PchSmiRecordInsert (
+             &mSrcDescPmeB0,
+             (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+             PchAcpiSmiPmeB0Type,
+             DispatchHandle
+             );
+  PchSmmClearSource (&mSrcDescPmeB0);
+  PchSmmEnableSource (&mSrcDescPmeB0);
+  if (!EFI_ERROR (Status)) {
+    SmiHandlerProfileRegisterHandler (&gPchAcpiSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+  }
+  return Status;
+}
+
+//
+// RtcAlarm srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescRtcAlarm = {
+  PCH_SMM_SCI_EN_DEPENDENT,
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_PM1_EN}
+      },
+      S_ACPI_IO_PM1_EN,
+      N_ACPI_IO_PM1_EN_RTC
+    },
+    NULL_BIT_DESC_INITIALIZER
+  },
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_PM1_STS}
+      },
+      S_ACPI_IO_PM1_STS,
+      N_ACPI_IO_PM1_STS_RTC
+    }
+  },
+  {
+    {
+      ACPI_ADDR_TYPE,
+      {R_ACPI_IO_SMI_STS}
+    },
+    S_ACPI_IO_SMI_STS,
+    N_ACPI_IO_SMI_STS_PM1_STS_REG
+  }
+};
+
+/**
+  The register function used to register SMI handler of RTC alarm event.
+
+  @param[in]  This                      The pointer to the protocol itself
+  @param[in]  DispatchFunction          Pointer to dispatch function to be invoked for this SMI source
+  @param[out] DispatchHandle            Handle of dispatch function to register.
+
+  @retval EFI_INVALID_PARAMETER         Error with NULL SMI source description
+  @retval EFI_OUT_OF_RESOURCES          Fail to allocate pool for database record
+  @retval EFI_SUCCESS                   The database record is created successfully.
+  @retval EFI_ACCESS_DENIED             Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchAcpiSmiRtcAlarmRegister (
+  IN  PCH_ACPI_SMI_DISPATCH_PROTOCOL    *This,
+  IN  PCH_ACPI_SMI_DISPATCH_CALLBACK    DispatchFunction,
+  OUT EFI_HANDLE                        *DispatchHandle
+  )
+{
+  EFI_STATUS                            Status;
+
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  Status = PchSmiRecordInsert (
+             &mSrcDescRtcAlarm,
+             (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+             PchAcpiSmiRtcAlarmType,
+             DispatchHandle
+             );
+
+  PchSmmClearSource (&mSrcDescRtcAlarm);
+  PchSmmEnableSource (&mSrcDescRtcAlarm);
+  if (!EFI_ERROR (Status)) {
+    SmiHandlerProfileRegisterHandler (&gPchAcpiSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+  }
+  return Status;
+}
+
+//
+// TmrOverflow srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescTmrOverflow = {
+  PCH_SMM_SCI_EN_DEPENDENT,
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_PM1_EN}
+      },
+      S_ACPI_IO_PM1_EN,
+      N_ACPI_IO_PM1_EN_TMROF
+    },
+    NULL_BIT_DESC_INITIALIZER
+  },
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_PM1_STS}
+      },
+      S_ACPI_IO_PM1_STS,
+      N_ACPI_IO_PM1_STS_TMROF
+    }
+  },
+  {
+    {
+      ACPI_ADDR_TYPE,
+      {R_ACPI_IO_SMI_STS}
+    },
+    S_ACPI_IO_SMI_STS,
+    N_ACPI_IO_SMI_STS_PM1_STS_REG
+  }
+};
+
+/**
+  The register function used to register SMI handler of Timer Overflow event.
+
+  @param[in]  This                      The pointer to the protocol itself
+  @param[in]  DispatchFunction          Pointer to dispatch function to be invoked for this SMI source
+  @param[out] DispatchHandle            Handle of dispatch function to register.
+
+  @retval EFI_INVALID_PARAMETER         Error with NULL SMI source description
+  @retval EFI_OUT_OF_RESOURCES          Fail to allocate pool for database record
+  @retval EFI_SUCCESS                   The database record is created successfully.
+  @retval EFI_ACCESS_DENIED             Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchAcpiSmiTmrOverflowRegister (
+  IN  PCH_ACPI_SMI_DISPATCH_PROTOCOL    *This,
+  IN  PCH_ACPI_SMI_DISPATCH_CALLBACK    DispatchFunction,
+  OUT EFI_HANDLE                        *DispatchHandle
+  )
+{
+  EFI_STATUS                            Status;
+
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  Status = PchSmiRecordInsert (
+             &mSrcDescTmrOverflow,
+             (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+             PchAcpiSmiTmrOverflowType,
+             DispatchHandle
+             );
+  PchSmmClearSource (&mSrcDescTmrOverflow);
+  PchSmmEnableSource (&mSrcDescTmrOverflow);
+  if (!EFI_ERROR (Status)) {
+    SmiHandlerProfileRegisterHandler (&gPchAcpiSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+  }
+
+  return Status;
+}
+
+/**
+  Unregister a child SMI source dispatch function with a parent SMM driver
+
+  @param[in] This                       Protocol instance pointer.
+  @param[in] DispatchHandle             Handle of dispatch function to deregister.
+
+  @retval EFI_SUCCESS                   The dispatch function has been successfully
+                                        unregistered and the SMI source has been disabled
+                                        if there are no other registered child dispatch
+                                        functions for this SMI source.
+  @retval EFI_INVALID_PARAMETER         Handle is invalid.
+  @retval EFI_ACCESS_DENIED             Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchAcpiSmiUnRegister (
+  IN  PCH_ACPI_SMI_DISPATCH_PROTOCOL    *This,
+  IN  EFI_HANDLE                        DispatchHandle
+  )
+{
+  DATABASE_RECORD                   *RecordToDelete;
+  EFI_STATUS                        Status;
+
+  RecordToDelete = DATABASE_RECORD_FROM_LINK (DispatchHandle);
+  Status = PchSmmCoreUnRegister (NULL, DispatchHandle);
+  if (!EFI_ERROR (Status)) {
+    SmiHandlerProfileUnregisterHandler (&gPchAcpiSmiDispatchProtocolGuid, RecordToDelete->Callback, NULL, 0);
+  }
+  return Status;
+}
+
+//
+// SerialIrq srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescSerialIrq = {
+  PCH_SMM_NO_FLAGS,
+  {
+    NULL_BIT_DESC_INITIALIZER,
+    NULL_BIT_DESC_INITIALIZER
+  },
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_STS}
+      },
+      S_ACPI_IO_SMI_STS,
+      N_ACPI_IO_SMI_STS_SERIRQ
+    }
+  },
+  {
+    {
+      ACPI_ADDR_TYPE,
+      {R_ACPI_IO_SMI_STS}
+    },
+    S_ACPI_IO_SMI_STS,
+    N_ACPI_IO_SMI_STS_SERIRQ
+  }
+};
+
+/**
+  The register function used to register SMI handler of Serial IRQ event.
+
+  @param[in]  This                      The pointer to the protocol itself
+  @param[in]  DispatchFunction          Pointer to dispatch function to be invoked for this SMI source
+  @param[out] DispatchHandle            Handle of dispatch function to register.
+
+  @retval EFI_INVALID_PARAMETER         Error with NULL SMI source description
+  @retval EFI_OUT_OF_RESOURCES          Fail to allocate pool for database record
+  @retval EFI_SUCCESS                   The database record is created successfully.
+  @retval EFI_ACCESS_DENIED             Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchSmiSerialIrqRegister (
+  IN  PCH_SMI_DISPATCH_PROTOCOL         *This,
+  IN  PCH_SMI_DISPATCH_CALLBACK         DispatchFunction,
+  OUT EFI_HANDLE                        *DispatchHandle
+  )
+{
+  EFI_STATUS                            Status;
+
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  Status = PchSmiRecordInsert (
+             &mSrcDescSerialIrq,
+             (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+             PchSmiSerialIrqType,
+             DispatchHandle
+             );
+  PchSmmClearSource (&mSrcDescSerialIrq);
+  PchSmmEnableSource (&mSrcDescSerialIrq);
+  if (!EFI_ERROR (Status)) {
+     SmiHandlerProfileRegisterHandler (&gPchSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+  }
+  return Status;
+}
+
+//
+// McSmi srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescMcSmi = {
+  PCH_SMM_NO_FLAGS,
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_EN}
+      },
+      S_ACPI_IO_SMI_EN,
+      N_ACPI_IO_SMI_EN_MCSMI
+    },
+    NULL_BIT_DESC_INITIALIZER
+  },
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_STS}
+      },
+      S_ACPI_IO_SMI_STS,
+      N_ACPI_IO_SMI_STS_MCSMI
+    }
+  },
+  {
+    {
+      ACPI_ADDR_TYPE,
+      {R_ACPI_IO_SMI_STS}
+    },
+    S_ACPI_IO_SMI_STS,
+    N_ACPI_IO_SMI_STS_MCSMI
+  }
+};
+
+/**
+  The register function used to register SMI handler of MCSMI event.
+
+  @param[in]  This                      The pointer to the protocol itself
+  @param[in]  DispatchFunction          Pointer to dispatch function to be invoked for this SMI source
+  @param[out] DispatchHandle            Handle of dispatch function to register.
+
+  @retval EFI_INVALID_PARAMETER         Error with NULL SMI source description
+  @retval EFI_OUT_OF_RESOURCES          Fail to allocate pool for database record
+  @retval EFI_SUCCESS                   The database record is created successfully.
+  @retval EFI_ACCESS_DENIED             Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchSmiMcSmiRegister (
+  IN  PCH_SMI_DISPATCH_PROTOCOL         *This,
+  IN  PCH_SMI_DISPATCH_CALLBACK         DispatchFunction,
+  OUT EFI_HANDLE                        *DispatchHandle
+  )
+{
+  EFI_STATUS                            Status;
+
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  Status = PchSmiRecordInsert (
+             &mSrcDescMcSmi,
+             (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+             PchSmiMcSmiType,
+             DispatchHandle
+             );
+  PchSmmClearSource (&mSrcDescMcSmi);
+  PchSmmEnableSource (&mSrcDescMcSmi);
+  if (!EFI_ERROR (Status)) {
+    SmiHandlerProfileRegisterHandler (&gPchSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+  }
+  return Status;
+}
+
+//
+// SmBus srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescSmbus = {
+  PCH_SMM_NO_FLAGS,
+  {
+    NULL_BIT_DESC_INITIALIZER,
+    NULL_BIT_DESC_INITIALIZER
+  },
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_STS}
+      },
+      S_ACPI_IO_SMI_STS,
+      N_ACPI_IO_SMI_STS_SMBUS
+    }
+  },
+  {
+    {
+      ACPI_ADDR_TYPE,
+      {R_ACPI_IO_SMI_STS}
+    },
+    S_ACPI_IO_SMI_STS,
+    N_ACPI_IO_SMI_STS_SMBUS
+  }
+};
+
+/**
+  The register function used to register SMI handler of SMBUS event.
+
+  @param[in]  This                      The pointer to the protocol itself
+  @param[in]  DispatchFunction          Pointer to dispatch function to be invoked for this SMI source
+  @param[out] DispatchHandle            Handle of dispatch function to register.
+
+  @retval EFI_INVALID_PARAMETER         Error with NULL SMI source description
+  @retval EFI_OUT_OF_RESOURCES          Fail to allocate pool for database record
+  @retval EFI_SUCCESS                   The database record is created successfully.
+  @retval EFI_ACCESS_DENIED             Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchSmiSmbusRegister (
+  IN  PCH_SMI_DISPATCH_PROTOCOL         *This,
+  IN  PCH_SMI_DISPATCH_CALLBACK         DispatchFunction,
+  OUT EFI_HANDLE                        *DispatchHandle
+  )
+{
+  EFI_STATUS                            Status;
+
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  Status = PchSmiRecordInsert (
+             &mSrcDescSmbus,
+             (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+             PchSmiSmBusType,
+             DispatchHandle
+             );
+  PchSmmClearSource (&mSrcDescSmbus);
+  PchSmmEnableSource (&mSrcDescSmbus);
+  if (!EFI_ERROR (Status)) {
+    SmiHandlerProfileRegisterHandler (&gPchSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+  }
+  return Status;
+}
+
+//
+// SpiAsyncSmi srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_SMM_SOURCE_DESC mSrcDescSpiAsyncSmi = {
+  PCH_SMM_NO_FLAGS,
+  {
+    {
+      {
+        PCIE_ADDR_TYPE,
+        { 0xFFFFFFFF } // to be updated in PchSmiDispatchUpdateDescriptors
+      },
+      S_SPI_CFG_BC,
+      N_SPI_CFG_BC_ASE_BWP
+    },
+    NULL_BIT_DESC_INITIALIZER
+  },
+  {
+    {
+      {
+        PCIE_ADDR_TYPE,
+        { 0xFFFFFFFF } // to be updated in PchSmiDispatchUpdateDescriptors
+      },
+      S_SPI_CFG_BC,
+      N_SPI_CFG_BC_ASYNC_SS
+    }
+  },
+  {
+    {
+      ACPI_ADDR_TYPE,
+      {R_ACPI_IO_SMI_STS}
+    },
+    S_ACPI_IO_SMI_STS,
+    N_ACPI_IO_SMI_STS_SPI
+  }
+};
+
+/**
+  Special handling for SPI Asynchronous SMI.
+  If SPI ASYNC SMI is enabled, De-assert SMI is sent when Flash Cycle Done
+  transitions from 1 to 0 or when the SMI enable becomes false.
+
+  @param[in]  SrcDesc   Not used
+**/
+VOID
+EFIAPI
+PchSmiSpiAsyncClearSource (
+  CONST PCH_SMM_SOURCE_DESC             *SrcDesc
+  )
+{
+  UINT64                                SpiRegBase;
+  UINT32                                SpiBar0;
+
+  SpiRegBase = SpiPciCfgBase ();
+  SpiBar0 = PciSegmentRead32 (SpiRegBase + R_SPI_CFG_BAR0) & ~(B_SPI_CFG_BAR0_MASK);
+  if (SpiBar0 != PCH_SPI_BASE_ADDRESS) {
+    //
+    // Temporary disable MSE, and override with SPI reserved MMIO address, then enable MSE.
+    //
+    SpiBar0 = PCH_SPI_BASE_ADDRESS;
+    PciSegmentAnd8 (SpiRegBase + PCI_COMMAND_OFFSET, (UINT8) ~EFI_PCI_COMMAND_MEMORY_SPACE);
+    PciSegmentWrite32 (SpiRegBase + R_SPI_CFG_BAR0, SpiBar0);
+    PciSegmentOr8 (SpiRegBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);
+  }
+
+  MmioOr32 (SpiBar0 + R_SPI_MEM_HSFSC, B_SPI_MEM_HSFSC_FDONE);
+}
+
+/**
+  Special handling to enable SPI Asynchronous SMI
+**/
+VOID
+PchSmiSpiAsyncEnableSource (
+  VOID
+  )
+{
+  UINT64 SpiRegBase;
+  UINT32 Data32And;
+  UINT32 Data32Or;
+
+  SpiRegBase = SpiPciCfgBase ();
+  Data32And = (UINT32) ~B_SPI_CFG_BC_SYNC_SS;
+  Data32Or = B_SPI_CFG_BC_ASE_BWP;
+
+  PciSegmentAndThenOr32 (
+    SpiRegBase + R_SPI_CFG_BC,
+    Data32And,
+    Data32Or
+    );
+  S3BootScriptSavePciCfgReadWrite (
+    S3BootScriptWidthUint32,
+    SpiRegBase + R_SPI_CFG_BC,
+    (VOID*) &Data32Or,
+    (VOID*) &Data32And
+    );
+
+  //
+  // Clear the source
+  //
+  PchSmiSpiAsyncClearSource (NULL);
+}
+
+/**
+  The register function used to register SMI handler of SPI Asynchronous event.
+
+  @param[in]  This                      The pointer to the protocol itself
+  @param[in]  DispatchFunction          Pointer to dispatch function to be invoked for this SMI source
+  @param[out] DispatchHandle            Handle of dispatch function to register.
+
+  @retval EFI_INVALID_PARAMETER         Error with NULL SMI source description
+  @retval EFI_OUT_OF_RESOURCES          Fail to allocate pool for database record
+  @retval EFI_SUCCESS                   The database record is created successfully.
+  @retval EFI_ACCESS_DENIED             Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchSmiSpiAsyncRegister (
+  IN  PCH_SMI_DISPATCH_PROTOCOL         *This,
+  IN  PCH_SMI_DISPATCH_CALLBACK         DispatchFunction,
+  OUT EFI_HANDLE                        *DispatchHandle
+  )
+{
+  EFI_STATUS                            Status;
+  DATABASE_RECORD                       *Record;
+
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  Status = PchSmiRecordInsert (
+             &mSrcDescSpiAsyncSmi,
+             (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+             PchSmiSpiAsyncType,
+             DispatchHandle
+             );
+
+  if (!EFI_ERROR (Status)) {
+    Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+    Record->ClearSource = PchSmiSpiAsyncClearSource;
+    PchSmiSpiAsyncClearSource (NULL);
+    PchSmiSpiAsyncEnableSource ();
+    SmiHandlerProfileRegisterHandler (&gPchSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+  }
+  return Status;
+}
+
+/**
+  Unregister a child SMI source dispatch function with a parent SMM driver
+
+  @param[in] This                       Protocol instance pointer.
+  @param[in] DispatchHandle             Handle of dispatch function to deregister.
+
+  @retval EFI_SUCCESS                   The dispatch function has been successfully
+                                        unregistered and the SMI source has been disabled
+                                        if there are no other registered child dispatch
+                                        functions for this SMI source.
+  @retval EFI_INVALID_PARAMETER         Handle is invalid.
+  @retval EFI_ACCESS_DENIED             Return access denied if the SmmReadyToLock event has been triggered
+  @retval EFI_ACCESS_DENIED             Return access denied since SPI aync SMI handler is not able to disabled.
+**/
+EFI_STATUS
+EFIAPI
+PchSmiUnRegister (
+  IN  PCH_SMI_DISPATCH_PROTOCOL         *This,
+  IN  EFI_HANDLE                        DispatchHandle
+  )
+{
+  DATABASE_RECORD                       *Record;
+  UINT64                                SpiRegBase;
+  EFI_STATUS                            Status;
+
+  Record = DATABASE_RECORD_FROM_LINK (DispatchHandle);
+  if ((Record->SrcDesc.En[0].Reg.Type == PCIE_ADDR_TYPE) &&
+      (Record->SrcDesc.En[0].Reg.Data.pcie.Fields.Dev == SpiDevNumber ()) &&
+      (Record->SrcDesc.En[0].Reg.Data.pcie.Fields.Fnc == SpiFuncNumber ()) &&
+      (Record->SrcDesc.En[0].Reg.Data.pcie.Fields.Reg == R_SPI_CFG_BC) &&
+      (Record->SrcDesc.En[0].Bit == N_SPI_CFG_BC_ASE_BWP)) {
+    SpiRegBase = SpiPciCfgBase ();
+    if (PciSegmentRead8 (SpiRegBase + R_SPI_CFG_BC) & B_SPI_CFG_BC_BILD) {
+      //
+      // SPI Asynchronous SMI cannot be disabled
+      //
+      return EFI_ACCESS_DENIED;
+    }
+  }
+  Status = PchSmmCoreUnRegister (NULL, DispatchHandle);
+  if (!EFI_ERROR (Status)) {
+    SmiHandlerProfileUnregisterHandler (&gPchSmiDispatchProtocolGuid, Record->Callback, NULL, 0);
+  }
+  return Status;
+}
+
+
+/**
+  Declaration of PCH TCO SMI DISPATCH PROTOCOL instance
+**/
+PCH_TCO_SMI_DISPATCH_PROTOCOL mPchTcoSmiDispatchProtocol = {
+  PCH_TCO_SMI_DISPATCH_REVISION,        // Revision
+  PchTcoSmiUnRegister,                  // Unregister
+  PchTcoSmiMchRegister,                 // Mch
+  PchTcoSmiTcoTimeoutRegister,          // TcoTimeout
+  PchTcoSmiOsTcoRegister,               // OsTco
+  PchTcoSmiNmiRegister,                 // Nmi
+  PchTcoSmiIntruderDetRegister,         // IntruderDectect
+  PchTcoSmiSpiBiosWpRegister,           // SpiBiosWp
+  PchTcoSmiLpcBiosWpRegister,           // LpcBiosWp
+  PchTcoSmiNewCenturyRegister           // NewCentury
+};
+
+/**
+  Declaration of PCH ACPI SMI DISPATCH PROTOCOL instance
+**/
+PCH_ACPI_SMI_DISPATCH_PROTOCOL mPchAcpiSmiDispatchProtocol = {
+  PCH_ACPI_SMI_DISPATCH_REVISION,       // Revision
+  PchAcpiSmiUnRegister,                 // Unregister
+  PchAcpiSmiPmeRegister,                // Pme
+  PchAcpiSmiPmeB0Register,              // PmeB0
+  PchAcpiSmiRtcAlarmRegister,           // RtcAlarm
+  PchAcpiSmiTmrOverflowRegister         // TmrOverflow
+};
+
+/**
+  Declaration of MISC PCH SMI DISPATCH PROTOCOL instance
+**/
+PCH_SMI_DISPATCH_PROTOCOL mPchSmiDispatchProtocol = {
+  PCH_SMI_DISPATCH_REVISION,            // Revision
+  PchSmiUnRegister,                     // Unregister
+  PchSmiSerialIrqRegister,              // SerialIrq
+  PchSmiMcSmiRegister,                  // McSmi
+  PchSmiSmbusRegister,                  // SmBus
+  PchSmiSpiAsyncRegister                // SpiAsync
+};
+
+/**
+  Install protocols of PCH specifics SMI types, including
+  PCH TCO SMI types, PCH PCIE SMI types, PCH ACPI SMI types, PCH MISC SMI types.
+
+  @retval                               the result of protocol installation
+**/
+EFI_STATUS
+InstallPchSmiDispatchProtocols (
+  VOID
+  )
+{
+  EFI_HANDLE                            Handle;
+  EFI_STATUS                            Status;
+
+  Handle = NULL;
+  Status = gSmst->SmmInstallProtocolInterface (
+                    &Handle,
+                    &gPchTcoSmiDispatchProtocolGuid,
+                    EFI_NATIVE_INTERFACE,
+                    &mPchTcoSmiDispatchProtocol
+                    );
+
+  Status = gSmst->SmmInstallProtocolInterface (
+                    &Handle,
+                    &gPchAcpiSmiDispatchProtocolGuid,
+                    EFI_NATIVE_INTERFACE,
+                    &mPchAcpiSmiDispatchProtocol
+                    );
+  Status = gSmst->SmmInstallProtocolInterface (
+                    &Handle,
+                    &gPchSmiDispatchProtocolGuid,
+                    EFI_NATIVE_INTERFACE,
+                    &mPchSmiDispatchProtocol
+                    );
+
+  return Status;
+}
+
+/**
+  The function to dispatch all callback function of PCH SMI types.
+
+  @retval EFI_SUCCESS                   Function successfully completed
+  @retval EFI_UNSUPPORTED               no
+**/
+EFI_STATUS
+PchSmiTypeCallbackDispatcher (
+  IN  DATABASE_RECORD                   *Record
+  )
+{
+  EFI_STATUS                            Status;
+  PCH_SMI_TYPES                         PchSmiType;
+
+  PchSmiType = Record->PchSmiType;
+  Status     = EFI_SUCCESS;
+
+  switch (PchSmiType) {
+    case PchTcoSmiMchType:
+    case PchTcoSmiTcoTimeoutType:
+    case PchTcoSmiOsTcoType:
+    case PchTcoSmiNmiType:
+    case PchTcoSmiIntruderDetectType:
+    case PchTcoSmiSpiBiosWpType:
+    case PchTcoSmiLpcBiosWpType:
+    case PchTcoSmiNewCenturyType:
+      ((PCH_TCO_SMI_DISPATCH_CALLBACK) (Record->PchSmiCallback)) ((EFI_HANDLE)&Record->Link);
+      break;
+    case PchPcieSmiRpHotplugType:
+    case PchPcieSmiRpLinkActiveType:
+    case PchPcieSmiRpLinkEqType:
+      break;
+    case PchAcpiSmiPmeType:
+    case PchAcpiSmiPmeB0Type:
+    case PchAcpiSmiRtcAlarmType:
+    case PchAcpiSmiTmrOverflowType:
+      ((PCH_ACPI_SMI_DISPATCH_CALLBACK) (Record->PchSmiCallback)) ((EFI_HANDLE)&Record->Link);
+      break;
+    case PchSmiSerialIrqType:
+    case PchSmiMcSmiType:
+    case PchSmiSmBusType:
+    case PchSmiSpiAsyncType:
+    case PchIoTrapSmiType:                ///< internal type for IoTrap
+      ((PCH_SMI_DISPATCH_CALLBACK) (Record->PchSmiCallback)) ((EFI_HANDLE)&Record->Link);
+      break;
+    default:
+      Status = EFI_UNSUPPORTED;
+      break;
+  }
+
+  return Status;
+}
+
+/**
+  Performs update of SmiDispatch descriptors with values that have to be evaluated during runtime.
+**/
+VOID
+PchSmiDispatchUpdateDescriptors (
+  VOID
+  )
+{
+  UINT32     SpiPcieAddr;
+  UINT32     LpcPcieAddr;
+
+  SpiPcieAddr = ((DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+                (SpiDevNumber ()             << 19) |
+                (SpiFuncNumber ()            << 16) |
+                R_SPI_CFG_BC);
+  LpcPcieAddr = ((DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+                (LpcDevNumber ()             << 19) |
+                (LpcFuncNumber ()            << 16) |
+                R_LPC_CFG_BC);
+  //
+  // mSrcDescSpiBiosWp
+  //
+  mSrcDescSpiBiosWp.En[1].Reg.Data.raw    = SpiPcieAddr;
+  mSrcDescSpiBiosWp.Sts[0].Reg.Data.raw   = SpiPcieAddr;
+
+  //
+  // mSrcDescLpcBiosWp
+  //
+  mSrcDescLpcBiosWp.En[1].Reg.Data.raw    = LpcPcieAddr;
+
+  //
+  // mSrcDescSpiAsyncSmi
+  //
+  mSrcDescSpiAsyncSmi.En[0].Reg.Data.raw  = SpiPcieAddr;
+  mSrcDescSpiAsyncSmi.Sts[0].Reg.Data.raw = SpiPcieAddr;
+}
\ No newline at end of file
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiDispatcher.inf b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiDispatcher.inf
new file mode 100644
index 0000000000..7031b5193a
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiDispatcher.inf
@@ -0,0 +1,106 @@
+## @file
+# Component description file for the Pch SMI Dispatch Handlers module
+#
+#   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+#   SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PchSmiDispatcher
+FILE_GUID = B0D6ED53-B844-43f5-BD2F-61095264E77E
+VERSION_STRING = 1.0
+MODULE_TYPE = DXE_SMM_DRIVER
+PI_SPECIFICATION_VERSION = 1.10
+ENTRY_POINT = InitializePchSmmDispatcher
+
+
+[LibraryClasses]
+UefiBootServicesTableLib
+UefiDriverEntryPoint
+IoLib
+DebugLib
+PcdLib
+BaseLib
+BaseMemoryLib
+HobLib
+DevicePathLib
+PchCycleDecodingLib
+PchPcieRpLib
+PchPcrLib
+SmmServicesTableLib
+ReportStatusCodeLib
+PerformanceLib
+DxeServicesTableLib
+GpioLib
+GpioPrivateLib
+EspiLib
+S3BootScriptLib
+ConfigBlockLib
+PmcPrivateLib
+PmcLib
+SmiHandlerProfileLib
+PchPciBdfLib
+P2SbSidebandAccessLib
+CpuPcieInfoFruLib
+
+[Packages]
+MdePkg/MdePkg.dec
+AlderlakeSiliconPkg/SiPkg.dec
+
+
+[Pcd]
+# Progress Code for S3 Suspend start.
+# PROGRESS_CODE_S3_SUSPEND_START = (EFI_SOFTWARE_SMM_DRIVER | (EFI_OEM_SPECIFIC | 0x00000000))    = 0x03078000
+gSiPkgTokenSpaceGuid.PcdProgressCodeS3SuspendStart
+# Progress Code for S3 Suspend end.
+# PROGRESS_CODE_S3_SUSPEND_END   = (EFI_SOFTWARE_SMM_DRIVER | (EFI_OEM_SPECIFIC | 0x00000001))    = 0x03078001
+gSiPkgTokenSpaceGuid.PcdProgressCodeS3SuspendEnd
+gSiPkgTokenSpaceGuid.PcdEfiGcdAllocateType
+
+
+[Sources]
+PchSmm.h
+PchSmmCore.c
+PchSmmHelpers.c
+PchxSmmHelpers.c
+SmmGlobalsPch.c
+PchSmmUsb.c
+PchSmmGpi.c
+PchSmmPowerButton.c
+PchSmmSw.c
+PchSmmSx.c
+PchSmmPeriodicTimer.c
+PchSmiDispatch.c
+PcieSmmClient.c
+
+
+[Protocols]
+gEfiPciRootBridgeIoProtocolGuid ## CONSUMES
+gEfiSmmGpiDispatch2ProtocolGuid ## PRODUCES
+gEfiSmmSxDispatch2ProtocolGuid ## PRODUCES
+gEfiSmmSwDispatch2ProtocolGuid ## PRODUCES
+gEfiSmmUsbDispatch2ProtocolGuid ## PRODUCES
+gEfiSmmPowerButtonDispatch2ProtocolGuid ## PRODUCES
+gEfiSmmPeriodicTimerDispatch2ProtocolGuid ## PRODUCES
+gEfiSmmBase2ProtocolGuid ## CONSUMES
+gEfiSmmCpuProtocolGuid ## CONSUMES
+gEfiSmmReadyToLockProtocolGuid ## CONSUMES
+gPchTcoSmiDispatchProtocolGuid ## PRODUCES
+gPchPcieSmiDispatchProtocolGuid ## PRODUCES
+gPchAcpiSmiDispatchProtocolGuid ## PRODUCES
+gPchSmiDispatchProtocolGuid ## PRODUCES
+gPchEspiSmiDispatchProtocolGuid ## PRODUCES
+gPchSmmPeriodicTimerControlGuid ## PRODUCES
+
+
+[Guids]
+
+
+[Depex]
+gEfiPciRootBridgeIoProtocolGuid AND
+gEfiPciHostBridgeResourceAllocationProtocolGuid AND ## This is to ensure that PCI MMIO resource has been prepared and available for this driver to allocate.
+gEfiSmmCpuProtocolGuid AND
+gEfiSmmBase2ProtocolGuid
+
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiHelper.h b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiHelper.h
new file mode 100644
index 0000000000..5ec9455797
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiHelper.h
@@ -0,0 +1,34 @@
+/** @file
+  eSPI SMI Dispatch header
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PCH_SMI_HELPER_H_
+#define _PCH_SMI_HELPER_H_
+#include <Uefi/UefiBaseType.h>
+
+/**
+  Get CPU or PCH Pcie Root Port Device and Function Number by Root Port physical Number
+
+  @param[in]  RpNumber              Root port physical number. (0-based)
+  @param[out] RpDev                 Return corresponding root port device number.
+  @param[out] RpFun                 Return corresponding root port function number.
+**/
+VOID
+GetPcieRpDevFun (
+  IN  UINTN   RpIndex,
+  OUT UINTN   *RpDev,
+  OUT UINTN   *RpFun
+  );
+
+/**
+  Performs update of SmiDispatch descriptors with values that have to be evaluated during runtime.
+**/
+VOID
+PchSmiDispatchUpdateDescriptors (
+  VOID
+  );
+
+#endif
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmm.h b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmm.h
new file mode 100644
index 0000000000..41969a0ec7
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmm.h
@@ -0,0 +1,1028 @@
+/** @file
+  Prototypes and defines for the PCH SMM Dispatcher.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_SMM_H_
+#define _PCH_SMM_H_
+
+#include <Uefi.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/SmmControl2.h>
+#include <Protocol/SmmUsbDispatch2.h>
+#include <Protocol/SmmSxDispatch2.h>
+#include <Protocol/SmmSwDispatch2.h>
+#include <Protocol/SmmGpiDispatch2.h>
+#include <Protocol/SmmPowerButtonDispatch2.h>
+#include <Protocol/SmmPeriodicTimerDispatch2.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Library/ReportStatusCodeLib.h>
+#include <Library/PerformanceLib.h>
+#include <Protocol/SmmReadyToLock.h>
+#include <IndustryStandard/Pci30.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/GpioLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/EspiLib.h>
+#include <Library/GpioPrivateLib.h>
+#include <Protocol/PchTcoSmiDispatch.h>
+#include <Protocol/PchPcieSmiDispatch.h>
+#include <Protocol/PchAcpiSmiDispatch.h>
+#include <Protocol/PchSmiDispatch.h>
+#include <Library/PmcLib.h>
+
+#define EFI_BAD_POINTER          0xAFAFAFAFAFAFAFAFULL
+
+extern BOOLEAN                   mReadyToLock;
+
+///
+/// Define an enumeration for all the supported protocols
+///
+#define PCH_SMM_PROTOCOL_TYPE_MAX       6
+
+typedef enum {
+  UsbType,
+  SxType,
+  SwType,
+  GpiType,
+  PowerButtonType,
+  PeriodicTimerType,
+  PchSmiDispatchType,
+  PchSmmProtocolTypeMax
+} PCH_SMM_PROTOCOL_TYPE;
+
+///
+/// Define all the supported types of PCH SMI
+///
+typedef enum {
+  PchTcoSmiMchType,
+  PchTcoSmiTcoTimeoutType,
+  PchTcoSmiOsTcoType,
+  PchTcoSmiNmiType,
+  PchTcoSmiIntruderDetectType,
+  PchTcoSmiSpiBiosWpType,
+  PchTcoSmiLpcBiosWpType,
+  PchTcoSmiNewCenturyType,
+  PchPcieSmiRpHotplugType,
+  PchPcieSmiRpLinkActiveType,
+  PchPcieSmiRpLinkEqType,
+  PchAcpiSmiPmeType,
+  PchAcpiSmiPmeB0Type,
+  PchAcpiSmiRtcAlarmType,
+  PchAcpiSmiTmrOverflowType,
+  PchEspiSmiEspiSlaveType,
+  PchSmiSerialIrqType,
+  PchSmiMcSmiType,
+  PchSmiSmBusType,
+  PchSmiSpiAsyncType,
+  PchIoTrapSmiType                      ///< internal SMI type
+} PCH_SMI_TYPES;
+
+///
+/// Generic funciton pointer to cover all Pch SMI function pointer types
+///
+typedef
+VOID
+(EFIAPI *PCH_SMI_CALLBACK_FUNCTIONS) (
+  IN EFI_HANDLE                         DispatchHandle,
+  ...
+  );
+
+
+///
+/// SPECIFYING A REGISTER
+/// We want a general way of referring to addresses.  For this case, we'll only
+/// need addresses in the ACPI table (and the TCO entries within the ACPI table).
+/// However, it's interesting to consider what it would take to support other types
+/// of addresses.  To address Will's concern, I think it prudent to accommodate it
+/// early on in the design.
+///
+/// Addresses we need to consider:
+///
+///  Type:                           Required:
+///  I/O                             Yes
+///    ACPI (special case of I/O)    Only if we want to
+///    TCO  (special case of I/O)    Only if we want to
+///  GPIO  (special case of MMIO)    Only if we want to
+///  Memory (or Memory Mapped I/O)   Only if we want to
+///  PCIE                            Yes, for BiosWp
+///
+typedef enum {
+  ///
+  ///  IO_ADDR_TYPE, /// unimplemented
+  ///
+  ACPI_ADDR_TYPE,
+  TCO_ADDR_TYPE,
+  ///
+  ///  MEMORY_ADDR_TYPE, /// unimplemented
+  ///
+  GPIO_ADDR_TYPE,
+  MEMORY_MAPPED_IO_ADDRESS_TYPE,
+  PCIE_ADDR_TYPE,
+  PCR_ADDR_TYPE,
+  NUM_ADDR_TYPES,                     ///< count of items in this enum
+  PCH_SMM_ADDR_TYPE_NULL        = -1  ///< sentinel to indicate NULL or to signal end of arrays
+} ADDR_TYPE;
+
+//
+// Assumption: 32-bits -- enum's evaluate to integer
+// Assumption: This code will only run on IA-32.  Justification: IA-64 doesn't have SMIs.
+// We don't have to worry about 64-bit addresses.
+// Typedef the size of addresses in case the numbers I'm using are wrong or in case
+// this changes.  This is a good idea because PCI_ADDR will change, for example, when
+// we add support for PciExpress.
+//
+typedef UINT16 IO_ADDR;
+typedef IO_ADDR ACPI_ADDR;  ///< can omit
+typedef IO_ADDR TCO_ADDR;   ///< can omit
+typedef UINTN MEM_ADDR;
+typedef MEM_ADDR *MEMORY_MAPPED_IO_ADDRESS;
+typedef MEM_ADDR *GPIO_ADDR;
+typedef union {
+  UINT32  Raw;
+  struct {
+    UINT32 Reg: 16;
+    UINT32 Fnc: 3;
+    UINT32 Dev: 5;
+    UINT32 Bus: 8;
+  } Fields;
+} PCIE_ADDR;
+
+typedef union {
+  UINT32  Raw;
+  struct {
+    UINT16 Offset;
+    UINT8  Pid;
+    UINT8  Base;
+  } Fields;
+} PCR_ADDR;
+
+typedef struct {
+  ADDR_TYPE Type;
+  union {
+    ///
+    /// used to initialize during declaration/definition
+    ///
+    UINT32                    raw;
+
+    ///
+    /// used to access useful data
+    ///
+    IO_ADDR                   io;
+    ACPI_ADDR                 acpi;
+    TCO_ADDR                  tco;
+    GPIO_ADDR                 gpio;
+    MEM_ADDR                  mem;
+    MEMORY_MAPPED_IO_ADDRESS  Mmio;
+    PCIE_ADDR                 pcie;
+    PCR_ADDR                  Pcr;
+
+  } Data;
+
+} PCH_SMM_ADDRESS;
+
+///
+/// SPECIFYING BITS WITHIN A REGISTER
+/// Here's a struct that helps us specify a source or enable bit.
+///
+typedef struct {
+  PCH_SMM_ADDRESS Reg;
+  UINT8           SizeInBytes;  ///< of the register
+  UINT8           Bit;
+} PCH_SMM_BIT_DESC;
+
+//
+// Sometimes, we'll have bit descriptions that are unused.  It'd be great to have a
+// way to easily identify them:
+//
+#define IS_BIT_DESC_NULL(BitDesc)   ((BitDesc).Reg.Type == PCH_SMM_ADDR_TYPE_NULL)  ///< "returns" true when BitDesc is NULL
+#define NULL_THIS_BIT_DESC(BitDesc) ((BitDesc).Reg.Type = PCH_SMM_ADDR_TYPE_NULL)   ///< will "return" an integer w/ value of 0
+#define NULL_BIT_DESC_INITIALIZER \
+  { \
+    { \
+      PCH_SMM_ADDR_TYPE_NULL, \
+      { \
+        0 \
+      } \
+    }, \
+    0, 0 \
+  }
+//
+// I'd like a type to specify the callback's Sts & En bits because they'll
+// be commonly used together:
+//
+#define NUM_EN_BITS   2
+#define NUM_STS_BITS  1
+
+//
+// Flags
+//
+typedef UINT8 PCH_SMM_SOURCE_FLAGS;
+
+//
+// Flags required to describe the event source
+//
+#define PCH_SMM_NO_FLAGS          0
+#define PCH_SMM_SCI_EN_DEPENDENT  1
+
+typedef struct {
+  PCH_SMM_SOURCE_FLAGS  Flags;
+  PCH_SMM_BIT_DESC      En[NUM_EN_BITS];    ///< Describes the enable bit(s) for the SMI event
+  PCH_SMM_BIT_DESC      Sts[NUM_STS_BITS];  ///< Describes the secondary status bit for the SMI event. Might be the same as TopLevelSmi
+  PCH_SMM_BIT_DESC      PmcSmiSts;          ///< Refereing to the top level status bit in PMC SMI_STS, i.e. R_PCH_SMI_STS
+} PCH_SMM_SOURCE_DESC;
+
+///
+/// Used to initialize null source descriptor
+///
+#define NULL_SOURCE_DESC_INITIALIZER \
+  { \
+    PCH_SMM_NO_FLAGS, \
+    { \
+      NULL_BIT_DESC_INITIALIZER, NULL_BIT_DESC_INITIALIZER \
+    }, \
+    { \
+      NULL_BIT_DESC_INITIALIZER \
+    }, \
+    NULL_BIT_DESC_INITIALIZER \
+  }
+
+///
+/// Define a PCIE RP event context for SmiProfileHandlerInfo tool
+///
+typedef struct {
+  PCH_SMI_TYPES               PchSmiType;
+  UINTN                       RpIndex;
+} PCH_SMM_PCIE_REGISTER_CONTEXT;
+
+///
+/// CHILD CONTEXTS
+/// To keep consistent w/ the architecture, we'll need to provide the context
+/// to the child when we call its callback function.  After talking with Will,
+/// we agreed that we'll need functions to "dig" the context out of the hardware
+/// in many cases (Sx, Trap, Gpi, etc), and we'll need a function to compare those
+/// contexts to prevent unnecessary dispatches.  I'd like a general type for these
+/// "GetContext" functions, so I'll need a union of all the protocol contexts for
+/// our internal use:
+///
+typedef union {
+  //
+  // (in no particular order)
+  //
+  EFI_SMM_SX_REGISTER_CONTEXT             Sx;
+  EFI_SMM_PERIODIC_TIMER_REGISTER_CONTEXT PeriodicTimer;
+  EFI_SMM_SW_REGISTER_CONTEXT             Sw;
+  EFI_SMM_POWER_BUTTON_REGISTER_CONTEXT   PowerButton;
+  EFI_SMM_USB_REGISTER_CONTEXT            Usb;
+  EFI_SMM_GPI_REGISTER_CONTEXT            Gpi;
+  PCH_SMM_PCIE_REGISTER_CONTEXT           Pcie;
+} PCH_SMM_CONTEXT;
+
+///
+/// Misc data for PchDispatcher usage.
+/// For PeriodicTimer, since the ElapsedTime is removed from EFI_SMM_PERIODIC_TIMER_REGISTER_CONTEXT of EDKII,
+/// and PchDispatcher needs it for every record. Thus move it here to support ElapsedTime.
+///
+typedef struct {
+  UINTN    ElapsedTime;
+  ///
+  /// A switch to control periodic timer SMI enabling
+  ///
+  BOOLEAN  TimerSmiEnabled;
+} PCH_SMM_MISC_DATA;
+
+//
+// Assumption: PeriodicTimer largest at 3x64-bits or 24 bytes
+//
+typedef struct _DATABASE_RECORD DATABASE_RECORD;
+
+///
+/// Assumption: the GET_CONTEXT function will be as small and simple as possible.
+/// Assumption: We don't need to pass in an enumeration for the protocol because each
+///    GET_CONTEXT function is written for only one protocol.
+/// We also need a function to compare contexts to see if the child should be dispatched
+/// In addition, we need a function to acquire CommBuffer and CommBufferSize for
+///    dispatch callback function of EDKII native support.
+///
+typedef
+VOID
+(EFIAPI *GET_CONTEXT) (
+  IN  DATABASE_RECORD    * Record,
+  OUT PCH_SMM_CONTEXT    * Context
+  );
+
+typedef
+BOOLEAN
+(EFIAPI *CMP_CONTEXT) (
+  IN PCH_SMM_CONTEXT     * Context1,
+  IN PCH_SMM_CONTEXT     * Context2
+  );
+
+typedef
+VOID
+(EFIAPI *GET_COMMBUFFER) (
+  IN  DATABASE_RECORD    * Record,
+  OUT VOID               **CommBuffer,
+  OUT UINTN              * CommBufferSize
+  );
+
+///
+/// Finally, every protocol will require a "Get Context" and "Compare Context" call, so
+/// we may as well wrap that up in a table, too.
+///
+typedef struct {
+  GET_CONTEXT     GetContext;
+  CMP_CONTEXT     CmpContext;
+  GET_COMMBUFFER  GetCommBuffer;
+} CONTEXT_FUNCTIONS;
+
+extern CONTEXT_FUNCTIONS          ContextFunctions[PCH_SMM_PROTOCOL_TYPE_MAX];
+
+///
+/// MAPPING CONTEXT TO BIT DESCRIPTIONS
+/// I'd like to have a general approach to mapping contexts to bit descriptions.
+/// Sometimes, we'll find that we can use table lookups or constant assignments;
+/// other times, we'll find that we'll need to use a function to perform the mapping.
+/// If we define a macro to mask that process, we'll never have to change the code.
+/// I don't know if this is desirable or not -- if it isn't, then we can get rid
+/// of the macros and just use function calls or variable assignments.  Doesn't matter
+/// to me.
+/// Mapping complex contexts requires a function
+///
+
+/**
+  Maps a USB context to a source description.
+
+  @param[in] Context              The context we need to map.  Type must be USB.
+  @param[out] SrcDesc             The source description that corresponds to the given context.
+
+**/
+VOID
+MapUsbToSrcDesc (
+  IN  PCH_SMM_CONTEXT         *Context,
+  OUT PCH_SMM_SOURCE_DESC     *SrcDesc
+  );
+
+/**
+  Figure out which timer the child is requesting and
+  send back the source description
+
+  @param[in] DispatchContext      The pointer to the Dispatch Context instances
+  @param[out] SrcDesc             The pointer to the source description
+
+**/
+VOID
+MapPeriodicTimerToSrcDesc (
+  IN  PCH_SMM_CONTEXT                                         *DispatchContext,
+  OUT PCH_SMM_SOURCE_DESC                                     *SrcDesc
+  );
+
+//
+// Mapping simple contexts can be done by assignment or lookup table
+//
+extern CONST PCH_SMM_SOURCE_DESC  mSxSourceDesc;
+extern CONST PCH_SMM_SOURCE_DESC  mPowerButtonSourceDesc;
+extern CONST PCH_SMM_SOURCE_DESC  mSrcDescNewCentury;
+extern CONST PCH_SMM_SOURCE_DESC  mGpiSourceDescTemplate;
+
+///
+/// For PCHx, APMC is UINT8 port, so the MAX SWI Value is 0xFF.
+///
+#define MAXIMUM_SWI_VALUE 0xFF
+///
+/// Open: Need to make sure this kind of type cast will actually work.
+///   May need an intermediate form w/ two VOID* arguments.  I'll figure
+///   that out when I start compiling.
+///
+typedef
+VOID
+(EFIAPI *PCH_SMM_CLEAR_SOURCE) (
+  CONST PCH_SMM_SOURCE_DESC * SrcDesc
+  );
+
+///
+/// "DATABASE" RECORD
+/// Linked list data structures
+///
+#define DATABASE_RECORD_SIGNATURE SIGNATURE_32 ('D', 'B', 'R', 'C')
+
+struct _DATABASE_RECORD {
+  UINT32                        Signature;
+  LIST_ENTRY                    Link;
+  BOOLEAN                       Processed;
+  ///
+  /// Status and Enable bit description
+  ///
+  PCH_SMM_SOURCE_DESC           SrcDesc;
+
+  ///
+  /// Callback function
+  ///
+  EFI_SMM_HANDLER_ENTRY_POINT2  Callback;
+  PCH_SMM_CONTEXT               ChildContext;
+  UINTN                         ContextSize;
+
+  ///
+  /// Special handling hooks -- init them to NULL if unused/unneeded
+  ///
+  PCH_SMM_CLEAR_SOURCE          ClearSource;
+
+  ///
+  /// Functions required to make callback code general
+  ///
+  CONTEXT_FUNCTIONS             ContextFunctions;
+
+  ///
+  /// The protocol that this record dispatches
+  ///
+  PCH_SMM_PROTOCOL_TYPE         ProtocolType;
+
+  ///
+  /// Misc data for private usage
+  ///
+  PCH_SMM_MISC_DATA             MiscData;
+
+  ///
+  /// PCH SMI callback function
+  ///
+  PCH_SMI_CALLBACK_FUNCTIONS    PchSmiCallback;
+  ///
+  /// Indicate the PCH SMI types.
+  ///
+  PCH_SMI_TYPES                 PchSmiType;
+};
+
+#define DATABASE_RECORD_FROM_LINK(_record)  CR (_record, DATABASE_RECORD, Link, DATABASE_RECORD_SIGNATURE)
+#define DATABASE_RECORD_FROM_CHILDCONTEXT(_record)  CR (_record, DATABASE_RECORD, ChildContext, DATABASE_RECORD_SIGNATURE)
+
+///
+/// HOOKING INTO THE ARCHITECTURE
+///
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SMM_GENERIC_REGISTER) (
+  IN  VOID                                    **This,
+  IN  VOID                                    *DispatchFunction,
+  IN  VOID                                    *DispatchContext,
+  OUT EFI_HANDLE                              *DispatchHandle
+  );
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SMM_GENERIC_UNREGISTER) (
+  IN  VOID                                    **This,
+  IN  EFI_HANDLE                              DispatchHandle
+  );
+
+///
+/// Define a memory "stamp" equivalent in size and function to most of the protocols
+///
+typedef struct {
+  PCH_SMM_GENERIC_REGISTER    Register;
+  PCH_SMM_GENERIC_UNREGISTER  Unregister;
+  UINTN                       Extra1;
+  UINTN                       Extra2; ///< may not need this one
+} PCH_SMM_GENERIC_PROTOCOL;
+
+/**
+  Register a child SMI dispatch function with a parent SMM driver.
+
+  @param[in] This                 Pointer to the PCH_SMM_GENERIC_PROTOCOL instance.
+  @param[in] DispatchFunction     Pointer to dispatch function to be invoked for this SMI source.
+  @param[in] DispatchContext      Pointer to the dispatch function's context.
+  @param[out] DispatchHandle      Handle of dispatch function, for when interfacing
+                                  with the parent SMM driver, will be the address of linked
+                                  list link in the call back record.
+
+  @retval EFI_OUT_OF_RESOURCES    Insufficient resources to create database record
+  @retval EFI_INVALID_PARAMETER   The input parameter is invalid
+  @retval EFI_SUCCESS             The dispatch function has been successfully
+                                  registered and the SMI source has been enabled.
+**/
+EFI_STATUS
+EFIAPI
+PchPiSmmCoreRegister (
+  IN  PCH_SMM_GENERIC_PROTOCOL                          *This,
+  IN  EFI_SMM_HANDLER_ENTRY_POINT2                      DispatchFunction,
+  IN  PCH_SMM_CONTEXT                                   *DispatchContext,
+  OUT EFI_HANDLE                                        *DispatchHandle
+  );
+
+/**
+  Unregister a child SMI source dispatch function with a parent SMM driver
+
+  @param[in] This                       Protocol instance pointer.
+  @param[in] DispatchHandle             Handle of dispatch function to deregister.
+
+  @retval EFI_SUCCESS                   The dispatch function has been successfully
+                                        unregistered and the SMI source has been disabled
+                                        if there are no other registered child dispatch
+                                        functions for this SMI source.
+  @retval EFI_INVALID_PARAMETER         Handle is invalid.
+  @retval EFI_ACCESS_DENIED             Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchPiSmmCoreUnRegister (
+  IN PCH_SMM_GENERIC_PROTOCOL                           *This,
+  IN EFI_HANDLE                                         *DispatchHandle
+  );
+
+
+/**
+  Unregister a child SMI source dispatch function with a parent SMM driver.
+
+  @param[in] This                 Pointer to the PCH_SMM_GENERIC_PROTOCOL instance.
+  @param[in] DispatchHandle       Handle of dispatch function to deregister.
+
+  @retval EFI_SUCCESS             The dispatch function has been successfully
+                                  unregistered and the SMI source has been disabled
+                                  if there are no other registered child dispatch
+                                  functions for this SMI source.
+  @retval EFI_INVALID_PARAMETER   Handle is invalid.
+**/
+EFI_STATUS
+EFIAPI
+PchSmmCoreUnRegister (
+  IN  PCH_SMM_GENERIC_PROTOCOL                         *This,
+  IN  EFI_HANDLE                                       *DispatchHandle
+  );
+
+typedef union {
+  PCH_SMM_GENERIC_PROTOCOL                    Generic;
+  EFI_SMM_USB_DISPATCH2_PROTOCOL              Usb;
+  EFI_SMM_SX_DISPATCH2_PROTOCOL               Sx;
+  EFI_SMM_SW_DISPATCH2_PROTOCOL               Sw;
+  EFI_SMM_GPI_DISPATCH2_PROTOCOL              Gpi;
+  EFI_SMM_POWER_BUTTON_DISPATCH2_PROTOCOL     PowerButton;
+  EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL   PeriodicTimer;
+} PCH_SMM_PROTOCOL;
+
+///
+/// Define a structure to help us identify the generic protocol
+///
+#define PROTOCOL_SIGNATURE  SIGNATURE_32 ('P', 'R', 'O', 'T')
+
+typedef struct {
+  UINTN                 Signature;
+
+  PCH_SMM_PROTOCOL_TYPE Type;
+  EFI_GUID              *Guid;
+  PCH_SMM_PROTOCOL      Protocols;
+} PCH_SMM_QUALIFIED_PROTOCOL;
+
+#define QUALIFIED_PROTOCOL_FROM_GENERIC(_generic) \
+  CR ( \
+  _generic, \
+  PCH_SMM_QUALIFIED_PROTOCOL, \
+  Protocols, \
+  PROTOCOL_SIGNATURE \
+  )
+
+///
+/// Create private data for the protocols that we'll publish
+///
+typedef struct {
+  LIST_ENTRY                  CallbackDataBase;
+  EFI_HANDLE                  SmiHandle;
+  EFI_HANDLE                  InstallMultProtHandle;
+  PCH_SMM_QUALIFIED_PROTOCOL  Protocols[PCH_SMM_PROTOCOL_TYPE_MAX];
+} PRIVATE_DATA;
+
+extern PRIVATE_DATA           mPrivateData;
+extern UINT16                 mAcpiBaseAddr;
+extern UINT16                 mTcoBaseAddr;
+
+/**
+  The internal function used to create and insert a database record
+
+  @param[in]  InsertRecord              Record to insert to database.
+  @param[out] DispatchHandle            Handle of dispatch function to register.
+
+  @retval EFI_INVALID_PARAMETER         Error with NULL SMI source description
+  @retval EFI_OUT_OF_RESOURCES          Fail to allocate pool for database record
+  @retval EFI_SUCCESS                   The database record is created successfully.
+**/
+EFI_STATUS
+SmmCoreInsertRecord (
+  IN  DATABASE_RECORD                   *NewRecord,
+  OUT EFI_HANDLE                        *DispatchHandle
+  );
+
+/**
+  Get the Sleep type
+
+  @param[in] Record               No use
+  @param[out] Context             The context that includes SLP_TYP bits to be filled
+**/
+VOID
+EFIAPI
+SxGetContext (
+  IN  DATABASE_RECORD    *Record,
+  OUT PCH_SMM_CONTEXT    *Context
+  );
+
+/**
+  Register a child SMI source dispatch function for the specified software SMI.
+
+  This service registers a function (DispatchFunction) which will be called when the software
+  SMI source specified by RegisterContext->SwSmiCpuIndex is detected. On return,
+  DispatchHandle contains a unique handle which may be used later to unregister the function
+  using UnRegister().
+
+  @param[in]  This                 Pointer to the EFI_SMM_SW_DISPATCH2_PROTOCOL instance.
+  @param[in]  DispatchFunction     Function to register for handler when the specified software
+                                   SMI is generated.
+  @param[in, out] RegisterContext  Pointer to the dispatch function's context.
+                                   The caller fills this context in before calling
+                                   the register function to indicate to the register
+                                   function which Software SMI input value the
+                                   dispatch function should be invoked for.
+  @param[out] DispatchHandle       Handle generated by the dispatcher to track the
+                                   function instance.
+
+  @retval EFI_SUCCESS            The dispatch function has been successfully
+                                 registered and the SMI source has been enabled.
+  @retval EFI_DEVICE_ERROR       The SW driver was unable to enable the SMI source.
+  @retval EFI_INVALID_PARAMETER  RegisterContext is invalid. The SW SMI input value
+                                 is not within a valid range or is already in use.
+  @retval EFI_OUT_OF_RESOURCES   There is not enough memory (system or SMM) to manage this
+                                 child.
+  @retval EFI_OUT_OF_RESOURCES   A unique software SMI value could not be assigned
+                                 for this dispatch.
+**/
+EFI_STATUS
+EFIAPI
+PchSwSmiRegister (
+  IN  EFI_SMM_SW_DISPATCH2_PROTOCOL       *This,
+  IN  EFI_SMM_HANDLER_ENTRY_POINT2        DispatchFunction,
+  IN  EFI_SMM_SW_REGISTER_CONTEXT         *DispatchContext,
+  OUT EFI_HANDLE                          *DispatchHandle
+  );
+
+/**
+  Unregister a child SMI source dispatch function for the specified software SMI.
+
+  This service removes the handler associated with DispatchHandle so that it will no longer be
+  called in response to a software SMI.
+
+  @param[in] This                Pointer to the EFI_SMM_SW_DISPATCH2_PROTOCOL instance.
+  @param[in] DispatchHandle      Handle of dispatch function to deregister.
+
+  @retval EFI_SUCCESS            The dispatch function has been successfully unregistered.
+  @retval EFI_INVALID_PARAMETER  The DispatchHandle was not valid.
+**/
+EFI_STATUS
+EFIAPI
+PchSwSmiUnRegister (
+  IN CONST EFI_SMM_SW_DISPATCH2_PROTOCOL  *This,
+  IN       EFI_HANDLE                     DispatchHandle
+  );
+
+/**
+  Init required protocol for Pch Sw Dispatch protocol.
+**/
+VOID
+PchSwDispatchInit (
+  VOID
+  );
+
+/**
+  Check whether sleep type of two contexts match
+
+  @param[in] Context1             Context 1 that includes sleep type 1
+  @param[in] Context2             Context 2 that includes sleep type 2
+
+  @retval FALSE                   Sleep types match
+  @retval TRUE                    Sleep types don't match
+**/
+BOOLEAN
+EFIAPI
+SxCmpContext (
+  IN PCH_SMM_CONTEXT     *Context1,
+  IN PCH_SMM_CONTEXT     *Context2
+  );
+
+/**
+  Update the elapsed time from the Interval data of DATABASE_RECORD
+
+  @param[in] Record               The pointer to the DATABASE_RECORD.
+  @param[out] HwContext           The Context to be updated.
+**/
+VOID
+EFIAPI
+PeriodicTimerGetContext (
+  IN  DATABASE_RECORD    *Record,
+  OUT PCH_SMM_CONTEXT    *Context
+  );
+
+/**
+  Check whether Periodic Timer of two contexts match
+
+  @param[in] Context1             Context 1 that includes Periodic Timer  1
+  @param[in] Context2             Context 2 that includes Periodic Timer  2
+
+  @retval FALSE                   Periodic Timer match
+  @retval TRUE                    Periodic Timer don't match
+**/
+BOOLEAN
+EFIAPI
+PeriodicTimerCmpContext (
+  IN PCH_SMM_CONTEXT     *Context1,
+  IN PCH_SMM_CONTEXT     *Context2
+  );
+
+/**
+  Gather the CommBuffer information of SmmPeriodicTimerDispatch2.
+
+  @param[in]  Record              No use
+  @param[out] CommBuffer          Point to the CommBuffer structure
+  @param[out] CommBufferSize      Point to the Size of CommBuffer structure
+**/
+VOID
+EFIAPI
+PeriodicTimerGetCommBuffer (
+  IN  DATABASE_RECORD    *Record,
+  OUT VOID               **CommBuffer,
+  OUT UINTN              *CommBufferSize
+  );
+
+/**
+  Get the power button status.
+
+  @param[in] Record               The pointer to the DATABASE_RECORD.
+  @param[out] Context             Calling context from the hardware, will be updated with the current power button status.
+**/
+VOID
+EFIAPI
+PowerButtonGetContext (
+  IN  DATABASE_RECORD    *Record,
+  OUT PCH_SMM_CONTEXT    *Context
+  );
+
+/**
+  Check whether Power Button status of two contexts match
+
+  @param[in] Context1             Context 1 that includes Power Button status 1
+  @param[in] Context2             Context 2 that includes Power Button status 2
+
+  @retval FALSE                   Power Button status match
+  @retval TRUE                    Power Button status don't match
+**/
+BOOLEAN
+EFIAPI
+PowerButtonCmpContext (
+  IN PCH_SMM_CONTEXT     *Context1,
+  IN PCH_SMM_CONTEXT     *Context2
+  );
+
+/**
+  This function is responsible for calculating and enabling any timers that are required
+  to dispatch messages to children. The SrcDesc argument isn't acutally used.
+
+  @param[in] SrcDesc              Pointer to the PCH_SMM_SOURCE_DESC instance.
+**/
+VOID
+EFIAPI
+PchSmmPeriodicTimerClearSource (
+  IN CONST PCH_SMM_SOURCE_DESC    *SrcDesc
+  );
+
+/**
+  This services returns the next SMI tick period that is supported by the chipset.
+  The order returned is from longest to shortest interval period.
+
+  @param[in] This                 Pointer to the EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL instance.
+  @param[in, out] SmiTickInterval Pointer to pointer of the next shorter SMI interval period that is supported by the child.
+
+  @retval EFI_SUCCESS             The service returned successfully.
+  @retval EFI_INVALID_PARAMETER   The parameter SmiTickInterval is invalid.
+**/
+EFI_STATUS
+PchSmmPeriodicTimerDispatchGetNextShorterInterval (
+  IN CONST EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL    *This,
+  IN OUT UINT64                                         **SmiTickInterval
+  );
+
+/**
+  Install PCH SMM periodic timer control protocol
+
+  @param[in] Handle                     handle for this driver
+
+  @retval EFI_SUCCESS                   Driver initialization completed successfully
+**/
+EFI_STATUS
+EFIAPI
+InstallPchSmmPeriodicTimerControlProtocol (
+  IN EFI_HANDLE                         Handle
+  );
+
+/**
+  Install protocols of PCH specifics SMI types, including
+  PCH TCO SMI types, PCH PCIE SMI types, PCH ACPI SMI types, PCH MISC SMI types.
+
+  @retval                               the result of protocol installation
+**/
+EFI_STATUS
+InstallPchSmiDispatchProtocols (
+  VOID
+  );
+
+/**
+  The function to dispatch all callback function of PCH SMI types.
+
+  @retval EFI_SUCCESS                   Function successfully completed
+  @retval EFI_UNSUPPORTED               no
+**/
+EFI_STATUS
+PchSmiTypeCallbackDispatcher (
+  IN  DATABASE_RECORD                   *Record
+  );
+
+/**
+  The register function used to register SMI handler of IoTrap event.
+  This is internal function and only used by Iotrap module.
+
+  @param[in]  DispatchFunction          Pointer to dispatch function to be invoked for this SMI source
+  @param[in]  IoTrapIndex               Index number of IOTRAP register
+  @param[out] DispatchHandle            Handle of dispatch function to register.
+
+  @retval EFI_INVALID_PARAMETER         Error with NULL SMI source description
+  @retval EFI_OUT_OF_RESOURCES          Fail to allocate pool for database record
+  @retval EFI_SUCCESS                   The database record is created successfully.
+**/
+EFI_STATUS
+PchInternalIoTrapSmiRegister (
+  IN  PCH_SMI_DISPATCH_CALLBACK         DispatchFunction,
+  IN  UINTN                             IoTrapIndex,
+  OUT EFI_HANDLE                        *DispatchHandle
+  );
+
+/**
+  Unregister a child SMI source dispatch function with a parent SMM driver
+
+  @param[in] DispatchHandle             Handle of dispatch function to deregister.
+
+  @retval EFI_SUCCESS                   The dispatch function has been successfully
+                                        unregistered and the SMI source has been disabled
+                                        if there are no other registered child dispatch
+                                        functions for this SMI source.
+  @retval EFI_INVALID_PARAMETER         Handle is invalid.
+**/
+EFI_STATUS
+PchInternalIoTrapSmiUnRegister (
+  IN  EFI_HANDLE                        DispatchHandle
+  );
+
+/**
+  Register an eSPI SMI handler based on the type
+
+  @param[in]  DispatchFunction        Callback in an event of eSPI SMI
+  @param[in]  PchSmiTypes             The eSPI type published by PchSmiDispatch
+  @param[out] DispatchHandle          The callback handle
+
+  @retval     EFI_INVALID_PARAMETER   Error with NULL SMI source description
+  @retval     EFI_OUT_OF_RESOURCES    Fail to allocate pool for database record
+  @retval     EFI_SUCCESS             Registration is successful.
+**/
+EFI_STATUS
+PchInternalEspiSmiRegister (
+  IN  PCH_SMI_DISPATCH_CALLBACK         DispatchFunction,
+  IN  PCH_SMI_TYPES                     PchSmiTypes,
+  OUT EFI_HANDLE                        *DispatchHandle
+  );
+
+/**
+  Unregister an eSPI SMI handler
+
+  @param[in] DispatchHandle             Handle of dispatch function to deregister.
+
+  @retval EFI_SUCCESS                   The dispatch function has been successfully
+                                        unregistered and the SMI source has been disabled
+                                        if there are no other registered child dispatch
+                                        functions for this SMI source.
+  @retval EFI_INVALID_PARAMETER         Handle is invalid.
+**/
+EFI_STATUS
+PchInternalEspiSmiUnRegister (
+  IN  EFI_HANDLE                        DispatchHandle
+  );
+
+/**
+  The internal function used to create and insert a database record
+  for SMI record of Pch Smi types.
+
+  @param[in]  SrcDesc                   The pointer to the SMI source description
+  @param[in]  DispatchFunction          Pointer to dispatch function to be invoked for this SMI source
+  @param[in]  PchSmiType                Specific SMI type of PCH SMI
+  @param[out] DispatchHandle            Handle of dispatch function to register.
+
+  @retval EFI_INVALID_PARAMETER         Error with NULL SMI source description
+  @retval EFI_OUT_OF_RESOURCES          Fail to allocate pool for database record
+  @retval EFI_SUCCESS                   The database record is created successfully.
+**/
+EFI_STATUS
+PchSmiRecordInsert (
+  IN  CONST PCH_SMM_SOURCE_DESC         *SrcDesc,
+  IN  PCH_SMI_CALLBACK_FUNCTIONS        DispatchFunction,
+  IN  PCH_SMI_TYPES                     PchSmiType,
+  OUT EFI_HANDLE                        *DispatchHandle
+  );
+
+extern CONST PCH_SMM_SOURCE_DESC mSrcDescSerialIrq;
+extern PCH_SMM_SOURCE_DESC mSrcDescLpcBiosWp;
+
+/**
+  Clear the TCO SMI status bit and block after the SMI handling is done
+
+  @param[in] SrcDesc                    Pointer to the PCH SMI source description table
+
+**/
+VOID
+EFIAPI
+PchTcoSmiClearSourceAndBlock (
+  CONST PCH_SMM_SOURCE_DESC             *SrcDesc
+  );
+
+/**
+  Clear the TCO SMI status bit after the SMI handling is done
+
+  @param[in] SrcDesc                    Pointer to the PCH SMI source description table
+
+**/
+VOID
+EFIAPI
+PchTcoSmiClearSource (
+  CONST PCH_SMM_SOURCE_DESC             *SrcDesc
+  );
+
+/**
+  Initialize Source descriptor structure
+
+  @param[in] SrcDesc                    Pointer to the PCH SMI source description table
+**/
+VOID
+EFIAPI
+NullInitSourceDesc (
+  PCH_SMM_SOURCE_DESC                   *SrcDesc
+  );
+
+/**
+  The register function used to register SMI handler of GPI SMI event.
+
+  @param[in]  This               Pointer to the EFI_SMM_GPI_DISPATCH2_PROTOCOL instance.
+  @param[in]  DispatchFunction   Function to register for handler when the specified GPI causes an SMI.
+  @param[in]  RegisterContext    Pointer to the dispatch function's context.
+                                 The caller fills this context in before calling
+                                 the register function to indicate to the register
+                                 function the GPI(s) for which the dispatch function
+                                 should be invoked.
+  @param[out] DispatchHandle     Handle generated by the dispatcher to track the
+                                 function instance.
+
+  @retval EFI_SUCCESS            The dispatch function has been successfully
+                                 registered and the SMI source has been enabled.
+  @retval EFI_ACCESS_DENIED      Register is not allowed
+  @retval EFI_INVALID_PARAMETER  RegisterContext is invalid. The GPI input value
+                                 is not within valid range.
+  @retval EFI_OUT_OF_RESOURCES   There is not enough memory (system or SMM) to manage this child.
+**/
+EFI_STATUS
+EFIAPI
+PchGpiSmiRegister (
+  IN CONST EFI_SMM_GPI_DISPATCH2_PROTOCOL  *This,
+  IN       EFI_SMM_HANDLER_ENTRY_POINT2    DispatchFunction,
+  IN       EFI_SMM_GPI_REGISTER_CONTEXT    *RegisterContext,
+  OUT      EFI_HANDLE                      *DispatchHandle
+  );
+
+/**
+  Unregister a GPI SMI source dispatch function with a parent SMM driver
+
+  @param[in] This                 Pointer to the EFI_SMM_GPI_DISPATCH2_PROTOCOL instance.
+  @param[in] DispatchHandle       Handle of dispatch function to deregister.
+
+  @retval EFI_SUCCESS             The dispatch function has been successfully
+                                  unregistered and the SMI source has been disabled
+                                  if there are no other registered child dispatch
+                                  functions for this SMI source.
+  @retval EFI_INVALID_PARAMETER   Handle is invalid.
+**/
+EFI_STATUS
+EFIAPI
+PchGpiSmiUnRegister (
+  IN CONST EFI_SMM_GPI_DISPATCH2_PROTOCOL  *This,
+  IN       EFI_HANDLE                      DispatchHandle
+  );
+
+#endif
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmCore.c b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmCore.c
new file mode 100644
index 0000000000..cb889b5ce3
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmCore.c
@@ -0,0 +1,905 @@
+/** @file
+  This driver is responsible for the registration of child drivers
+  and the abstraction of the PCH SMI sources.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "PchSmm.h"
+#include "PchSmmHelpers.h"
+#include "PchSmiHelper.h"
+#include <Library/SmiHandlerProfileLib.h>
+#include <Register/GpioRegs.h>
+#include <Register/PmcRegs.h>
+#include <Register/TcoRegs.h>
+#include <Register/RtcRegs.h>
+
+#define PROGRESS_CODE_S3_SUSPEND_START  PcdGet32 (PcdProgressCodeS3SuspendStart)
+//
+// MODULE / GLOBAL DATA
+//
+// Module variables used by the both the main dispatcher and the source dispatchers
+// Declared in PchSmm.h
+//
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16                mAcpiBaseAddr;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16                mTcoBaseAddr;
+GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN               mReadyToLock;
+GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN               mS3SusStart;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT32                mNumOfRootPorts;
+
+GLOBAL_REMOVE_IF_UNREFERENCED PRIVATE_DATA          mPrivateData = {
+  {
+    NULL,
+    NULL
+  },                                    // CallbackDataBase linked list head
+  NULL,                                 // EFI handle returned when calling InstallMultipleProtocolInterfaces
+  NULL,                                 //
+  {                                     // protocol arrays
+    //
+    // elements within the array
+    //
+    {
+      PROTOCOL_SIGNATURE,
+      UsbType,
+      &gEfiSmmUsbDispatch2ProtocolGuid,
+      {{
+        (PCH_SMM_GENERIC_REGISTER) PchPiSmmCoreRegister,
+        (PCH_SMM_GENERIC_UNREGISTER) PchPiSmmCoreUnRegister
+      }}
+    },
+    {
+      PROTOCOL_SIGNATURE,
+      SxType,
+      &gEfiSmmSxDispatch2ProtocolGuid,
+      {{
+        (PCH_SMM_GENERIC_REGISTER) PchPiSmmCoreRegister,
+        (PCH_SMM_GENERIC_UNREGISTER) PchPiSmmCoreUnRegister
+      }}
+    },
+    {
+      PROTOCOL_SIGNATURE,
+      SwType,
+      &gEfiSmmSwDispatch2ProtocolGuid,
+      {{
+        (PCH_SMM_GENERIC_REGISTER) PchSwSmiRegister,
+        (PCH_SMM_GENERIC_UNREGISTER) PchSwSmiUnRegister,
+        (UINTN) MAXIMUM_SWI_VALUE
+      }}
+    },
+    {
+      PROTOCOL_SIGNATURE,
+      GpiType,
+      &gEfiSmmGpiDispatch2ProtocolGuid,
+      {{
+        (PCH_SMM_GENERIC_REGISTER) PchGpiSmiRegister,
+        (PCH_SMM_GENERIC_UNREGISTER) PchGpiSmiUnRegister,
+        (UINTN) PCH_GPIO_NUM_SUPPORTED_GPIS
+      }}
+    },
+    {
+      PROTOCOL_SIGNATURE,
+      PowerButtonType,
+      &gEfiSmmPowerButtonDispatch2ProtocolGuid,
+      {{
+        (PCH_SMM_GENERIC_REGISTER) PchPiSmmCoreRegister,
+        (PCH_SMM_GENERIC_UNREGISTER) PchPiSmmCoreUnRegister
+      }}
+    },
+    {
+      PROTOCOL_SIGNATURE,
+      PeriodicTimerType,
+      &gEfiSmmPeriodicTimerDispatch2ProtocolGuid,
+      {{
+        (PCH_SMM_GENERIC_REGISTER) PchPiSmmCoreRegister,
+        (PCH_SMM_GENERIC_UNREGISTER) PchPiSmmCoreUnRegister,
+        (UINTN) PchSmmPeriodicTimerDispatchGetNextShorterInterval
+      }}
+    },
+  }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONTEXT_FUNCTIONS     mContextFunctions[PCH_SMM_PROTOCOL_TYPE_MAX] = {
+  {
+    NULL,
+    NULL,
+    NULL
+  },
+  {
+    SxGetContext,
+    SxCmpContext,
+    NULL
+  },
+  {
+    NULL,
+    NULL,
+    NULL
+  },
+  {
+    NULL,
+    NULL,
+    NULL
+  },
+  {
+    PowerButtonGetContext,
+    PowerButtonCmpContext,
+    NULL
+  },
+  {
+    PeriodicTimerGetContext,
+    PeriodicTimerCmpContext,
+    PeriodicTimerGetCommBuffer
+  },
+};
+
+//
+// PROTOTYPES
+//
+// Functions use only in this file
+//
+EFI_STATUS
+EFIAPI
+PchSmmCoreDispatcher (
+  IN       EFI_HANDLE         SmmImageHandle,
+  IN CONST VOID               *PchSmmCore,     OPTIONAL
+  IN OUT   VOID               *CommunicationBuffer,
+  IN OUT   UINTN              *SourceSize
+  );
+
+//
+// FUNCTIONS
+//
+/**
+  SMM ready to lock notification event handler.
+
+  @param  Protocol   Points to the protocol's unique identifier
+  @param  Interface  Points to the interface instance
+  @param  Handle     The handle on which the interface was installed
+
+  @retval EFI_SUCCESS   SmmReadyToLockCallback runs successfully
+
+**/
+EFI_STATUS
+EFIAPI
+SmmReadyToLockCallback (
+  IN CONST EFI_GUID                       *Protocol,
+  IN VOID                                 *Interface,
+  IN EFI_HANDLE                           Handle
+  )
+{
+  mReadyToLock = TRUE;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  <b>PchSmiDispatcher SMM Module Entry Point</b>\n
+  - <b>Introduction</b>\n
+    The PchSmiDispatcher module is an SMM driver which  provides SMI handler registration
+    services for PCH generated SMIs.
+
+  - <b>Details</b>\n
+    This module provides SMI handler registration servicies for PCH SMIs.
+    NOTE: All the register/unregister functions will be locked after SMM ready to boot signal event.
+    Please make sure no handler is installed after that.
+
+  - @pre
+    - EFI_SMM_BASE2_PROTOCOL
+      - Documented in the System Management Mode Core Interface Specification
+    - EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+      - Documented in the UEFI 2.0 Specification and above
+    - EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+      - This is to ensure that PCI MMIO and IO resource has been prepared and available for this driver to allocate.
+    - EFI_SMM_CPU_PROTOCOL
+
+  - @result
+    The PchSmiDispatcher driver produces:
+    - EFI_SMM_USB_DISPATCH2_PROTOCOL
+    - EFI_SMM_SX_DISPATCH2_PROTOCOL
+    - EFI_SMM_SW_DISPATCH2_PROTOCOL
+    - EFI_SMM_GPI_DISPATCH2_PROTOCOL
+    - EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL
+    - EFI_SMM_POWER_BUTTON_DISPATCH2_PROTOCOL
+    - EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL
+    - @link _PCH_SMM_IO_TRAP_CONTROL_PROTOCOL PCH_SMM_IO_TRAP_CONTROL_PROTOCOL @endlink
+    - @link _PCH_PCIE_SMI_DISPATCH_PROTOCOL PCH_PCIE_SMI_DISPATCH_PROTOCOL @endlink
+    - @link _PCH_TCO_SMI_DISPATCH_PROTOCOL PCH_TCO_SMI_DISPATCH_PROTOCOL @endlink
+    - @link _PCH_ACPI_SMI_DISPATCH_PROTOCOL PCH_ACPI_SMI_DISPATCH_PROTOCOL @endlink
+    - @link _PCH_SMI_DISPATCH_PROTOCOL PCH_SMI_DISPATCH_PROTOCOL @endlink
+
+  @param[in] ImageHandle          Pointer to the loaded image protocol for this driver
+  @param[in] SystemTable          Pointer to the EFI System Table
+
+  @retval EFI_SUCCESS             PchSmmDispatcher Initialization completed.
+**/
+EFI_STATUS
+EFIAPI
+InitializePchSmmDispatcher (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS           Status;
+  VOID                 *SmmReadyToLockRegistration;
+
+  mS3SusStart = FALSE;
+
+  PchSmiDispatchUpdateDescriptors ();
+
+  //
+  // Access ACPI Base Addresses Register
+  //
+  mAcpiBaseAddr = PmcGetAcpiBase ();
+  ASSERT (mAcpiBaseAddr != 0);
+
+  //
+  // Access TCO Base Addresses Register
+  //
+  PchTcoBaseGet (&mTcoBaseAddr);
+  ASSERT (mTcoBaseAddr != 0);
+
+  mNumOfRootPorts = GetPchMaxPciePortNum ();
+
+  //
+  // Register a callback function to handle subsequent SMIs.  This callback
+  // will be called by SmmCoreDispatcher.
+  //
+  Status = gSmst->SmiHandlerRegister (PchSmmCoreDispatcher, NULL, &mPrivateData.SmiHandle);
+  ASSERT_EFI_ERROR (Status);
+  //
+  // Initialize Callback DataBase
+  //
+  InitializeListHead (&mPrivateData.CallbackDataBase);
+
+  //
+  // Enable SMIs on the PCH now that we have a callback
+  //
+  PchSmmInitHardware ();
+
+  //
+  // Install and initialize all the needed protocols
+  //
+  PchSwDispatchInit ();
+  PchSmmPublishDispatchProtocols ();
+  InstallPchSmiDispatchProtocols ();
+  InstallPchSmmPeriodicTimerControlProtocol (mPrivateData.InstallMultProtHandle);
+
+  //
+  // Register EFI_SMM_READY_TO_LOCK_PROTOCOL_GUID notify function.
+  //
+  Status = gSmst->SmmRegisterProtocolNotify (
+                    &gEfiSmmReadyToLockProtocolGuid,
+                    SmmReadyToLockCallback,
+                    &SmmReadyToLockRegistration
+                    );
+  ASSERT_EFI_ERROR (Status);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  The internal function used to create and insert a database record
+
+  @param[in]  InsertRecord              Record to insert to database.
+  @param[out] DispatchHandle            Handle of dispatch function to register.
+
+  @retval EFI_INVALID_PARAMETER         Error with NULL SMI source description
+  @retval EFI_OUT_OF_RESOURCES          Fail to allocate pool for database record
+  @retval EFI_SUCCESS                   The database record is created successfully.
+**/
+EFI_STATUS
+SmmCoreInsertRecord (
+  IN  DATABASE_RECORD                   *NewRecord,
+  OUT EFI_HANDLE                        *DispatchHandle
+  )
+{
+  EFI_STATUS                            Status;
+  DATABASE_RECORD                       *Record;
+
+  if ((NewRecord == NULL) ||
+      (NewRecord->Signature != DATABASE_RECORD_SIGNATURE))
+  {
+    ASSERT (FALSE);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = gSmst->SmmAllocatePool (EfiRuntimeServicesData, sizeof (DATABASE_RECORD), (VOID **) &Record);
+  if (EFI_ERROR (Status)) {
+    ASSERT (FALSE);
+    return EFI_OUT_OF_RESOURCES;
+  }
+  CopyMem (Record, NewRecord, sizeof (DATABASE_RECORD));
+
+  //
+  // After ensuring the source of event is not null, we will insert the record into the database
+  //
+  InsertTailList (&mPrivateData.CallbackDataBase, &Record->Link);
+
+  //
+  // Child's handle will be the address linked list link in the record
+  //
+  *DispatchHandle = (EFI_HANDLE) (&Record->Link);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Unregister a child SMI source dispatch function with a parent SMM driver
+
+  @param[in] This                       Protocol instance pointer.
+  @param[in] DispatchHandle             Handle of dispatch function to deregister.
+
+  @retval EFI_SUCCESS                   The dispatch function has been successfully
+                                        unregistered and the SMI source has been disabled
+                                        if there are no other registered child dispatch
+                                        functions for this SMI source.
+  @retval EFI_INVALID_PARAMETER         Handle is invalid.
+  @retval EFI_ACCESS_DENIED             Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchPiSmmCoreUnRegister (
+  IN PCH_SMM_GENERIC_PROTOCOL                           *This,
+  IN EFI_HANDLE                                         *DispatchHandle
+  )
+{
+  DATABASE_RECORD                   *RecordToDelete;
+  EFI_STATUS                        Status;
+  PCH_SMM_QUALIFIED_PROTOCOL        *Qualified;
+
+  Qualified      = QUALIFIED_PROTOCOL_FROM_GENERIC (This);
+  RecordToDelete = DATABASE_RECORD_FROM_LINK (DispatchHandle);
+  Status         = PchSmmCoreUnRegister (NULL, DispatchHandle);
+  if (!EFI_ERROR (Status)) {
+    SmiHandlerProfileUnregisterHandler (
+      Qualified->Guid,
+      RecordToDelete->Callback,
+      &RecordToDelete->ChildContext,
+      RecordToDelete->ContextSize
+      );
+  }
+  return Status;
+}
+
+/**
+  Register a child SMI dispatch function with a parent SMM driver.
+
+  @param[in] This                 Pointer to the PCH_SMM_GENERIC_PROTOCOL instance.
+  @param[in] DispatchFunction     Pointer to dispatch function to be invoked for this SMI source.
+  @param[in] DispatchContext      Pointer to the dispatch function's context.
+  @param[out] DispatchHandle      Handle of dispatch function, for when interfacing
+                                  with the parent SMM driver, will be the address of linked
+                                  list link in the call back record.
+
+  @retval EFI_OUT_OF_RESOURCES    Insufficient resources to create database record
+  @retval EFI_INVALID_PARAMETER   The input parameter is invalid
+  @retval EFI_SUCCESS             The dispatch function has been successfully
+                                  registered and the SMI source has been enabled.
+**/
+EFI_STATUS
+EFIAPI
+PchPiSmmCoreRegister (
+  IN  PCH_SMM_GENERIC_PROTOCOL                          *This,
+  IN  EFI_SMM_HANDLER_ENTRY_POINT2                      DispatchFunction,
+  IN  PCH_SMM_CONTEXT                                   *DispatchContext,
+  OUT EFI_HANDLE                                        *DispatchHandle
+  )
+{
+  EFI_STATUS                  Status;
+  DATABASE_RECORD             Record;
+  PCH_SMM_QUALIFIED_PROTOCOL  *Qualified;
+  PCH_SMM_SOURCE_DESC         NullSourceDesc;
+
+  //
+  // Initialize NullSourceDesc
+  //
+  NullInitSourceDesc (&NullSourceDesc);
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "Register is not allowed if the EndOfDxe event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  ZeroMem (&Record, sizeof (DATABASE_RECORD));
+
+  //
+  // Gather information about the registration request
+  //
+  Record.Callback          = DispatchFunction;
+
+  Qualified                = QUALIFIED_PROTOCOL_FROM_GENERIC (This);
+
+  Record.ProtocolType      = Qualified->Type;
+
+  Record.ContextFunctions  = mContextFunctions[Qualified->Type];
+  //
+  // Perform linked list housekeeping
+  //
+  Record.Signature         = DATABASE_RECORD_SIGNATURE;
+
+  switch (Qualified->Type) {
+    //
+    // By the end of this switch statement, we'll know the
+    // source description the child is registering for
+    //
+    case UsbType:
+      Record.ContextSize = sizeof (EFI_SMM_USB_REGISTER_CONTEXT);
+      CopyMem (&Record.ChildContext, DispatchContext, Record.ContextSize);
+      //
+      // Check the validity of Context Type
+      //
+      if ((Record.ChildContext.Usb.Type < UsbLegacy) || (Record.ChildContext.Usb.Type > UsbWake)) {
+        return EFI_INVALID_PARAMETER;
+      }
+
+      PchSmmUsbUpdateDescriptors ();
+      MapUsbToSrcDesc (DispatchContext, &Record.SrcDesc);
+      Record.ClearSource = NULL;
+      //
+      // use default clear source function
+      //
+      break;
+
+    case SxType:
+      Record.ContextSize = sizeof (EFI_SMM_SX_REGISTER_CONTEXT);
+      CopyMem (&Record.ChildContext, DispatchContext, Record.ContextSize);
+      //
+      // Check the validity of Context Type and Phase
+      //
+      if ((Record.ChildContext.Sx.Type < SxS0) ||
+          (Record.ChildContext.Sx.Type >= EfiMaximumSleepType) ||
+          (Record.ChildContext.Sx.Phase < SxEntry) ||
+          (Record.ChildContext.Sx.Phase >= EfiMaximumPhase)
+          ) {
+        return EFI_INVALID_PARAMETER;
+      }
+
+      CopyMem (&Record.SrcDesc, &mSxSourceDesc, sizeof (PCH_SMM_SOURCE_DESC));
+      Record.ClearSource = NULL;
+      //
+      // use default clear source function
+      //
+      break;
+
+    case PowerButtonType:
+      Record.ContextSize = sizeof (EFI_SMM_POWER_BUTTON_REGISTER_CONTEXT);
+      CopyMem (&Record.ChildContext, DispatchContext, Record.ContextSize);
+      //
+      // Check the validity of Context Phase
+      //
+      if ((Record.ChildContext.PowerButton.Phase < EfiPowerButtonEntry) ||
+          (Record.ChildContext.PowerButton.Phase > EfiPowerButtonExit))
+      {
+        return EFI_INVALID_PARAMETER;
+      }
+
+      CopyMem (&Record.SrcDesc, &mPowerButtonSourceDesc, sizeof (PCH_SMM_SOURCE_DESC));
+      Record.ClearSource = NULL;
+      //
+      // use default clear source function
+      //
+      break;
+
+    case PeriodicTimerType:
+      Record.ContextSize = sizeof (EFI_SMM_PERIODIC_TIMER_REGISTER_CONTEXT);
+      CopyMem (&Record.ChildContext, DispatchContext, Record.ContextSize);
+      //
+      // Check the validity of timer value
+      //
+      if (DispatchContext->PeriodicTimer.SmiTickInterval <= 0) {
+        return EFI_INVALID_PARAMETER;
+      }
+
+      MapPeriodicTimerToSrcDesc (DispatchContext, &Record.SrcDesc);
+      Record.MiscData.TimerSmiEnabled = TRUE;
+      Record.ClearSource = PchSmmPeriodicTimerClearSource;
+      break;
+
+    default:
+      return EFI_INVALID_PARAMETER;
+      break;
+  }
+
+  if (CompareSources (&Record.SrcDesc, &NullSourceDesc)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // After ensuring the source of event is not null, we will insert the record into the database
+  // Child's handle will be the address linked list link in the record
+  //
+  Status = SmmCoreInsertRecord (
+             &Record,
+             DispatchHandle
+             );
+  ASSERT_EFI_ERROR (Status);
+
+  if (Record.ClearSource == NULL) {
+    //
+    // Clear the SMI associated w/ the source using the default function
+    //
+    PchSmmClearSource (&Record.SrcDesc);
+  } else {
+    //
+    // This source requires special handling to clear
+    //
+    Record.ClearSource (&Record.SrcDesc);
+  }
+
+  PchSmmEnableSource (&Record.SrcDesc);
+  SmiHandlerProfileRegisterHandler (
+    Qualified->Guid,
+    DispatchFunction,
+    (UINTN)RETURN_ADDRESS (0),
+    DispatchContext,
+    Record.ContextSize
+    );
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Unregister a child SMI source dispatch function with a parent SMM driver.
+
+  @param[in] This                 Pointer to the PCH_SMM_GENERIC_PROTOCOL instance.
+  @param[in] DispatchHandle       Handle of dispatch function to deregister.
+
+  @retval EFI_SUCCESS             The dispatch function has been successfully
+                                  unregistered and the SMI source has been disabled
+                                  if there are no other registered child dispatch
+                                  functions for this SMI source.
+  @retval EFI_INVALID_PARAMETER   Handle is invalid.
+**/
+EFI_STATUS
+EFIAPI
+PchSmmCoreUnRegister (
+  IN PCH_SMM_GENERIC_PROTOCOL                           *This,
+  IN EFI_HANDLE                                         *DispatchHandle
+  )
+{
+  EFI_STATUS                   Status;
+  BOOLEAN                      NeedClearEnable;
+  UINTN                        DescIndex;
+  DATABASE_RECORD              *RecordToDelete;
+  DATABASE_RECORD              *RecordInDb;
+  LIST_ENTRY                   *LinkInDb;
+
+  if (DispatchHandle == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "UnRegister is not allowed if the SmmReadyToLock event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  RecordToDelete = DATABASE_RECORD_FROM_LINK (DispatchHandle);
+
+  //
+  // Take the entry out of the linked list
+  //
+  if (RecordToDelete->Link.ForwardLink == (LIST_ENTRY *) EFI_BAD_POINTER) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  RemoveEntryList (&RecordToDelete->Link);
+
+  //
+  // Loop through all the souces in record linked list to see if any source enable is equal.
+  // If any source enable is equal, we do not want to disable it.
+  //
+  for (DescIndex = 0; DescIndex < NUM_EN_BITS; ++DescIndex) {
+    if (IS_BIT_DESC_NULL (RecordToDelete->SrcDesc.En[DescIndex])) {
+      continue;
+    }
+    NeedClearEnable = TRUE;
+    LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);
+    while (!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {
+      RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);
+      if (IsBitEqualToAnySourceEn (&RecordToDelete->SrcDesc.En[DescIndex], &RecordInDb->SrcDesc)) {
+        NeedClearEnable = FALSE;
+        break;
+      }
+      LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, &RecordInDb->Link);
+    }
+    if (NeedClearEnable == FALSE) {
+      continue;
+    }
+    WriteBitDesc (&RecordToDelete->SrcDesc.En[DescIndex], 0, FALSE);
+  }
+  Status = gSmst->SmmFreePool (RecordToDelete);
+  if (EFI_ERROR (Status)) {
+    ASSERT (FALSE);
+    return Status;
+  }
+  return EFI_SUCCESS;
+}
+
+/**
+  This function clears the pending SMI status before set EOS.
+  NOTE: This only clears the pending SMI with known reason.
+        Please do not clear unknown pending SMI status since that will hide potential issues.
+
+  @param[in] SmiStsValue                SMI status
+  @param[in] SciEn                      Sci Enable status
+**/
+STATIC
+VOID
+ClearPendingSmiStatus (
+  UINT32  SmiStsValue,
+  BOOLEAN SciEn
+  )
+{
+  //
+  // Clear NewCentury status if it's not handled.
+  //
+  if (SmiStsValue & B_ACPI_IO_SMI_STS_TCO) {
+    if (IoRead16 (mTcoBaseAddr + R_TCO_IO_TCO1_STS) & B_TCO_IO_TCO1_STS_NEWCENTURY) {
+      PchTcoSmiClearSourceAndBlock (&mSrcDescNewCentury);
+    }
+  }
+  // Clear PWRBTNOR_STS if it's not handled.
+  //
+  if (IoRead16 (mAcpiBaseAddr + R_ACPI_IO_PM1_STS) & B_ACPI_IO_PM1_STS_PRBTNOR) {
+    IoWrite16 (mAcpiBaseAddr + R_ACPI_IO_PM1_STS, B_ACPI_IO_PM1_STS_PRBTNOR);
+  }
+  //
+  // Clear WADT_STS if this is triggered by WADT timer.
+  //
+  if (!SciEn) {
+    if ((IoRead32 (mAcpiBaseAddr + R_ACPI_IO_GPE0_EN_127_96) & B_ACPI_IO_GPE0_EN_127_96_WADT) &&
+        (IoRead32 (mAcpiBaseAddr + R_ACPI_IO_GPE0_STS_127_96) & B_ACPI_IO_GPE0_STS_127_96_WADT)) {
+      IoWrite32 (mAcpiBaseAddr + R_ACPI_IO_GPE0_STS_127_96, B_ACPI_IO_GPE0_STS_127_96_WADT);
+    }
+  }
+  //
+  // Clear GPIO_UNLOCK_SMI_STS in case it is set as GPIO Unlock SMI is not supported
+  //
+  if (SmiStsValue & B_ACPI_IO_SMI_STS_GPIO_UNLOCK) {
+    IoWrite32 (mAcpiBaseAddr + R_ACPI_IO_SMI_STS, B_ACPI_IO_SMI_STS_GPIO_UNLOCK);
+  }
+}
+
+/**
+  The callback function to handle subsequent SMIs.  This callback will be called by SmmCoreDispatcher.
+
+  @param[in] SmmImageHandle             Not used
+  @param[in] PchSmmCore                 Not used
+  @param[in, out] CommunicationBuffer   Not used
+  @param[in, out] SourceSize            Not used
+
+  @retval EFI_SUCCESS                   Function successfully completed
+**/
+EFI_STATUS
+EFIAPI
+PchSmmCoreDispatcher (
+  IN       EFI_HANDLE         SmmImageHandle,
+  IN CONST VOID               *PchSmmCore,
+  IN OUT   VOID               *CommunicationBuffer,
+  IN OUT   UINTN              *SourceSize
+  )
+{
+  //
+  // Used to prevent infinite loops
+  //
+  UINTN               EscapeCount;
+
+  BOOLEAN             ContextsMatch;
+  BOOLEAN             EosSet;
+  BOOLEAN             SxChildWasDispatched;
+
+  DATABASE_RECORD     *RecordInDb;
+  LIST_ENTRY          *LinkInDb;
+  DATABASE_RECORD     *RecordToExhaust;
+  LIST_ENTRY          *LinkToExhaust;
+
+  PCH_SMM_CONTEXT     Context;
+  VOID                *CommBuffer;
+  UINTN               CommBufferSize;
+
+  EFI_STATUS          Status;
+  BOOLEAN             SciEn;
+  UINT32              SmiEnValue;
+  UINT32              SmiStsValue;
+  UINT8               Port74Save;
+  UINT8               Port76Save;
+
+  PCH_SMM_SOURCE_DESC ActiveSource;
+
+  //
+  // Initialize ActiveSource
+  //
+  NullInitSourceDesc (&ActiveSource);
+
+  EscapeCount           = 3;
+  ContextsMatch         = FALSE;
+  EosSet                = FALSE;
+  SxChildWasDispatched  = FALSE;
+  Status                = EFI_SUCCESS;
+
+  //
+  // Save IO index registers
+  // @note: Save/Restore port 70h directly might break NMI_EN# setting,
+  //       then save/restore 74h/76h instead.
+  // @note: CF8 is not saved. Prefer method is to use MMIO instead of CF8
+  //
+  Port76Save = IoRead8 (R_RTC_IO_EXT_INDEX_ALT);
+  Port74Save = IoRead8 (R_RTC_IO_INDEX_ALT);
+
+  if (!IsListEmpty (&mPrivateData.CallbackDataBase)) {
+    //
+    // We have children registered w/ us -- continue
+    //
+    while ((!EosSet) && (EscapeCount > 0)) {
+      EscapeCount--;
+
+      LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);
+
+      //
+      // Cache SciEn, SmiEnValue and SmiStsValue to determine if source is active
+      //
+      SciEn       = PchSmmGetSciEn ();
+      SmiEnValue  = IoRead32 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_SMI_EN));
+      SmiStsValue = IoRead32 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_SMI_STS));
+
+      while (!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {
+        RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);
+
+        //
+        // look for the first active source
+        //
+        if (!SourceIsActive (&RecordInDb->SrcDesc, SciEn, SmiEnValue, SmiStsValue)) {
+          //
+          // Didn't find the source yet, keep looking
+          //
+          LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, &RecordInDb->Link);
+
+          //
+          // if it's the last one, try to clear EOS
+          //
+          if (IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {
+            //
+            // Clear pending SMI status before EOS
+            //
+            ClearPendingSmiStatus (SmiStsValue, SciEn);
+            EosSet = PchSmmSetAndCheckEos ();
+          }
+        } else {
+          //
+          // We found a source. If this is a sleep type, we have to go to
+          // appropriate sleep state anyway.No matter there is sleep child or not
+          //
+          if (RecordInDb->ProtocolType == SxType) {
+            SxChildWasDispatched = TRUE;
+          }
+          //
+          // "cache" the source description and don't query I/O anymore
+          //
+          CopyMem ((VOID *) &ActiveSource, (VOID *) &(RecordInDb->SrcDesc), sizeof (PCH_SMM_SOURCE_DESC));
+          LinkToExhaust = LinkInDb;
+
+          //
+          // exhaust the rest of the queue looking for the same source
+          //
+          while (!IsNull (&mPrivateData.CallbackDataBase, LinkToExhaust)) {
+            RecordToExhaust = DATABASE_RECORD_FROM_LINK (LinkToExhaust);
+            //
+            // RecordToExhaust->Link might be removed (unregistered) by Callback function, and then the
+            // system will hang in ASSERT() while calling GetNextNode().
+            // To prevent the issue, we need to get next record in DB here (before Callback function).
+            //
+            LinkToExhaust = GetNextNode (&mPrivateData.CallbackDataBase, &RecordToExhaust->Link);
+
+            if (CompareSources (&RecordToExhaust->SrcDesc, &ActiveSource)) {
+              //
+              // These source descriptions are equal, so this callback should be
+              // dispatched.
+              //
+              if (RecordToExhaust->ContextFunctions.GetContext != NULL) {
+                //
+                // This child requires that we get a calling context from
+                // hardware and compare that context to the one supplied
+                // by the child.
+                //
+                ASSERT (RecordToExhaust->ContextFunctions.CmpContext != NULL);
+
+                //
+                // Make sure contexts match before dispatching event to child
+                //
+                RecordToExhaust->ContextFunctions.GetContext (RecordToExhaust, &Context);
+                ContextsMatch = RecordToExhaust->ContextFunctions.CmpContext (&Context, &RecordToExhaust->ChildContext);
+
+              } else {
+                //
+                // This child doesn't require any more calling context beyond what
+                // it supplied in registration.  Simply pass back what it gave us.
+                //
+                Context       = RecordToExhaust->ChildContext;
+                ContextsMatch = TRUE;
+              }
+
+              if (ContextsMatch) {
+                if (RecordToExhaust->ProtocolType == PchSmiDispatchType) {
+                  //
+                  // For PCH SMI dispatch protocols
+                  //
+                  PchSmiTypeCallbackDispatcher (RecordToExhaust);
+                } else {
+                  if ((RecordToExhaust->ProtocolType == SxType) && (Context.Sx.Type == SxS3) && (Context.Sx.Phase == SxEntry) && !mS3SusStart) {
+                    REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PROGRESS_CODE_S3_SUSPEND_START);
+                    mS3SusStart = TRUE;
+                  }
+                  //
+                  // For EFI standard SMI dispatch protocols
+                  //
+                  if (RecordToExhaust->Callback != NULL) {
+                    if (RecordToExhaust->ContextFunctions.GetCommBuffer != NULL) {
+                      //
+                      // This callback function needs CommBuffer and CommBufferSize.
+                      // Get those from child and then pass to callback function.
+                      //
+                      RecordToExhaust->ContextFunctions.GetCommBuffer (RecordToExhaust, &CommBuffer, &CommBufferSize);
+                    } else {
+                      //
+                      // Child doesn't support the CommBuffer and CommBufferSize.
+                      // Just pass NULL value to callback function.
+                      //
+                      CommBuffer     = NULL;
+                      CommBufferSize = 0;
+                    }
+
+                    PERF_START_EX (NULL, "SmmFunction", NULL, AsmReadTsc (), RecordToExhaust->ProtocolType);
+                    RecordToExhaust->Callback ((EFI_HANDLE) & RecordToExhaust->Link, &Context, CommBuffer, &CommBufferSize);
+                    PERF_END_EX (NULL, "SmmFunction", NULL, AsmReadTsc (), RecordToExhaust->ProtocolType);
+                    if (RecordToExhaust->ProtocolType == SxType) {
+                      SxChildWasDispatched = TRUE;
+                    }
+                  } else {
+                    ASSERT (FALSE);
+                  }
+                }
+              }
+            }
+          }
+
+          if (RecordInDb->ClearSource == NULL) {
+            //
+            // Clear the SMI associated w/ the source using the default function
+            //
+            PchSmmClearSource (&ActiveSource);
+          } else {
+            //
+            // This source requires special handling to clear
+            //
+            RecordInDb->ClearSource (&ActiveSource);
+          }
+          //
+          // Clear pending SMI status before EOS
+          //
+          ClearPendingSmiStatus (SmiStsValue, SciEn);
+          //
+          // Also, try to clear EOS
+          //
+          EosSet = PchSmmSetAndCheckEos ();
+          //
+          // Queue is empty, reset the search
+          //
+          break;
+        }
+      }
+    }
+  }
+  //
+  // Restore IO index registers
+  // @note: Save/Restore port 70h directly might break NMI_EN# setting,
+  //       then save/restore 74h/76h instead.
+  //
+  IoWrite8 (R_RTC_IO_EXT_INDEX_ALT, Port76Save);
+  IoWrite8 (R_RTC_IO_INDEX_ALT, Port74Save);
+
+  return Status;
+}
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmGpi.c b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmGpi.c
new file mode 100644
index 0000000000..4c59c07bac
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmGpi.c
@@ -0,0 +1,255 @@
+/** @file
+  File to contain all the hardware specific stuff for the Smm Gpi dispatch protocol.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "PchSmm.h"
+#include "PchSmmHelpers.h"
+#include <Library/SmiHandlerProfileLib.h>
+#include <Register/GpioRegs.h>
+#include <Register/PmcRegs.h>
+
+//
+// Structure for GPI SMI is a template which needs to have
+// GPI Smi bit offset and Smi Status & Enable registers updated (accordingly
+// to choosen group and pad number) after adding it to SMM Callback database
+//
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mPchGpiSourceDescTemplate = {
+  PCH_SMM_NO_FLAGS,
+  {
+    NULL_BIT_DESC_INITIALIZER,
+    NULL_BIT_DESC_INITIALIZER
+  },
+  {
+    {
+      {
+        GPIO_ADDR_TYPE, {0x0}
+      },
+      S_GPIO_PCR_GP_SMI_STS, 0x0,
+    }
+  },
+  {
+    {
+      ACPI_ADDR_TYPE,
+      {R_ACPI_IO_SMI_STS}
+    },
+    S_ACPI_IO_SMI_STS,
+    N_ACPI_IO_SMI_STS_GPIO_SMI
+  }
+};
+
+/**
+  The register function used to register SMI handler of GPI SMI event.
+
+  @param[in]  This               Pointer to the EFI_SMM_GPI_DISPATCH2_PROTOCOL instance.
+  @param[in]  DispatchFunction   Function to register for handler when the specified GPI causes an SMI.
+  @param[in]  RegisterContext    Pointer to the dispatch function's context.
+                                 The caller fills this context in before calling
+                                 the register function to indicate to the register
+                                 function the GPI(s) for which the dispatch function
+                                 should be invoked.
+  @param[out] DispatchHandle     Handle generated by the dispatcher to track the
+                                 function instance.
+
+  @retval EFI_SUCCESS            The dispatch function has been successfully
+                                 registered and the SMI source has been enabled.
+  @retval EFI_ACCESS_DENIED      Register is not allowed
+  @retval EFI_INVALID_PARAMETER  RegisterContext is invalid. The GPI input value
+                                 is not within valid range.
+  @retval EFI_OUT_OF_RESOURCES   There is not enough memory (system or SMM) to manage this child.
+**/
+EFI_STATUS
+EFIAPI
+PchGpiSmiRegister (
+  IN CONST EFI_SMM_GPI_DISPATCH2_PROTOCOL  *This,
+  IN       EFI_SMM_HANDLER_ENTRY_POINT2    DispatchFunction,
+  IN       EFI_SMM_GPI_REGISTER_CONTEXT    *RegisterContext,
+  OUT      EFI_HANDLE                      *DispatchHandle
+  )
+{
+  EFI_STATUS                  Status;
+  DATABASE_RECORD             Record;
+  GPIO_PAD                    GpioPad;
+  UINT8                       GpiSmiBitOffset;
+  UINT32                      GpiHostSwOwnRegAddress;
+  UINT32                      GpiSmiStsRegAddress;
+  UINT32                      Data32And;
+
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "Register is not allowed if the EndOfDxe event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  Status = GpioGetPadAndSmiRegs (
+             (UINT32) RegisterContext->GpiNum,
+             &GpioPad,
+             &GpiSmiBitOffset,
+             &GpiHostSwOwnRegAddress,
+             &GpiSmiStsRegAddress
+             );
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  ZeroMem (&Record, sizeof (DATABASE_RECORD));
+
+  //
+  // Gather information about the registration request
+  //
+  Record.Callback          = DispatchFunction;
+  Record.ChildContext.Gpi  = *RegisterContext;
+  Record.ProtocolType      = GpiType;
+  Record.Signature         = DATABASE_RECORD_SIGNATURE;
+
+  CopyMem (&Record.SrcDesc, &mPchGpiSourceDescTemplate, sizeof (PCH_SMM_SOURCE_DESC) );
+
+  Record.SrcDesc.Sts[0].Reg.Data.raw = GpiSmiStsRegAddress;  // GPI SMI Status register
+  Record.SrcDesc.Sts[0].Bit = GpiSmiBitOffset;               // Bit position for selected pad
+
+  //
+  // Insert GpiSmi handler to PchSmmCore database
+  //
+  *DispatchHandle = NULL;
+
+  Status = SmmCoreInsertRecord (
+             &Record,
+             DispatchHandle
+             );
+  ASSERT_EFI_ERROR (Status);
+
+  SmiHandlerProfileRegisterHandler (
+    &gEfiSmmGpiDispatch2ProtocolGuid,
+    (EFI_SMM_HANDLER_ENTRY_POINT2) DispatchFunction,
+    (UINTN)RETURN_ADDRESS (0),
+    RegisterContext,
+    sizeof(*RegisterContext)
+    );
+
+  //
+  // Enable GPI SMI
+  // HOSTSW_OWN with respect to generating GPI SMI has negative logic:
+  //  - 0 (ACPI mode) - GPIO pad will be capable of generating SMI/NMI/SCI
+  //  - 1 (GPIO mode) - GPIO pad will not generate SMI/NMI/SCI
+  //
+  Data32And  = (UINT32)~(1u << GpiSmiBitOffset);
+  MmioAnd32 (GpiHostSwOwnRegAddress, Data32And);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Unregister a GPI SMI source dispatch function with a parent SMM driver
+
+  @param[in] This                 Pointer to the EFI_SMM_GPI_DISPATCH2_PROTOCOL instance.
+  @param[in] DispatchHandle       Handle of dispatch function to deregister.
+
+  @retval EFI_SUCCESS             The dispatch function has been successfully
+                                  unregistered and the SMI source has been disabled
+                                  if there are no other registered child dispatch
+                                  functions for this SMI source.
+  @retval EFI_INVALID_PARAMETER   Handle is invalid.
+**/
+EFI_STATUS
+EFIAPI
+PchGpiSmiUnRegister (
+  IN CONST EFI_SMM_GPI_DISPATCH2_PROTOCOL  *This,
+  IN       EFI_HANDLE                      DispatchHandle
+  )
+{
+  EFI_STATUS      Status;
+  DATABASE_RECORD *RecordToDelete;
+  DATABASE_RECORD *RecordInDb;
+  LIST_ENTRY      *LinkInDb;
+  GPIO_PAD        GpioPad;
+  UINT8           GpiSmiBitOffset;
+  UINT32          GpiHostSwOwnRegAddress;
+  UINT32          GpiSmiStsRegAddress;
+  UINT32          Data32Or;
+  UINT32          Data32And;
+  BOOLEAN         DisableGpiSmiSource;
+
+
+  if (DispatchHandle == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  RecordToDelete = DATABASE_RECORD_FROM_LINK (DispatchHandle);
+  if ((RecordToDelete->Signature != DATABASE_RECORD_SIGNATURE) ||
+      (RecordToDelete->ProtocolType != GpiType)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "UnRegister is not allowed if the SmmReadyToLock event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  DisableGpiSmiSource = TRUE;
+  //
+  // Loop through all sources in record linked list to see if any other GPI SMI
+  // is installed on the same pin. If no then disable GPI SMI capability on this pad
+  //
+  LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);
+  while (!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {
+    RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);
+    LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, &RecordInDb->Link);
+    //
+    // If this is the record to delete skip it
+    //
+    if (RecordInDb == RecordToDelete) {
+      continue;
+    }
+    //
+    // Check if record is GPI SMI type
+    //
+    if (RecordInDb->ProtocolType == GpiType) {
+      //
+      // Check if same GPIO pad is the source of this SMI
+      //
+      if (RecordInDb->ChildContext.Gpi.GpiNum == RecordToDelete->ChildContext.Gpi.GpiNum) {
+        DisableGpiSmiSource = FALSE;
+        break;
+      }
+    }
+  }
+
+  if (DisableGpiSmiSource) {
+    GpioGetPadAndSmiRegs (
+      (UINT32) RecordToDelete->ChildContext.Gpi.GpiNum,
+      &GpioPad,
+      &GpiSmiBitOffset,
+      &GpiHostSwOwnRegAddress,
+      &GpiSmiStsRegAddress
+      );
+
+    Data32Or = 1u << GpiSmiBitOffset;
+    Data32And = 0xFFFFFFFF;
+    MmioOr32 (GpiHostSwOwnRegAddress, Data32Or);
+  }
+
+
+  RemoveEntryList (&RecordToDelete->Link);
+  ZeroMem (RecordToDelete, sizeof (DATABASE_RECORD));
+  Status = gSmst->SmmFreePool (RecordToDelete);
+
+  if (EFI_ERROR (Status)) {
+    ASSERT (FALSE);
+    return Status;
+  }
+  SmiHandlerProfileUnregisterHandler (
+    &gEfiSmmGpiDispatch2ProtocolGuid,
+    RecordToDelete->Callback,
+    &RecordToDelete->ChildContext,
+    RecordToDelete->ContextSize
+    );
+  return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmHelpers.c b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmHelpers.c
new file mode 100644
index 0000000000..724a383855
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmHelpers.c
@@ -0,0 +1,332 @@
+/** @file
+  Helper functions for PCH SMM dispatcher.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "PchSmmHelpers.h"
+#include <Register/PmcRegs.h>
+
+///
+/// #define BIT_ZERO 0x00000001
+///
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32  BIT_ZERO = 0x00000001;
+
+///
+/// SUPPORT / HELPER FUNCTIONS (PCH version-independent)
+///
+
+/**
+  Compare 2 SMM source descriptors' enable settings.
+
+  @param[in] Src1                 Pointer to the PCH SMI source description table 1
+  @param[in] Src2                 Pointer to the PCH SMI source description table 2
+
+  @retval TRUE                    The enable settings of the 2 SMM source descriptors are identical.
+  @retval FALSE                   The enable settings of the 2 SMM source descriptors are not identical.
+**/
+BOOLEAN
+CompareEnables (
+  CONST IN PCH_SMM_SOURCE_DESC *Src1,
+  CONST IN PCH_SMM_SOURCE_DESC *Src2
+  )
+{
+  BOOLEAN IsEqual;
+  UINTN   DescIndex;
+
+  IsEqual = TRUE;
+  for (DescIndex = 0; DescIndex < NUM_EN_BITS; DescIndex++) {
+    ///
+    /// It's okay to compare a NULL bit description to a non-NULL bit description.
+    /// They are unequal and these tests will generate the correct result.
+    ///
+    if (Src1->En[DescIndex].Bit != Src2->En[DescIndex].Bit ||
+        Src1->En[DescIndex].Reg.Type != Src2->En[DescIndex].Reg.Type ||
+        Src1->En[DescIndex].Reg.Data.raw != Src2->En[DescIndex].Reg.Data.raw
+        ) {
+      IsEqual = FALSE;
+      break;
+      ///
+      /// out of for loop
+      ///
+    }
+  }
+
+  return IsEqual;
+}
+
+/**
+  Compare a bit descriptor to the enables of source descriptor. Includes null address type.
+
+  @param[in] BitDesc              Pointer to the PCH SMI bit descriptor
+  @param[in] Src                  Pointer to the PCH SMI source description table 2
+
+  @retval TRUE                    The bit desc is equal to any of the enables in source descriptor
+  @retval FALSE                   The bid desc is not equal to all of the enables in source descriptor
+**/
+BOOLEAN
+IsBitEqualToAnySourceEn (
+  CONST IN PCH_SMM_BIT_DESC    *BitDesc,
+  CONST IN PCH_SMM_SOURCE_DESC *Src
+  )
+{
+  BOOLEAN IsEqual;
+  UINTN   DescIndex;
+
+  IsEqual = FALSE;
+
+  for (DescIndex = 0; DescIndex < NUM_EN_BITS; ++DescIndex) {
+    if ((BitDesc->Reg.Type == Src->En[DescIndex].Reg.Type) &&
+        (BitDesc->Reg.Data.raw == Src->En[DescIndex].Reg.Data.raw) &&
+        (BitDesc->Bit == Src->En[DescIndex].Bit)) {
+      IsEqual = TRUE;
+      break;
+    }
+  }
+  return IsEqual;
+}
+
+/**
+  Compare 2 SMM source descriptors' statuses.
+
+  @param[in] Src1                 Pointer to the PCH SMI source description table 1
+  @param[in] Src2                 Pointer to the PCH SMI source description table 2
+
+  @retval TRUE                    The statuses of the 2 SMM source descriptors are identical.
+  @retval FALSE                   The statuses of the 2 SMM source descriptors are not identical.
+**/
+BOOLEAN
+CompareStatuses (
+  CONST IN PCH_SMM_SOURCE_DESC *Src1,
+  CONST IN PCH_SMM_SOURCE_DESC *Src2
+  )
+{
+  BOOLEAN IsEqual;
+  UINTN   DescIndex;
+
+  IsEqual = TRUE;
+
+  for (DescIndex = 0; DescIndex < NUM_STS_BITS; DescIndex++) {
+    ///
+    /// It's okay to compare a NULL bit description to a non-NULL bit description.
+    /// They are unequal and these tests will generate the correct result.
+    ///
+    if (Src1->Sts[DescIndex].Bit != Src2->Sts[DescIndex].Bit ||
+        Src1->Sts[DescIndex].Reg.Type != Src2->Sts[DescIndex].Reg.Type ||
+        Src1->Sts[DescIndex].Reg.Data.raw != Src2->Sts[DescIndex].Reg.Data.raw
+        ) {
+      IsEqual = FALSE;
+      break;
+      ///
+      /// out of for loop
+      ///
+    }
+  }
+
+  return IsEqual;
+}
+
+/**
+  Compare 2 SMM source descriptors, based on Enable settings and Status settings of them.
+
+  @param[in] Src1                 Pointer to the PCH SMI source description table 1
+  @param[in] Src2                 Pointer to the PCH SMI source description table 2
+
+  @retval TRUE                    The 2 SMM source descriptors are identical.
+  @retval FALSE                   The 2 SMM source descriptors are not identical.
+**/
+BOOLEAN
+CompareSources (
+  CONST IN PCH_SMM_SOURCE_DESC *Src1,
+  CONST IN PCH_SMM_SOURCE_DESC *Src2
+  )
+{
+  return (BOOLEAN) (CompareEnables (Src1, Src2) && CompareStatuses (Src1, Src2));
+}
+
+/**
+  Check if an SMM source is active.
+
+  @param[in] Src                  Pointer to the PCH SMI source description table
+  @param[in] SciEn                Indicate if SCI is enabled or not
+  @param[in] SmiEnValue           Value from R_ACPI_IO_SMI_EN
+  @param[in] SmiStsValue          Value from R_ACPI_IO_SMI_STS
+
+  @retval TRUE                    It is active.
+  @retval FALSE                   It is inactive.
+**/
+BOOLEAN
+SourceIsActive (
+  CONST IN PCH_SMM_SOURCE_DESC  *Src,
+  CONST IN BOOLEAN              SciEn,
+  CONST IN UINT32               SmiEnValue,
+  CONST IN UINT32               SmiStsValue
+  )
+{
+  UINTN   DescIndex;
+
+  ///
+  /// This source is dependent on SciEn, and SciEn == 1.  An ACPI OS is present,
+  /// so we shouldn't do anything w/ this source until SciEn == 0.
+  ///
+  if ((Src->Flags == PCH_SMM_SCI_EN_DEPENDENT) && (SciEn)) {
+    return FALSE;
+  }
+
+  ///
+  /// Checking top level SMI status. If the status is not active, return false immediately
+  ///
+  if (!IS_BIT_DESC_NULL (Src->PmcSmiSts)) {
+    if ((Src->PmcSmiSts.Reg.Type == ACPI_ADDR_TYPE) &&
+        (Src->PmcSmiSts.Reg.Data.acpi == R_ACPI_IO_SMI_STS) &&
+        ((SmiStsValue & (1u << Src->PmcSmiSts.Bit)) == 0)) {
+      return FALSE;
+    }
+  }
+
+  ///
+  /// Read each bit desc from hardware and make sure it's a one
+  ///
+  for (DescIndex = 0; DescIndex < NUM_EN_BITS; DescIndex++) {
+    if (!IS_BIT_DESC_NULL (Src->En[DescIndex])) {
+      if ((Src->En[DescIndex].Reg.Type == ACPI_ADDR_TYPE) &&
+          (Src->En[DescIndex].Reg.Data.acpi == R_ACPI_IO_SMI_EN) &&
+          ((SmiEnValue & (1u << Src->En[DescIndex].Bit)) == 0)) {
+        return FALSE;
+      } else if (ReadBitDesc (&Src->En[DescIndex]) == 0) {
+        return FALSE;
+      }
+    }
+  }
+
+  ///
+  /// Read each bit desc from hardware and make sure it's a one
+  ///
+  for (DescIndex = 0; DescIndex < NUM_STS_BITS; DescIndex++) {
+    if (!IS_BIT_DESC_NULL (Src->Sts[DescIndex])) {
+      if ((Src->Sts[DescIndex].Reg.Type == ACPI_ADDR_TYPE) &&
+          (Src->Sts[DescIndex].Reg.Data.acpi == R_ACPI_IO_SMI_STS) &&
+          ((SmiStsValue & (1u << Src->Sts[DescIndex].Bit)) == 0)) {
+        return FALSE;
+      } else if (ReadBitDesc (&Src->Sts[DescIndex]) == 0) {
+        return FALSE;
+      }
+    }
+  }
+
+  return TRUE;
+}
+
+/**
+  Enable the SMI source event by set the SMI enable bit, this function would also clear SMI
+  status bit to make initial state is correct
+
+  @param[in] SrcDesc              Pointer to the PCH SMI source description table
+
+**/
+VOID
+PchSmmEnableSource (
+  CONST PCH_SMM_SOURCE_DESC *SrcDesc
+  )
+{
+  UINTN DescIndex;
+
+  ///
+  /// Set enables to 1 by writing a 1
+  ///
+  for (DescIndex = 0; DescIndex < NUM_EN_BITS; DescIndex++) {
+    if (!IS_BIT_DESC_NULL (SrcDesc->En[DescIndex])) {
+      WriteBitDesc (&SrcDesc->En[DescIndex], 1, FALSE);
+    }
+  }
+  ///
+  /// Clear statuses to 0 by writing a 1
+  ///
+  for (DescIndex = 0; DescIndex < NUM_STS_BITS; DescIndex++) {
+    if (!IS_BIT_DESC_NULL (SrcDesc->Sts[DescIndex])) {
+      WriteBitDesc (&SrcDesc->Sts[DescIndex], 1, TRUE);
+    }
+  }
+}
+
+/**
+  Disable the SMI source event by clear the SMI enable bit
+
+  @param[in] SrcDesc              Pointer to the PCH SMI source description table
+
+**/
+VOID
+PchSmmDisableSource (
+  CONST PCH_SMM_SOURCE_DESC *SrcDesc
+  )
+{
+  UINTN DescIndex;
+
+  for (DescIndex = 0; DescIndex < NUM_EN_BITS; DescIndex++) {
+    if (!IS_BIT_DESC_NULL (SrcDesc->En[DescIndex])) {
+      WriteBitDesc (&SrcDesc->En[DescIndex], 0, FALSE);
+    }
+  }
+}
+
+/**
+  Clear the SMI status bit by set the source bit of SMI status register
+
+  @param[in] SrcDesc              Pointer to the PCH SMI source description table
+
+**/
+VOID
+PchSmmClearSource (
+  CONST PCH_SMM_SOURCE_DESC *SrcDesc
+  )
+{
+  UINTN DescIndex;
+
+  for (DescIndex = 0; DescIndex < NUM_STS_BITS; DescIndex++) {
+    if (!IS_BIT_DESC_NULL (SrcDesc->Sts[DescIndex])) {
+      WriteBitDesc (&SrcDesc->Sts[DescIndex], 1, TRUE);
+    }
+  }
+}
+
+/**
+  Sets the source to a 1 and then waits for it to clear.
+  Be very careful when calling this function -- it will not
+  ASSERT.  An acceptable case to call the function is when
+  waiting for the NEWCENTURY_STS bit to clear (which takes
+  3 RTCCLKs).
+
+  @param[in] SrcDesc              Pointer to the PCH SMI source description table
+
+**/
+VOID
+PchSmmClearSourceAndBlock (
+  CONST PCH_SMM_SOURCE_DESC *SrcDesc
+  )
+{
+  UINTN   DescIndex;
+  BOOLEAN IsSet;
+
+  for (DescIndex = 0; DescIndex < NUM_STS_BITS; DescIndex++) {
+
+    if (!IS_BIT_DESC_NULL (SrcDesc->Sts[DescIndex])) {
+      ///
+      /// Write the bit
+      ///
+      WriteBitDesc (&SrcDesc->Sts[DescIndex], 1, TRUE);
+
+      ///
+      /// Don't return until the bit actually clears.
+      ///
+      IsSet = TRUE;
+      while (IsSet) {
+        IsSet = ReadBitDesc (&SrcDesc->Sts[DescIndex]);
+        ///
+        /// IsSet will eventually clear -- or else we'll have
+        /// an infinite loop.
+        ///
+      }
+    }
+  }
+}
+
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmHelpers.h b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmHelpers.h
new file mode 100644
index 0000000000..93ab8564ff
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmHelpers.h
@@ -0,0 +1,163 @@
+/** @file
+  Helper functions for PCH SMM
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef PCH_SMM_HELPERS_H
+#define PCH_SMM_HELPERS_H
+
+#include "PchSmm.h"
+#include "PchxSmmHelpers.h"
+//
+// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// SUPPORT / HELPER FUNCTIONS (PCH version-independent)
+//
+
+/**
+  Publish SMI Dispatch protocols.
+
+
+**/
+VOID
+PchSmmPublishDispatchProtocols (
+  VOID
+  );
+
+/**
+  Compare 2 SMM source descriptors' enable settings.
+
+  @param[in] Src1                 Pointer to the PCH SMI source description table 1
+  @param[in] Src2                 Pointer to the PCH SMI source description table 2
+
+  @retval TRUE                    The enable settings of the 2 SMM source descriptors are identical.
+  @retval FALSE                   The enable settings of the 2 SMM source descriptors are not identical.
+**/
+BOOLEAN
+CompareEnables (
+  CONST IN PCH_SMM_SOURCE_DESC *Src1,
+  CONST IN PCH_SMM_SOURCE_DESC *Src2
+  );
+
+/**
+  Compare a bit descriptor to the enables of source descriptor. Includes null address type.
+
+  @param[in] BitDesc              Pointer to the PCH SMI bit descriptor
+  @param[in] Src                  Pointer to the PCH SMI source description table 2
+
+  @retval TRUE                    The bit desc is equal to any of the enables in source descriptor
+  @retval FALSE                   The bid desc is not equal to all of the enables in source descriptor
+**/
+BOOLEAN
+IsBitEqualToAnySourceEn (
+  CONST IN PCH_SMM_BIT_DESC    *BitDesc,
+  CONST IN PCH_SMM_SOURCE_DESC *Src
+  );
+
+/**
+  Compare 2 SMM source descriptors' statuses.
+
+  @param[in] Src1                 Pointer to the PCH SMI source description table 1
+  @param[in] Src2                 Pointer to the PCH SMI source description table 2
+
+  @retval TRUE                    The statuses of the 2 SMM source descriptors are identical.
+  @retval FALSE                   The statuses of the 2 SMM source descriptors are not identical.
+**/
+BOOLEAN
+CompareStatuses (
+  CONST IN PCH_SMM_SOURCE_DESC *Src1,
+  CONST IN PCH_SMM_SOURCE_DESC *Src2
+  );
+
+/**
+  Compare 2 SMM source descriptors, based on Enable settings and Status settings of them.
+
+  @param[in] Src1                 Pointer to the PCH SMI source description table 1
+  @param[in] Src2                 Pointer to the PCH SMI source description table 2
+
+  @retval TRUE                    The 2 SMM source descriptors are identical.
+  @retval FALSE                   The 2 SMM source descriptors are not identical.
+**/
+BOOLEAN
+CompareSources (
+  CONST IN PCH_SMM_SOURCE_DESC *Src1,
+  CONST IN PCH_SMM_SOURCE_DESC *Src2
+  );
+
+/**
+  Check if an SMM source is active.
+
+  @param[in] Src                  Pointer to the PCH SMI source description table
+  @param[in] SciEn                Indicate if SCI is enabled or not
+  @param[in] SmiEnValue           Value from R_PCH_SMI_EN
+  @param[in] SmiStsValue          Value from R_PCH_SMI_STS
+
+  @retval TRUE                    It is active.
+  @retval FALSE                   It is inactive.
+**/
+BOOLEAN
+SourceIsActive (
+  CONST IN PCH_SMM_SOURCE_DESC  *Src,
+  CONST IN BOOLEAN              SciEn,
+  CONST IN UINT32               SmiEnValue,
+  CONST IN UINT32               SmiStsValue
+  );
+
+/**
+  Enable the SMI source event by set the SMI enable bit, this function would also clear SMI
+  status bit to make initial state is correct
+
+  @param[in] SrcDesc              Pointer to the PCH SMI source description table
+
+**/
+VOID
+PchSmmEnableSource (
+  CONST PCH_SMM_SOURCE_DESC *SrcDesc
+  );
+
+/**
+  Disable the SMI source event by clear the SMI enable bit
+
+  @param[in] SrcDesc              Pointer to the PCH SMI source description table
+
+**/
+VOID
+PchSmmDisableSource (
+  CONST PCH_SMM_SOURCE_DESC *SrcDesc
+  );
+
+/**
+  Clear the SMI status bit by set the source bit of SMI status register
+
+  @param[in] SrcDesc              Pointer to the PCH SMI source description table
+
+**/
+VOID
+PchSmmClearSource (
+  CONST PCH_SMM_SOURCE_DESC *SrcDesc
+  );
+
+/**
+  Sets the source to a 1 and then waits for it to clear.
+  Be very careful when calling this function -- it will not
+  ASSERT.  An acceptable case to call the function is when
+  waiting for the NEWCENTURY_STS bit to clear (which takes
+  3 RTCCLKs).
+
+  @param[in] SrcDesc              Pointer to the PCH SMI source description table
+
+**/
+VOID
+PchSmmClearSourceAndBlock (
+  CONST PCH_SMM_SOURCE_DESC *SrcDesc
+  );
+
+/**
+  Performs update of SmmUsb descriptors with values that have to be evaluated during runtime.
+**/
+VOID
+PchSmmUsbUpdateDescriptors (
+  VOID
+  );
+
+#endif
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmPeriodicTimer.c b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmPeriodicTimer.c
new file mode 100644
index 0000000000..3078d0c696
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmPeriodicTimer.c
@@ -0,0 +1,670 @@
+/** @file
+  File to contain all the hardware specific stuff for the Periodical Timer dispatch protocol.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "PchSmmHelpers.h"
+#include <Protocol/PchSmmPeriodicTimerControl.h>
+#include <Library/PmcPrivateLib.h>
+
+//
+// There is only one instance for PeriodicTimerCommBuffer.
+// It's safe in SMM since there is no re-entry for the function.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_PERIODIC_TIMER_CONTEXT          mPchPeriodicTimerCommBuffer;
+
+typedef enum {
+  PERIODIC_TIMER= 0,
+  SWSMI_TIMER,
+  NUM_TIMERS
+} SUPPORTED_TIMER;
+
+typedef struct _TIMER_INTERVAL {
+  UINT64  Interval;
+  UINT8   AssociatedTimer;
+} TIMER_INTERVAL;
+
+#define NUM_INTERVALS 8
+
+//
+// Time constants, in 100 nano-second units
+//
+#define TIME_64s    640000000 ///< 64   s
+#define TIME_32s    320000000 ///< 32   s
+#define TIME_16s    160000000 ///< 16   s
+#define TIME_8s     80000000  ///<  8   s
+#define TIME_64ms   640000    ///< 64   ms
+#define TIME_32ms   320000    ///< 32   ms
+#define TIME_16ms   160000    ///< 16   ms
+#define TIME_1_5ms  15000     ///< 1.5  ms
+
+typedef enum {
+  INDEX_TIME_64s  = 0,
+  INDEX_TIME_32s,
+  INDEX_TIME_16s,
+  INDEX_TIME_8s,
+  INDEX_TIME_64ms,
+  INDEX_TIME_32ms,
+  INDEX_TIME_16ms,
+  INDEX_TIME_1_5ms,
+  INDEX_TIME_MAX
+} TIMER_INTERVAL_INDEX;
+
+static TIMER_INTERVAL mSmmPeriodicTimerIntervals[NUM_INTERVALS] = {
+  {
+    TIME_64s,
+    PERIODIC_TIMER
+  },
+  {
+    TIME_32s,
+    PERIODIC_TIMER
+  },
+  {
+    TIME_16s,
+    PERIODIC_TIMER
+  },
+  {
+    TIME_8s,
+    PERIODIC_TIMER
+  },
+  {
+    TIME_64ms,
+    SWSMI_TIMER
+  },
+  {
+    TIME_32ms,
+    SWSMI_TIMER
+  },
+  {
+    TIME_16ms,
+    SWSMI_TIMER
+  },
+  {
+    TIME_1_5ms,
+    SWSMI_TIMER
+  },
+};
+
+typedef struct _TIMER_INFO {
+  UINTN   NumChildren;        ///< number of children using this timer
+  UINT64  MinReqInterval;     ///< minimum interval required by children
+  UINTN   CurrentSetting;     ///< interval this timer is set at right now (index into interval table)
+} TIMER_INFO;
+
+GLOBAL_REMOVE_IF_UNREFERENCED TIMER_INFO          mTimers[NUM_TIMERS];
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mTimerSourceDesc[NUM_TIMERS] = {
+  {
+    PCH_SMM_NO_FLAGS,
+    {
+      {
+        {
+          ACPI_ADDR_TYPE,
+          {R_ACPI_IO_SMI_EN}
+        },
+        S_ACPI_IO_SMI_EN,
+        N_ACPI_IO_SMI_EN_PERIODIC
+      },
+      NULL_BIT_DESC_INITIALIZER
+    },
+    {
+      {
+        {
+          ACPI_ADDR_TYPE,
+          {R_ACPI_IO_SMI_STS}
+        },
+        S_ACPI_IO_SMI_STS,
+        N_ACPI_IO_SMI_STS_PERIODIC
+      }
+    },
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_STS}
+      },
+      S_ACPI_IO_SMI_STS,
+      N_ACPI_IO_SMI_STS_PERIODIC
+    }
+  },
+  {
+    PCH_SMM_NO_FLAGS,
+    {
+      {
+        {
+          ACPI_ADDR_TYPE,
+          {R_ACPI_IO_SMI_EN}
+        },
+        S_ACPI_IO_SMI_EN,
+        N_ACPI_IO_SMI_EN_SWSMI_TMR
+      },
+      NULL_BIT_DESC_INITIALIZER
+    },
+    {
+      {
+        {
+          ACPI_ADDR_TYPE,
+          {R_ACPI_IO_SMI_STS}
+        },
+        S_ACPI_IO_SMI_STS,
+        N_ACPI_IO_SMI_STS_SWSMI_TMR
+      }
+    },
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_STS}
+      },
+      S_ACPI_IO_SMI_STS,
+      N_ACPI_IO_SMI_STS_SWSMI_TMR
+    }
+  }
+};
+
+/**
+  Program Smm Periodic Timer
+
+  @param[in] SrcDesc              Pointer to the PCH_SMM_SOURCE_DESC instance.
+**/
+VOID
+PchSmmPeriodicTimerProgramTimers (
+  IN CONST PCH_SMM_SOURCE_DESC    *SrcDesc
+  );
+
+/**
+  Convert the dispatch context to the timer interval, this function will assert if then either:
+  (1) The context contains an invalid interval
+  (2) The timer interval table is corrupt
+
+  @param[in] DispatchContext      The pointer to the Dispatch Context
+
+  @retval TIMER_INTERVAL          The timer interval of input dispatch context
+**/
+TIMER_INTERVAL *
+ContextToTimerInterval (
+  IN  PCH_SMM_CONTEXT     *DispatchContext
+  )
+{
+  UINTN loopvar;
+
+  ///
+  /// Determine which timer this child is using
+  ///
+  for (loopvar = 0; loopvar < NUM_INTERVALS; loopvar++) {
+    if (((DispatchContext->PeriodicTimer.SmiTickInterval == 0) &&
+         (DispatchContext->PeriodicTimer.Period >= mSmmPeriodicTimerIntervals[loopvar].Interval)) ||
+        (DispatchContext->PeriodicTimer.SmiTickInterval == mSmmPeriodicTimerIntervals[loopvar].Interval)) {
+      return &mSmmPeriodicTimerIntervals[loopvar];
+    }
+  }
+  ///
+  /// If this assertion fires, then either:
+  ///    (1) the context contains an invalid interval
+  ///    (2) the timer interval table is corrupt
+  ///
+  ASSERT (FALSE);
+
+  return NULL;
+}
+
+/**
+  Figure out which timer the child is requesting and
+  send back the source description
+
+  @param[in] DispatchContext      The pointer to the Dispatch Context instances
+  @param[out] SrcDesc             The pointer to the source description
+
+**/
+VOID
+MapPeriodicTimerToSrcDesc (
+  IN  PCH_SMM_CONTEXT             *DispatchContext,
+  OUT PCH_SMM_SOURCE_DESC         *SrcDesc
+  )
+{
+  TIMER_INTERVAL  *TimerInterval;
+
+  ///
+  /// Figure out which timer the child is requesting and
+  /// send back the source description
+  ///
+  TimerInterval = ContextToTimerInterval (DispatchContext);
+  if (TimerInterval == NULL) {
+    return;
+  }
+
+  CopyMem (
+    (VOID *) SrcDesc,
+    (VOID *) (&mTimerSourceDesc[TimerInterval->AssociatedTimer]),
+    sizeof (PCH_SMM_SOURCE_DESC)
+    );
+
+  ///
+  /// Program the value of the interval into hardware
+  ///
+  PchSmmPeriodicTimerProgramTimers (SrcDesc);
+}
+
+/**
+  Update the elapsed time from the Interval data of DATABASE_RECORD
+
+  @param[in] Record               The pointer to the DATABASE_RECORD.
+  @param[out] HwContext           The Context to be updated.
+
+**/
+VOID
+EFIAPI
+PeriodicTimerGetContext (
+  IN  DATABASE_RECORD    *Record,
+  OUT PCH_SMM_CONTEXT    *HwContext
+  )
+{
+  TIMER_INTERVAL  *TimerInterval;
+
+  ASSERT (Record->ProtocolType == PeriodicTimerType);
+
+  TimerInterval = ContextToTimerInterval (&Record->ChildContext);
+  if (TimerInterval == NULL) {
+    return;
+  }
+  ///
+  /// Ignore the hardware context. It's not required for this protocol.
+  /// Instead, just increment the child's context.
+  /// Update the elapsed time w/ the data from our tables
+  ///
+  Record->MiscData.ElapsedTime += mTimers[TimerInterval->AssociatedTimer].MinReqInterval;
+  *HwContext = Record->ChildContext;
+}
+
+/**
+  Check whether Periodic Timer of two contexts match
+
+  @param[in] Context1             Context 1 that includes Periodic Timer  1
+  @param[in] Context2             Context 2 that includes Periodic Timer  2
+
+  @retval FALSE                   Periodic Timer match
+  @retval TRUE                    Periodic Timer don't match
+**/
+BOOLEAN
+EFIAPI
+PeriodicTimerCmpContext (
+  IN PCH_SMM_CONTEXT     *HwContext,
+  IN PCH_SMM_CONTEXT     *ChildContext
+  )
+{
+  DATABASE_RECORD        *Record;
+  Record = DATABASE_RECORD_FROM_CHILDCONTEXT (ChildContext);
+
+  if (!Record->MiscData.TimerSmiEnabled) {
+    return FALSE;
+  }
+  if (Record->MiscData.ElapsedTime >= ChildContext->PeriodicTimer.Period) {
+    ///
+    /// For EDKII, the ElapsedTime is reset when PeriodicTimerGetCommBuffer
+    ///
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+/**
+  Gather the CommBuffer information of SmmPeriodicTimerDispatch2.
+
+  @param[in]  Record              No use
+  @param[out] CommBuffer          Point to the CommBuffer structure
+  @param[out] CommBufferSize      Point to the Size of CommBuffer structure
+
+**/
+VOID
+EFIAPI
+PeriodicTimerGetCommBuffer (
+  IN  DATABASE_RECORD    *Record,
+  OUT VOID               **CommBuffer,
+  OUT UINTN              *CommBufferSize
+  )
+{
+  ASSERT (Record->ProtocolType == PeriodicTimerType);
+
+  mPchPeriodicTimerCommBuffer.ElapsedTime = Record->MiscData.ElapsedTime;
+
+  ///
+  /// For EDKII, the ElapsedTime is reset here
+  ///
+  Record->MiscData.ElapsedTime = 0;
+
+  ///
+  /// Return the CommBuffer
+  ///
+  *CommBuffer = (VOID *) &mPchPeriodicTimerCommBuffer;
+  *CommBufferSize = sizeof (EFI_SMM_PERIODIC_TIMER_CONTEXT);
+}
+
+/**
+  Program Smm Periodic Timer
+
+  @param[in] SrcDesc              Pointer to the PCH_SMM_SOURCE_DESC instance.
+**/
+VOID
+PchSmmPeriodicTimerProgramTimers (
+  IN CONST PCH_SMM_SOURCE_DESC    *SrcDesc
+  )
+{
+  SUPPORTED_TIMER Timer;
+  DATABASE_RECORD *RecordInDb;
+  LIST_ENTRY      *LinkInDb;
+  TIMER_INTERVAL  *TimerInterval;
+
+  ///
+  /// Find the minimum required interval for each timer
+  ///
+  for (Timer = 0; Timer < NUM_TIMERS; Timer++) {
+    mTimers[Timer].MinReqInterval = ~ (UINT64) 0x0;
+    mTimers[Timer].NumChildren    = 0;
+  }
+
+  LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);
+  while (!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {
+    RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);
+    if (RecordInDb->ProtocolType == PeriodicTimerType) {
+      if (RecordInDb->MiscData.TimerSmiEnabled) {
+        ///
+        /// This child is registerd with the PeriodicTimer protocol
+        ///
+        TimerInterval = ContextToTimerInterval (&RecordInDb->ChildContext);
+        if (TimerInterval == NULL) {
+          return;
+        }
+
+        Timer = TimerInterval->AssociatedTimer;
+        if (Timer < 0 || Timer >= NUM_TIMERS) {
+          ASSERT (FALSE);
+          CpuDeadLoop ();
+          return;
+        }
+        if (mTimers[Timer].MinReqInterval > RecordInDb->ChildContext.PeriodicTimer.SmiTickInterval) {
+          mTimers[Timer].MinReqInterval = RecordInDb->ChildContext.PeriodicTimer.SmiTickInterval;
+        }
+        mTimers[Timer].NumChildren++;
+      }
+    }
+    LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, &RecordInDb->Link);
+  }
+  ///
+  /// Program the hardware
+  ///
+  if (mTimers[PERIODIC_TIMER].NumChildren > 0) {
+    switch (mTimers[PERIODIC_TIMER].MinReqInterval) {
+      case TIME_64s:
+        PmcSetPeriodicSmiRate (PmcPeriodicSmiRate64s);
+        mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_64s;
+        break;
+
+      case TIME_32s:
+        PmcSetPeriodicSmiRate (PmcPeriodicSmiRate32s);
+        mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_32s;
+        break;
+
+      case TIME_16s:
+        PmcSetPeriodicSmiRate (PmcPeriodicSmiRate16s);
+        mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_16s;
+        break;
+
+      case TIME_8s:
+        PmcSetPeriodicSmiRate (PmcPeriodicSmiRate8s);
+        mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_8s;
+        break;
+
+      default:
+        ASSERT (FALSE);
+        break;
+    }
+
+    ///
+    /// Restart the timer here, just need to clear the SMI
+    ///
+    if (SrcDesc->Sts[0].Bit == N_ACPI_IO_SMI_STS_PERIODIC) {
+      PchSmmClearSource (&mTimerSourceDesc[PERIODIC_TIMER]);
+    }
+  } else {
+    PchSmmDisableSource (&mTimerSourceDesc[PERIODIC_TIMER]);
+  }
+
+  if (mTimers[SWSMI_TIMER].NumChildren > 0) {
+    switch (mTimers[SWSMI_TIMER].MinReqInterval) {
+      case TIME_64ms:
+        PmcSetSwSmiRate (PmcSwSmiRate64ms);
+        mTimers[SWSMI_TIMER].CurrentSetting = INDEX_TIME_64ms;
+        break;
+
+      case TIME_32ms:
+        PmcSetSwSmiRate (PmcSwSmiRate32ms);
+        mTimers[SWSMI_TIMER].CurrentSetting = INDEX_TIME_32ms;
+        break;
+
+      case TIME_16ms:
+        PmcSetSwSmiRate (PmcSwSmiRate16ms);
+        mTimers[SWSMI_TIMER].CurrentSetting = INDEX_TIME_16ms;
+        break;
+
+      case TIME_1_5ms:
+        PmcSetSwSmiRate (PmcSwSmiRate1p5ms);
+        mTimers[SWSMI_TIMER].CurrentSetting = INDEX_TIME_1_5ms;
+        break;
+
+      default:
+        ASSERT (FALSE);
+        break;
+    }
+
+    ///
+    /// Restart the timer here, need to disable, clear, then enable to restart this timer
+    ///
+    if (SrcDesc->Sts[0].Bit == N_ACPI_IO_SMI_STS_SWSMI_TMR) {
+      PchSmmDisableSource (&mTimerSourceDesc[SWSMI_TIMER]);
+      PchSmmClearSource (&mTimerSourceDesc[SWSMI_TIMER]);
+      PchSmmEnableSource (&mTimerSourceDesc[SWSMI_TIMER]);
+    }
+  } else {
+    PchSmmDisableSource (&mTimerSourceDesc[SWSMI_TIMER]);
+  }
+}
+
+/**
+  This services returns the next SMI tick period that is supported by the chipset.
+  The order returned is from longest to shortest interval period.
+
+  @param[in] This                 Pointer to the EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL instance.
+  @param[in, out] SmiTickInterval Pointer to pointer of the next shorter SMI interval period that is supported by the child.
+
+  @retval EFI_SUCCESS             The service returned successfully.
+  @retval EFI_INVALID_PARAMETER   The parameter SmiTickInterval is invalid.
+**/
+EFI_STATUS
+PchSmmPeriodicTimerDispatchGetNextShorterInterval (
+  IN CONST EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL  *This,
+  IN OUT   UINT64                                     **SmiTickInterval
+  )
+{
+  TIMER_INTERVAL  *IntervalPointer;
+
+  ASSERT (SmiTickInterval != NULL);
+  if (SmiTickInterval == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  IntervalPointer = (TIMER_INTERVAL *) *SmiTickInterval;
+
+  if (IntervalPointer == NULL) {
+    ///
+    /// The first time child requesting an interval
+    ///
+    IntervalPointer = &mSmmPeriodicTimerIntervals[0];
+  } else if (IntervalPointer == &mSmmPeriodicTimerIntervals[NUM_INTERVALS - 1]) {
+    ///
+    /// At end of the list
+    ///
+    IntervalPointer = NULL;
+  } else {
+    if ((IntervalPointer >= &mSmmPeriodicTimerIntervals[0]) &&
+        (IntervalPointer < &mSmmPeriodicTimerIntervals[NUM_INTERVALS - 1])
+        ) {
+      ///
+      /// Get the next interval in the list
+      ///
+      IntervalPointer++;
+    } else {
+      ///
+      /// Input is out of range
+      ///
+      return EFI_INVALID_PARAMETER;
+    }
+  }
+
+  if (IntervalPointer != NULL) {
+    *SmiTickInterval = &IntervalPointer->Interval;
+  } else {
+    *SmiTickInterval = NULL;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  This function is responsible for calculating and enabling any timers that are required
+  to dispatch messages to children. The SrcDesc argument isn't acutally used.
+
+  @param[in] SrcDesc              Pointer to the PCH_SMM_SOURCE_DESC instance.
+
+**/
+VOID
+EFIAPI
+PchSmmPeriodicTimerClearSource (
+  IN CONST PCH_SMM_SOURCE_DESC    *SrcDesc
+  )
+{
+  PchSmmPeriodicTimerProgramTimers (SrcDesc);
+}
+
+
+/**
+  Check if the handle is in type of PeriodicTimer
+
+  @retval TRUE                          The handle is in type of PeriodicTimer.
+  @retval FALSE                         The handle is not in type of PeriodicTimer.
+**/
+BOOLEAN
+IsSmmPeriodicTimerHandle (
+  IN EFI_HANDLE                         DispatchHandle
+  )
+{
+  DATABASE_RECORD                       *RecordInDb;
+  LIST_ENTRY                            *LinkInDb;
+
+  LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);
+  while (!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {
+    if (DispatchHandle == (EFI_HANDLE) LinkInDb) {
+      RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);
+      if (RecordInDb->ProtocolType == PeriodicTimerType) {
+        return TRUE;
+      }
+    }
+    LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, LinkInDb);
+  }
+  return FALSE;
+}
+
+/**
+  Pause SMM periodic timer callback function.
+
+  This function disable the SMI enable of SMI timer according to the DispatchHandle,
+  which is returned by SMM periodic timer callback registration.
+
+  @retval EFI_SUCCESS                   This operation is complete.
+  @retval EFI_INVALID_PARAMETER         The DispatchHandle is invalid.
+**/
+EFI_STATUS
+EFIAPI
+PchSmmPeriodicTimerControlPause (
+  IN PCH_SMM_PERIODIC_TIMER_CONTROL_PROTOCOL      *This,
+  IN EFI_HANDLE                                   DispatchHandle
+  )
+{
+  DATABASE_RECORD                       *RecordInDb;
+
+  if (IsSmmPeriodicTimerHandle (DispatchHandle) == FALSE) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  RecordInDb = DATABASE_RECORD_FROM_LINK (DispatchHandle);
+  RecordInDb->MiscData.TimerSmiEnabled = FALSE;
+  //
+  // reset the timer interval per SMI trigger due to stop a periodic timer SMI
+  //
+  PchSmmPeriodicTimerProgramTimers (&RecordInDb->SrcDesc);
+  return EFI_SUCCESS;
+}
+
+/**
+  Resume SMM periodic timer callback function.
+
+  This function enable the SMI enable of SMI timer according to the DispatchHandle,
+  which is returned by SMM periodic timer callback registration.
+
+  @retval EFI_SUCCESS                   This operation is complete.
+  @retval EFI_INVALID_PARAMETER         The DispatchHandle is invalid.
+**/
+EFI_STATUS
+EFIAPI
+PchSmmPeriodicTimerControlResume (
+  IN PCH_SMM_PERIODIC_TIMER_CONTROL_PROTOCOL      *This,
+  IN EFI_HANDLE                                   DispatchHandle
+  )
+{
+  DATABASE_RECORD                       *RecordInDb;
+
+  if (IsSmmPeriodicTimerHandle (DispatchHandle) == FALSE) {
+    return EFI_INVALID_PARAMETER;
+  }
+  RecordInDb = DATABASE_RECORD_FROM_LINK (DispatchHandle);
+  RecordInDb->MiscData.TimerSmiEnabled = TRUE;
+  //
+  // reset the timer interval per SMI trigger due to resume a periodic timer SMI
+  //
+  PchSmmPeriodicTimerProgramTimers (&RecordInDb->SrcDesc);
+  return EFI_SUCCESS;
+}
+
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_SMM_PERIODIC_TIMER_CONTROL_PROTOCOL mPchSmmPeriodicTimerControlProtocol = {
+  PchSmmPeriodicTimerControlPause,
+  PchSmmPeriodicTimerControlResume
+};
+
+/**
+  Install PCH SMM periodic timer control protocol
+
+  @param[in] Handle                     handle for this driver
+
+  @retval EFI_SUCCESS                   Driver initialization completed successfully
+**/
+EFI_STATUS
+EFIAPI
+InstallPchSmmPeriodicTimerControlProtocol (
+  IN EFI_HANDLE                         Handle
+  )
+{
+  EFI_STATUS                            Status;
+
+  //
+  // Install protocol interface
+  //
+  Status = gSmst->SmmInstallProtocolInterface (
+                    &Handle,
+                    &gPchSmmPeriodicTimerControlGuid,
+                    EFI_NATIVE_INTERFACE,
+                    &mPchSmmPeriodicTimerControlProtocol
+                    );
+  ASSERT_EFI_ERROR (Status);
+
+  return EFI_SUCCESS;
+}
+
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmPowerButton.c b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmPowerButton.c
new file mode 100644
index 0000000000..e6d3bf012f
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmPowerButton.c
@@ -0,0 +1,77 @@
+/** @file
+  File to contain all the hardware specific stuff for the Smm Power Button dispatch protocol.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <PchSmmHelpers.h>
+#include <Library/PmcPrivateLib.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mPowerButtonSourceDesc = {
+  PCH_SMM_SCI_EN_DEPENDENT,
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_PM1_EN}
+      },
+      S_ACPI_IO_PM1_EN,
+      N_ACPI_IO_PM1_EN_PWRBTN
+    },
+    NULL_BIT_DESC_INITIALIZER
+  },
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_PM1_STS}
+      },
+      S_ACPI_IO_PM1_STS,
+      N_ACPI_IO_PM1_STS_PWRBTN
+    }
+  },
+  {
+    {
+      ACPI_ADDR_TYPE,
+      {R_ACPI_IO_SMI_STS}
+    },
+    S_ACPI_IO_SMI_STS,
+    N_ACPI_IO_SMI_STS_PM1_STS_REG
+  }
+};
+
+/**
+  Get the power button status.
+
+  @param[in] Record               The pointer to the DATABASE_RECORD.
+  @param[out] Context             Calling context from the hardware, will be updated with the current power button status.
+
+**/
+VOID
+EFIAPI
+PowerButtonGetContext (
+  IN  DATABASE_RECORD    *Record,
+  OUT PCH_SMM_CONTEXT    *Context
+  )
+{
+  return;
+}
+
+/**
+  Check whether Power Button status of two contexts match
+
+  @param[in] Context1             Context 1 that includes Power Button status 1
+  @param[in] Context2             Context 2 that includes Power Button status 2
+
+  @retval FALSE                   Power Button status match
+  @retval TRUE                    Power Button status don't match
+**/
+BOOLEAN
+EFIAPI
+PowerButtonCmpContext (
+  IN PCH_SMM_CONTEXT     *Context1,
+  IN PCH_SMM_CONTEXT     *Context2
+  )
+{
+ return TRUE;
+}
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmSw.c b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmSw.c
new file mode 100644
index 0000000000..311a21820c
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmSw.c
@@ -0,0 +1,381 @@
+/** @file
+  File to contain all the hardware specific stuff for the Smm Sw dispatch protocol.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "PchSmmHelpers.h"
+#include <Protocol/SmmCpu.h>
+#include <Register/PchRegsLpc.h>
+#include <Register/PmcRegs.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_CPU_PROTOCOL          *mSmmCpuProtocol;
+
+STATIC LIST_ENTRY                       mSwSmiCallbackDataBase;
+
+//
+// "SWSMI" RECORD
+// Linked list data structures
+//
+#define SW_SMI_RECORD_SIGNATURE         SIGNATURE_32 ('S', 'W', 'S', 'M')
+
+#define SW_SMI_RECORD_FROM_LINK(_record)  CR (_record, SW_SMI_RECORD, Link, SW_SMI_RECORD_SIGNATURE)
+
+typedef struct {
+  UINT32                                Signature;
+  LIST_ENTRY                            Link;
+  EFI_SMM_SW_REGISTER_CONTEXT           Context;
+  EFI_SMM_HANDLER_ENTRY_POINT2          Callback;
+} SW_SMI_RECORD;
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSwSourceDesc = {
+  PCH_SMM_NO_FLAGS,
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_EN}
+      },
+      S_ACPI_IO_SMI_EN,
+      N_ACPI_IO_SMI_EN_APMC
+    },
+    NULL_BIT_DESC_INITIALIZER
+  },
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_STS}
+      },
+      S_ACPI_IO_SMI_STS,
+      N_ACPI_IO_SMI_STS_APM
+    }
+  },
+  {
+    {
+      ACPI_ADDR_TYPE,
+      {R_ACPI_IO_SMI_STS}
+    },
+    S_ACPI_IO_SMI_STS,
+    N_ACPI_IO_SMI_STS_APM
+  }
+};
+
+/**
+  Check the SwSmiInputValue to see if there is a duplicated one in the database
+
+  @param[in] SwSmiInputValue      SwSmiInputValue
+
+  @retval EFI_SUCCESS             There is no duplicated SwSmiInputValue
+  @retval EFI_INVALID_PARAMETER   There is a duplicated SwSmiInputValue
+**/
+EFI_STATUS
+SmiInputValueDuplicateCheck (
+  IN UINTN  SwSmiInputValue
+  )
+{
+  SW_SMI_RECORD   *SwSmiRecord;
+  LIST_ENTRY      *LinkInDb;
+
+  LinkInDb = GetFirstNode (&mSwSmiCallbackDataBase);
+  while (!IsNull (&mSwSmiCallbackDataBase, LinkInDb)) {
+    SwSmiRecord = SW_SMI_RECORD_FROM_LINK (LinkInDb);
+    if (SwSmiRecord->Context.SwSmiInputValue == SwSmiInputValue) {
+      return EFI_INVALID_PARAMETER;
+    }
+    LinkInDb = GetNextNode (&mSwSmiCallbackDataBase, &SwSmiRecord->Link);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Register a child SMI source dispatch function for the specified software SMI.
+
+  This service registers a function (DispatchFunction) which will be called when the software
+  SMI source specified by RegisterContext->SwSmiCpuIndex is detected. On return,
+  DispatchHandle contains a unique handle which may be used later to unregister the function
+  using UnRegister().
+
+  @param[in]  This                 Pointer to the EFI_SMM_SW_DISPATCH2_PROTOCOL instance.
+  @param[in]  DispatchFunction     Function to register for handler when the specified software
+                                   SMI is generated.
+  @param[in, out] RegisterContext  Pointer to the dispatch function's context.
+                                   The caller fills this context in before calling
+                                   the register function to indicate to the register
+                                   function which Software SMI input value the
+                                   dispatch function should be invoked for.
+  @param[out] DispatchHandle       Handle generated by the dispatcher to track the
+                                   function instance.
+
+  @retval EFI_SUCCESS            The dispatch function has been successfully
+                                 registered and the SMI source has been enabled.
+  @retval EFI_DEVICE_ERROR       The SW driver was unable to enable the SMI source.
+  @retval EFI_INVALID_PARAMETER  RegisterContext is invalid. The SW SMI input value
+                                 is not within a valid range or is already in use.
+  @retval EFI_OUT_OF_RESOURCES   There is not enough memory (system or SMM) to manage this
+                                 child.
+  @retval EFI_OUT_OF_RESOURCES   A unique software SMI value could not be assigned
+                                 for this dispatch.
+**/
+EFI_STATUS
+EFIAPI
+PchSwSmiRegister (
+  IN  EFI_SMM_SW_DISPATCH2_PROTOCOL       *This,
+  IN  EFI_SMM_HANDLER_ENTRY_POINT2        DispatchFunction,
+  IN  EFI_SMM_SW_REGISTER_CONTEXT         *DispatchContext,
+  OUT EFI_HANDLE                          *DispatchHandle
+  )
+{
+  EFI_STATUS       Status;
+  SW_SMI_RECORD    *SwSmiRecord;
+  UINTN            Index;
+
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  //
+  // Find available SW SMI value if the input is -1
+  //
+  if (DispatchContext->SwSmiInputValue == (UINTN) -1) {
+    for (Index = 1; Index < MAXIMUM_SWI_VALUE; Index++) {
+      if (!EFI_ERROR (SmiInputValueDuplicateCheck (Index))) {
+        DispatchContext->SwSmiInputValue = Index;
+        break;
+      }
+    }
+    if (DispatchContext->SwSmiInputValue == (UINTN) -1) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+  }
+  //
+  // Check if it's a valid SW SMI value.
+  // The value must not bigger than 0xFF.
+  // And the value must not be 0xFF sincie it's used for SmmControll protocol.
+  //
+  if (DispatchContext->SwSmiInputValue >= MAXIMUM_SWI_VALUE) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (EFI_ERROR (SmiInputValueDuplicateCheck (DispatchContext->SwSmiInputValue))) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Create database record and add to database
+  //
+  Status = gSmst->SmmAllocatePool (
+                    EfiRuntimeServicesData,
+                    sizeof (SW_SMI_RECORD),
+                    (VOID **) &SwSmiRecord
+                    );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Failed to allocate memory for SwSmiRecord! \n"));
+    return EFI_OUT_OF_RESOURCES;
+  }
+  //
+  // Gather information about the registration request
+  //
+  SwSmiRecord->Signature               = SW_SMI_RECORD_SIGNATURE;
+  SwSmiRecord->Context.SwSmiInputValue = DispatchContext->SwSmiInputValue;
+  SwSmiRecord->Callback                = DispatchFunction;
+  //
+  // Publish the S/W SMI numbers in Serial logs used for Debug build.
+  //
+  DEBUG ((DEBUG_INFO, "SW SMI NUM %x  Sw Record at Address 0x%X\n", SwSmiRecord->Context.SwSmiInputValue, SwSmiRecord));
+
+  InsertTailList (&mSwSmiCallbackDataBase, &SwSmiRecord->Link);
+
+  //
+  // Child's handle will be the address linked list link in the record
+  //
+  *DispatchHandle = (EFI_HANDLE) (&SwSmiRecord->Link);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Unregister a child SMI source dispatch function for the specified software SMI.
+
+  This service removes the handler associated with DispatchHandle so that it will no longer be
+  called in response to a software SMI.
+
+  @param[in] This                Pointer to the EFI_SMM_SW_DISPATCH2_PROTOCOL instance.
+  @param[in] DispatchHandle      Handle of dispatch function to deregister.
+
+  @retval EFI_SUCCESS            The dispatch function has been successfully unregistered.
+  @retval EFI_INVALID_PARAMETER  The DispatchHandle was not valid.
+**/
+EFI_STATUS
+EFIAPI
+PchSwSmiUnRegister (
+  IN CONST EFI_SMM_SW_DISPATCH2_PROTOCOL  *This,
+  IN       EFI_HANDLE                     DispatchHandle
+  )
+{
+  EFI_STATUS            Status;
+  SW_SMI_RECORD         *RecordToDelete;
+
+  if (DispatchHandle == 0) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Return access denied if the SmmReadyToLock event has been triggered
+  //
+  if (mReadyToLock == TRUE) {
+    DEBUG ((DEBUG_ERROR, "UnRegister is not allowed if the SmmReadyToLock event has been triggered! \n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  RecordToDelete = SW_SMI_RECORD_FROM_LINK (DispatchHandle);
+  //
+  // Take the entry out of the linked list
+  //
+  if (RecordToDelete->Signature != SW_SMI_RECORD_SIGNATURE) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  RemoveEntryList (&RecordToDelete->Link);
+  ZeroMem (RecordToDelete, sizeof (SW_SMI_RECORD));
+  Status = gSmst->SmmFreePool (RecordToDelete);
+  ASSERT_EFI_ERROR (Status);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Main entry point for an SMM handler dispatch or communicate-based callback.
+
+  @param[in]     DispatchHandle  The unique handle assigned to this handler by SmiHandlerRegister().
+  @param[in]     Context         Points to an optional handler context which was specified when the
+                                 handler was registered.
+  @param[in,out] CommBuffer      A pointer to a collection of data in memory that will
+                                 be conveyed from a non-SMM environment into an SMM environment.
+  @param[in,out] CommBufferSize  The size of the CommBuffer.
+
+  @retval EFI_SUCCESS                         The interrupt was handled and quiesced. No other handlers
+                                              should still be called.
+  @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED  The interrupt has been quiesced but other handlers should
+                                              still be called.
+  @retval EFI_WARN_INTERRUPT_SOURCE_PENDING   The interrupt is still pending and other handlers should still
+                                              be called.
+  @retval EFI_INTERRUPT_PENDING               The interrupt could not be quiesced.
+**/
+EFI_STATUS
+EFIAPI
+PchSwSmiDispatcher (
+  IN       EFI_HANDLE         DispatchHandle,
+  IN CONST VOID               *Context,
+  IN OUT   VOID               *CommBuffer,
+  IN OUT   UINTN              *CommBufferSize
+  )
+{
+  EFI_STATUS                            Status;
+  EFI_SMM_SAVE_STATE_IO_INFO            SmiIoInfo;
+  UINTN                                 CpuIndex;
+  SW_SMI_RECORD                         *SwSmiRecord;
+  LIST_ENTRY                            *LinkInDb;
+  EFI_SMM_SW_CONTEXT                    SwSmiCommBuffer;
+  UINTN                                 SwSmiCommBufferSize;
+
+  SwSmiCommBufferSize      = sizeof (EFI_SMM_SW_CONTEXT);
+  //
+  // The value in DataPort might not be accurate in multiple thread environment.
+  // There might be racing condition for R_PCH_IO_APM_STS port.
+  // Therefor, this is just for reference.
+  //
+  SwSmiCommBuffer.DataPort = IoRead8 (R_PCH_IO_APM_STS);
+
+  for (CpuIndex = 0; CpuIndex < gSmst->NumberOfCpus; CpuIndex++) {
+    Status = mSmmCpuProtocol->ReadSaveState (
+                                mSmmCpuProtocol,
+                                sizeof (EFI_SMM_SAVE_STATE_IO_INFO),
+                                EFI_SMM_SAVE_STATE_REGISTER_IO,
+                                CpuIndex,
+                                &SmiIoInfo
+                                );
+    //
+    // If this is not the SMI source, skip it.
+    //
+    if (EFI_ERROR (Status)) {
+      continue;
+    }
+    //
+    // If the IO address is not "BYTE" "WRITE" to "R_PCH_IO_APM_CNT (0xB2)", skip it.
+    //
+    if ((SmiIoInfo.IoPort != R_PCH_IO_APM_CNT) ||
+        (SmiIoInfo.IoType != EFI_SMM_SAVE_STATE_IO_TYPE_OUTPUT) ||
+        (SmiIoInfo.IoWidth != EFI_SMM_SAVE_STATE_IO_WIDTH_UINT8))
+    {
+      continue;
+    }
+    //
+    // If the IO data is used for SmmControl protocol, skip it.
+    //
+    if (SmiIoInfo.IoData == 0xFF) {
+      continue;
+    }
+
+    SwSmiCommBuffer.SwSmiCpuIndex = CpuIndex;
+    SwSmiCommBuffer.CommandPort   = (UINT8) SmiIoInfo.IoData;
+
+    LinkInDb = GetFirstNode (&mSwSmiCallbackDataBase);
+    while (!IsNull (&mSwSmiCallbackDataBase, LinkInDb)) {
+      SwSmiRecord = SW_SMI_RECORD_FROM_LINK (LinkInDb);
+      if (SwSmiRecord->Context.SwSmiInputValue == SmiIoInfo.IoData) {
+        SwSmiRecord->Callback ((EFI_HANDLE) &SwSmiRecord->Link, &SwSmiRecord->Context, &SwSmiCommBuffer, &SwSmiCommBufferSize);
+      }
+      LinkInDb = GetNextNode (&mSwSmiCallbackDataBase, &SwSmiRecord->Link);
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Init required protocol for Pch Sw Dispatch protocol.
+**/
+VOID
+PchSwDispatchInit (
+  VOID
+  )
+{
+  EFI_STATUS                            Status;
+  EFI_HANDLE                            DispatchHandle;
+  DATABASE_RECORD                       Record;
+
+  //
+  // Locate PI SMM CPU protocol
+  //
+  Status = gSmst->SmmLocateProtocol (&gEfiSmmCpuProtocolGuid, NULL, (VOID **)&mSmmCpuProtocol);
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Initialize SW SMI Callback DataBase
+  //
+  InitializeListHead (&mSwSmiCallbackDataBase);
+
+  //
+  // Insert SwSmi handler to PchSmmCore database
+  // There will always be one SwType record in PchSmmCore database
+  //
+  ZeroMem (&Record, sizeof (DATABASE_RECORD));
+  Record.Signature    = DATABASE_RECORD_SIGNATURE;
+  Record.Callback     = PchSwSmiDispatcher;
+  Record.ProtocolType = SwType;
+
+  CopyMem (&Record.SrcDesc, &mSwSourceDesc, sizeof (PCH_SMM_SOURCE_DESC));
+
+  DispatchHandle      = NULL;
+  Status = SmmCoreInsertRecord (
+             &Record,
+             &DispatchHandle
+             );
+  ASSERT_EFI_ERROR (Status);
+}
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmSx.c b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmSx.c
new file mode 100644
index 0000000000..798fb33347
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmSx.c
@@ -0,0 +1,117 @@
+/** @file
+  File to contain all the hardware specific stuff for the Smm Sx dispatch protocol.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "PchSmmHelpers.h"
+#include <Register/PmcRegs.h>
+#include "PchSmiHelper.h"
+
+extern BOOLEAN               mS3SusStart;
+#define PROGRESS_CODE_S3_SUSPEND_END  PcdGet32 (PcdProgressCodeS3SuspendEnd)
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSxSourceDesc = {
+  PCH_SMM_NO_FLAGS,
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_EN}
+      },
+      S_ACPI_IO_SMI_EN,
+      N_ACPI_IO_SMI_EN_ON_SLP_EN
+    },
+    NULL_BIT_DESC_INITIALIZER
+  },
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_STS}
+      },
+      S_ACPI_IO_SMI_STS,
+      N_ACPI_IO_SMI_STS_ON_SLP_EN
+    }
+  },
+  {
+    {
+      ACPI_ADDR_TYPE,
+      {R_ACPI_IO_SMI_STS}
+    },
+    S_ACPI_IO_SMI_STS,
+    N_ACPI_IO_SMI_STS_ON_SLP_EN
+  }
+};
+
+/**
+  Get the Sleep type
+
+  @param[in] Record               No use
+  @param[out] Context             The context that includes SLP_TYP bits to be filled
+
+**/
+VOID
+EFIAPI
+SxGetContext (
+  IN  DATABASE_RECORD    *Record,
+  OUT PCH_SMM_CONTEXT    *Context
+  )
+{
+  UINT32  Pm1Cnt;
+
+  Pm1Cnt = IoRead32 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_PM1_CNT));
+
+  ///
+  /// By design, the context phase will always be ENTRY
+  ///
+  Context->Sx.Phase = SxEntry;
+
+  ///
+  /// Map the PM1_CNT register's SLP_TYP bits to the context type
+  ///
+  switch (Pm1Cnt & B_ACPI_IO_PM1_CNT_SLP_TYP) {
+    case V_ACPI_IO_PM1_CNT_S0:
+      Context->Sx.Type = SxS0;
+      break;
+
+    case V_ACPI_IO_PM1_CNT_S1:
+      Context->Sx.Type = SxS1;
+      break;
+
+    case V_ACPI_IO_PM1_CNT_S3:
+      Context->Sx.Type = SxS3;
+      break;
+
+    case V_ACPI_IO_PM1_CNT_S4:
+      Context->Sx.Type = SxS4;
+      break;
+
+    case V_ACPI_IO_PM1_CNT_S5:
+      Context->Sx.Type = SxS5;
+      break;
+
+    default:
+      ASSERT (FALSE);
+      break;
+  }
+}
+
+/**
+  Check whether sleep type of two contexts match
+
+  @param[in] Context1             Context 1 that includes sleep type 1
+  @param[in] Context2             Context 2 that includes sleep type 2
+
+  @retval FALSE                   Sleep types match
+  @retval TRUE                    Sleep types don't match
+**/
+BOOLEAN
+EFIAPI
+SxCmpContext (
+  IN PCH_SMM_CONTEXT     *Context1,
+  IN PCH_SMM_CONTEXT     *Context2
+  )
+{
+  return (BOOLEAN) (Context1->Sx.Type == Context2->Sx.Type);
+}
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmUsb.c b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmUsb.c
new file mode 100644
index 0000000000..6b23956c4a
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmUsb.c
@@ -0,0 +1,244 @@
+/** @file
+  File to contain all the hardware specific stuff for the Smm USB dispatch protocol.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "PchSmmHelpers.h"
+#include <Register/PmcRegs.h>
+#include <Library/PchPciBdfLib.h>
+
+typedef enum {
+  PchUsbControllerLpc0 = 0,
+  PchUsbControllerXhci,
+  PchUsbControllerTypeMax
+} PCH_USB_CONTROLLER_TYPE;
+
+typedef struct {
+  UINT8                   Function;
+  UINT8                   Device;
+  PCH_USB_CONTROLLER_TYPE UsbConType;
+} PCH_USB_CONTROLLER;
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mUsb1Legacy = {
+  PCH_SMM_NO_FLAGS,
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_EN}
+      },
+      S_ACPI_IO_SMI_EN,
+      N_ACPI_IO_SMI_EN_LEGACY_USB
+    },
+    NULL_BIT_DESC_INITIALIZER
+  },
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_STS}
+      },
+      S_ACPI_IO_SMI_STS,
+      N_ACPI_IO_SMI_STS_LEGACY_USB
+    }
+  },
+  {
+    {
+      ACPI_ADDR_TYPE,
+      {R_ACPI_IO_SMI_STS}
+    },
+    S_ACPI_IO_SMI_STS,
+    N_ACPI_IO_SMI_STS_LEGACY_USB
+  }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mUsb3Legacy = {
+  PCH_SMM_NO_FLAGS,
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_EN}
+      },
+      S_ACPI_IO_SMI_EN,
+      N_ACPI_IO_SMI_EN_LEGACY_USB3
+    },
+    NULL_BIT_DESC_INITIALIZER
+  },
+  {
+    {
+      {
+        ACPI_ADDR_TYPE,
+        {R_ACPI_IO_SMI_STS}
+      },
+      S_ACPI_IO_SMI_STS,
+      N_ACPI_IO_SMI_STS_LEGACY_USB3
+    }
+  },
+  {
+    {
+      ACPI_ADDR_TYPE,
+      {R_ACPI_IO_SMI_STS}
+    },
+    S_ACPI_IO_SMI_STS,
+    N_ACPI_IO_SMI_STS_LEGACY_USB3
+  }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_USB_CONTROLLER  mUsbControllersMap[] = {
+  {
+    0xFF, // to be updated in PchSmmUsbUpdateDescriptors
+    0xFF, // to be updated in PchSmmUsbUpdateDescriptors
+    PchUsbControllerLpc0
+  },
+  {
+    0xFF, // to be updated in PchSmmUsbUpdateDescriptors
+    0xFF, // to be updated in PchSmmUsbUpdateDescriptors
+    PchUsbControllerXhci
+  }
+};
+
+/**
+  Performs update of SmmUsb descriptors with values that have to be evaluated during runtime.
+**/
+VOID
+PchSmmUsbUpdateDescriptors (
+  VOID
+  )
+{
+  //
+  // mUsbControllersMap
+  //
+  mUsbControllersMap[0].Function  = LpcFuncNumber ();
+  mUsbControllersMap[0].Device    = LpcDevNumber ();
+  mUsbControllersMap[1].Function  = PchXhciFuncNumber ();
+  mUsbControllersMap[1].Device    = PchXhciDevNumber ();
+}
+
+/**
+  Find the handle that best matches the input Device Path and return the USB controller type
+
+  @param[in] DevicePath           Pointer to the device Path table
+  @param[out] Controller          Returned with the USB controller type of the input device path
+
+  @retval EFI_SUCCESS             Find the handle that best matches the input Device Path
+  @exception EFI_UNSUPPORTED      Invalid device Path table or can't find any match USB device path
+                                  PCH_USB_CONTROLLER_TYPE The USB controller type of the input
+                                  device path
+**/
+EFI_STATUS
+DevicePathToSupportedController (
+  IN  EFI_DEVICE_PATH_PROTOCOL   *DevicePath,
+  OUT PCH_USB_CONTROLLER_TYPE    *Controller
+  )
+{
+  EFI_STATUS                Status;
+  EFI_HANDLE                DeviceHandle;
+  ACPI_HID_DEVICE_PATH      *AcpiNode;
+  PCI_DEVICE_PATH           *PciNode;
+  EFI_DEVICE_PATH_PROTOCOL  *RemaingDevicePath;
+  UINT8                     UsbIndex;
+  ///
+  /// Find the handle that best matches the Device Path. If it is only a
+  /// partial match the remaining part of the device path is returned in
+  /// RemainingDevicePath.
+  ///
+  RemaingDevicePath = DevicePath;
+  Status = gBS->LocateDevicePath (
+                  &gEfiPciRootBridgeIoProtocolGuid,
+                  &DevicePath,
+                  &DeviceHandle
+                  );
+  if (EFI_ERROR (Status)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  DevicePath = RemaingDevicePath;
+
+  ///
+  /// Get first node: Acpi Node
+  ///
+  AcpiNode = (ACPI_HID_DEVICE_PATH *) RemaingDevicePath;
+
+  if (AcpiNode->Header.Type != ACPI_DEVICE_PATH ||
+      AcpiNode->Header.SubType != ACPI_DP ||
+      DevicePathNodeLength (&AcpiNode->Header) != sizeof (ACPI_HID_DEVICE_PATH) ||
+      AcpiNode->HID != EISA_PNP_ID (0x0A03) ||
+      AcpiNode->UID != 0
+      ) {
+    return EFI_UNSUPPORTED;
+  } else {
+    ///
+    /// Get the next node: Pci Node
+    ///
+    RemaingDevicePath = NextDevicePathNode (RemaingDevicePath);
+    PciNode           = (PCI_DEVICE_PATH *) RemaingDevicePath;
+    if (PciNode->Header.Type != HARDWARE_DEVICE_PATH ||
+        PciNode->Header.SubType != HW_PCI_DP ||
+        DevicePathNodeLength (&PciNode->Header) != sizeof (PCI_DEVICE_PATH)
+        ) {
+      return EFI_UNSUPPORTED;
+    }
+
+    for (UsbIndex = 0; UsbIndex < sizeof (mUsbControllersMap) / sizeof (PCH_USB_CONTROLLER); UsbIndex++) {
+      if ((PciNode->Device == mUsbControllersMap[UsbIndex].Device) &&
+          (PciNode->Function == mUsbControllersMap[UsbIndex].Function)) {
+        *Controller = mUsbControllersMap[UsbIndex].UsbConType;
+        return EFI_SUCCESS;
+      }
+    }
+
+    return EFI_UNSUPPORTED;
+  }
+}
+
+/**
+  Maps a USB context to a source description.
+
+  @param[in] Context              The context we need to map.  Type must be USB.
+  @param[in] SrcDesc              The source description that corresponds to the given context.
+
+**/
+VOID
+MapUsbToSrcDesc (
+  IN  PCH_SMM_CONTEXT         *Context,
+  OUT PCH_SMM_SOURCE_DESC     *SrcDesc
+  )
+{
+  PCH_USB_CONTROLLER_TYPE Controller;
+  EFI_STATUS              Status;
+
+  Status = DevicePathToSupportedController (Context->Usb.Device, &Controller);
+  ///
+  /// Either the device path passed in by the child is incorrect or
+  /// the ones stored here internally are incorrect.
+  ///
+  ASSERT_EFI_ERROR (Status);
+
+  switch (Context->Usb.Type) {
+    case UsbLegacy:
+      switch (Controller) {
+        case PchUsbControllerLpc0:
+          CopyMem ((VOID *) SrcDesc, (VOID *) (&mUsb1Legacy), sizeof (PCH_SMM_SOURCE_DESC));
+          break;
+
+        case PchUsbControllerXhci:
+          CopyMem ((VOID *) SrcDesc, (VOID *) (&mUsb3Legacy), sizeof (PCH_SMM_SOURCE_DESC));
+          break;
+
+        default:
+          ASSERT (FALSE);
+          break;
+      }
+      break;
+
+    case UsbWake:
+      ASSERT (FALSE);
+      break;
+
+    default:
+      ASSERT (FALSE);
+      break;
+  }
+}
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.c b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.c
new file mode 100644
index 0000000000..c0ce5785fd
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.c
@@ -0,0 +1,682 @@
+/** @file
+  This driver is responsible for the registration of child drivers
+  and the abstraction of the PCH SMI sources.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "PchSmmHelpers.h"
+#include <Register/PchRegs.h>
+#include <Register/PmcRegs.h>
+#include <Register/TcoRegs.h>
+
+extern UINT32 mTco1StsClear;
+//
+// Help handle porting bit shifts to IA-64.
+//
+#define BIT_ZERO  0x00000001
+
+/**
+  Publish SMI Dispatch protocols.
+
+
+**/
+VOID
+PchSmmPublishDispatchProtocols (
+  VOID
+  )
+{
+  EFI_STATUS Status = EFI_SUCCESS;
+  UINTN      Index;
+  //
+  // Install protocol interfaces.
+  //
+  for (Index = 0; Index < PCH_SMM_PROTOCOL_TYPE_MAX; Index++) {
+    Status = gSmst->SmmInstallProtocolInterface (
+                      &mPrivateData.InstallMultProtHandle,
+                      mPrivateData.Protocols[Index].Guid,
+                      EFI_NATIVE_INTERFACE,
+                      &mPrivateData.Protocols[Index].Protocols.Generic
+                      );
+  }
+  ASSERT_EFI_ERROR (Status);
+}
+
+/**
+  Initialize bits that aren't necessarily related to an SMI source.
+
+
+  @retval EFI_SUCCESS             SMI source initialization completed.
+  @retval Asserts                 Global Smi Bit is not enabled successfully.
+**/
+EFI_STATUS
+PchSmmInitHardware (
+  VOID
+  )
+{
+  EFI_STATUS  Status;
+
+  //
+  // Clear all SMIs
+  //
+  PchSmmClearSmi ();
+
+  Status = PchSmmEnableGlobalSmiBit ();
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Be *really* sure to clear all SMIs
+  //
+  PchSmmClearSmi ();
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Enables the PCH to generate SMIs. Note that no SMIs will be generated
+  if no SMI sources are enabled. Conversely, no enabled SMI source will
+  generate SMIs if SMIs are not globally enabled. This is the main
+  switchbox for SMI generation.
+
+
+  @retval EFI_SUCCESS             Enable Global Smi Bit completed
+**/
+EFI_STATUS
+PchSmmEnableGlobalSmiBit (
+  VOID
+  )
+{
+  UINT32  SmiEn;
+
+  SmiEn = IoRead32 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_SMI_EN));
+
+  //
+  // Set the "global smi enable" bit
+  //
+  SmiEn |= B_ACPI_IO_SMI_EN_GBL_SMI;
+
+  IoWrite32 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_SMI_EN), SmiEn);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Clears the SMI after all SMI source have been processed.
+  Note that this function will not work correctly (as it is
+  written) unless all SMI sources have been processed.
+  A revision of this function could manually clear all SMI
+  status bits to guarantee success.
+
+
+  @retval EFI_SUCCESS             Clears the SMIs completed
+  @retval Asserts                 EOS was not set to a 1
+**/
+EFI_STATUS
+PchSmmClearSmi (
+  VOID
+  )
+{
+  return EFI_SUCCESS;
+}
+
+/**
+  Set the SMI EOS bit after all SMI source have been processed.
+
+
+  @retval FALSE                   EOS was not set to a 1; this is an error
+  @retval TRUE                    EOS was correctly set to a 1
+**/
+BOOLEAN
+PchSmmSetAndCheckEos (
+  VOID
+  )
+{
+  UINT32  SmiEn;
+
+  SmiEn = IoRead32 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_SMI_EN));
+
+  //
+  // Reset the PCH to generate subsequent SMIs
+  //
+  SmiEn |= B_ACPI_IO_SMI_EN_EOS;
+
+  IoWrite32 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_SMI_EN), SmiEn);
+
+  //
+  // Double check that the assert worked
+  //
+  SmiEn = IoRead32 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_SMI_EN));
+
+  //
+  // Return TRUE if EOS is set correctly
+  //
+  if ((SmiEn & B_ACPI_IO_SMI_EN_EOS) == 0) {
+    //
+    // EOS was not set to a 1; this is an error
+    //
+    return FALSE;
+  } else {
+    //
+    // EOS was correctly set to a 1
+    //
+    return TRUE;
+  }
+}
+
+/**
+  Determine whether an ACPI OS is present (via the SCI_EN bit)
+
+
+  @retval TRUE                    ACPI OS is present
+  @retval FALSE                   ACPI OS is not present
+**/
+BOOLEAN
+PchSmmGetSciEn (
+  VOID
+  )
+{
+  BOOLEAN SciEn;
+  UINT32  Pm1Cnt;
+
+  //
+  // Determine whether an ACPI OS is present (via the SCI_EN bit)
+  //
+  Pm1Cnt  = IoRead32 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_PM1_CNT));
+  SciEn   = (BOOLEAN) ((Pm1Cnt & B_ACPI_IO_PM1_CNT_SCI_EN) == B_ACPI_IO_PM1_CNT_SCI_EN);
+
+  return SciEn;
+}
+
+/**
+  Read a specifying bit with the register
+  These may or may not need to change w/ the PCH version; they're highly IA-32 dependent, though.
+
+  @param[in] BitDesc              The struct that includes register address, size in byte and bit number
+
+  @retval TRUE                    The bit is enabled
+  @retval FALSE                   The bit is disabled
+**/
+BOOLEAN
+ReadBitDesc (
+  CONST PCH_SMM_BIT_DESC  *BitDesc
+  )
+{
+  EFI_STATUS  Status;
+  UINT64      Register;
+  UINT32      PciBus;
+  UINT32      PciDev;
+  UINT32      PciFun;
+  UINT32      PciReg;
+  UINTN       RegSize;
+  BOOLEAN     BitWasOne;
+  UINTN       ShiftCount;
+  UINTN       RegisterOffset;
+  UINT32      BaseAddr;
+  UINT64      PciBaseAddress;
+
+  ASSERT (BitDesc != NULL);
+  if (BitDesc == NULL) {
+    return FALSE;
+  }
+  ASSERT (!IS_BIT_DESC_NULL (*BitDesc));
+
+  RegSize     = 0;
+  Register    = 0;
+  ShiftCount  = 0;
+  BitWasOne   = FALSE;
+
+  switch (BitDesc->Reg.Type) {
+
+    case ACPI_ADDR_TYPE:
+    case TCO_ADDR_TYPE:
+      if (BitDesc->Reg.Type == ACPI_ADDR_TYPE) {
+        RegisterOffset  = BitDesc->Reg.Data.acpi;
+        BaseAddr        = mAcpiBaseAddr;
+      } else {
+        RegisterOffset  = BitDesc->Reg.Data.tco;
+        BaseAddr        = mTcoBaseAddr;
+      }
+      switch (BitDesc->SizeInBytes) {
+
+        case 0:
+          //
+          // Chances are that this field didn't get initialized.
+          // Check your assignments to bit descriptions.
+          //
+          ASSERT (FALSE);
+          break;
+
+        case 1:
+          RegSize = SMM_IO_UINT8;
+          break;
+
+        case 2:
+          RegSize = SMM_IO_UINT16;
+          break;
+
+        case 4:
+          RegSize = SMM_IO_UINT32;
+          break;
+
+        case 8:
+          RegSize = SMM_IO_UINT64;
+          break;
+
+        default:
+          //
+          // Unsupported or invalid register size
+          //
+          ASSERT (FALSE);
+          break;
+      }
+      //
+      // Double check that we correctly read in the acpi base address
+      //
+      ASSERT ((BaseAddr != 0x0) && ((BaseAddr & 0x1) != 0x1));
+
+      ShiftCount      = BitDesc->Bit;
+      //
+      // As current CPU Smm Io can only support at most
+      // 32-bit read/write,if Operation is 64 bit,
+      // we do a 32 bit operation according to BitDesc->Bit
+      //
+      if (RegSize == SMM_IO_UINT64) {
+        RegSize = SMM_IO_UINT32;
+        //
+        // If the operation is for high 32 bits
+        //
+        if (BitDesc->Bit >= 32) {
+          RegisterOffset += 4;
+          ShiftCount -= 32;
+        }
+      }
+
+      Status = gSmst->SmmIo.Io.Read (
+                                 &gSmst->SmmIo,
+                                 RegSize,
+                                 BaseAddr + RegisterOffset,
+                                 1,
+                                 &Register
+                                 );
+      ASSERT_EFI_ERROR (Status);
+
+      if ((Register & (LShiftU64 (BIT_ZERO, ShiftCount))) != 0) {
+        BitWasOne = TRUE;
+      } else {
+        BitWasOne = FALSE;
+      }
+      break;
+
+    case GPIO_ADDR_TYPE:
+    case MEMORY_MAPPED_IO_ADDRESS_TYPE:
+      //
+      // Read the register, and it with the bit to read
+      //
+      switch (BitDesc->SizeInBytes) {
+        case 1:
+          Register = (UINT64) MmioRead8 ((UINTN) BitDesc->Reg.Data.Mmio);
+          break;
+
+        case 2:
+          Register = (UINT64) MmioRead16 ((UINTN) BitDesc->Reg.Data.Mmio);
+          break;
+
+        case 4:
+          Register = (UINT64) MmioRead32 ((UINTN) BitDesc->Reg.Data.Mmio);
+          break;
+
+        case 8:
+          Register                      = (UINT64) MmioRead32 ((UINTN) BitDesc->Reg.Data.Mmio);
+          *((UINT32 *) (&Register) + 1) = MmioRead32 ((UINTN) BitDesc->Reg.Data.Mmio + 4);
+          break;
+
+        default:
+          //
+          // Unsupported or invalid register size
+          //
+          ASSERT (FALSE);
+          break;
+      }
+
+      Register = Register & (LShiftU64 (BIT0, BitDesc->Bit));
+      if (Register) {
+        BitWasOne = TRUE;
+      } else {
+        BitWasOne = FALSE;
+      }
+      break;
+
+    case PCIE_ADDR_TYPE:
+      PciBus  = BitDesc->Reg.Data.pcie.Fields.Bus;
+      PciDev  = BitDesc->Reg.Data.pcie.Fields.Dev;
+      PciFun  = BitDesc->Reg.Data.pcie.Fields.Fnc;
+      PciReg  = BitDesc->Reg.Data.pcie.Fields.Reg;
+      PciBaseAddress = PCI_SEGMENT_LIB_ADDRESS (DEFAULT_PCI_SEGMENT_NUMBER_PCH, PciBus, PciDev, PciFun, 0);
+      switch (BitDesc->SizeInBytes) {
+
+        case 0:
+          //
+          // Chances are that this field didn't get initialized.
+          // Check your assignments to bit descriptions.
+          //
+          ASSERT (FALSE);
+          break;
+
+        case 1:
+          Register = (UINT64) PciSegmentRead8 (PciBaseAddress + PciReg);
+          break;
+
+        case 2:
+          Register = (UINT64) PciSegmentRead16 (PciBaseAddress + PciReg);
+          break;
+
+        case 4:
+          Register = (UINT64) PciSegmentRead32 (PciBaseAddress + PciReg);
+          break;
+
+        default:
+          //
+          // Unsupported or invalid register size
+          //
+          ASSERT (FALSE);
+          break;
+      }
+
+      if ((Register & (LShiftU64 (BIT_ZERO, BitDesc->Bit))) != 0) {
+        BitWasOne = TRUE;
+      } else {
+        BitWasOne = FALSE;
+      }
+      break;
+
+    case PCR_ADDR_TYPE:
+      //
+      // Read the register, and it with the bit to read
+      //
+      switch (BitDesc->SizeInBytes) {
+        case 1:
+          Register = PchPcrRead8  (BitDesc->Reg.Data.Pcr.Fields.Pid, BitDesc->Reg.Data.Pcr.Fields.Offset);
+          break;
+
+        case 2:
+          Register = PchPcrRead16 (BitDesc->Reg.Data.Pcr.Fields.Pid, BitDesc->Reg.Data.Pcr.Fields.Offset);
+          break;
+
+        case 4:
+          Register = PchPcrRead32 (BitDesc->Reg.Data.Pcr.Fields.Pid, BitDesc->Reg.Data.Pcr.Fields.Offset);
+          break;
+
+        default:
+          //
+          // Unsupported or invalid register size
+          //
+          ASSERT (FALSE);
+          break;
+      }
+
+      Register = Register & (LShiftU64 (BIT0, BitDesc->Bit));
+      if (Register) {
+        BitWasOne = TRUE;
+      } else {
+        BitWasOne = FALSE;
+      }
+      break;
+
+    default:
+      //
+      // This address type is not yet implemented
+      //
+      ASSERT (FALSE);
+      break;
+  }
+
+  return BitWasOne;
+}
+
+/**
+  Write a specifying bit with the register
+
+  @param[in] BitDesc              The struct that includes register address, size in byte and bit number
+  @param[in] ValueToWrite         The value to be wrote
+  @param[in] WriteClear           If the rest bits of the register is write clear
+
+**/
+VOID
+WriteBitDesc (
+  CONST PCH_SMM_BIT_DESC  *BitDesc,
+  CONST BOOLEAN           ValueToWrite,
+  CONST BOOLEAN           WriteClear
+  )
+{
+  EFI_STATUS  Status;
+  UINT64      Register;
+  UINT64      AndVal;
+  UINT64      OrVal;
+  UINT32      RegSize;
+  UINT32      PciBus;
+  UINT32      PciDev;
+  UINT32      PciFun;
+  UINT32      PciReg;
+  UINTN       RegisterOffset;
+  UINT32      BaseAddr;
+  UINT64      PciBaseAddress;
+
+  ASSERT (BitDesc != NULL);
+  if (BitDesc == NULL) {
+    return;
+  }
+  ASSERT (!IS_BIT_DESC_NULL (*BitDesc));
+
+  RegSize   = 0;
+  Register  = 0;
+
+  if (WriteClear) {
+    AndVal = LShiftU64 (BIT_ZERO, BitDesc->Bit);
+  } else {
+    AndVal = ~(LShiftU64 (BIT_ZERO, BitDesc->Bit));
+  }
+
+  OrVal = (LShiftU64 ((UINT32) ValueToWrite, BitDesc->Bit));
+
+  switch (BitDesc->Reg.Type) {
+
+    case ACPI_ADDR_TYPE:
+    case TCO_ADDR_TYPE:
+      if (BitDesc->Reg.Type == ACPI_ADDR_TYPE) {
+        RegisterOffset  = BitDesc->Reg.Data.acpi;
+        BaseAddr        = mAcpiBaseAddr;
+      } else {
+        RegisterOffset  = BitDesc->Reg.Data.tco;
+        BaseAddr        = mTcoBaseAddr;
+      }
+
+      switch (BitDesc->SizeInBytes) {
+
+        case 0:
+          //
+          // Chances are that this field didn't get initialized.
+          // Check your assignments to bit descriptions.
+          //
+          ASSERT (FALSE);
+          break;
+
+        case 1:
+          RegSize = SMM_IO_UINT8;
+          break;
+
+        case 2:
+          RegSize = SMM_IO_UINT16;
+          break;
+
+        case 4:
+          RegSize = SMM_IO_UINT32;
+          break;
+
+        case 8:
+          RegSize = SMM_IO_UINT64;
+          break;
+
+        default:
+          //
+          // Unsupported or invalid register size
+          //
+          ASSERT (FALSE);
+          break;
+      }
+      //
+      // Double check that we correctly read in the acpi base address
+      //
+      ASSERT ((BaseAddr != 0x0) && ((BaseAddr & 0x1) != 0x1));
+
+      //
+      // As current CPU Smm Io can only support at most
+      // 32-bit read/write,if Operation is 64 bit,
+      // we do a 32 bit operation according to BitDesc->Bit
+      //
+      if (RegSize == SMM_IO_UINT64) {
+        RegSize = SMM_IO_UINT32;
+        //
+        // If the operation is for high 32 bits
+        //
+        if (BitDesc->Bit >= 32) {
+          RegisterOffset += 4;
+
+          if (WriteClear) {
+            AndVal = LShiftU64 (BIT_ZERO, BitDesc->Bit - 32);
+          } else {
+            AndVal = ~(LShiftU64 (BIT_ZERO, BitDesc->Bit - 32));
+          }
+
+          OrVal = LShiftU64 ((UINT32) ValueToWrite, BitDesc->Bit - 32);
+        }
+      }
+
+      Status = gSmst->SmmIo.Io.Read (
+                                 &gSmst->SmmIo,
+                                 RegSize,
+                                 BaseAddr + RegisterOffset,
+                                 1,
+                                 &Register
+                                 );
+      ASSERT_EFI_ERROR (Status);
+
+      Register &= AndVal;
+      Register |= OrVal;
+
+      Status = gSmst->SmmIo.Io.Write (
+                                 &gSmst->SmmIo,
+                                 RegSize,
+                                 BaseAddr + RegisterOffset,
+                                 1,
+                                 &Register
+                                 );
+      ASSERT_EFI_ERROR (Status);
+      break;
+
+    case GPIO_ADDR_TYPE:
+    case MEMORY_MAPPED_IO_ADDRESS_TYPE:
+      //
+      // Read the register, or it with the bit to set, then write it back.
+      //
+      switch (BitDesc->SizeInBytes) {
+        case 1:
+          MmioAndThenOr8  ((UINTN) BitDesc->Reg.Data.Mmio, (UINT8)  AndVal, (UINT8)  OrVal);
+          break;
+
+        case 2:
+          MmioAndThenOr16 ((UINTN) BitDesc->Reg.Data.Mmio, (UINT16) AndVal, (UINT16) OrVal);
+          break;
+
+        case 4:
+          MmioAndThenOr32 ((UINTN) BitDesc->Reg.Data.Mmio, (UINT32) AndVal, (UINT32) OrVal);
+          break;
+
+        case 8:
+          Register                      = (UINT64) MmioRead32 ((UINTN) BitDesc->Reg.Data.Mmio);
+          *((UINT32 *) (&Register) + 1) = MmioRead32 ((UINTN) BitDesc->Reg.Data.Mmio + 4);
+          Register &= AndVal;
+          Register |= OrVal;
+          MmioWrite32 ((UINTN) BitDesc->Reg.Data.Mmio, (UINT32) Register);
+          MmioWrite32 ((UINTN) BitDesc->Reg.Data.Mmio + 4, *((UINT32 *) (&Register) + 1));
+          break;
+
+        default:
+          //
+          // Unsupported or invalid register size
+          //
+          ASSERT (FALSE);
+          break;
+      }
+      break;
+
+    case PCIE_ADDR_TYPE:
+      PciBus  = BitDesc->Reg.Data.pcie.Fields.Bus;
+      PciDev  = BitDesc->Reg.Data.pcie.Fields.Dev;
+      PciFun  = BitDesc->Reg.Data.pcie.Fields.Fnc;
+      PciReg  = BitDesc->Reg.Data.pcie.Fields.Reg;
+      PciBaseAddress = PCI_SEGMENT_LIB_ADDRESS (DEFAULT_PCI_SEGMENT_NUMBER_PCH, PciBus, PciDev, PciFun, 0);
+      switch (BitDesc->SizeInBytes) {
+
+        case 0:
+          //
+          // Chances are that this field didn't get initialized -- check your assignments
+          // to bit descriptions.
+          //
+          ASSERT (FALSE);
+          break;
+
+        case 1:
+          PciSegmentAndThenOr8 (PciBaseAddress + PciReg, (UINT8) AndVal, (UINT8) OrVal);
+          break;
+
+        case 2:
+          PciSegmentAndThenOr16 (PciBaseAddress + PciReg, (UINT16) AndVal, (UINT16) OrVal);
+          break;
+
+        case 4:
+          PciSegmentAndThenOr32 (PciBaseAddress + PciReg, (UINT32) AndVal, (UINT32) OrVal);
+          break;
+
+        default:
+          //
+          // Unsupported or invalid register size
+          //
+          ASSERT (FALSE);
+          break;
+      }
+      break;
+
+    case PCR_ADDR_TYPE:
+      //
+      // Read the register, or it with the bit to set, then write it back.
+      //
+      switch (BitDesc->SizeInBytes) {
+        case 1:
+          PchPcrAndThenOr8  ((PCH_SBI_PID) BitDesc->Reg.Data.Pcr.Fields.Pid, (UINT16) BitDesc->Reg.Data.Pcr.Fields.Offset, (UINT8)  AndVal, (UINT8)  OrVal);
+          break;
+
+        case 2:
+          PchPcrAndThenOr16 ((PCH_SBI_PID) BitDesc->Reg.Data.Pcr.Fields.Pid, (UINT16) BitDesc->Reg.Data.Pcr.Fields.Offset, (UINT16) AndVal, (UINT16) OrVal);
+          break;
+
+        case 4:
+          PchPcrAndThenOr32 ((PCH_SBI_PID) BitDesc->Reg.Data.Pcr.Fields.Pid, (UINT16) BitDesc->Reg.Data.Pcr.Fields.Offset, (UINT32) AndVal, (UINT32) OrVal);
+          break;
+
+        default:
+          //
+          // Unsupported or invalid register size
+          //
+          ASSERT (FALSE);
+          break;
+      }
+      break;
+
+    default:
+      //
+      // This address type is not yet implemented
+      //
+      ASSERT (FALSE);
+      break;
+  }
+}
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.h b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.h
new file mode 100644
index 0000000000..998b38e159
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.h
@@ -0,0 +1,107 @@
+/** @file
+  This driver is responsible for the registration of child drivers
+  and the abstraction of the PCH SMI sources.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCHX_SMM_HELPERS_H_
+#define _PCHX_SMM_HELPERS_H_
+
+#include "PchSmm.h"
+
+/**
+  Initialize bits that aren't necessarily related to an SMI source.
+
+
+  @retval EFI_SUCCESS             SMI source initialization completed.
+  @retval Asserts                 Global Smi Bit is not enabled successfully.
+**/
+EFI_STATUS
+PchSmmInitHardware (
+  VOID
+  );
+
+/**
+  Enables the PCH to generate SMIs. Note that no SMIs will be generated
+  if no SMI sources are enabled. Conversely, no enabled SMI source will
+  generate SMIs if SMIs are not globally enabled. This is the main
+  switchbox for SMI generation.
+
+
+  @retval EFI_SUCCESS             Enable Global Smi Bit completed
+**/
+EFI_STATUS
+PchSmmEnableGlobalSmiBit (
+  VOID
+  );
+
+/**
+  Clears the SMI after all SMI source have been processed.
+  Note that this function will not work correctly (as it is
+  written) unless all SMI sources have been processed.
+  A revision of this function could manually clear all SMI
+  status bits to guarantee success.
+
+
+  @retval EFI_SUCCESS             Clears the SMIs completed
+  @retval Asserts                 EOS was not set to a 1
+**/
+EFI_STATUS
+PchSmmClearSmi (
+  VOID
+  );
+
+/**
+  Set the SMI EOS bit after all SMI source have been processed.
+
+
+  @retval FALSE                   EOS was not set to a 1; this is an error
+  @retval TRUE                    EOS was correctly set to a 1
+**/
+BOOLEAN
+PchSmmSetAndCheckEos (
+  VOID
+  );
+
+/**
+  Determine whether an ACPI OS is present (via the SCI_EN bit)
+
+
+  @retval TRUE                    ACPI OS is present
+  @retval FALSE                   ACPI OS is not present
+**/
+BOOLEAN
+PchSmmGetSciEn (
+  VOID
+  );
+
+/**
+  Read a specifying bit with the register
+
+  @param[in] BitDesc              The struct that includes register address, size in byte and bit number
+
+  @retval TRUE                    The bit is enabled
+  @retval FALSE                   The bit is disabled
+**/
+BOOLEAN
+ReadBitDesc (
+  CONST PCH_SMM_BIT_DESC *BitDesc
+  );
+
+/**
+  Write a specifying bit with the register
+
+  @param[in] BitDesc              The struct that includes register address, size in byte and bit number
+  @param[in] ValueToWrite         The value to be wrote
+  @param[in] WriteClear           If the rest bits of the register is write clear
+
+**/
+VOID
+WriteBitDesc (
+  CONST PCH_SMM_BIT_DESC  *BitDesc,
+  CONST BOOLEAN           ValueToWrite,
+  CONST BOOLEAN           WriteClear
+  );
+
+#endif
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PcieSmmClient.c b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PcieSmmClient.c
new file mode 100644
index 0000000000..6d210f671b
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PcieSmmClient.c
@@ -0,0 +1,38 @@
+/** @file
+  This function handle the register/unregister of PCH PCIe specific SMI events.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "PchSmmHelpers.h"
+#include <Register/PmcRegs.h>
+#include <Register/PchPcieRpRegs.h>
+#include <Library/CpuPcieInfoFruLib.h>
+#include <CpuPcieInfo.h>
+#include <Library/PchPcieRpLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchPciBdfLib.h>
+
+extern UINT32  mNumOfRootPorts;
+
+/**
+  Get CPU or PCH Pcie Root Port Device and Function Number by Root Port physical Number
+
+  @param[in]  RpNumber              Root port physical number. (0-based)
+  @param[out] RpDev                 Return corresponding root port device number.
+  @param[out] RpFun                 Return corresponding root port function number.
+**/
+VOID
+GetPcieRpDevFun (
+  IN  UINTN   RpIndex,
+  OUT UINTN   *RpDev,
+  OUT UINTN   *RpFun
+  )
+{
+  if (RpIndex >= CpuRpIndex0 && RpIndex <= CpuRpIndex3) {
+    GetCpuPcieRpDevFun ((RpIndex - CpuRpIndex0), RpDev, RpFun);
+  } else {
+    *RpDev = PchPcieRpDevNumber (RpIndex);
+    *RpFun = PchPcieRpFuncNumber (RpIndex);
+  }
+}
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/SmmGlobalsPch.c b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/SmmGlobalsPch.c
new file mode 100644
index 0000000000..f66079884f
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/SmmGlobalsPch.c
@@ -0,0 +1,20 @@
+/** @file
+  This driver is responsible for the registration of child drivers
+  and the abstraction of the PCH SMI sources.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Register/TcoRegs.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mTco1StsClear =
+  (
+    B_TCO_IO_TCO1_STS_DMISERR |
+    B_TCO_IO_TCO1_STS_DMISMI |
+    B_TCO_IO_TCO1_STS_DMISCI |
+    B_TCO_IO_TCO1_STS_BIOSWR |
+    B_TCO_IO_TCO1_STS_NEWCENTURY |
+    B_TCO_IO_TCO1_STS_TIMEOUT |
+    B_TCO_IO_TCO1_STS_TCO_INT |
+    B_TCO_IO_TCO1_STS_SW_TCO_SMI
+    );
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControl.inf b/Silicon/Intel/AlderlakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControl.inf
new file mode 100644
index 0000000000..d73c12f964
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControl.inf
@@ -0,0 +1,53 @@
+## @file
+# Component description file for SmmControl module
+#
+#   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+#   SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = SmmControl
+FILE_GUID = A0BAD9F7-AB78-491b-B583-C52B7F84B9E0
+VERSION_STRING = 1.0
+MODULE_TYPE = DXE_RUNTIME_DRIVER
+ENTRY_POINT = SmmControlDriverEntryInit
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+
+
+[LibraryClasses]
+IoLib
+UefiDriverEntryPoint
+DebugLib
+UefiBootServicesTableLib
+UefiRuntimeServicesTableLib
+PmcLib
+GpioLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+AlderlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+SmmControlDriver.h
+SmmControlDriver.c
+
+
+[Protocols]
+gEfiSmmControl2ProtocolGuid ## PRODUCES
+
+
+[Guids]
+gEfiEventVirtualAddressChangeGuid
+
+
+[Depex]
+TRUE
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.c b/Silicon/Intel/AlderlakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.c
new file mode 100644
index 0000000000..8864d18787
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.c
@@ -0,0 +1,338 @@
+/** @file
+  This is the driver that publishes the SMM Control Protocol.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Guid/EventGroup.h>
+#include <Library/PmcLib.h>
+#include <Library/GpioLib.h>
+#include <IndustryStandard/Pci30.h>
+#include <Register/PchRegsLpc.h>
+#include <Register/SpiRegs.h>
+#include <Register/PmcRegs.h>
+#include "SmmControlDriver.h"
+
+STATIC SMM_CONTROL_PRIVATE_DATA mSmmControl;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16                          mABase;
+
+/**
+  Fixup internal data pointers so that the services can be called in virtual mode.
+
+  @param[in] Event                The event registered.
+  @param[in] Context              Event context.
+
+**/
+VOID
+EFIAPI
+SmmControlVirtualAddressChangeEvent (
+  IN EFI_EVENT                  Event,
+  IN VOID                       *Context
+  )
+{
+  gRT->ConvertPointer (0, (VOID *) &(mSmmControl.SmmControl.Trigger));
+  gRT->ConvertPointer (0, (VOID *) &(mSmmControl.SmmControl.Clear));
+}
+
+/**
+  <b>SmmControl DXE RUNTIME Module Entry Point</b>\n
+  - <b>Introduction</b>\n
+    The SmmControl module is a DXE RUNTIME driver that provides a standard way
+    for other drivers to trigger software SMIs.
+
+  - @pre
+    - PCH Power Management I/O space base address has already been programmed.
+      If SmmControl Runtime DXE driver is run before Status Code Runtime Protocol
+      is installed and there is the need to use Status code in the driver, it will
+      be necessary to add EFI_STATUS_CODE_RUNTIME_PROTOCOL_GUID to the dependency file.
+    - EFI_SMM_BASE2_PROTOCOL
+      - Documented in the System Management Mode Core Interface Specification.
+
+  - @result
+    The SmmControl driver produces the EFI_SMM_CONTROL_PROTOCOL documented in
+    System Management Mode Core Interface Specification.
+
+  @param[in] ImageHandle          Handle for the image of this driver
+  @param[in] SystemTable          Pointer to the EFI System Table
+
+  @retval EFI_STATUS              Results of the installation of the SMM Control Protocol
+**/
+EFI_STATUS
+EFIAPI
+SmmControlDriverEntryInit (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  )
+{
+  EFI_STATUS  Status;
+  EFI_EVENT   Event;
+
+  DEBUG ((DEBUG_INFO, "SmmControlDriverEntryInit() Start\n"));
+
+  //
+  // Get the Power Management I/O space base address. We assume that
+  // this base address has already been programmed if this driver is
+  // being run.
+  //
+  mABase = PmcGetAcpiBase ();
+
+  Status = EFI_SUCCESS;
+  if (mABase != 0) {
+    //
+    // Install the instance of the protocol
+    //
+    mSmmControl.Signature                       = SMM_CONTROL_PRIVATE_DATA_SIGNATURE;
+    mSmmControl.Handle                          = ImageHandle;
+
+    mSmmControl.SmmControl.Trigger              = Activate;
+    mSmmControl.SmmControl.Clear                = Deactivate;
+    mSmmControl.SmmControl.MinimumTriggerPeriod = 0;
+
+    //
+    // Install our protocol interfaces on the device's handle
+    //
+    Status = gBS->InstallMultipleProtocolInterfaces (
+                    &mSmmControl.Handle,
+                    &gEfiSmmControl2ProtocolGuid,
+                    &mSmmControl.SmmControl,
+                    NULL
+                    );
+  } else {
+    Status = EFI_DEVICE_ERROR;
+    return Status;
+  }
+
+  Status = gBS->CreateEventEx (
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_NOTIFY,
+                  SmmControlVirtualAddressChangeEvent,
+                  NULL,
+                  &gEfiEventVirtualAddressChangeGuid,
+                  &Event
+                  );
+
+  DEBUG ((DEBUG_INFO, "SmmControlDriverEntryInit() End\n"));
+
+  return Status;
+}
+
+/**
+  Trigger the software SMI
+
+  @param[in] Command              The value to be set on the software SMI command port
+  @param[in] Data                 The value to be set on the software SMI data port
+
+  @retval EFI_SUCCESS             Function completes successfully
+**/
+EFI_STATUS
+EFIAPI
+SmmTrigger (
+  IN UINT8   Command,
+  IN UINT8   Data
+  )
+{
+  UINT32  OutputData;
+  UINT32  OutputPort;
+
+  //
+  // Enable the APMC SMI
+  //
+  OutputPort  = mABase + R_ACPI_IO_SMI_EN;
+  OutputData  = IoRead32 ((UINTN) OutputPort);
+  OutputData |= (B_ACPI_IO_SMI_EN_APMC | B_ACPI_IO_SMI_EN_GBL_SMI);
+  DEBUG (
+    (DEBUG_VERBOSE,
+     "The SMI Control Port at address %x will be written to %x.\n",
+     OutputPort,
+     OutputData)
+    );
+  IoWrite32 (
+    (UINTN) OutputPort,
+    (UINT32) (OutputData)
+    );
+
+  OutputPort  = R_PCH_IO_APM_STS;
+  OutputData  = Data;
+
+  //
+  // Write data to APM DATA PORT
+  //
+  IoWrite8 (
+    (UINTN) OutputPort,
+    (UINT8) (OutputData)
+    );
+  OutputPort  = R_PCH_IO_APM_CNT;
+  OutputData  = Command;
+
+  //
+  // Generate the APMC SMI
+  //
+  IoWrite8 (
+    (UINTN) OutputPort,
+    (UINT8) (OutputData)
+    );
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Clear the SMI status
+
+
+  @retval EFI_SUCCESS             The function completes successfully
+  @retval EFI_DEVICE_ERROR        Something error occurred
+**/
+EFI_STATUS
+EFIAPI
+SmmClear (
+  VOID
+  )
+{
+  EFI_STATUS  Status;
+  UINT32      OutputData;
+  UINT32      OutputPort;
+
+  Status = EFI_SUCCESS;
+
+  //
+  // Clear the Power Button Override Status Bit, it gates EOS from being set.
+  //
+  OutputPort  = mABase + R_ACPI_IO_PM1_STS;
+  OutputData  = B_ACPI_IO_PM1_STS_PRBTNOR;
+  DEBUG (
+    (DEBUG_VERBOSE,
+     "The PM1 Status Port at address %x will be written to %x.\n",
+     OutputPort,
+     OutputData)
+    );
+  IoWrite16 (
+    (UINTN) OutputPort,
+    (UINT16) (OutputData)
+    );
+
+  //
+  // Clear the APM SMI Status Bit
+  //
+  OutputPort  = mABase + R_ACPI_IO_SMI_STS;
+  OutputData  = B_ACPI_IO_SMI_STS_APM;
+  DEBUG (
+    (DEBUG_VERBOSE,
+     "The SMI Status Port at address %x will be written to %x.\n",
+     OutputPort,
+     OutputData)
+    );
+  IoWrite32 (
+    (UINTN) OutputPort,
+    (UINT32) (OutputData)
+    );
+
+  //
+  // Set the EOS Bit
+  //
+  OutputPort  = mABase + R_ACPI_IO_SMI_EN;
+  OutputData  = IoRead32 ((UINTN) OutputPort);
+  OutputData |= B_ACPI_IO_SMI_EN_EOS;
+  DEBUG (
+    (DEBUG_VERBOSE,
+     "The SMI Control Port at address %x will be written to %x.\n",
+     OutputPort,
+     OutputData)
+    );
+  IoWrite32 (
+    (UINTN) OutputPort,
+    (UINT32) (OutputData)
+    );
+
+  //
+  // There is no need to read EOS back and check if it is set.
+  // This can lead to a reading of zero if an SMI occurs right after the SMI_EN port read
+  // but before the data is returned to the CPU.
+  // SMM Dispatcher should make sure that EOS is set after all SMI sources are processed.
+  //
+  return Status;
+}
+
+/**
+  This routine generates an SMI
+
+  @param[in] This                       The EFI SMM Control protocol instance
+  @param[in, out] CommandPort           The buffer contains data to the command port
+  @param[in, out] DataPort              The buffer contains data to the data port
+  @param[in] Periodic                   Periodic or not
+  @param[in] ActivationInterval         Interval of periodic SMI
+
+  @retval EFI Status                    Describing the result of the operation
+  @retval EFI_INVALID_PARAMETER         Some parameter value passed is not supported
+**/
+EFI_STATUS
+EFIAPI
+Activate (
+  IN CONST EFI_SMM_CONTROL2_PROTOCOL                    * This,
+  IN OUT  UINT8                                         *CommandPort       OPTIONAL,
+  IN OUT  UINT8                                         *DataPort          OPTIONAL,
+  IN      BOOLEAN                                       Periodic           OPTIONAL,
+  IN      UINTN                                         ActivationInterval OPTIONAL
+  )
+{
+  EFI_STATUS  Status;
+  UINT8       Command;
+  UINT8       Data;
+
+  if (Periodic) {
+    DEBUG ((DEBUG_WARN, "Invalid parameter\n"));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Extract the values from CommandPort and DataPort
+  //
+  if (CommandPort == NULL) {
+    Command = 0xFF;
+  } else {
+    Command = *CommandPort;
+  }
+
+  if (DataPort == NULL) {
+    Data = 0x00;
+  } else {
+    Data = *DataPort;
+  }
+
+  //
+  // Clear any pending the APM SMI
+  //
+  Status = SmmClear ();
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  return SmmTrigger (Command, Data);
+}
+
+/**
+  This routine clears an SMI
+
+  @param[in] This                 The EFI SMM Control protocol instance
+  @param[in] Periodic             Periodic or not
+
+  @retval EFI Status              Describing the result of the operation
+  @retval EFI_INVALID_PARAMETER   Some parameter value passed is not supported
+**/
+EFI_STATUS
+EFIAPI
+Deactivate (
+  IN CONST EFI_SMM_CONTROL2_PROTOCOL       *This,
+  IN  BOOLEAN                              Periodic OPTIONAL
+  )
+{
+  if (Periodic) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return SmmClear ();
+}
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.h b/Silicon/Intel/AlderlakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.h
new file mode 100644
index 0000000000..a366de7d5e
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.h
@@ -0,0 +1,122 @@
+/** @file
+  Header file for SMM Control Driver.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _SMM_CONTROL_DRIVER_H_
+#define _SMM_CONTROL_DRIVER_H_
+
+#include <Protocol/SmmControl2.h>
+
+
+#define SMM_CONTROL_PRIVATE_DATA_SIGNATURE  SIGNATURE_32 ('i', '4', 's', 'c')
+
+typedef struct {
+  UINTN                           Signature;
+  EFI_HANDLE                      Handle;
+  EFI_SMM_CONTROL2_PROTOCOL       SmmControl;
+} SMM_CONTROL_PRIVATE_DATA;
+
+#define SMM_CONTROL_PRIVATE_DATA_FROM_THIS(a) CR (a, SMM_CONTROL_PRIVATE_DATA, SmmControl, SMM_CONTROL_DEV_SIGNATURE)
+
+//
+// Prototypes
+//
+
+/**
+  <b>SmmControl DXE RUNTIME Module Entry Point</b>\n
+  - <b>Introduction</b>\n
+    The SmmControl module is a DXE RUNTIME driver that provides a standard way
+    for other drivers to trigger software SMIs.
+
+  - @pre
+    - PCH Power Management I/O space base address has already been programmed.
+      If SmmControl Runtime DXE driver is run before Status Code Runtime Protocol
+      is installed and there is the need to use Status code in the driver, it will
+      be necessary to add EFI_STATUS_CODE_RUNTIME_PROTOCOL_GUID to the dependency file.
+    - EFI_SMM_BASE2_PROTOCOL
+      - Documented in the System Management Mode Core Interface Specification.
+
+  - @result
+    The SmmControl driver produces the EFI_SMM_CONTROL_PROTOCOL documented in
+    System Management Mode Core Interface Specification.
+
+  @param[in] ImageHandle          Handle for the image of this driver
+  @param[in] SystemTable          Pointer to the EFI System Table
+
+  @retval EFI_STATUS              Results of the installation of the SMM Control Protocol
+**/
+EFI_STATUS
+EFIAPI
+SmmControlDriverEntryInit (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  );
+
+/**
+  Trigger the software SMI
+
+  @param[in] Command              The value to be set on the software SMI command port
+  @param[in] Data                 The value to be set on the software SMI data port
+
+  @retval EFI_SUCCESS             Function completes successfully
+**/
+EFI_STATUS
+EFIAPI
+SmmTrigger (
+  IN UINT8   Command,
+  IN UINT8   Data
+  );
+
+/**
+  Clear the SMI status
+
+
+  @retval EFI_SUCCESS             The function completes successfully
+  @retval EFI_DEVICE_ERROR        Something error occurred
+**/
+EFI_STATUS
+EFIAPI
+SmmClear (
+  VOID
+  );
+
+/**
+  This routine generates an SMI
+
+  @param[in] This                       The EFI SMM Control protocol instance
+  @param[in, out] ArgumentBuffer        The buffer of argument
+  @param[in, out] ArgumentBufferSize    The size of the argument buffer
+  @param[in] Periodic                   Periodic or not
+  @param[in] ActivationInterval         Interval of periodic SMI
+
+  @retval EFI Status                    Describing the result of the operation
+  @retval EFI_INVALID_PARAMETER         Some parameter value passed is not supported
+**/
+EFI_STATUS
+EFIAPI
+Activate (
+  IN CONST EFI_SMM_CONTROL2_PROTOCOL    *This,
+  IN OUT  UINT8                         *ArgumentBuffer OPTIONAL,
+  IN OUT  UINT8                         *ArgumentBufferSize OPTIONAL,
+  IN      BOOLEAN                       Periodic OPTIONAL,
+  IN      UINTN                         ActivationInterval OPTIONAL
+  );
+
+/**
+  This routine clears an SMI
+
+  @param[in] This                 The EFI SMM Control protocol instance
+  @param[in] Periodic             Periodic or not
+
+  @retval EFI Status              Describing the result of the operation
+  @retval EFI_INVALID_PARAMETER   Some parameter value passed is not supported
+**/
+EFI_STATUS
+EFIAPI
+Deactivate (
+  IN CONST EFI_SMM_CONTROL2_PROTOCOL    *This,
+  IN       BOOLEAN                      Periodic OPTIONAL
+  );
+#endif
-- 
2.36.1.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#107161): https://edk2.groups.io/g/devel/message/107161
Mute This Topic: https://groups.io/mt/99554480/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [edk2-devel] [PATCH 6/8] AlderlakeSiliconPkg/SystemAgent: Add NVS support
  2023-06-15 17:53 ` [PATCH 6/8] AlderlakeSiliconPkg/SystemAgent: Add NVS support Saloni Kasbekar
@ 2023-07-24  7:58   ` Chaganty, Rangasai V
  0 siblings, 0 replies; 15+ messages in thread
From: Chaganty, Rangasai V @ 2023-07-24  7:58 UTC (permalink / raw)
  To: Kasbekar, Saloni, devel@edk2.groups.io
  Cc: Desimone, Nathaniel L, Oram, Isaac W, Chuang, Rosen

Reviewed-by: Sai Chaganty <rangasai.v.chaganty@intel.com>

-----Original Message-----
From: Kasbekar, Saloni <saloni.kasbekar@intel.com> 
Sent: Thursday, June 15, 2023 10:53 AM
To: devel@edk2.groups.io
Cc: Kasbekar, Saloni <saloni.kasbekar@intel.com>; Chaganty, Rangasai V <rangasai.v.chaganty@intel.com>; Desimone, Nathaniel L <nathaniel.l.desimone@intel.com>; Oram, Isaac W <isaac.w.oram@intel.com>; Chuang, Rosen <rosen.chuang@intel.com>
Subject: [PATCH 6/8] AlderlakeSiliconPkg/SystemAgent: Add NVS support

Adds the System Agent NVS ACPI table and structures

Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Isaac Oram <isaac.w.oram@intel.com>
Cc: Rosen Chuang <rosen.chuang@intel.com>
Signed-off-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
---
 .../SystemAgent/AcpiTables/SaSsdt/SaNvs.asl   | 18 +++++++++++
 .../IncludePrivate/Protocol/SaNvsArea.h       | 30 +++++++++++++++++++
 .../SystemAgent/IncludePrivate/SaNvsAreaDef.h | 22 ++++++++++++++
 3 files changed, 70 insertions(+)
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/SaNvs.asl
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/IncludePrivate/Protocol/SaNvsArea.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/IncludePrivate/SaNvsAreaDef.h

diff --git a/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/SaNvs.asl b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/SaNvs.asl
new file mode 100644
index 0000000000..e9785873d2
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/Sa
+++ Nvs.asl
@@ -0,0 +1,18 @@
+/**@file
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent **/
+
+  //
+  // Define SA NVS Area operation region.
+  //
+
+
+  OperationRegion(SANV,SystemMemory,SANB,SANL)
+  Field(SANV,AnyAcc,Lock,Preserve)
+  {  Offset(0),      M64B, 64, // Offset(0),   Base of above 4GB MMIO resource
+  Offset(8),    M64L, 64, // Offset(8),   Length of above 4GB MMIO resource
+  Offset(16),    M32B, 32, // Offset(16),   Base of below 4GB MMIO resource
+  Offset(20),    M32L, 32, // Offset(20),   Length of below 4GB MMIO resource
+  }
\ No newline at end of file
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/IncludePrivate/Protocol/SaNvsArea.h b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/IncludePrivate/Protocol/SaNvsArea.h
new file mode 100644
index 0000000000..3a75465843
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/IncludePrivate/Proto
+++ col/SaNvsArea.h
@@ -0,0 +1,30 @@
+/** @file
+  Definition of the System Agent global NVS area protocol.
+  This protocol publishes the address and format of a global ACPI NVS 
+buffer
+  used as a communications buffer between SMM/DXE/PEI code and ASL code.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent **/
+
+#ifndef _SYSTEM_AGENT_NVS_AREA_H_
+#define _SYSTEM_AGENT_NVS_AREA_H_
+
+//
+// SA NVS Area definition
+//
+#include <SaNvsAreaDef.h>
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gSaNvsAreaProtocolGuid;
+
+///
+/// System Agent Global NVS Area Protocol /// typedef struct {
+  SYSTEM_AGENT_NVS_AREA *Area;        ///< System Agent Global NVS Area Structure
+} SYSTEM_AGENT_NVS_AREA_PROTOCOL;
+
+#endif // _SYSTEM_AGENT_NVS_AREA_H_
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/IncludePrivate/SaNvsAreaDef.h b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/IncludePrivate/SaNvsAreaDef.h
new file mode 100644
index 0000000000..5b8136866a
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/IncludePrivate/SaNvs
+++ AreaDef.h
@@ -0,0 +1,22 @@
+/**@file
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent **/
+
+  //
+  // Define SA NVS Area operation region.
+  //
+#ifndef _SA_NVS_AREA_DEF_H_
+#define _SA_NVS_AREA_DEF_H_
+
+#pragma pack (push,1)
+typedef struct {
+  UINT64   Mmio64Base;                              ///< Offset 0     Base of above 4GB MMIO resource
+  UINT64   Mmio64Length;                            ///< Offset 8     Length of above 4GB MMIO resource
+  UINT32   Mmio32Base;                              ///< Offset 16     Base of below 4GB MMIO resource
+  UINT32   Mmio32Length;                            ///< Offset 20     Length of below 4GB MMIO resource
+} SYSTEM_AGENT_NVS_AREA;
+
+#pragma pack(pop)
+#endif
--
2.36.1.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#107162): https://edk2.groups.io/g/devel/message/107162
Mute This Topic: https://groups.io/mt/99554477/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [edk2-devel] [PATCH 7/8] AlderlakeSiliconPkg/SystemAgent: Add include headers
  2023-06-15 17:53 ` [PATCH 7/8] AlderlakeSiliconPkg/SystemAgent: Add include headers Saloni Kasbekar
@ 2023-07-24  8:03   ` Chaganty, Rangasai V
  0 siblings, 0 replies; 15+ messages in thread
From: Chaganty, Rangasai V @ 2023-07-24  8:03 UTC (permalink / raw)
  To: Kasbekar, Saloni, devel@edk2.groups.io
  Cc: Desimone, Nathaniel L, Oram, Isaac W, Chuang, Rosen

Reviewed-by: Sai Chaganty <rangasai.v.chaganty@intel.com>

-----Original Message-----
From: Kasbekar, Saloni <saloni.kasbekar@intel.com> 
Sent: Thursday, June 15, 2023 10:53 AM
To: devel@edk2.groups.io
Cc: Kasbekar, Saloni <saloni.kasbekar@intel.com>; Chaganty, Rangasai V <rangasai.v.chaganty@intel.com>; Desimone, Nathaniel L <nathaniel.l.desimone@intel.com>; Oram, Isaac W <isaac.w.oram@intel.com>; Chuang, Rosen <rosen.chuang@intel.com>
Subject: [PATCH 7/8] AlderlakeSiliconPkg/SystemAgent: Add include headers

Adds the following header files:
* SystemAgent/Include

Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Isaac Oram <isaac.w.oram@intel.com>
Cc: Rosen Chuang <rosen.chuang@intel.com>
Signed-off-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
---
 .../Include/ConfigBlock/MemoryDxeConfig.h     | 126 ++++++++++
 .../ConfigBlock/SaMiscPeiPreMemConfig.h       | 112 +++++++++
 .../Include/Library/DxeSaPolicyLib.h          |  58 +++++
 .../Include/Library/PeiSaPolicyLib.h          |  13 ++
 .../SystemAgent/Include/MemInfoHob.h          | 220 ++++++++++++++++++
 .../SystemAgent/Include/Protocol/SaPolicy.h   |  54 +++++
 .../SystemAgent/Include/SaDataHob.h           |  28 +++
 7 files changed, 611 insertions(+)
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/ConfigBlock/MemoryDxeConfig.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/ConfigBlock/SaMiscPeiPreMemConfig.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/Library/DxeSaPolicyLib.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/Library/PeiSaPolicyLib.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/MemInfoHob.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/Protocol/SaPolicy.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/SaDataHob.h

diff --git a/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/ConfigBlock/MemoryDxeConfig.h b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/ConfigBlock/MemoryDxeConfig.h
new file mode 100644
index 0000000000..eca0c2f1ba
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/ConfigBlock/
+++ MemoryDxeConfig.h
@@ -0,0 +1,126 @@
+/** @file
+  Memory DXE Policy definitions
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent **/ #ifndef 
+_MEMORY_DXE_CONFIG_H_ #define _MEMORY_DXE_CONFIG_H_
+
+#pragma pack(push, 1)
+
+/**
+ Making any setup structure change after code frozen  will need to 
+maintain backward compatibility, bump up  structure revision and update 
+below history table\n
+  <b>Revision 1</b>:  - Initial version.
+**/
+#define MEMORY_DXE_CONFIG_REVISION 2
+
+typedef struct _MEMORY_DXE_CONFIG  MEMORY_DXE_CONFIG;
+
+/**
+  Retrieves the OEM custom string for the SMBIOS Type 17 Table DeviceLocator field.
+  Implementation of this function is optional, if this function pointer 
+is NULL then
+  the reference implementation of DeviceLocator will be used.
+
+  @param[in]  This                          A pointer to this instance of MEMORY_DXE_CONFIG.
+  @param[in]  Controller                    Desired Controller to get a DeviceLocator string for.
+  @param[in]  Dimm                          Desired DIMM to get a DeviceLocator string for.
+  @param[in]  MdSocket                      0 = Memory Down, 1 = Socketed.
+
+  @retval                                   The DeviceLocator string
+  @retval     NULL                          If the return value is NULL, the default value will be used.
+**/
+typedef
+CHAR8*
+(EFIAPI *MEMORY_DXE_CONFIG_GET_DEVICE_LOCATOR_STRING)(
+  IN CONST    MEMORY_DXE_CONFIG   *This,
+  IN          UINT8               Controller,
+  IN          UINT8               Dimm,
+  IN          UINT8               MdSocket
+  );
+
+/**
+  Retrieves the OEM custom string for the SMBIOS Type 17 Table BankLocator field.
+  Implementation of this function is optional, if this function pointer 
+is NULL then
+  the reference implementation of DeviceLocator will be used.
+
+  @param[in]  This                          A pointer to this instance of MEMORY_DXE_CONFIG.
+  @param[in]  Controller                    Desired Controller to get a BankLocator string for.
+  @param[in]  Dimm                          Desired DIMM to get a BankLocator string for.
+  @param[in]  MdSocket                      0 = Memory Down, 1 = Socketed.
+
+  @retval                                   The BankLocator string
+  @retval     NULL                          If the return value is NULL, the default value will be used.
+**/
+typedef
+CHAR8*
+(EFIAPI *MEMORY_DXE_CONFIG_GET_BANK_LOCATOR_STRING)(
+  IN CONST    MEMORY_DXE_CONFIG   *This,
+  IN          UINT8               Controller,
+  IN          UINT8               Dimm,
+  IN          UINT8               MdSocket
+  );
+
+/**
+  The Memory Configuration includes DIMM SPD address Map and DIMM Slot Mechanical present bit map.
+  The data elements should be initialized by a Platform Module.\n
+  <b>Revision 1</b>:
+  - Initial version.
+**/
+struct _MEMORY_DXE_CONFIG {
+  CONFIG_BLOCK_HEADER   Header;                   ///< Offset 0-27: Config Block Header
+/**
+  Offset 28:
+  Dimm SPD address
+  Only Server support 2 channels * 3 slots per channel = 6 sockets 
+totally
+  The Desktop and mobile only support 2 channels * 2 slots per channel 
+= 4 sockets totally
+  So there is mapping rule here for Desktop and mobile that there are no more 4 DIMMS totally in a system:
+    Channel A/ Slot 0 --> Dimm 0 --> SpdAddressTable[0]
+    Channel A/ Slot 1 --> Dimm 1 --> SpdAddressTable[1]
+    Channel B/ Slot 0 --> Dimm 2 --> SpdAddressTable[2]
+    Channel B/ Slot 1 --> Dimm 3 --> SpdAddressTable[3]
+  Refer to SmbiosMemory.c for use
+  If change the mapping rule, please update the Revision number.
+**/
+  UINT8                                           *SpdAddressTable;
+/**
+  Offset 36:
+  ChannelASlotMap and ChannelBSlotMap change to use SlotMap as the DIMM slot map solution.
+  Reserve 2-bytes in order to comply with 4-bytes alignment and keep the offset of other members.
+**/
+  UINT8                                           ChannelASlotMap;
+  UINT8                                           ChannelBSlotMap;
+/**
+  Offset 38:
+  MRC execution time measurement: <b>0=Disable</b>, 1=Enable **/
+  UINT8                                           MrcTimeMeasure;
+/**
+  Offset 39:
+  Fast boot: 0=Disable, <b>1=Enable</b> **/
+  UINT8                                           MrcFastBoot;
+/**
+  Offset 40:
+  Retrieves the OEM custom string for the SMBIOS Type 17 Table DeviceLocator field.
+**/
+  MEMORY_DXE_CONFIG_GET_DEVICE_LOCATOR_STRING     GetDeviceLocatorString;
+/**
+  Offset 48:
+  Retrieves the OEM custom string for the SMBIOS Type 17 Table BankLocator field.
+**/
+  MEMORY_DXE_CONFIG_GET_BANK_LOCATOR_STRING       GetBankLocatorString;
+/**
+  Offset 56:
+  Each DIMM Slot Mechanical present bit map, bit 0 -> DIMM 0, bit 1 -> DIMM1, ...
+  if the bit is 1, the related DIMM slot is present.
+  E.g. if memory controller 0 channel 3 has 2 DIMMs,  SlotMap[0][3] = 
+0x03;
+  E.g. if memory controller 1 channel 2 has only 1 DIMMs,  
+SlotMap[1][2] = 0x0; **/
+  UINT8                                           **SlotMap;
+};
+#pragma pack(pop)
+
+#endif // _MEMORY_DXE_CONFIG_H_
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/ConfigBlock/SaMiscPeiPreMemConfig.h b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/ConfigBlock/SaMiscPeiPreMemConfig.h
new file mode 100644
index 0000000000..cb75696b61
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/ConfigBlock/
+++ SaMiscPeiPreMemConfig.h
@@ -0,0 +1,112 @@
+/** @file
+  Policy details for miscellaneous configuration in System Agent
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent **/ #ifndef 
+_SA_MISC_PEI_PREMEM_CONFIG_H_ #define _SA_MISC_PEI_PREMEM_CONFIG_H_
+
+#pragma pack(push, 1)
+
+#ifndef MEM_CFG_MAX_SOCKETS
+#define MEM_CFG_MAX_SOCKETS 16
+#endif
+
+#define SA_MISC_PEI_PREMEM_CONFIG_REVISION 1
+
+/**
+  This configuration block is to configure SA Miscellaneous variables 
+during PEI Pre-Mem phase like programming
+  different System Agent BARs, TsegSize, MmioSize required etc.
+  <b>Revision 1</b>:
+  - Initial version.
+**/
+typedef struct {
+  CONFIG_BLOCK_HEADER  Header;               ///< Offset 0-27 Config Block Header
+  /**
+    Offset 28 Memory DIMMs' SPD address for reading SPD data.
+    TGL Mapping
+      0 - Controller 0 Channel 0 Dimm 0 - DDR4 - DDR5 - LPDDR4 - LPDDR5
+      1 - Controller 0 Channel 0 Dimm 1 - DDR4
+      2 - Controller 0 Channel 1 Dimm 0 -------- DDR5 - LPDDR4 - LPDDR5
+      3 - Controller 0 Channel 1 Dimm 1 -------- DDR5 2DPC
+      4 - Controller 0 Channel 2 Dimm 0 --------------- LPDDR4 - LPDDR5
+      6 - Controller 0 Channel 3 Dimm 0 --------------- LPDDR4 - LPDDR5
+      8 - Controller 1 Channel 0 Dimm 0 - DDR4 - DDR5 - LPDDR4 - LPDDR5
+      9 - Controller 1 Channel 0 Dimm 1 - DDR4
+     10 - Controller 1 Channel 1 Dimm 0 -------- DDR5 - LPDDR4 - LPDDR5
+     11 - Controller 1 Channel 1 Dimm 1 -------- DDR5 2DPC
+     12 - Controller 1 Channel 2 Dimm 0 --------------- LPDDR4 - LPDDR5
+     14 - Controller 1 Channel 3 Dimm 0 --------------- LPDDR4 - LPDDR5
+  **/
+  UINT8   SpdAddressTable[MEM_CFG_MAX_SOCKETS];
+  VOID    *S3DataPtr;                        ///< Offset 44 Memory data save pointer for S3 resume. The memory space should be allocated and filled with proper S3 resume data on a resume path
+  UINT32  SmbusBar;                          ///< Offset 48 Address of System Agent SMBUS BAR: <b>0xEFA0</b>
+  /**
+    Offset 52 Size of TSEG in bytes. (Must be power of 2)
+    <b>0x400000</b>: 4MB for Release build (When IED enabled, it will be 8MB)
+    0x1000000      : 16MB for Debug build (Regardless IED enabled or disabled)
+  **/
+  UINT32  TsegSize;
+  /**
+    Offset 56
+    <b>(Test)</b> Size of IED region in bytes.
+    <b>0</b> : IED Disabled (no memory occupied)
+    0x400000 : 4MB SMM memory occupied by IED (Part of TSEG)
+    <b>Note: Enabling IED may also enlarge TsegSize together.</b>
+    @deprecated
+  **/
+  UINT32  IedSize;
+  UINT32  SkipExtGfxScan:1;                  ///< <b>(Test)</b> OFfset 60:0 :1=Skip External Gfx Device Scan; <b>0=Scan for external graphics devices</b>. Set this policy to skip External Graphics card scanning if the platform uses Internal Graphics only.
+  UINT32  BdatEnable:1;                      ///< Offset 60:1 :This field enables the generation of the BIOS DATA ACPI Tables: <b>0=FALSE</b>, 1=TRUE.
+  UINT32  TxtImplemented:1;                  ///< OFfset 60:2 :This field currently is used to tell MRC if it should run after TXT initializatoin completed: <b>0=Run without waiting for TXT</b>, 1=Run after TXT initialization by callback
+  /**
+   Offset 60:3 :
+   <b>(Test)</b> Scan External Discrete Graphics Devices for Legacy 
+Only VGA OpROMs
+
+   When enabled, if the primary graphics device is an external discrete graphics device, Si will scan the
+   graphics device for legacy only VGA OpROMs.
+
+   This is intended to ease the implementation of a BIOS feature to automatically enable CSM if the Primary Gfx device
+   only supports Legacy VBIOS (No UEFI GOP Present).  Otherwise disabling CSM won't result in no video being displayed.
+   This is useful for platforms that implement PCIe slots that allow the end user to install an arbitrary Gfx device.
+
+   This setting will only take effect if SkipExtGfxScan == 0.  It is ignored otherwise.
+
+  - Disabled (0x0)         : Don't Scan for Legacy Only VGA OpROMs (Default)
+  - <b>Enabled</b>  (0x1)  : Scan External Gfx for Legacy Only VGA 
+ OpROM  **/
+  UINT32  ScanExtGfxForLegacyOpRom:1;
+  UINT32  RsvdBits0  :28;                    ///< Offset 60:4 :Reserved for future use
+  UINT8   UserBd;                            ///< Offset 64 <b>0=Mobile/Mobile Halo</b>, 1=Desktop/DT Halo, 2=Desktop 2DPC DDR5, 5=ULT/ULX/Mobile Halo Type3, 6=ULT/ULX/Mobile Halo Type4, 8=UP Server
+  UINT8   LockPTMregs;                       ///< <b>(Test)</b> Offset 65 Lock PCU Thermal Management registers: 0=FALSE, <b>1=TRUE</b>
+  UINT8   BdatTestType;                      ///< Offset 66 When BdatEnable is set to TRUE, this option selects the type of data which will be populated in the BIOS Data ACPI Tables: <b>0=RMT</b>, 1=RMT Per Bit, 2=Margin 2D.
+  UINT8   CridEnable;                        ///< Offset 67 For Platforms supporting Intel(R) SIPP, this policy is use control enable/disable Compatibility Revision ID (CRID) feature: <b>0=FALSE</b>, 1=TRUE
+  UINT32  AcpiReservedMemorySize;            ///< Offset 68 The Size of a Reserved memory buffer allocated in previous boot for S3 resume used. Originally it is retrieved from AcpiVariableCompatibility variable.
+  UINT64  AcpiReservedMemoryBase;            ///< Offset 80 The Base address of a Reserved memory buffer allocated in previous boot for S3 resume used. Originally it is retrieved from AcpiVariableCompatibility variable.
+  UINT64  SystemMemoryLength;                ///< Offset 88 Total system memory length from previous boot, this is required for S3 resume. Originally it is retrieved from AcpiVariableCompatibility variable.
+
+  UINT8   WrcFeatureEnable;                   ///< Offset 96: Enable/Disable WRC (Write Cache) feature of IOP. When enabled, supports IO devices allocating onto the ring and into LLC.
+  UINT8   FirstDimmBitMask;                   ///< Offset 97: Defines which DIMM should be populated first on a 2DPC board.
+                                              ///<            4 bit mask: Bit[0]: MC0 DIMM0, Bit[1]: MC0 DIMM1, Bit[2]: MC1 DIMM0, Bit[3]: MC1 DIMM1.
+                                              ///<            For each MC, the first DIMM to be populated should be set to '1'.
+                                              ///<            Note: this mask is only for non-ECC DIMM.
+  UINT8   FirstDimmBitMaskEcc;                ///< Offset 98: Defines which ECC DIMM should be populated first on a 2DPC board.
+                                              ///<            4 bit mask: Bit[0]: MC0 DIMM0, Bit[1]: MC0 DIMM1, Bit[2]: MC1 DIMM0, Bit[3]: MC1 DIMM1.
+                                              ///<            For each MC, the first DIMM to be populated should be set to '1'.
+                                              ///<            For example, if one MC is T-topology, there is no special population rule, can put it as 11 for this MC and it means either D0 or D1 can be
+                                              ///<            be populated firstly.
+                                              ///<            Note: this mask is only for ECC DIMM, not for non-ECC DIMM.
+
+  UINT8   DisableMrcRetrainingOnRtcPowerLoss; ///< Offset 99: Enable/Disable DisableMrcRetrainingOnRtcPowerLoss.
+
+
+  // Since the biggest element is UINT64, this structure should be aligned with 64 bits.
+  UINT8   Rsvd[4];                           ///< Reserved for config block alignment.
+  UINT8  ResizableBarSupport;
+
+  UINT8  Rsrvd1[7];
+} SA_MISC_PEI_PREMEM_CONFIG;
+#pragma pack(pop)
+
+#endif // _SA_MISC_PEI_PREMEM_CONFIG_H_
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/Library/DxeSaPolicyLib.h b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/Library/DxeSaPolicyLib.h
new file mode 100644
index 0000000000..5f5eeeeb63
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/Library/DxeS
+++ aPolicyLib.h
@@ -0,0 +1,58 @@
+/** @file
+  Prototype of the DxeSaPolicyLib library.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent **/ #ifndef 
+_DXE_SA_POLICY_LIB_H_ #define _DXE_SA_POLICY_LIB_H_
+
+#include <Protocol/SaPolicy.h>
+
+/**
+  This function prints the DXE phase policy.
+
+  @param[in] SaPolicy    - SA DXE Policy protocol
+**/
+VOID
+SaPrintPolicyProtocol (
+  IN  SA_POLICY_PROTOCOL         *SaPolicy
+  )
+;
+
+/**
+  CreateSaDxeConfigBlocks generates the config blocksg of SA DXE Policy.
+  It allocates and zero out buffer, and fills in the Intel default settings.
+
+  @param[out] SaPolicy                  The pointer to get SA Policy Protocol instance
+
+  @retval EFI_SUCCESS                   The policy default is initialized.
+  @retval EFI_OUT_OF_RESOURCES          Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+CreateSaDxeConfigBlocks(
+  IN OUT  SA_POLICY_PROTOCOL      **SaPolicy
+);
+
+/**
+  SaInstallPolicyProtocol installs SA Policy.
+  While installed, RC assumes the Policy is ready and finalized. So 
+please update and override
+  any setting before calling this function.
+
+  @param[in] ImageHandle                Image handle of this driver.
+  @param[in] SaPolicy                   The pointer to SA Policy Protocol instance
+
+  @retval EFI_SUCCESS                   The policy is installed.
+  @retval EFI_OUT_OF_RESOURCES          Insufficient resources to create buffer
+
+**/
+EFI_STATUS
+EFIAPI
+SaInstallPolicyProtocol (
+  IN  EFI_HANDLE                  ImageHandle,
+  IN  SA_POLICY_PROTOCOL         *SaPolicy
+  )
+;
+
+#endif // _DXE_SA_POLICY_LIB_H_
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/Library/PeiSaPolicyLib.h b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/Library/PeiSaPolicyLib.h
new file mode 100644
index 0000000000..8b941b4420
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/Library/PeiS
+++ aPolicyLib.h
@@ -0,0 +1,13 @@
+/** @file
+  Prototype of the PeiSaPolicy library.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent **/ #ifndef 
+_PEI_SA_POLICY_LIB_H_ #define _PEI_SA_POLICY_LIB_H_
+
+#include <Ppi/SiPolicy.h>
+#include <Library/ConfigBlockLib.h>
+
+#endif // _PEI_SA_POLICY_LIBRARY_H_
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/MemInfoHob.h b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/MemInfoHob.h
new file mode 100644
index 0000000000..d6c670d4ce
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/MemInfoHob.h
@@ -0,0 +1,220 @@
+/** @file
+  This file contains definitions required for creation of
+  Memory S3 Save data, Memory Info data and Memory Platform
+  data hobs.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent **/ #ifndef 
+_MEM_INFO_HOB_H_ #define _MEM_INFO_HOB_H_
+
+
+#pragma pack (push, 1)
+
+extern EFI_GUID gSiMemoryS3DataGuid;
+extern EFI_GUID gSiMemoryInfoDataGuid;
+extern EFI_GUID gSiMemoryPlatformDataGuid;
+
+#define MAX_NODE        2
+#define MAX_CH          4
+#define MAX_DIMM        2
+#define HOB_MAX_SAGV_POINTS 4
+
+///
+/// Defines taken from MRC so avoid having to include MrcInterface.h 
+///
+
+//
+// Matches MAX_SPD_SAVE define in MRC
+//
+#ifndef MAX_SPD_SAVE
+#define MAX_SPD_SAVE 29
+#endif
+
+//
+// MRC version description.
+//
+typedef struct {
+  UINT8  Major;     ///< Major version number
+  UINT8  Minor;     ///< Minor version number
+  UINT8  Rev;       ///< Revision number
+  UINT8  Build;     ///< Build number
+} SiMrcVersion;
+
+//
+// Matches MrcChannelSts enum in MRC
+//
+#ifndef CHANNEL_NOT_PRESENT
+#define CHANNEL_NOT_PRESENT     0  // There is no channel present on the controller.
+#endif
+#ifndef CHANNEL_DISABLED
+#define CHANNEL_DISABLED        1  // There is a channel present but it is disabled.
+#endif
+#ifndef CHANNEL_PRESENT
+#define CHANNEL_PRESENT         2  // There is a channel present and it is enabled.
+#endif
+
+//
+// Matches MrcDimmSts enum in MRC
+//
+#ifndef DIMM_ENABLED
+#define DIMM_ENABLED     0  // DIMM/rank Pair is enabled, presence will be detected.
+#endif
+#ifndef DIMM_DISABLED
+#define DIMM_DISABLED    1  // DIMM/rank Pair is disabled, regardless of presence.
+#endif
+#ifndef DIMM_PRESENT
+#define DIMM_PRESENT     2  // There is a DIMM present in the slot/rank pair and it will be used.
+#endif
+#ifndef DIMM_NOT_PRESENT
+#define DIMM_NOT_PRESENT 3  // There is no DIMM present in the slot/rank pair.
+#endif
+
+//
+// Matches MrcDdrType enum in MRC
+//
+#ifndef MRC_DDR_TYPE_DDR5
+#define MRC_DDR_TYPE_DDR5     1
+#endif
+#ifndef MRC_DDR_TYPE_LPDDR5
+#define MRC_DDR_TYPE_LPDDR5   2
+#endif
+#ifndef MRC_DDR_TYPE_LPDDR4
+#define MRC_DDR_TYPE_LPDDR4   3
+#endif
+#ifndef MRC_DDR_TYPE_UNKNOWN
+#define MRC_DDR_TYPE_UNKNOWN  4
+#endif
+
+#define MAX_PROFILE_NUM     7 // number of memory profiles supported
+#define MAX_XMP_PROFILE_NUM 5 // number of XMP profiles supported
+
+//
+// DIMM timings
+//
+typedef struct {
+  UINT32 tCK;       ///< Memory cycle time, in femtoseconds.
+  UINT16 NMode;     ///< Number of tCK cycles for the channel DIMM's command rate mode.
+  UINT16 tCL;       ///< Number of tCK cycles for the channel DIMM's CAS latency.
+  UINT16 tCWL;      ///< Number of tCK cycles for the channel DIMM's minimum CAS write latency time.
+  UINT16 tFAW;      ///< Number of tCK cycles for the channel DIMM's minimum four activate window delay time.
+  UINT16 tRAS;      ///< Number of tCK cycles for the channel DIMM's minimum active to precharge delay time.
+  UINT16 tRCDtRP;   ///< Number of tCK cycles for the channel DIMM's minimum RAS# to CAS# delay time and Row Precharge delay time.
+  UINT16 tREFI;     ///< Number of tCK cycles for the channel DIMM's minimum Average Periodic Refresh Interval.
+  UINT16 tRFC;      ///< Number of tCK cycles for the channel DIMM's minimum refresh recovery delay time.
+  UINT16 tRFCpb;    ///< Number of tCK cycles for the channel DIMM's minimum per bank refresh recovery delay time.
+  UINT16 tRFC2;     ///< Number of tCK cycles for the channel DIMM's minimum refresh recovery delay time.
+  UINT16 tRFC4;     ///< Number of tCK cycles for the channel DIMM's minimum refresh recovery delay time.
+  UINT16 tRPab;     ///< Number of tCK cycles for the channel DIMM's minimum row precharge delay time for all banks.
+  UINT16 tRRD;      ///< Number of tCK cycles for the channel DIMM's minimum row active to row active delay time.
+  UINT16 tRRD_L;    ///< Number of tCK cycles for the channel DIMM's minimum row active to row active delay time for same bank groups.
+  UINT16 tRRD_S;    ///< Number of tCK cycles for the channel DIMM's minimum row active to row active delay time for different bank groups.
+  UINT16 tRTP;      ///< Number of tCK cycles for the channel DIMM's minimum internal read to precharge command delay time.
+  UINT16 tWR;       ///< Number of tCK cycles for the channel DIMM's minimum write recovery time.
+  UINT16 tWTR;      ///< Number of tCK cycles for the channel DIMM's minimum internal write to read command delay time.
+  UINT16 tWTR_L;    ///< Number of tCK cycles for the channel DIMM's minimum internal write to read command delay time for same bank groups.
+  UINT16 tWTR_S;    ///< Number of tCK cycles for the channel DIMM's minimum internal write to read command delay time for different bank groups.
+  UINT16 tCCD_L;  ///< Number of tCK cycles for the channel DIMM's minimum CAS-to-CAS delay for same bank group.
+} MRC_CH_TIMING;
+
+typedef struct {
+  UINT16 tRDPRE;     ///< Read CAS to Precharge cmd delay
+} MRC_IP_TIMING;
+
+///
+/// Memory SMBIOS & OC Memory Data Hob
+///
+typedef struct {
+  UINT8            Status;                  ///< See MrcDimmStatus for the definition of this field.
+  UINT8            DimmId;
+  UINT32           DimmCapacity;            ///< DIMM size in MBytes.
+  UINT16           MfgId;
+  UINT8            ModulePartNum[20];       ///< Module part number for DDR3 is 18 bytes however for DRR4 20 bytes as per JEDEC Spec, so reserving 20 bytes
+  UINT8            RankInDimm;              ///< The number of ranks in this DIMM.
+  UINT8            SpdDramDeviceType;       ///< Save SPD DramDeviceType information needed for SMBIOS structure creation.
+  UINT8            SpdModuleType;           ///< Save SPD ModuleType information needed for SMBIOS structure creation.
+  UINT8            SpdModuleMemoryBusWidth; ///< Save SPD ModuleMemoryBusWidth information needed for SMBIOS structure creation.
+  UINT8            SpdSave[MAX_SPD_SAVE];   ///< Save SPD Manufacturing information needed for SMBIOS structure creation.
+  UINT16           Speed;                   ///< The maximum capable speed of the device, in MHz
+  UINT8            MdSocket;                ///< MdSocket: 0 = Memory Down, 1 = Socketed. Needed for SMBIOS structure creation.
+} DIMM_INFO;
+
+typedef struct {
+  UINT8            Status;                  ///< Indicates whether this channel should be used.
+  UINT8            ChannelId;
+  UINT8            DimmCount;               ///< Number of valid DIMMs that exist in the channel.
+  MRC_CH_TIMING    Timing[MAX_PROFILE_NUM]; ///< The channel timing values.
+  DIMM_INFO        DimmInfo[MAX_DIMM];      ///< Save the DIMM output characteristics.
+} CHANNEL_INFO;
+
+typedef struct {
+  UINT8            Status;                  ///< Indicates whether this controller should be used.
+  UINT16           DeviceId;                ///< The PCI device id of this memory controller.
+  UINT8            RevisionId;              ///< The PCI revision id of this memory controller.
+  UINT8            ChannelCount;            ///< Number of valid channels that exist on the controller.
+  CHANNEL_INFO     ChannelInfo[MAX_CH];     ///< The following are channel level definitions.
+} CONTROLLER_INFO;
+
+/// This data structure contains per-SaGv timing values that are considered output by the MRC.
+typedef struct {
+  UINT32        DataRate;    ///< The memory rate for the current SaGv Point in units of MT/s
+  MRC_CH_TIMING JedecTiming; ///< Timings used for this entry's corresponding SaGv Point - derived from JEDEC SPD spec
+  MRC_IP_TIMING IpTiming;    ///< Timings used for this entry's corresponding SaGv Point - IP specific
+} HOB_SAGV_TIMING_OUT;
+
+/// This data structure contains SAGV config values that are considered output by the MRC.
+typedef struct {
+  UINT32              NumSaGvPointsEnabled; ///< Count of the total number of SAGV Points enabled.
+  UINT32              SaGvPointMask;        ///< Bit mask where each bit indicates an enabled SAGV point.
+  HOB_SAGV_TIMING_OUT SaGvTiming[HOB_MAX_SAGV_POINTS]; } HOB_SAGV_INFO;
+
+typedef struct {
+  UINT8             Revision;
+  UINT16            DataWidth;              ///< Data width, in bits, of this memory device
+  /** As defined in SMBIOS 3.0 spec
+    Section 7.18.2 and Table 75
+  **/
+  UINT8             MemoryType;             ///< DDR type: DDR3, DDR4, or LPDDR3
+  UINT16            MaximumMemoryClockSpeed;///< The maximum capable speed of the device, in megahertz (MHz)
+  UINT16            ConfiguredMemoryClockSpeed; ///< The configured clock speed to the memory device, in megahertz (MHz)
+  /** As defined in SMBIOS 3.0 spec
+    Section 7.17.3 and Table 72
+  **/
+  UINT8             ErrorCorrectionType;
+
+  SiMrcVersion      Version;
+  BOOLEAN           EccSupport;
+  UINT8             MemoryProfile;
+  UINT8             IsDMBRunning;                      ///< Deprecated.
+  UINT32            TotalPhysicalMemorySize;
+  UINT32            DefaultXmptCK[MAX_XMP_PROFILE_NUM];///< Stores the tCK value read from SPD XMP profiles if they exist.
+  ///
+  /// Set of bit flags showing XMP and User Profile capability status for the DIMMs detected in system. For each bit, 1 is supported, 0 is unsupported.
+  /// Bit 0: XMP Profile 1 capability status
+  /// Bit 1: XMP Profile 2 capability status
+  /// Bit 2: XMP Profile 3 capability status
+  /// Bit 3: User Profile 4 capability status
+  /// Bit 4: User Profile 5 capability status
+  ///
+  UINT8             XmpProfileEnable;
+  UINT8             XmpConfigWarning;                  ///< If XMP capable DIMMs config support only 1DPC, but 2DPC is installed
+  UINT8             Ratio;                             ///< DDR Frequency Ratio, Max Value 255
+  UINT8             RefClk;
+  UINT32            VddVoltage[MAX_PROFILE_NUM];
+  UINT32            VddqVoltage[MAX_PROFILE_NUM];
+  UINT32            VppVoltage[MAX_PROFILE_NUM];
+  CONTROLLER_INFO   Controller[MAX_NODE];
+  UINT16            Ratio_UINT16;                      ///< DDR Frequency Ratio, used for programs that require ratios higher then 255
+  UINT32            NumPopulatedChannels;              ///< Total number of memory channels populated
+  HOB_SAGV_INFO     SagvConfigInfo;                    ///< This data structure contains SAGV config values that are considered output by the MRC.
+  UINT16            TotalMemWidth;                     ///< Total Memory Width in bits from all populated channels
+  BOOLEAN           MemorySpeedReducedWrongDimmSlot;   ///< Can be used by OEM BIOS to display a warning on the screen that DDR speed was reduced due to wrong DIMM population
+  BOOLEAN           MemorySpeedReducedMixedConfig;     ///< Can be used by OEM BIOS to display a warning on the screen that DDR speed was reduced due to mixed DIMM config
+  BOOLEAN           DynamicMemoryBoostTrainingFailed;  ///< TRUE if Dynamic Memory Boost failed to train and was force disabled on the last full training boot. FALSE otherwise.
+} MEMORY_INFO_DATA_HOB;
+
+#pragma pack (pop)
+
+#endif // _MEM_INFO_HOB_H_
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/Protocol/SaPolicy.h b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/Protocol/SaPolicy.h
new file mode 100644
index 0000000000..cc258debe1
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/Protocol/SaP
+++ olicy.h
@@ -0,0 +1,54 @@
+/** @file
+  Interface definition details between System Agent and platform drivers during DXE phase.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent **/ #ifndef 
+_SA_POLICY_H_ #define _SA_POLICY_H_
+
+#include <ConfigBlock.h>
+#include <Library/ConfigBlockLib.h>
+#include <GraphicsConfig.h>
+#include <ConfigBlock/MemoryDxeConfig.h>
+
+///
+/// Extern the GUID for protocol users.
+///
+extern EFI_GUID gSaPolicyProtocolGuid;
+extern EFI_GUID gGraphicsDxeConfigGuid; extern EFI_GUID 
+gMemoryDxeConfigGuid;
+
+/**
+  Don't change the original SA_POLICY_PROTOCOL_REVISION macro, external
+  modules maybe have consumed this macro in their source code.  
+Directly
+  update the SA_POLICY_PROTOCOL_REVISION version number may cause those
+  external modules to auto mark themselves wrong version info.
+  Always create new version macro for new Policy protocol interface.
+**/
+#define SA_POLICY_PROTOCOL_REVISION  1
+
+
+
+
+/**
+  SA DXE Policy
+
+ The SA_POLICY_PROTOCOL producer drvier is recommended to set all the 
+ SA_POLICY_PROTOCOL size buffer zero before init any member parameter, 
+ this clear step can make sure no random value for those unknow new version parameters.
+
+ Make sure to update the Revision if any change to the protocol, 
+including the existing  internal structure definations.\n
+  Note: Here revision will be bumped up when adding/removing any config 
+block under this structure.\n
+  <b>Revision 1</b>:
+  - Initial version.
+**/
+typedef struct {
+  CONFIG_BLOCK_TABLE_HEADER      TableHeader;    ///< Offset 0-31
+/*
+  Individual Config Block Structures are added here in memory as part 
+of AddConfigBlock() */ } SA_POLICY_PROTOCOL;
+
+#endif
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/SaDataHob.h b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/SaDataHob.h
new file mode 100644
index 0000000000..bded1851f4
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Include/SaDataHob.h
@@ -0,0 +1,28 @@
+/** @file
+  The GUID definition for SaDataHob
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent **/ #ifndef 
+_SA_DATA_HOB_H_ #define _SA_DATA_HOB_H_
+
+#include <Base.h>
+#include <CpuPcieInfo.h>
+#include <Library/PcdLib.h>
+
+extern EFI_GUID gSaDataHobGuid;
+#pragma pack (push,1)
+
+///
+/// System Agent Data Hob
+///
+typedef struct {
+  EFI_HOB_GUID_TYPE        EfiHobGuidType;                       ///< GUID Hob type structure for gSaDataHobGuid
+  UINT8                    PrimaryDisplay;
+  BOOLEAN                  ResizableBarSupport;                  ///< Resizable BAR Support
+  UINT8                    Rsvd1[2];                             ///< Reserved for future use
+} SA_DATA_HOB;
+
+#pragma pack (pop)
+#endif
--
2.36.1.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#107163): https://edk2.groups.io/g/devel/message/107163
Mute This Topic: https://groups.io/mt/99554478/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [edk2-devel] [PATCH 8/8] AlderlakeSiliconPkg/SystemAgent: Add library and driver modules
  2023-06-15 17:53 ` [PATCH 8/8] AlderlakeSiliconPkg/SystemAgent: Add library and driver modules Saloni Kasbekar
@ 2023-07-24  8:07   ` Chaganty, Rangasai V
  0 siblings, 0 replies; 15+ messages in thread
From: Chaganty, Rangasai V @ 2023-07-24  8:07 UTC (permalink / raw)
  To: Kasbekar, Saloni, devel@edk2.groups.io
  Cc: Desimone, Nathaniel L, Oram, Isaac W, Chuang, Rosen

Reviewed-by: Sai Chaganty <rangasai.v.chaganty@intel.com>

-----Original Message-----
From: Kasbekar, Saloni <saloni.kasbekar@intel.com> 
Sent: Thursday, June 15, 2023 10:53 AM
To: devel@edk2.groups.io
Cc: Kasbekar, Saloni <saloni.kasbekar@intel.com>; Chaganty, Rangasai V <rangasai.v.chaganty@intel.com>; Desimone, Nathaniel L <nathaniel.l.desimone@intel.com>; Oram, Isaac W <isaac.w.oram@intel.com>; Chuang, Rosen <rosen.chuang@intel.com>
Subject: [PATCH 8/8] AlderlakeSiliconPkg/SystemAgent: Add library and driver modules

Adds the following modules:
- Library/DxeSaPolicyLib
- SaInit

Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Isaac Oram <isaac.w.oram@intel.com>
Cc: Rosen Chuang <rosen.chuang@intel.com>
Signed-off-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
---
 .../Library/DxeSaPolicyLib/DxeSaPolicyLib.c   | 225 ++++++++++++++++++
 .../Library/DxeSaPolicyLib/DxeSaPolicyLib.inf |  46 ++++
 .../DxeSaPolicyLib/DxeSaPolicyLibrary.h       |  30 +++
 .../SystemAgent/SaInit/Dxe/SaAcpi.c           | 193 +++++++++++++++
 .../SystemAgent/SaInit/Dxe/SaInit.c           |  97 ++++++++
 .../SystemAgent/SaInit/Dxe/SaInit.h           |  42 ++++
 .../SystemAgent/SaInit/Dxe/SaInitDxe.c        |  90 +++++++
 .../SystemAgent/SaInit/Dxe/SaInitDxe.h        | 119 +++++++++
 .../SystemAgent/SaInit/Dxe/SaInitDxe.inf      |  98 ++++++++
 9 files changed, 940 insertions(+)
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLib.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLib.inf
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLibrary.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaAcpi.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInit.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInit.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.c
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.h
 create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.inf

diff --git a/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLib.c b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLib.c
new file mode 100644
index 0000000000..d812f300c1
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Library/DxeSaPolicyL
+++ ib/DxeSaPolicyLib.c
@@ -0,0 +1,225 @@
+/** @file
+  This file provide services for DXE phase policy default 
+initialization
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent **/
+
+#include "DxeSaPolicyLibrary.h"
+#include <Library/DxeGraphicsPolicyLib.h> #include 
+<Register/SaRegsHostBridge.h> #include "MemoryConfig.h"
+
+extern EFI_GUID gMemoryDxeConfigGuid;
+
+/**
+  This function prints the SA DXE phase policy.
+
+  @param[in] SaPolicy - SA DXE Policy protocol **/ VOID 
+SaPrintPolicyProtocol (
+  IN  SA_POLICY_PROTOCOL      *SaPolicy
+  )
+{
+  UINT8                       ControllerIndex;
+  UINT8                       ChannelIndex;
+  EFI_STATUS                  Status;
+  MEMORY_DXE_CONFIG           *MemoryDxeConfig;
+
+  Status = GetConfigBlock ((VOID *) SaPolicy, &gMemoryDxeConfigGuid, 
+ (VOID *)&MemoryDxeConfig);  ASSERT_EFI_ERROR (Status);
+
+
+  DEBUG_CODE_BEGIN ();
+  INTN  i;
+
+  DEBUG ((DEBUG_INFO, "\n------------------------ SA Policy (DXE) print 
+ BEGIN -----------------\n"));  DEBUG ((DEBUG_INFO, "Revision : %x\n", 
+ SaPolicy->TableHeader.Header.Revision));
+  ASSERT (SaPolicy->TableHeader.Header.Revision == 
+ SA_POLICY_PROTOCOL_REVISION);
+
+  DEBUG ((DEBUG_INFO, "------------------------ SA_MEMORY_CONFIGURATION 
+ -----------------\n"));
+
+  DEBUG ((DEBUG_INFO, " SpdAddressTable[%d] :", 4));  for (i = 0; i < 
+ 4; i++) {
+    DEBUG ((DEBUG_INFO, " %x", MemoryDxeConfig->SpdAddressTable[i]));
+  }
+  DEBUG ((DEBUG_INFO, "\n"));
+
+  for (ControllerIndex = 0; ControllerIndex < MEM_CFG_MAX_CONTROLLERS; ControllerIndex++) {
+    for (ChannelIndex = 0; ChannelIndex < MEM_CFG_MAX_CHANNELS; ChannelIndex++) {
+      DEBUG ((DEBUG_INFO, " SlotMap[%d][%d] : 0x%x\n", ControllerIndex, ChannelIndex, MemoryDxeConfig->SlotMap[ControllerIndex][ChannelIndex]));
+    }
+  }
+  DEBUG ((DEBUG_INFO, " MrcTimeMeasure  : %x\n", MemoryDxeConfig->MrcTimeMeasure));
+  DEBUG ((DEBUG_INFO, " MrcFastBoot     : %x\n", MemoryDxeConfig->MrcFastBoot));
+
+  DEBUG ((DEBUG_INFO, "------------------------ CPU_PCIE_CONFIGURATION 
+ -----------------\n"));  DEBUG ((DEBUG_INFO, " PegAspm[%d] :", 
+ SA_PEG_MAX_FUN));  DEBUG ((DEBUG_INFO, " PegRootPortHPE[%d] :", 
+ SA_PEG_MAX_FUN));  DEBUG ((DEBUG_INFO, "\n"));
+
+
+  DEBUG ((DEBUG_INFO, "\n------------------------ SA Policy (DXE) print 
+ END -----------------\n"));  DEBUG_CODE_END ();
+
+  return;
+}
+
+/**
+  Load DXE Config block default
+
+  @param[in] ConfigBlockPointer         Pointer to config block
+**/
+VOID
+LoadMemoryDxeDefault (
+  IN VOID    *ConfigBlockPointer
+  )
+{
+  UINT8                    ControllerIndex;
+  UINT8                    ChannelIndex;
+  MEMORY_DXE_CONFIG        *MemoryDxeConfig;
+
+  MemoryDxeConfig = ConfigBlockPointer;
+  ///
+  /// Initialize the Memory Configuration
+  ///
+  ///
+  /// DIMM SMBus addresses info
+  /// Refer to the SpdAddressTable[] mapping rule in 
+DxeSaPolicyLibrary.h
+  ///
+  MemoryDxeConfig->SpdAddressTable = AllocateZeroPool (sizeof (UINT8) * 
+4);
+  ASSERT (MemoryDxeConfig->SpdAddressTable != NULL);
+  if (MemoryDxeConfig->SpdAddressTable != NULL) {
+    MemoryDxeConfig->SpdAddressTable[0] = DIMM_SMB_SPD_P0C0D0;
+    MemoryDxeConfig->SpdAddressTable[1] = DIMM_SMB_SPD_P0C0D1;
+    MemoryDxeConfig->SpdAddressTable[2] = DIMM_SMB_SPD_P0C1D0;
+    MemoryDxeConfig->SpdAddressTable[3] = DIMM_SMB_SPD_P0C1D1;
+  }
+  MemoryDxeConfig->SlotMap = (UINT8**)AllocateZeroPool (sizeof (UINT8*) 
+* MEM_CFG_MAX_CONTROLLERS);
+  ASSERT (MemoryDxeConfig->SlotMap != NULL);
+  if (MemoryDxeConfig->SlotMap != NULL) {
+    for (ControllerIndex = 0; ControllerIndex < MEM_CFG_MAX_CONTROLLERS; ControllerIndex++) {
+      MemoryDxeConfig->SlotMap[ControllerIndex] = (UINT8*)AllocateZeroPool (sizeof (UINT8) * MEM_CFG_MAX_CHANNELS);
+      ASSERT (MemoryDxeConfig->SlotMap[ControllerIndex] != NULL);
+      if (MemoryDxeConfig->SlotMap[ControllerIndex] != NULL) {
+        for (ChannelIndex = 0; ChannelIndex < MEM_CFG_MAX_CHANNELS; ChannelIndex++) {
+          MemoryDxeConfig->SlotMap[ControllerIndex][ChannelIndex] = 0x01;
+        }
+      }
+    }
+  }
+}
+
+/**
+  LoadSaDxeConfigBlockDefault - Initialize default settings for each SA 
+Config block
+
+  @param[in] ConfigBlockPointer         The buffer pointer that will be initialized as specific config block
+  @param[in] BlockId                    Request to initialize defaults of specified config block by given Block ID
+
+  @retval EFI_SUCCESS                   The given buffer has contained the defaults of requested config block
+  @retval EFI_NOT_FOUND                 Block ID is not defined so no default Config block will be initialized
+**/
+
+GLOBAL_REMOVE_IF_UNREFERENCED COMPONENT_BLOCK_ENTRY  mSaDxeIpBlocks [] = {
+  {&gMemoryDxeConfigGuid,   sizeof (MEMORY_DXE_CONFIG),   MEMORY_DXE_CONFIG_REVISION,    LoadMemoryDxeDefault}
+};
+
+
+/**
+  CreateSaDxeConfigBlocks generates the config blocksg of SA DXE Policy.
+  It allocates and zero out buffer, and fills in the Intel default settings.
+
+  @param[out] SaPolicy               The pointer to get SA  DXE Protocol instance
+
+  @retval EFI_SUCCESS                   The policy default is initialized.
+  @retval EFI_OUT_OF_RESOURCES          Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+CreateSaDxeConfigBlocks (
+  IN OUT  SA_POLICY_PROTOCOL      **SaPolicy
+  )
+{
+  UINT16              TotalBlockSize;
+  EFI_STATUS          Status;
+  SA_POLICY_PROTOCOL  *SaInitPolicy;
+  UINT16              RequiredSize;
+
+  DEBUG ((DEBUG_INFO, "SA Create Dxe Config Blocks\n"));
+
+  SaInitPolicy = NULL;
+
+  TotalBlockSize = GetComponentConfigBlockTotalSize 
+ (&mSaDxeIpBlocks[0], sizeof (mSaDxeIpBlocks) / sizeof 
+ (COMPONENT_BLOCK_ENTRY));  TotalBlockSize += 
+ GraphicsGetConfigBlockTotalSizeDxe ();  DEBUG ((DEBUG_INFO, 
+ "TotalBlockSize = 0x%x\n", TotalBlockSize));
+
+  RequiredSize = sizeof (CONFIG_BLOCK_TABLE_HEADER) + TotalBlockSize;
+
+  Status = CreateConfigBlockTable (RequiredSize, (VOID *) 
+ &SaInitPolicy);  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Initialize Policy Revision
+  //
+  SaInitPolicy->TableHeader.Header.Revision = 
+ SA_POLICY_PROTOCOL_REVISION;  //  // Add config blocks.
+  //
+  Status =  AddComponentConfigBlocks ((VOID *) SaInitPolicy, 
+ &mSaDxeIpBlocks[0], sizeof (mSaDxeIpBlocks) / sizeof 
+ (COMPONENT_BLOCK_ENTRY));  ASSERT_EFI_ERROR (Status);
+
+
+  // Gfx
+  Status = GraphicsAddConfigBlocksDxe ((VOID *) SaInitPolicy);  
+ ASSERT_EFI_ERROR (Status);
+
+  //
+  // Assignment for returning SaInitPolicy config block base address
+  //
+  *SaPolicy = SaInitPolicy;
+  return Status;
+}
+
+
+/**
+  SaInstallPolicyProtocol installs SA Policy.
+  While installed, RC assumes the Policy is ready and finalized. So 
+please update and override
+  any setting before calling this function.
+
+  @param[in] ImageHandle                Image handle of this driver.
+  @param[in] SaPolicy                   The pointer to SA Policy Protocol instance
+
+  @retval EFI_SUCCESS                   The policy is installed.
+  @retval EFI_OUT_OF_RESOURCES          Insufficient resources to create buffer
+
+**/
+EFI_STATUS
+EFIAPI
+SaInstallPolicyProtocol (
+  IN  EFI_HANDLE                  ImageHandle,
+  IN  SA_POLICY_PROTOCOL         *SaPolicy
+  )
+{
+  EFI_STATUS            Status;
+
+  ///
+  /// Print SA DXE Policy
+  ///
+  SaPrintPolicyProtocol (SaPolicy);
+  GraphicsDxePolicyPrint (SaPolicy);
+
+  ///
+  /// Install protocol to to allow access to this Policy.
+  ///
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &ImageHandle,
+                  &gSaPolicyProtocolGuid,
+                  SaPolicy,
+                  NULL
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}
+
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLib.inf b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLib.inf
new file mode 100644
index 0000000000..02d52b6e6b
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Library/DxeSaPolicyL
+++ ib/DxeSaPolicyLib.inf
@@ -0,0 +1,46 @@
+## @file
+# Component description file for the PeiSaPolicy library.
+#
+#   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+#   SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = DxeSaPolicyLib
+FILE_GUID = B402A3A4-4B82-410E-B79C-5914880A05E7
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = DxeSaPolicyLib
+
+
+[LibraryClasses]
+BaseMemoryLib
+UefiRuntimeServicesTableLib
+UefiBootServicesTableLib
+DebugLib
+PostCodeLib
+ConfigBlockLib
+HobLib
+DxeGraphicsPolicyLib
+CpuPlatformLib
+
+[Packages]
+MdePkg/MdePkg.dec
+AlderlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+DxeSaPolicyLib.c
+DxeSaPolicyLibrary.h
+
+
+[Guids]
+gMemoryDxeConfigGuid
+
+
+[Protocols]
+gSaPolicyProtocolGuid ## PRODUCES
+
+[Pcd]
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLibrary.h b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLibrary.h
new file mode 100644
index 0000000000..14fc02512e
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/Library/DxeSaPolicyL
+++ ib/DxeSaPolicyLibrary.h
@@ -0,0 +1,30 @@
+/** @file
+  Header file for the DxeSaPolicy library.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent **/ #ifndef 
+_DXE_SA_POLICY_LIBRARY_H_ #define _DXE_SA_POLICY_LIBRARY_H_
+
+#include <Uefi.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h> #include 
+<Library/ConfigBlockLib.h> #include <CpuPcieConfigGen3.h> #include 
+<CpuPcieConfig.h> #include <Protocol/SaPolicy.h>
+
+#define WORD_FIELD_VALID_BIT  BIT15
+///
+/// DIMM SMBus addresses
+///
+#define DIMM_SMB_SPD_P0C0D0 0xA0
+#define DIMM_SMB_SPD_P0C0D1 0xA2
+#define DIMM_SMB_SPD_P0C1D0 0xA4
+#define DIMM_SMB_SPD_P0C1D1 0xA6
+
+#endif // _DXE_SA_POLICY_LIBRARY_H_
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaAcpi.c b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaAcpi.c
new file mode 100644
index 0000000000..f73995be0c
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaAcpi.c
@@ -0,0 +1,193 @@
+/** @file
+  This is the driver that initializes the Intel System Agent.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include 
+"SaInitDxe.h"
+#include "SaInit.h"
+#include <Protocol/SaNvsArea.h>
+#include <Library/PchInfoLib.h>
+#include <CpuPcieInfo.h>
+#include <Library/AslUpdateLib.h>
+#include <HostBridgeDataHob.h>
+#include <Library/CpuPlatformLib.h>
+#include <Library/PeiDxeSmmReserveMmio64SizeLib.h>
+#include <Register/Cpuid.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <Pi/PiFirmwareFile.h>
+
+///
+/// Global Variables
+///
+GLOBAL_REMOVE_IF_UNREFERENCED SYSTEM_AGENT_NVS_AREA_PROTOCOL  
+mSaNvsAreaProtocol;
+
+/**
+  A protocol callback which updates 64bits MMIO Base and Length in SA 
+GNVS area **/ VOID UpdateSaGnvsForMmioResourceBaseLength (
+  VOID
+  )
+{
+  EFI_PHYSICAL_ADDRESS      PciBaseAddress;
+  UINT32                    Tolud;
+  UINT64                    Length;
+  UINT64                    McD0BaseAddress;
+  UINTN                     ResMemLimit1;
+  BOOLEAN                   EnableAbove4GBMmioBiosAssignemnt;
+  VOID                      *CpuHob;
+  UINT8                     PhysicalAddressBits;
+  UINT64                    PhysicalAddressLimit;
+
+  PciBaseAddress                   = 0;
+  Tolud                            = 0;
+  Length                           = 0;
+  ResMemLimit1                     = 0;
+  EnableAbove4GBMmioBiosAssignemnt = TRUE;
+  CpuHob                           = NULL;
+  PhysicalAddressBits              = 0;
+  PhysicalAddressLimit             = 0;
+  //
+  // Read memory map registers
+  //
+  McD0BaseAddress        = PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, SA_MC_BUS, 0, 0, 0);
+  Tolud                  = PciSegmentRead32 (McD0BaseAddress + R_SA_TOLUD) & B_SA_TOLUD_TOLUD_MASK;
+  PciBaseAddress         = Tolud;
+
+  ResMemLimit1 = (UINTN) PcdGet64 (PcdSiPciExpressBaseAddress);
+
+  Length = ResMemLimit1 - PciBaseAddress;
+
+  CpuHob = GetFirstHob (EFI_HOB_TYPE_CPU);  if (CpuHob != NULL) {
+    PhysicalAddressBits  = ((EFI_HOB_CPU *) CpuHob)->SizeOfMemorySpace;
+    PhysicalAddressLimit = LShiftU64 (1, PhysicalAddressBits);  }  //  
+ // Check Enable Above 4GB MMIO or not  //
+
+  DEBUG ((DEBUG_INFO, "Update SA GNVS Area.\n"));
+  mSaNvsAreaProtocol.Area->Mmio32Base   = (UINT32) PciBaseAddress;
+  mSaNvsAreaProtocol.Area->Mmio32Length = (UINT32) Length;
+  if (EnableAbove4GBMmioBiosAssignemnt == TRUE) {
+    if (PhysicalAddressBits != 0 && ( PhysicalAddressLimit % 0x4000000000) == 0) { // Checking Memory Size multiples of 256GB
+      mSaNvsAreaProtocol.Area->Mmio64Base   = BASE_256GB;
+      //
+      // Some platforms need to reserve MMIO space from PhysicalAddressLimit for P2SB usage.
+      //
+      mSaNvsAreaProtocol.Area->Mmio64Length = PhysicalAddressLimit - mSaNvsAreaProtocol.Area->Mmio64Base - ReserveMmio64Size ();
+    } else {
+      mSaNvsAreaProtocol.Area->Mmio64Base   = BASE_256GB;
+      mSaNvsAreaProtocol.Area->Mmio64Length = SIZE_256GB;
+    }
+  }
+  DEBUG ((DEBUG_INFO, "SaNvsAreaProtocol.Area->Mmio64Base = %lx\n", 
+mSaNvsAreaProtocol.Area->Mmio64Base));
+  DEBUG ((DEBUG_INFO, "SaNvsAreaProtocol.Area->Mmio64Length = %lx\n", 
+mSaNvsAreaProtocol.Area->Mmio64Length));
+  DEBUG ((DEBUG_INFO, "SaNvsAreaProtocol.Area->Mmio32Base = %lx\n", 
+mSaNvsAreaProtocol.Area->Mmio32Base));
+  DEBUG ((DEBUG_INFO, "SaNvsAreaProtocol.Area->Mmio32Length = %lx\n", 
+mSaNvsAreaProtocol.Area->Mmio32Length));
+}
+
+/**
+  Initialize SA Nvs Area operation region.
+
+  @retval EFI_SUCCESS    initialized successfully
+  @retval EFI_NOT_FOUND  Nvs Area operation region is not found **/ 
+EFI_STATUS PatchSaNvsAreaAddress (
+  VOID
+  )
+{
+  EFI_STATUS                            Status;
+  UINT32                                Address;
+  UINT16                                Length;
+
+  Address = (UINT32) (UINTN) mSaNvsAreaProtocol.Area;  Length  = 
+ (UINT16) sizeof (SYSTEM_AGENT_NVS_AREA);  DEBUG ((DEBUG_INFO, 
+ "PatchSaNvsAreaAddress: SA NVS Address %x Length %x\n", Address, 
+ Length));
+
+  Status  = UpdateNameAslCode (SIGNATURE_32 ('S','A','N','B'), 
+ &Address, sizeof (Address));  ASSERT_EFI_ERROR (Status);  Status  = 
+ UpdateNameAslCode (SIGNATURE_32 ('S','A','N','L'), &Length, sizeof 
+ (Length));  ASSERT_EFI_ERROR (Status);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  This function gets registered as a callback to perform Dmar Igd
+
+  @param[in] Event     - A pointer to the Event that triggered the callback.
+  @param[in] Context   - A pointer to private data registered with the callback function.
+**/
+VOID
+EFIAPI
+SaAcpiEndOfDxeCallback (
+  IN EFI_EVENT    Event,
+  IN VOID         *Context
+  )
+{
+
+  DEBUG ((DEBUG_INFO, "%a - Start\n", __FUNCTION__));
+
+  PatchSaNvsAreaAddress();
+
+  DEBUG ((DEBUG_INFO, "%a - End\n", __FUNCTION__));
+  return;
+}
+
+
+/**
+  SystemAgent Acpi Initialization.
+
+  @param[in] ImageHandle             Handle for the image of this driver
+
+  @retval EFI_SUCCESS             The function completed successfully
+  @retval EFI_OUT_OF_RESOURCES    No enough buffer to allocate
+**/
+EFI_STATUS
+EFIAPI
+SaAcpiInit (
+  IN EFI_HANDLE         ImageHandle
+  )
+{
+  EFI_STATUS                Status;
+  EFI_EVENT                 EndOfDxeEvent;
+
+  ///
+  /// Install System Agent Global NVS protocol  ///  DEBUG 
+ ((DEBUG_INFO, "Install SA GNVS protocol\n"));  Status = 
+ (gBS->AllocatePool) (EfiACPIMemoryNVS, sizeof (SYSTEM_AGENT_NVS_AREA), 
+ (VOID **) &mSaNvsAreaProtocol.Area);  ASSERT_EFI_ERROR (Status);  
+ ZeroMem ((VOID *) mSaNvsAreaProtocol.Area, sizeof 
+ (SYSTEM_AGENT_NVS_AREA));
+
+
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &ImageHandle,
+                  &gSaNvsAreaProtocolGuid,
+                  &mSaNvsAreaProtocol,
+                  NULL
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+
+  ///
+  /// Register an end of DXE event for SA ACPI to do tasks before 
+ invoking any UEFI drivers,  /// applications, or connecting consoles,...
+  ///
+  
+  Status = gBS->CreateEventEx (
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_CALLBACK,
+                  SaAcpiEndOfDxeCallback,
+                  NULL,
+                  &gEfiEndOfDxeEventGroupGuid,
+                  &EndOfDxeEvent
+                  );
+
+  return EFI_SUCCESS;
+}
+
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInit.c b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInit.c
new file mode 100644
index 0000000000..5e472b0f60
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInit.c
@@ -0,0 +1,97 @@
+/** @file
+  This is the Common driver that initializes the Intel System Agent.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "SaInit.h"
+#include <Library/PciSegmentLib.h>
+#include <HostBridgeDataHob.h>
+#include <Protocol/PciEnumerationComplete.h>
+#include <Library/CpuPlatformLib.h>
+#include <Register/SaRegsHostBridge.h>
+
+///
+/// Global Variables
+///
+BOOLEAN                                                              mSkipPamLock = FALSE;
+
+/*
+  Intel(R) Core Processor Skylake BWG version 0.4.0
+
+  18.6 System Agent Configuration Locking
+   For reliable operation and security, System BIOS must set the following bits:
+   1. For all modern Intel processors, Intel strongly recommends that BIOS should set
+       the D_LCK bit. Set B0:D0:F0.R088h [4] = 1b to lock down SMRAM space.
+  BaseAddr values for mSaSecurityRegisters that uses 
+PciExpressBaseAddress will be initialized at
+  Runtime inside function CpuPcieInitPolicy().
+*/
+GLOBAL_REMOVE_IF_UNREFERENCED BOOT_SCRIPT_REGISTER_SETTING 
+mSaSecurityRegisters[] = {
+  {0,  R_SA_SMRAMC,  0xFFFFFFFF,  BIT4} };
+
+/**
+  SystemAgent Initialization Common Function.
+
+  @retval EFI_SUCCESS   - Always.
+**/
+
+VOID
+SaInitEntryPoint (
+  VOID
+  )
+{
+  HOST_BRIDGE_DATA_HOB        *HostBridgeDataHob;
+
+  ///
+  /// Get Host Bridge Data HOB
+  ///
+  HostBridgeDataHob = NULL;
+  HostBridgeDataHob = (HOST_BRIDGE_DATA_HOB *) GetFirstGuidHob 
+(&gHostBridgeDataHobGuid);
+  if (HostBridgeDataHob != NULL) {
+    mSkipPamLock = HostBridgeDataHob->SkipPamLock;
+  }
+  return;
+}
+
+/**
+  This function does SA security lock
+**/
+VOID
+SaSecurityLock (
+  VOID
+  )
+{
+  UINT8           Index;
+  UINT64          BaseAddress;
+  UINT32          RegOffset;
+  UINT32          Data32And;
+  UINT32          Data32Or;
+
+  ///
+  /// 17.2 System Agent Security Lock configuration  ///  DEBUG 
+ ((DEBUG_INFO, "DXE SaSecurityLock\n"));  for (Index = 0; Index < 
+ (sizeof (mSaSecurityRegisters) / sizeof (BOOT_SCRIPT_REGISTER_SETTING)); Index++) {
+    BaseAddress = mSaSecurityRegisters[Index].BaseAddr;
+    RegOffset   = mSaSecurityRegisters[Index].Offset;
+    Data32And   = mSaSecurityRegisters[Index].AndMask;
+    Data32Or    = mSaSecurityRegisters[Index].OrMask;
+
+    if (RegOffset == R_SA_SMRAMC) {
+      ///
+      /// SMRAMC LOCK must use CF8/CFC access
+      ///
+      PciCf8Or8 (PCI_CF8_LIB_ADDRESS (SA_MC_BUS, SA_MC_DEV, SA_MC_FUN, R_SA_SMRAMC), (UINT8) Data32Or);
+      BaseAddress = S3_BOOT_SCRIPT_LIB_PCI_ADDRESS (SA_MC_BUS, SA_MC_DEV, SA_MC_FUN, R_SA_SMRAMC);
+      S3BootScriptSavePciCfgReadWrite (
+        S3BootScriptWidthUint8,
+        (UINTN) BaseAddress,
+        &Data32Or,
+        &Data32And
+        );
+    }
+  }
+
+}
+
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInit.h b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInit.h
new file mode 100644
index 0000000000..14e48a3eb4
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInit.h
@@ -0,0 +1,42 @@
+/** @file
+  Header file for SA Common Initialization Driver.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent **/ #ifndef 
+_SA_INITIALIZATION_DRIVER_H_ #define _SA_INITIALIZATION_DRIVER_H_
+
+#include <Uefi.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Pci.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/UefiLib.h>
+#include <Library/IoLib.h>
+#include <Library/PciCf8Lib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h> #include 
+<Library/S3BootScriptLib.h> #include <Guid/EventGroup.h> #include 
+<CpuRegs.h> #include <Library/CpuPlatformLib.h> #include 
+<Protocol/SaPolicy.h>
+
+typedef struct {
+  UINT64  BaseAddr;
+  UINT32  Offset;
+  UINT32  AndMask;
+  UINT32  OrMask;
+} BOOT_SCRIPT_REGISTER_SETTING;
+
+/**
+  SystemAgent Initialization Common Function.
+
+  @retval EFI_SUCCESS   - Always.
+**/
+VOID
+SaInitEntryPoint (
+  VOID
+  );
+#endif
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.c b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.c
new file mode 100644
index 0000000000..0e613fce3a
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe
+++ .c
@@ -0,0 +1,90 @@
+/** @file
+  This is the driver that initializes the Intel System Agent.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include 
+"SaInitDxe.h"
+#include "SaInit.h"
+#include <MemInfoHob.h>
+#include <Protocol/PciEnumerationComplete.h>
+#include <Library/CpuPlatformLib.h>
+#include <Library/CpuPcieInfoFruLib.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16                   mPcieIoTrapAddress;
+
+/**
+  SystemAgent Dxe Initialization.
+
+  @param[in] ImageHandle             Handle for the image of this driver
+  @param[in] SystemTable             Pointer to the EFI System Table
+
+  @retval EFI_SUCCESS             The function completed successfully
+  @retval EFI_OUT_OF_RESOURCES    No enough buffer to allocate
+**/
+EFI_STATUS
+EFIAPI
+SaInitEntryPointDxe (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  )
+{
+  EFI_STATUS                Status;
+  VOID                      *Registration;
+#if FixedPcdGetBool(PcdFspWrapperEnable) == 0
+  EFI_EVENT                 Event;
+#endif
+
+  DEBUG ((DEBUG_INFO, "SaInitDxe Start\n"));
+
+  SaInitEntryPoint ();
+
+  Status = SaAcpiInit (ImageHandle);
+  ///
+  /// Create PCI Enumeration Completed callback for CPU PCIe  ///  
+ EfiCreateProtocolNotifyEvent (
+    &gEfiPciEnumerationCompleteProtocolGuid,
+    TPL_CALLBACK,
+    CpuPciEnumCompleteCallback,
+    NULL,
+    &Registration
+    );
+
+  DEBUG ((DEBUG_INFO, "SaInitDxe End\n"));
+
+  return EFI_SUCCESS;
+}
+
+/**
+  This function gets registered as a callback to perform CPU PCIe 
+initialization before EndOfDxe
+
+  @param[in] Event     - A pointer to the Event that triggered the callback.
+  @param[in] Context   - A pointer to private data registered with the callback function.
+**/
+VOID
+EFIAPI
+CpuPciEnumCompleteCallback (
+  IN EFI_EVENT    Event,
+  IN VOID         *Context
+  )
+{
+  EFI_STATUS          Status;
+  VOID                *ProtocolPointer;
+
+  DEBUG ((DEBUG_INFO, "CpuPciEnumCompleteCallback Start\n"));  ///  /// 
+ Check if this is first time called by EfiCreateProtocolNotifyEvent() 
+ or not,  /// if it is, we will skip it until real event is triggered  
+ ///  Status = gBS->LocateProtocol 
+ (&gEfiPciEnumerationCompleteProtocolGuid, NULL, (VOID **) 
+ &ProtocolPointer);  if (EFI_SUCCESS != Status) {
+    return;
+  }
+
+  gBS->CloseEvent (Event);
+
+  UpdateSaGnvsForMmioResourceBaseLength ();
+  DEBUG ((DEBUG_INFO, "CpuPciEnumCompleteCallback End\n"));
+  return;
+}
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.h b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.h
new file mode 100644
index 0000000000..72c0a25493
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe
+++ .h
@@ -0,0 +1,119 @@
+/** @file
+  Header file for SA Initialization Driver.
+
+   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+   SPDX-License-Identifier: BSD-2-Clause-Patent **/ #ifndef 
+_SA_INIT_DXE_DRIVER_H_ #define _SA_INIT_DXE_DRIVER_H_
+
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/AcpiTable.h>
+#include <Library/DxeIgdOpRegionInitLib.h> #include 
+<Library/CpuPlatformLib.h> #include <Register/SaRegsHostBridge.h>
+
+///
+/// Driver Consumed Protocol Prototypes /// #include 
+<Protocol/SaPolicy.h>
+
+typedef struct {
+  UINT64                Address;
+  EFI_BOOT_SCRIPT_WIDTH Width;
+  UINT32                Value;
+} BOOT_SCRIPT_PCI_REGISTER_SAVE;
+
+///
+/// Function Prototype
+///
+/**
+  This function gets registered as a callback to perform CPU PCIe 
+initialization before ExitPmAuth
+
+  @param[in] Event     - A pointer to the Event that triggered the callback.
+  @param[in] Context   - A pointer to private data registered with the callback function.
+
+**/
+VOID
+EFIAPI
+CpuPciEnumCompleteCallback (
+  IN EFI_EVENT Event,
+  IN VOID      *Context
+  );
+
+/**
+  <b>System Agent Initialization DXE Driver Entry Point</b>
+  - <b>Introduction</b> \n
+    Based on the information/data in SA_POLICY_PROTOCOL, this module performs further SA initialization in DXE phase,
+    e.g. internal devices enable/disable, SSVID/SID programming, graphic power-management, VT-d, IGD OpRegion initialization.
+    From the perspective of a PCI Express hierarchy, the Broadwell System Agent and PCH together appear as a Root Complex with root ports the number of which depends on how the 8 PCH ports and 4 System Agent PCIe ports are configured [4x1, 2x8, 1x16].
+    There is an internal link (DMI or OPI) that connects the System Agent to the PCH component. This driver includes initialization of SA DMI, PCI Express, SA & PCH Root Complex Topology.
+    For iGFX, this module implements the initialization of the Graphics Technology Power Management from the Broadwell System Agent BIOS Specification and the initialization of the IGD OpRegion/Software SCI - BIOS Specification.
+    The ASL files that go along with the driver define the IGD OpRegion mailboxes in ACPI space and implement the software SCI interrupt mechanism.
+    The IGD OpRegion/Software SCI code serves as a communication interface between system BIOS, ASL, and Intel graphics driver including making a block of customizable data (VBT) from the Intel video BIOS available.
+    Reference Code for the SCI service functions "Get BIOS Data" and "System BIOS Callback" can be found in the ASL files, those functions can be platform specific, the sample provided in the reference code are implemented for Intel CRB.
+    This module implements the VT-d functionality described in the Broadwell System Agent BIOS Specification.
+    This module publishes the LegacyRegion protocol to control the read and write accesses to the Legacy BIOS ranges.
+    E000 and F000 segments are the legacy BIOS ranges and contain pointers to the ACPI regions, SMBIOS tables and so on. This is a private protocol used by Intel Framework.
+    This module registers CallBack function that performs SA security registers lockdown at end of post as required from Broadwell Bios Spec.
+    In addition, this module publishes the SaInfo Protocol with information such as current System Agent reference code version#.
+
+  - @pre
+    - EFI_FIRMWARE_VOLUME_PROTOCOL: Documented in Firmware Volume Specification, available at the URL: http://www.intel.com/technology/framework/spec.htm
+    - SA_POLICY_PROTOCOL: A protocol published by a platform DXE module executed earlier; this is documented in this document as well.
+    - EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL: Documented in the Unified Extensible Firmware Interface Specification, version 2.0, available at the URL: http://www.uefi.org/specs/
+    - EFI_BOOT_SCRIPT_SAVE_PROTOCOL: A protocol published by a platform DXE module executed earlier; refer to the Sample Code section of the Framework PCH Reference Code.
+    - EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL: Documented in the Unified Extensible Firmware Interface Specification, version 2.0, available at the URL: http://www.uefi.org/specs/
+    - EFI_ACPI_TABLE_PROTOCOL : Documented in PI Specification 1.2
+    - EFI_CPU_IO_PROTOCOL: Documented in CPU I/O Protocol Specification, available at the URL: http://www.intel.com/technology/framework/spec.htm
+    - EFI_DATA_HUB_PROTOCOL: Documented in EFI Data Hub Infrastructure Specification, available at the URL: http://www.intel.com/technology/framework/spec.htm
+    - EFI_HII_PROTOCOL (or EFI_HII_DATABASE_PROTOCOL for UEFI 2.1): Documented in Human Interface Infrastructure Specification, available at the URL: http://www.intel.com/technology/framework/spec.htm
+    (For EFI_HII_DATABASE_PROTOCOL, refer to UEFI Specification Version 
+ 2.1 available at the URL: http://www.uefi.org/)
+
+  - @result
+    IGD power-management functionality is initialized;  VT-d is 
+ initialized (meanwhile, the DMAR table is updated); IGD OpRegion is 
+ initialized - IGD_OPREGION_PROTOCOL installed, IGD OpRegion allocated 
+ and mailboxes initialized, chipset initialized and ready to generate 
+ Software SCI for Internal graphics events. Publishes the 
+ SA_INFO_PROTOCOL with current SA reference code version #. Publishes 
+ the EFI_LEGACY_REGION_PROTOCOL documented in the Compatibility Support 
+ Module Specification, version 0.9, available at the URL: 
+ http://www.intel.com/technology/framework/spec.htm
+
+  - <b>References</b> \n
+    IGD OpRegion/Software SCI for Broadwell
+    Advanced Configuration and Power Interface Specification Revision 4.0a.
+
+  - <b>Porting Recommendations</b> \n
+    No modification of the DXE driver should be typically necessary.
+    This driver should be executed after all related devices (audio, video, ME, etc.) are initialized to ensure correct data in DMAR table and DMA-remapping registers.
+
+  @param[in] ImageHandle             Handle for the image of this driver
+  @param[in] SystemTable             Pointer to the EFI System Table
+
+  @retval EFI_SUCCESS             The function completed successfully
+  @retval EFI_OUT_OF_RESOURCES    No enough buffer to allocate
+**/
+EFI_STATUS
+EFIAPI
+SaInitEntryPointDxe (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  );
+
+/**
+  SystemAgent Acpi Initialization.
+
+  @param[in] ImageHandle             Handle for the image of this driver
+
+  @retval EFI_SUCCESS             The function completed successfully
+  @retval EFI_OUT_OF_RESOURCES    No enough buffer to allocate
+**/
+EFI_STATUS
+EFIAPI
+SaAcpiInit (
+  IN EFI_HANDLE         ImageHandle
+  );
+
+/**
+  A protocol callback which updates 64bits MMIO Base and Length in SA 
+GNVS area **/ VOID UpdateSaGnvsForMmioResourceBaseLength (
+  VOID
+  );
+
+#endif
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.inf b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.inf
new file mode 100644
index 0000000000..b434ce9027
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe
+++ .inf
@@ -0,0 +1,98 @@
+## @file
+# Component description file for SystemAgent Initialization driver #
+#   Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+#   SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = SaInitDxe
+FILE_GUID = DE23ACEE-CF55-4fb6-AA77-984AB53DE811
+VERSION_STRING = 1.0
+MODULE_TYPE = DXE_DRIVER
+ENTRY_POINT = SaInitEntryPointDxe
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC
+#
+
+
+
+[LibraryClasses]
+UefiDriverEntryPoint
+UefiLib
+UefiBootServicesTableLib
+DxeServicesTableLib
+DebugLib
+TimerLib
+PciCf8Lib
+PciSegmentLib
+BaseMemoryLib
+MemoryAllocationLib
+CpuPlatformLib
+IoLib
+S3BootScriptLib
+PmcLib
+PchCycleDecodingLib
+PchInfoLib
+GpioLib
+ConfigBlockLib
+PchPcieRpLib
+DxeIgdOpRegionInitLib
+AslUpdateLib
+PeiDxeSmmReserveMmio64SizeLib
+CpuPcieInfoFruLib
+
+[Packages]
+MdePkg/MdePkg.dec
+UefiCpuPkg/UefiCpuPkg.dec
+IntelSiliconPkg/IntelSiliconPkg.dec
+AlderlakeSiliconPkg/SiPkg.dec
+
+[Pcd]
+gSiPkgTokenSpaceGuid.PcdSiPciExpressBaseAddress
+gSiPkgTokenSpaceGuid.PcdMchBaseAddress
+gSiPkgTokenSpaceGuid.PcdSiIoApicBaseAddress
+gSiPkgTokenSpaceGuid.PcdFspWrapperEnable
+gSiPkgTokenSpaceGuid.PcdCpuPcieEnable                  ## CONSUMES
+
+[FixedPcd]
+gSiPkgTokenSpaceGuid.PcdAdlLpSupport               ## CONSUMES
+gSiPkgTokenSpaceGuid.PcdAdlSSupport
+
+[Sources]
+SaInitDxe.h
+SaInitDxe.c
+SaInit.h
+SaInit.c
+SaAcpi.c
+
+[Protocols]
+gEfiAcpiTableProtocolGuid              ## CONSUMES
+gSaNvsAreaProtocolGuid                 ## PRODUCES
+gSaPolicyProtocolGuid                  ## CONSUMES
+gEfiCpuArchProtocolGuid                ## CONSUMES
+gEfiPciEnumerationCompleteProtocolGuid ## CONSUMES
+gEfiPciRootBridgeIoProtocolGuid        ## CONSUMES
+gIgdOpRegionProtocolGuid               ## PRODUCES
+gEfiFirmwareVolume2ProtocolGuid        ## CONSUMES
+gGopComponentName2ProtocolGuid         ## CONSUMES
+
+[Guids]
+gEfiEndOfDxeEventGroupGuid
+gSiConfigHobGuid        ## CONSUMES
+gGraphicsDxeConfigGuid
+gMemoryDxeConfigGuid
+gSaDataHobGuid
+gHostBridgeDataHobGuid
+
+[Depex]
+gEfiAcpiTableProtocolGuid AND
+gEfiFirmwareVolume2ProtocolGuid AND
+gSaPolicyProtocolGuid AND
+gEfiPciRootBridgeIoProtocolGuid AND
+gEfiPciHostBridgeResourceAllocationProtocolGuid AND # This is to ensure that PCI MMIO resource has been prepared and available for this driver to allocate.
+gEfiHiiDatabaseProtocolGuid
--
2.36.1.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#107164): https://edk2.groups.io/g/devel/message/107164
Mute This Topic: https://groups.io/mt/99554481/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2023-07-24  8:08 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-06-15 17:52 [PATCH 1/8] AlderlakeSiliconPkg: Add package and library instances Saloni Kasbekar
2023-06-15 17:53 ` [PATCH 2/8] AlderlakeSiliconPkg: Add Cpu modules Saloni Kasbekar
2023-06-15 17:53 ` [PATCH 3/8] AlderlakeSiliconPkg/Pch: Add include headers Saloni Kasbekar
2023-07-24  7:38   ` [edk2-devel] " Chaganty, Rangasai V
2023-06-15 17:53 ` [PATCH 4/8] AlderlakeSiliconPkg/Pch: Add libraries Saloni Kasbekar
2023-07-24  7:42   ` [edk2-devel] " Chaganty, Rangasai V
2023-06-15 17:53 ` [PATCH 5/8] AlderlakeSiliconPkg/Pch: Add drivers Saloni Kasbekar
2023-07-24  7:54   ` [edk2-devel] " Chaganty, Rangasai V
2023-06-15 17:53 ` [PATCH 6/8] AlderlakeSiliconPkg/SystemAgent: Add NVS support Saloni Kasbekar
2023-07-24  7:58   ` [edk2-devel] " Chaganty, Rangasai V
2023-06-15 17:53 ` [PATCH 7/8] AlderlakeSiliconPkg/SystemAgent: Add include headers Saloni Kasbekar
2023-07-24  8:03   ` [edk2-devel] " Chaganty, Rangasai V
2023-06-15 17:53 ` [PATCH 8/8] AlderlakeSiliconPkg/SystemAgent: Add library and driver modules Saloni Kasbekar
2023-07-24  8:07   ` [edk2-devel] " Chaganty, Rangasai V
2023-07-23  0:04 ` [edk2-devel] [PATCH 1/8] AlderlakeSiliconPkg: Add package and library instances Chaganty, Rangasai V

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox