public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: Zhen Gong <zhen.gong@intel.com>
To: devel@edk2.groups.io
Cc: Zhen Gong <zhen.gong@intel.com>
Subject: [edk2-devel] [PATCH edk2-platforms 1/4] IpmiFeaturePkg: Add Elog drivers
Date: Fri, 27 Oct 2023 13:11:13 -0700	[thread overview]
Message-ID: <151e2cd3461b6c577cd15e0ce862309e409129f0.1698437221.git.zhen.gong@intel.com> (raw)
In-Reply-To: <cover.1698437221.git.zhen.gong@intel.com>

Add generic Elog driver and support BMC Elog operations.

Signed-off-by: Zhen Gong <zhen.gong@intel.com>
---
 .../IpmiFeaturePkg/IpmiFeaturePkg.dec         |   5 +
 .../IpmiFeaturePkg/Include/IpmiFeature.dsc    |   7 +-
 .../IpmiFeaturePkg/Include/PostMemory.fdf     |   5 +-
 .../IpmiFeaturePkg/Include/PreMemory.fdf      |   1 +
 .../BmcElog/{BmcElog.inf => DxeBmcElog.inf}   |  25 +-
 .../IpmiFeaturePkg/BmcElog/PeiBmcElog.inf     |  43 ++
 .../IpmiFeaturePkg/BmcElog/SmmBmcElog.inf     |  44 ++
 .../GenericElog/Dxe/GenericElog.inf           |  38 ++
 .../GenericElog/Smm/GenericElog.inf           |  38 ++
 .../BmcElog/Common/BmcElogCommon.h            | 144 +++++
 .../IpmiFeaturePkg/BmcElog/Dxe/BmcElog.h      |  42 ++
 .../IpmiFeaturePkg/BmcElog/Pei/BmcElog.h      |  44 ++
 .../IpmiFeaturePkg/BmcElog/Smm/BmcElog.h      |  43 ++
 .../GenericElog/Dxe/GenericElog.h             | 194 ++++++
 .../GenericElog/Smm/GenericElog.h             | 216 +++++++
 .../IpmiFeaturePkg/Include/Ppi/GenericElog.h  |  84 +++
 .../Include/Protocol/GenericElog.h            |  99 +++
 .../IpmiFeaturePkg/BmcElog/BmcElog.c          | 236 -------
 .../BmcElog/Common/BmcElogCommon.c            | 465 ++++++++++++++
 .../IpmiFeaturePkg/BmcElog/Dxe/BmcElog.c      | 287 +++++++++
 .../IpmiFeaturePkg/BmcElog/Pei/BmcElog.c      | 297 +++++++++
 .../IpmiFeaturePkg/BmcElog/Smm/BmcElog.c      | 288 +++++++++
 .../GenericElog/Dxe/GenericElog.c             | 576 ++++++++++++++++++
 .../GenericElog/Smm/GenericElog.c             | 558 +++++++++++++++++
 24 files changed, 3535 insertions(+), 244 deletions(-)
 rename Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/{BmcElog.inf => DxeBmcElog.inf} (56%)
 create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/PeiBmcElog.inf
 create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/SmmBmcElog.inf
 create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Dxe/GenericElog.inf
 create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Smm/GenericElog.inf
 create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Common/BmcElogCommon.h
 create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Dxe/BmcElog.h
 create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Pei/BmcElog.h
 create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Smm/BmcElog.h
 create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Dxe/GenericElog.h
 create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Smm/GenericElog.h
 create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Ppi/GenericElog.h
 create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/GenericElog.h
 delete mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/BmcElog.c
 create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Common/BmcElogCommon.c
 create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Dxe/BmcElog.c
 create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Pei/BmcElog.c
 create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Smm/BmcElog.c
 create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Dxe/GenericElog.c
 create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Smm/GenericElog.c

diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFeaturePkg.dec b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFeaturePkg.dec
index 5df71300cbd1..22bc4e69be8a 100644
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFeaturePkg.dec
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFeaturePkg.dec
@@ -67,6 +67,7 @@ [Guids]
 [Ppis]
   gPeiIpmiTransportPpiGuid = {0x7bf5fecc, 0xc5b5, 0x4b25, {0x81, 0x1b, 0xb4, 0xb5, 0xb, 0x28, 0x79, 0xf7}}
   gPeiIpmiTransport2PpiGuid = {0x8122CEBD, 0xF4FD, 0x4EA8, { 0x97, 0x6C, 0xF0, 0x30, 0xAD, 0xDC, 0x4C, 0xB4 }}
+  gPeiRedirElogPpiGuid = { 0x7a7c1591, 0xfc67, 0x4f69, { 0xa3, 0x78, 0xfc, 0x3d, 0x4a, 0xd7, 0x92, 0xf7 } }
 
 [Protocols]
   gIpmiTransportProtocolGuid  = {0x6bb945e8, 0x3743, 0x433e, {0xb9, 0x0e, 0x29, 0xb3, 0x0d, 0x5d, 0xc6, 0x30}}
@@ -74,6 +75,10 @@ [Protocols]
   gEfiVideoPrintProtocolGuid     = {0x3dbf3e06, 0x9d0c, 0x40d3, {0xb2, 0x17, 0x45, 0x5f, 0x33, 0x9e, 0x29, 0x09}}
   gIpmiTransport2ProtocolGuid = { 0x4A1D0E66, 0x5271, 0x4E22, { 0x83, 0xFE, 0x90, 0x92, 0x1B, 0x74, 0x82, 0x13 }}
   gSmmIpmiTransport2ProtocolGuid = { 0x1DBD1503, 0x0A60, 0x4230, { 0xAA, 0xA3, 0x80, 0x16, 0xD8, 0xC3, 0xDE, 0x2F }}
+  gEfiGenericElogProtocolGuid = { 0x59d02fcd, 0x9233, 0x4d34, { 0xbc, 0xfe, 0x87, 0xca, 0x81, 0xd3, 0xdd, 0xa7 } }
+  gSmmGenericElogProtocolGuid = { 0x664ef1f6, 0x19bf, 0x4498, { 0xab, 0x6a, 0xfc, 0x05, 0x72, 0xfb, 0x98, 0x51 } }
+  gEfiRedirElogProtocolGuid = { 0x16d11030, 0x71ba, 0x4e5e, { 0xa9, 0xf9, 0xb4, 0x75, 0xa5, 0x49, 0x4, 0x8a } }
+  gSmmRedirElogProtocolGuid = { 0x79ac2d9c, 0x9216, 0x43c5, { 0xa0, 0x74, 0x0b, 0x45, 0xc7, 0x64, 0x22, 0xc1 } }
 
 [PcdsFeatureFlag]
   gIpmiFeaturePkgTokenSpaceGuid.PcdIpmiFeatureEnable|FALSE|BOOLEAN|0xA0000001
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiFeature.dsc b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiFeature.dsc
index 0401974b82e2..fa98e5672d83 100644
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiFeature.dsc
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiFeature.dsc
@@ -57,6 +57,7 @@ [LibraryClasses.common.DXE_RUNTIME_DRIVER, LibraryClasses.common.DXE_DRIVER]
   IpmbInterfaceLib|IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/IpmbInterfaceLib/DxeIpmbInterfaceLib.inf
 
 [LibraryClasses.common.DXE_SMM_DRIVER]
+  IpmiBaseLib|IpmiFeaturePkg/Library/SmmIpmiBaseLib/SmmIpmiBaseLib.inf
   SsifInterfaceLib|IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInterfaceLib/SmmSsifInterfaceLib.inf
   IpmbInterfaceLib|IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/IpmbInterfaceLib/SmmIpmbInterfaceLib.inf
 
@@ -96,6 +97,7 @@ [Components.IA32]
   IpmiFeaturePkg/GenericIpmi/Pei/PeiGenericIpmi.inf
   IpmiFeaturePkg/Frb/FrbPei.inf
   IpmiFeaturePkg/IpmiInit/PeiIpmiInit.inf
+  IpmiFeaturePkg/BmcElog/PeiBmcElog.inf
 
 #
 # Feature DXE Components
@@ -119,7 +121,10 @@ [Components.X64]
   IpmiFeaturePkg/GenericIpmi/Dxe/GenericIpmi.inf
   IpmiFeaturePkg/Library/SmmIpmiBaseLib/SmmIpmiBaseLib.inf
   IpmiFeaturePkg/BmcAcpi/BmcAcpi.inf
-  IpmiFeaturePkg/BmcElog/BmcElog.inf
+  IpmiFeaturePkg/BmcElog/DxeBmcElog.inf
+  IpmiFeaturePkg/BmcElog/SmmBmcElog.inf
+  IpmiFeaturePkg/GenericElog/Dxe/GenericElog.inf
+  IpmiFeaturePkg/GenericElog/Smm/GenericElog.inf
   IpmiFeaturePkg/Frb/FrbDxe.inf
   IpmiFeaturePkg/IpmiFru/IpmiFru.inf
   IpmiFeaturePkg/IpmiInit/DxeIpmiInit.inf
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/PostMemory.fdf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/PostMemory.fdf
index e0f3bbe158d9..f29810bc0b34 100644
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/PostMemory.fdf
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/PostMemory.fdf
@@ -10,8 +10,11 @@
 INF IpmiFeaturePkg/GenericIpmi/Dxe/GenericIpmi.inf
 INF IpmiFeaturePkg/IpmiInit/DxeIpmiInit.inf
 INF RuleOverride = DRIVER_ACPITABLE IpmiFeaturePkg/BmcAcpi/BmcAcpi.inf
-INF IpmiFeaturePkg/BmcElog/BmcElog.inf
+INF IpmiFeaturePkg/BmcElog/DxeBmcElog.inf
+INF IpmiFeaturePkg/BmcElog/SmmBmcElog.inf
 INF IpmiFeaturePkg/Frb/FrbDxe.inf
 INF IpmiFeaturePkg/IpmiFru/IpmiFru.inf
+INF IpmiFeaturePkg/GenericElog/Dxe/GenericElog.inf
+INF IpmiFeaturePkg/GenericElog/Smm/GenericElog.inf
 INF IpmiFeaturePkg/OsWdt/OsWdt.inf
 INF IpmiFeaturePkg/SolStatus/SolStatus.inf
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/PreMemory.fdf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/PreMemory.fdf
index d214988bd141..ca20546e9aa8 100644
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/PreMemory.fdf
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/PreMemory.fdf
@@ -10,3 +10,4 @@
 INF IpmiFeaturePkg/GenericIpmi/Pei/PeiGenericIpmi.inf
 INF IpmiFeaturePkg/IpmiInit/PeiIpmiInit.inf
 INF IpmiFeaturePkg/Frb/FrbPei.inf
+INF IpmiFeaturePkg/BmcElog/PeiBmcElog.inf
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/BmcElog.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/DxeBmcElog.inf
similarity index 56%
rename from Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/BmcElog.inf
rename to Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/DxeBmcElog.inf
index 388dd2740c69..dce3bc42ce05 100644
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/BmcElog.inf
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/DxeBmcElog.inf
@@ -1,12 +1,12 @@
 ### @file
-# Component description file for BMC ELOG.
 #
-# Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
 #
 # SPDX-License-Identifier: BSD-2-Clause-Patent
 #
 ###
 
+
 [Defines]
   INF_VERSION              = 0x00010005
   BASE_NAME                = BmcElog
@@ -17,17 +17,30 @@ [Defines]
   ENTRY_POINT              = InitializeBmcElogLayer
 
 [Sources]
-  BmcElog.c
+  Dxe/BmcElog.c
+  Dxe/BmcElog.h
+  Common/BmcElogCommon.h
+  Common/BmcElogCommon.c
 
 [Packages]
-  MdePkg/MdePkg.dec
   IpmiFeaturePkg/IpmiFeaturePkg.dec
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
 
 [LibraryClasses]
   UefiDriverEntryPoint
   DebugLib
   UefiBootServicesTableLib
-  IpmiCommandLib
+  ReportStatusCodeLib
+  MemoryAllocationLib
+  IpmiBaseLib
+
+[Protocols]
+  gEfiRedirElogProtocolGuid   # PROTOCOL ALWAYS_PRODUCED
 
 [Depex]
-  TRUE
+  gEfiLoadedImageProtocolGuid AND
+  gIpmiTransportProtocolGuid
+
+
+
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/PeiBmcElog.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/PeiBmcElog.inf
new file mode 100644
index 000000000000..8274033e42e6
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/PeiBmcElog.inf
@@ -0,0 +1,43 @@
+### @file
+#
+# Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+###
+
+
+[Defines]
+  INF_VERSION              = 0x00010005
+  BASE_NAME                = BmcElog
+  FILE_GUID                = FD2A000E-09EA-4899-B40E-32BE30A58EBD
+  MODULE_TYPE              = PEIM
+  VERSION_STRING           = 1.0
+  ENTRY_POINT              = InitializeBmcElogLayer
+
+[Sources]
+  Pei/BmcElog.c
+  Pei/BmcElog.h
+  Common/BmcElogCommon.h
+  Common/BmcElogCommon.c
+
+[Packages]
+  IpmiFeaturePkg/IpmiFeaturePkg.dec
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+  DebugLib
+  ReportStatusCodeLib
+  MemoryAllocationLib
+  PeiServicesLib
+  PeimEntryPoint
+  IpmiBaseLib
+
+[Ppis]
+  gPeiRedirElogPpiGuid   # PPI ALWAYS_PRODUCED
+  gPeiIpmiTransportPpiGuid
+
+[Depex]
+  TRUE
+
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/SmmBmcElog.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/SmmBmcElog.inf
new file mode 100644
index 000000000000..d6880f8baa1b
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/SmmBmcElog.inf
@@ -0,0 +1,44 @@
+### @file
+#
+# Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+###
+
+
+[Defines]
+  INF_VERSION              = 0x00010005
+  BASE_NAME                = SmBmcElog
+  FILE_GUID                = BE29A700-9D5A-4bb9-86B1-D1DB7A05D594
+  MODULE_TYPE              = DXE_SMM_DRIVER
+  PI_SPECIFICATION_VERSION = 0x0001000A
+  VERSION_STRING           = 1.0
+  ENTRY_POINT              = InitializeSmBmcElogLayer
+
+[Sources]
+  Smm/BmcElog.c
+  Smm/BmcElog.h
+  Common/BmcElogCommon.h
+  Common/BmcElogCommon.c
+
+[Packages]
+  IpmiFeaturePkg/IpmiFeaturePkg.dec
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+  UefiDriverEntryPoint
+  DebugLib
+  UefiBootServicesTableLib
+  ReportStatusCodeLib
+  SmmServicesTableLib
+  IpmiBaseLib
+
+[Protocols]
+  gSmmRedirElogProtocolGuid   # PROTOCOL ALWAYS_PRODUCED
+
+[Depex]
+  gEfiLoadedImageProtocolGuid AND
+  gSmmIpmiTransportProtocolGuid
+
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Dxe/GenericElog.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Dxe/GenericElog.inf
new file mode 100644
index 000000000000..1073d3687d38
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Dxe/GenericElog.inf
@@ -0,0 +1,38 @@
+### @file
+#
+# Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+###
+
+
+[Defines]
+  INF_VERSION              = 0x00010005
+  BASE_NAME                = GenericElog
+  FILE_GUID                = FD2D7E66-C5A7-47de-BDCC-4F1B5DC6ADA8
+  MODULE_TYPE              = DXE_DRIVER
+  VERSION_STRING           = 1.0
+  ENTRY_POINT              = InitializeElogLayer
+
+[Sources]
+  GenericElog.c
+  GenericElog.h
+
+[Packages]
+  IpmiFeaturePkg/IpmiFeaturePkg.dec
+  MdePkg/MdePkg.dec
+
+[LibraryClasses]
+  UefiDriverEntryPoint
+  BaseMemoryLib
+  DebugLib
+  UefiBootServicesTableLib
+  MemoryAllocationLib
+
+[Protocols]
+  gEfiGenericElogProtocolGuid   # PROTOCOL ALWAYS_PRODUCED
+  gEfiRedirElogProtocolGuid       #PROTOCOL ALWAYS_COMSUMED
+
+[Depex]
+  gEfiRedirElogProtocolGuid
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Smm/GenericElog.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Smm/GenericElog.inf
new file mode 100644
index 000000000000..00f4154cdd39
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Smm/GenericElog.inf
@@ -0,0 +1,38 @@
+### @file
+#
+# Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+###
+
+
+[Defines]
+  INF_VERSION              = 0x00010005
+  BASE_NAME                = SmGenericElog
+  FILE_GUID                = 870B000E-D3AD-4fb2-B846-AB0ADE8799CB
+  MODULE_TYPE              = DXE_SMM_DRIVER
+  PI_SPECIFICATION_VERSION = 0x0001000A
+  VERSION_STRING           = 1.0
+  ENTRY_POINT              = InitializeSmElogLayer
+
+[Sources]
+  GenericElog.c
+  GenericElog.h
+
+[Packages]
+  IpmiFeaturePkg/IpmiFeaturePkg.dec
+  MdePkg/MdePkg.dec
+
+[LibraryClasses]
+  UefiDriverEntryPoint
+  DebugLib
+  SmmServicesTableLib
+
+[Protocols]
+  gSmmGenericElogProtocolGuid     # PROTOCOL ALWAYS_PRODUCED
+  gSmmRedirElogProtocolGuid       #PROTOCOL ALWAYS_COMSUMED
+
+[Depex]
+  gSmmRedirElogProtocolGuid AND
+  gSmmIpmiTransportProtocolGuid
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Common/BmcElogCommon.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Common/BmcElogCommon.h
new file mode 100644
index 000000000000..23c535d1dd6c
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Common/BmcElogCommon.h
@@ -0,0 +1,144 @@
+/** @file
+  BMC Event Log functions.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _BMCELOG_COMMON_H_
+#define _BMCELOG_COMMON_H_
+
+//
+// Statements that include other files
+//
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/ReportStatusCodeLib.h>
+#include "ServerManagement.h"
+#include <SmStatusCodes.h>
+#include <IndustryStandard/Ipmi.h>
+#include <Library/IpmiBaseLib.h>
+
+#define MAX_TEMP_DATA       160
+#define CLEAR_SEL_COUNTER   0x200
+#define SEL_RECORD_SIZE     0x10       // 16 bytes : Entire SEL Record size
+#define SEL_RECORD_ID_SIZE  0x2        // 2 bytes  : SEL Record-ID size
+
+#ifndef _EFI_SM_ELOG_TYPE
+#define _EFI_SM_ELOG_TYPE
+typedef enum {
+  EfiElogSmSMBIOS,
+  EfiElogSmIPMI,
+  EfiElogSmMachineCritical,
+  EfiElogSmASF,
+  EfiElogSmOEM,
+  EfiSmElogMax
+} EFI_SM_ELOG_TYPE;
+#endif
+
+/**
+  WaitTillClearSel.
+
+  @param ResvId               Reserved ID
+
+  @retval EFI_SUCCESS
+  @retval EFI_NO_RESPONSE
+
+**/
+EFI_STATUS
+WaitTillClearSel (
+  UINT8  *ResvId
+  );
+
+/**
+  Set Bmc Elog Data.
+
+
+  @param ElogData      Buffer for log storage
+  @param DataType      Event Log type
+  @param AlertEvent    If it is an alert event
+  @param Size          Log data size
+  @param RecordId      Indicate which recorder it is
+
+  @retval EFI_STATUS
+
+**/
+EFI_STATUS
+SetBmcElogRecord (
+  IN  UINT8             *ElogData,
+  IN  EFI_SM_ELOG_TYPE  DataType,
+  IN  BOOLEAN           AlertEvent,
+  IN  UINTN             Size,
+  OUT UINT64            *RecordId
+  );
+
+/**
+  Get Bmc Elog Data.
+
+  @param ElogData      Buffer for log data store
+  @param DataType      Event log type
+  @param Size          Size of log data
+  @param RecordId      indicate which recorder it is
+
+  @retval EFI_STATUS
+
+**/
+EFI_STATUS
+GetBmcElogRecord (
+  IN UINT8             *ElogData,
+  IN EFI_SM_ELOG_TYPE  DataType,
+  IN OUT UINTN         *Size,
+  IN OUT UINT64        *RecordId
+  );
+
+/**
+  Erase Bmc Elog Data.
+
+  @param This          Protocol pointer
+  @param DataType      Event log type
+  @param RecordId      return which recorder it is
+
+  @retval EFI_STATUS
+
+**/
+EFI_STATUS
+EraseBmcElogRecord (
+  IN EFI_SM_ELOG_TYPE  DataType,
+  IN OUT UINT64        *RecordId
+  );
+
+/**
+  Activate Bmc Elog.
+
+  @param DataType      indicate event log type
+  @param EnableElog    Enable/Disable event log
+  @param ElogStatus    return log status
+
+  @retval EFI_STATUS
+
+**/
+EFI_STATUS
+ActivateBmcElog (
+  IN  EFI_SM_ELOG_TYPE  DataType,
+  IN  BOOLEAN           *EnableElog,
+  OUT BOOLEAN           *ElogStatus
+  );
+
+/**
+  This function verifies the BMC SEL is full and When it is reports the error to the Error Manager.
+
+  @retval EFI_SUCCESS
+  @retval EFI_DEVICE_ERROR
+
+**/
+EFI_STATUS
+EFIAPI
+CheckIfSelIsFull (
+  VOID
+  );
+
+#endif
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Dxe/BmcElog.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Dxe/BmcElog.h
new file mode 100644
index 000000000000..d70261c7c537
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Dxe/BmcElog.h
@@ -0,0 +1,42 @@
+/** @file
+  BMC Event Log functions.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _EFI_BMCELOG_H_
+#define _EFI_BMCELOG_H_
+
+//
+// Statements that include other files
+//
+
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Protocol/IpmiTransportProtocol.h>
+#include <Protocol/GenericElog.h>
+#include "BmcElogCommon.h"
+
+//
+// BMC Elog instance data
+//
+typedef struct {
+  UINTN                         Signature;
+  SM_COM_ADDRESS                ControllerAddress;
+  SM_COM_ADDRESS                TargetAddress;
+  UINT16                        Instance;
+  EFI_SM_ELOG_TYPE              DataType;
+  UINT8                         TempData[MAX_TEMP_DATA + 1];
+  EFI_SM_ELOG_REDIR_PROTOCOL    BmcElog;
+} EFI_BMC_ELOG_INSTANCE_DATA;
+
+//
+// BMC Elog Instance signature
+//
+#define EFI_ELOG_REDIR_SIGNATURE  SIGNATURE_32 ('e', 'e', 'l', 'g')
+
+#define INSTANCE_FROM_EFI_ELOG_REDIR_THIS(a)  CR (a, EFI_BMC_ELOG_INSTANCE_DATA, BmcElog, EFI_ELOG_REDIR_SIGNATURE)
+
+#endif
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Pei/BmcElog.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Pei/BmcElog.h
new file mode 100644
index 000000000000..c1b53f3e468d
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Pei/BmcElog.h
@@ -0,0 +1,44 @@
+/** @file
+  BMC Event Log functions.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _EFI_PEIBMCELOG_H_
+#define _EFI_PEIBMCELOG_H_
+
+//
+// Statements that include other files
+//
+
+#include <Ppi/GenericElog.h>
+#include <Ppi/IpmiTransportPpi.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PeiServicesTablePointerLib.h>
+#include <IndustryStandard/Ipmi.h>
+#include "BmcElogCommon.h"
+
+//
+// BMC Elog instance data
+//
+typedef struct {
+  UINTN                     Signature;
+  SM_COM_ADDRESS            ControllerAddress;
+  SM_COM_ADDRESS            TargetAddress;
+  UINT16                    Instance;
+  EFI_SM_ELOG_TYPE          DataType;
+  UINT8                     TempData[MAX_TEMP_DATA + 1];
+  EFI_SM_ELOG_REDIR_PPI     BmcElogPpi;
+  EFI_PEI_PPI_DESCRIPTOR    BmcElog;
+} EFI_PEI_BMC_ELOG_INSTANCE_DATA;
+
+//
+// BMC Elog Instance signature
+//
+#define EFI_PEI_ELOG_REDIR_SIGNATURE  SIGNATURE_32 ('e', 'p', 'l', 'g')
+
+#define INSTANCE_FROM_EFI_PEI_ELOG_REDIR_THIS(a)  CR (a, EFI_PEI_BMC_ELOG_INSTANCE_DATA, BmcElogPpi, EFI_PEI_ELOG_REDIR_SIGNATURE)
+
+#endif
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Smm/BmcElog.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Smm/BmcElog.h
new file mode 100644
index 000000000000..218af380a229
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Smm/BmcElog.h
@@ -0,0 +1,43 @@
+/** @file
+  BMC Event Log functions.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _SMM_BMCELOG_H_
+#define _SMM_BMCELOG_H_
+
+//
+// Statements that include other files
+//
+
+#include <Library/SmmServicesTableLib.h>
+#include <Library/SmmLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/IpmiTransportProtocol.h>
+#include <Protocol/GenericElog.h>
+#include "BmcElogCommon.h"
+
+//
+// BMC Elog instance data
+//
+typedef struct {
+  UINTN                         Signature;
+  SM_COM_ADDRESS                ControllerAddress;
+  SM_COM_ADDRESS                TargetAddress;
+  UINT16                        Instance;
+  EFI_SM_ELOG_TYPE              DataType;
+  UINT8                         TempData[MAX_TEMP_DATA + 1];
+  EFI_SM_ELOG_REDIR_PROTOCOL    BmcElog;
+} EFI_BMC_ELOG_INSTANCE_DATA;
+
+//
+// BMC Elog Instance signature
+//
+#define SM_ELOG_REDIR_SIGNATURE  SIGNATURE_32 ('e', 'l', 'o', 'f')
+
+#define INSTANCE_FROM_EFI_SM_ELOG_REDIR_THIS(a)  CR (a, EFI_BMC_ELOG_INSTANCE_DATA, BmcElog, SM_ELOG_REDIR_SIGNATURE)
+
+#endif //_SMM_BMCELOG_H_
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Dxe/GenericElog.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Dxe/GenericElog.h
new file mode 100644
index 000000000000..460185455648
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Dxe/GenericElog.h
@@ -0,0 +1,194 @@
+/** @file
+  Generic Event Log functions.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _EFI_GENELOG_H_
+#define _EFI_GENELOG_H_
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include "ServerManagement.h"
+
+#include <Protocol/IpmiTransportProtocol.h>
+#include <Protocol/GenericElog.h>
+
+#define EFI_ELOG_PHYSICAL     0
+#define EFI_ELOG_VIRTUAL      1
+#define MAX_REDIR_DESCRIPTOR  10
+
+///
+/// A pointer to a function in IPF points to a plabel.
+///
+typedef struct {
+  UINT64    EntryPoint;
+  UINT64    GP;
+} EFI_PLABEL;
+
+typedef struct {
+  EFI_PLABEL    *Function;
+  EFI_PLABEL    Plabel;
+} FUNCTION_PTR;
+
+typedef struct {
+  EFI_SM_ELOG_REDIR_PROTOCOL    *This;
+  FUNCTION_PTR                  SetEventLogData;
+  FUNCTION_PTR                  GetEventLogData;
+  FUNCTION_PTR                  EraseEventLogData;
+  FUNCTION_PTR                  ActivateEventLog;
+} REDIR_MODULE_PROC;
+
+typedef struct {
+  BOOLEAN              Valid;
+  REDIR_MODULE_PROC    Command[2];
+} REDIR_MODULES;
+
+typedef struct {
+  REDIR_MODULES    Redir[MAX_REDIR_DESCRIPTOR];
+  UINTN            MaxDescriptors;
+} ELOG_MODULE_GLOBAL;
+
+/**
+  Efi Convert Function.
+
+  @param Function
+
+  @retval EFI_SUCCESS
+**/
+EFI_STATUS
+EfiConvertFunction (
+  IN  FUNCTION_PTR  *Function
+  );
+
+/**
+  Efi Set Function Entry.
+
+  @param FunctionPointer
+  @param Function
+
+  @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EfiSetFunctionEntry (
+  IN  FUNCTION_PTR  *FunctionPointer,
+  IN  VOID          *Function
+  );
+
+/**
+  Elog Service Initialize.
+
+  @param ImageHandle
+  @param SystemTable
+
+  @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+ElogServiceInitialize (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  );
+
+/**
+  Efi Lib Set Elog Data.
+
+  @param ElogData
+  @param DataType
+  @param AlertEvent
+  @param DataSize
+  @param RecordId
+  @param Global
+  @param Virtual
+
+  @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EfiLibSetElogData (
+  IN  UINT8             *ElogData,
+  IN  EFI_SM_ELOG_TYPE  DataType,
+  IN  BOOLEAN           AlertEvent,
+  IN  UINTN             DataSize,
+  OUT UINT64            *RecordId,
+  ELOG_MODULE_GLOBAL    *Global,
+  BOOLEAN               Virtual
+  );
+
+/**
+  Efi Lib Get Elog Data.
+
+  @param ElogData
+  @param DataType
+  @param DataSize
+  @param RecordId
+  @param Global
+  @param Virtual
+
+  @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EfiLibGetElogData (
+  IN UINT8             *ElogData,
+  IN EFI_SM_ELOG_TYPE  DataType,
+  IN OUT UINTN         *DataSize,
+  IN OUT UINT64        *RecordId,
+  ELOG_MODULE_GLOBAL   *Global,
+  BOOLEAN              Virtual
+  );
+
+/**
+  Efi Lib Erase Elog Data.
+
+  @param DataType
+  @param RecordId
+  @param Global
+  @param Virtual
+
+  @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EfiLibEraseElogData (
+  IN EFI_SM_ELOG_TYPE  DataType,
+  IN OUT UINT64        *RecordId,
+  ELOG_MODULE_GLOBAL   *Global,
+  BOOLEAN              Virtual
+  );
+
+/**
+  This API enables/Disables Event Log.
+
+  @param DataType              - Type of Elog Data that is being Activated.
+  @param EnableElog            - Enables (TRUE) / Disables (FALSE) Event Log. If NULL just returns the
+                                 Current ElogStatus.
+  @param ElogStatus            - Current (New) Status of Event Log. Enabled (TRUE), Disabled (FALSE).
+  @param Global                - The module global variable pointer.
+  @param Virtual               - If this function is called in virtual mode or physical mode
+
+  @retval EFI_SUCCESS           - Event-Log was recorded successfully
+  @retval EFI_UNSUPPORTED       - The Data Type is unsupported
+
+**/
+
+EFI_STATUS
+EfiLibActivateElog (
+  IN  EFI_SM_ELOG_TYPE  DataType,
+  IN BOOLEAN            *EnableElog,
+  OUT BOOLEAN           *ElogStatus,
+  ELOG_MODULE_GLOBAL    *Global,
+  BOOLEAN               Virtual
+  );
+
+#endif //_EFI_GENELOG_H_
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Smm/GenericElog.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Smm/GenericElog.h
new file mode 100644
index 000000000000..ad6530616309
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Smm/GenericElog.h
@@ -0,0 +1,216 @@
+/** @file
+  Generic Event Log functions.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _SMM_GENELOG_H_
+#define _SMM_GENELOG_H_
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/SmmLib.h>
+#include <Library/DebugLib.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include "ServerManagement.h"
+#include <Protocol/IpmiTransportProtocol.h>
+#include <Protocol/GenericElog.h>
+
+#define EFI_ELOG_PHYSICAL     0
+#define EFI_ELOG_VIRTUAL      1
+#define MAX_REDIR_DESCRIPTOR  10
+
+///
+/// A pointer to a function in IPF points to a plabel.
+///
+typedef struct {
+  UINT64    EntryPoint;
+  UINT64    GP;
+} EFI_PLABEL;
+
+typedef struct {
+  EFI_PLABEL    *Function;
+  EFI_PLABEL    Plabel;
+} FUNCTION_PTR;
+
+typedef struct {
+  EFI_SM_ELOG_REDIR_PROTOCOL    *This;
+  FUNCTION_PTR                  SetEventLogData;
+  FUNCTION_PTR                  GetEventLogData;
+  FUNCTION_PTR                  EraseEventLogData;
+  FUNCTION_PTR                  ActivateEventLog;
+} REDIR_MODULE_PROC;
+
+typedef struct {
+  BOOLEAN              Valid;
+  REDIR_MODULE_PROC    Command[2];
+} REDIR_MODULES;
+
+typedef struct {
+  REDIR_MODULES    Redir[MAX_REDIR_DESCRIPTOR];
+  UINTN            MaxDescriptors;
+} ELOG_MODULE_GLOBAL;
+
+/**
+  Efi Convert Function.
+
+  @param Function
+
+  @retval EFI_SUCCESS
+**/
+EFI_STATUS
+EfiConvertFunction (
+  IN  FUNCTION_PTR  *Function
+  );
+
+/**
+  Set the function entry.
+
+  @param FunctionPointer - The destination function pointer
+  @param Function        - The source function pointer
+
+  @retval EFI_SUCCESS - Set the function pointer successfully
+
+**/
+EFI_STATUS
+EfiSetFunctionEntry (
+  IN  FUNCTION_PTR  *FunctionPointer,
+  IN  VOID          *Function
+  );
+
+/**
+  Entry point of SM Elog service Driver
+
+  @param ImageHandle         - The Image handle of this driver.
+  @param SystemTable         - The pointer of EFI_SYSTEM_TABLE.
+
+  @retval EFI_SUCCESS - The driver successfully initialized
+
+**/
+EFI_STATUS
+SmElogServiceInitialize (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  );
+
+/**
+  Sm Redir Address Change Event.
+
+  @param Event
+  @param Context
+
+**/
+VOID
+SmRedirAddressChangeEvent (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  );
+
+/**
+  Sends the Event-Log data to the destination.
+
+  @param ElogData              - Pointer to the Event-Log data that needs to be recorded.
+  @param DataType              - Type of Elog Data that is being recorded.
+  @param AlertEvent            - This is an indication that the input data type is an Alert.
+  @param DataSize              - Data Size.
+  @param RecordId              - Record ID sent by the target.
+  @param Global                - The module global variable pointer.
+  @param Virtual               - If this function is called in virtual mode or physical mode
+
+  @retval EFI_SUCCESS            - Event-Log was recorded successfully.
+  @retval EFI_OUT_OF_RESOURCES   - Not enough resources to record data.
+  @retval EFI_UNSUPPORTED        - The Data Type is unsupported.
+
+**/
+EFI_STATUS
+EfiLibSetElogData (
+  IN  UINT8             *ElogData,
+  IN  EFI_SM_ELOG_TYPE  DataType,
+  IN  BOOLEAN           AlertEvent,
+  IN  UINTN             DataSize,
+  OUT UINT64            *RecordId,
+  ELOG_MODULE_GLOBAL    *Global,
+  BOOLEAN               Virtual
+  );
+
+/**
+  Gets the Event-Log data from the destination.
+
+  @param ElogData              - Pointer to the Event-Log data buffer that will contain the data to be retrieved.
+  @param DataType              - Type of Elog Data that is being recorded.
+  @param DataSize              - Data Size.
+  @param RecordId              - This is the RecordId of the next record. If ElogData is NULL,
+                                this gives the RecordId of the first record available in the database with the correct DataSize.
+                                A value of 0 on return indicates the last record if the EFI_STATUS indicates a success
+  @param Global                - The module global variable pointer.
+  @param Virtual               - If this function is called in virtual mode or physical mode
+
+  @retval EFI_SUCCESS           - Event-Log was retrieved successfully.
+  @retval EFI_NOT_FOUND         - Event-Log target not found.
+  @retval EFI_BUFFER_TOO_SMALL  - Target buffer is too small to retrieve the data.
+  @retval EFI_UNSUPPORTED       - The Data Type is unsupported
+
+**/
+EFI_STATUS
+EfiLibGetElogData (
+  IN UINT8             *ElogData,
+  IN EFI_SM_ELOG_TYPE  DataType,
+  IN OUT UINTN         *DataSize,
+  IN OUT UINT64        *RecordId,
+  ELOG_MODULE_GLOBAL   *Global,
+  BOOLEAN              Virtual
+  );
+
+/**
+  Erases the Event-Log data from the destination.
+
+  @param DataType              - Type of Elog Data that is being Erased.
+  @param RecordId              - This is the RecordId of the data to be erased. If RecordId is NULL, all
+                                 the records on the database are erased if permitted by the target.
+                                 Contains the deleted RecordId on return
+  @param Global                - The module global variable pointer.
+  @param Virtual               - If this function is called in virtual mode or physical mode
+
+  @retval EFI_SUCCESS           - Event-Log was erased successfully
+  @retval EFI_UNSUPPORTED       - The Data Type is unsupported
+  @retval EFI_NOT_FOUND         - Event-Log target not found
+
+**/
+EFI_STATUS
+EfiLibEraseElogData (
+  IN EFI_SM_ELOG_TYPE  DataType,
+  IN OUT UINT64        *RecordId,
+  ELOG_MODULE_GLOBAL   *Global,
+  BOOLEAN              Virtual
+  );
+
+/**
+  This API enables/Disables Event Log.
+
+  @param DataType              - Type of Elog Data that is being Activated.
+  @param EnableElog            - Enables (TRUE) / Disables (FALSE) Event Log. If NULL just returns the
+                                 Current ElogStatus.
+  @param ElogStatus            - Current (New) Status of Event Log. Enabled (TRUE), Disabled (FALSE).
+  @param Global                - The module global variable pointer.
+  @param Virtual               - If this function is called in virtual mode or physical mode
+
+  @retval EFI_SUCCESS           - Event-Log was recorded successfully
+  @retval EFI_UNSUPPORTED       - The Data Type is unsupported
+
+**/
+EFI_STATUS
+EfiLibActivateElog (
+  IN  EFI_SM_ELOG_TYPE  DataType,
+  IN BOOLEAN            *EnableElog,
+  OUT BOOLEAN           *ElogStatus,
+  ELOG_MODULE_GLOBAL    *Global,
+  BOOLEAN               Virtual
+  );
+
+#endif //_SMM_GENELOG_H_
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Ppi/GenericElog.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Ppi/GenericElog.h
new file mode 100644
index 000000000000..4b3b3ee2af33
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Ppi/GenericElog.h
@@ -0,0 +1,84 @@
+/** @file
+  This code abstracts the generic ELOG Protocol.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _GENERIC_ELOG_H_
+#define _GENERIC_ELOG_H_
+
+#include "ServerManagement.h"
+
+typedef struct _EFI_SM_ELOG_PPI EFI_SM_ELOG_REDIR_PPI;
+
+//
+// Common Defines
+//
+#ifndef _EFI_SM_ELOG_TYPE
+#define _EFI_SM_ELOG_TYPE
+typedef enum {
+  EfiElogSmSMBIOS,
+  EfiElogSmIPMI,
+  EfiElogSmMachineCritical,
+  EfiElogSmASF,
+  EfiElogSmOEM,
+  EfiSmElogMax
+} EFI_SM_ELOG_TYPE;
+#endif
+
+//
+//  Generic ELOG Function Prototypes
+//
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SET_ELOG_DATA)(
+  IN  EFI_SM_ELOG_REDIR_PPI             *This,
+  IN  UINT8                             *ElogData,
+  IN  EFI_SM_ELOG_TYPE                  DataType,
+  IN  BOOLEAN                           AlertEvent,
+  IN  UINTN                             DataSize,
+  OUT UINT64                            *RecordId
+  );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_GET_ELOG_DATA)(
+  IN  EFI_SM_ELOG_REDIR_PPI             *This,
+  IN  OUT UINT8                         *ElogData,
+  IN  EFI_SM_ELOG_TYPE                  DataType,
+  IN  OUT UINTN                         *DataSize,
+  IN  OUT UINT64                        *RecordId
+  );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_ERASE_ELOG_DATA)(
+  IN EFI_SM_ELOG_REDIR_PPI              *This,
+  IN EFI_SM_ELOG_TYPE                   DataType,
+  IN OUT UINT64                         *RecordId
+  );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_ACTIVATE_ELOG)(
+  IN EFI_SM_ELOG_REDIR_PPI              *This,
+  IN EFI_SM_ELOG_TYPE                   DataType,
+  IN BOOLEAN                            *EnableElog,
+  OUT BOOLEAN                           *ElogStatus
+  );
+
+//
+// IPMI TRANSPORT PPI
+//
+struct _EFI_SM_ELOG_PPI {
+  EFI_SET_ELOG_DATA      SetEventLogData;
+  EFI_GET_ELOG_DATA      GetEventLogData;
+  EFI_ERASE_ELOG_DATA    EraseEventlogData;
+  EFI_ACTIVATE_ELOG      ActivateEventLog;
+};
+
+extern EFI_GUID  gPeiRedirElogPpiGuid;
+
+#endif
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/GenericElog.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/GenericElog.h
new file mode 100644
index 000000000000..19726ff58f0f
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/GenericElog.h
@@ -0,0 +1,99 @@
+/** @file
+  This code abstracts the generic ELOG Protocol.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _GENERIC_ELOG_H_
+#define _GENERIC_ELOG_H_
+
+#include "ServerManagement.h"
+
+#define EFI_SM_ELOG_PROTOCOL_GUID \
+  { \
+    0x59d02fcd, 0x9233, 0x4d34, 0xbc, 0xfe, 0x87, 0xca, 0x81, 0xd3, 0xdd, 0xa7 \
+  }
+
+#define EFI_SM_ELOG_REDIR_PROTOCOL_GUID \
+  { \
+    0x16d11030, 0x71ba, 0x4e5e, 0xa9, 0xf9, 0xb4, 0x75, 0xa5, 0x49, 0x4, 0x8a \
+  }
+
+//
+// Common Defines
+//
+#ifndef _EFI_SM_ELOG_TYPE
+#define _EFI_SM_ELOG_TYPE
+typedef enum {
+  EfiElogSmSMBIOS,
+  EfiElogSmIPMI,
+  EfiElogSmMachineCritical,
+  EfiElogSmASF,
+  EfiElogSmOEM,
+  EfiSmElogMax
+} EFI_SM_ELOG_TYPE;
+#endif
+
+typedef struct _EFI_SM_ELOG_PROTOCOL EFI_SM_ELOG_PROTOCOL;
+
+typedef struct _EFI_SM_ELOG_PROTOCOL EFI_SM_ELOG_REDIR_PROTOCOL;
+
+//
+//  Generic ELOG Function Prototypes
+//
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SET_ELOG_DATA)(
+  IN EFI_SM_ELOG_PROTOCOL               *This,
+  IN  UINT8                             *ElogData,
+  IN  EFI_SM_ELOG_TYPE                  DataType,
+  IN  BOOLEAN                           AlertEvent,
+  IN  UINTN                             DataSize,
+  OUT UINT64                            *RecordId
+  );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_GET_ELOG_DATA)(
+  IN EFI_SM_ELOG_PROTOCOL               *This,
+  IN OUT UINT8                          *ElogData,
+  IN EFI_SM_ELOG_TYPE                   DataType,
+  IN OUT UINTN                          *DataSize,
+  IN OUT UINT64                         *RecordId
+  );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_ERASE_ELOG_DATA)(
+  IN EFI_SM_ELOG_PROTOCOL               *This,
+  IN EFI_SM_ELOG_TYPE                   DataType,
+  IN OUT UINT64                         *RecordId
+  );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_ACTIVATE_ELOG)(
+  IN EFI_SM_ELOG_PROTOCOL               *This,
+  IN EFI_SM_ELOG_TYPE                   DataType,
+  IN BOOLEAN                            *EnableElog,
+  OUT BOOLEAN                           *ElogStatus
+  );
+
+//
+// IPMI TRANSPORT PROTOCOL
+//
+struct _EFI_SM_ELOG_PROTOCOL {
+  EFI_SET_ELOG_DATA      SetEventLogData;
+  EFI_GET_ELOG_DATA      GetEventLogData;
+  EFI_ERASE_ELOG_DATA    EraseEventlogData;
+  EFI_ACTIVATE_ELOG      ActivateEventLog;
+};
+
+extern EFI_GUID  gEfiGenericElogProtocolGuid;
+extern EFI_GUID  gEfiRedirElogProtocolGuid;
+extern EFI_GUID  gSmmGenericElogProtocolGuid;
+extern EFI_GUID  gSmmRedirElogProtocolGuid;
+
+#endif
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/BmcElog.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/BmcElog.c
deleted file mode 100644
index a6d075b19c49..000000000000
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/BmcElog.c
+++ /dev/null
@@ -1,236 +0,0 @@
-/** @file
-  BMC Event Log functions.
-
-Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include <Uefi.h>
-#include <Library/BaseLib.h>
-#include <Library/DebugLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/UefiRuntimeServicesTableLib.h>
-#include <Library/IpmiCommandLib.h>
-
-EFI_STATUS
-EFIAPI
-CheckIfSelIsFull (
-  VOID
-  );
-
-/*++
-
-  Routine Description:
-    This function verifies the BMC SEL is full and When it is reports the error to the Error Manager.
-
-  Arguments:
-    None
-
-  Returns:
-    EFI_SUCCESS
-    EFI_DEVICE_ERROR
-
---*/
-EFI_STATUS
-WaitTillErased (
-  UINT8                                 *ResvId
-  )
-/*++
-
-Routine Description:
-
-Arguments:
-
-  BmcElogPrivateData  - Bmc event log instance
-  ResvId              - Reserved ID
-
-Returns:
-
-  EFI_SUCCESS
-  EFI_NO_RESPONSE
-
---*/
-{
-  INTN                     Counter;
-  IPMI_CLEAR_SEL_REQUEST   ClearSel;
-  IPMI_CLEAR_SEL_RESPONSE  ClearSelResponse;
-
-  Counter   = 0x200;
-  ZeroMem (&ClearSelResponse, sizeof(ClearSelResponse));
-
-  while (TRUE) {
-    ZeroMem (&ClearSel, sizeof(ClearSel));
-    ClearSel.Reserve[0]  = ResvId[0];
-    ClearSel.Reserve[1]  = ResvId[1];
-    ClearSel.AscC        = 0x43;
-    ClearSel.AscL        = 0x4C;
-    ClearSel.AscR        = 0x52;
-    ClearSel.Erase       = 0x00;
-
-    IpmiClearSel (
-      &ClearSel,
-      &ClearSelResponse
-      );
-
-    if ((ClearSelResponse.ErasureProgress & 0xf) == 1) {
-      return EFI_SUCCESS;
-    }
-    //
-    //  If there is not a response from the BMC controller we need to return and not hang.
-    //
-    --Counter;
-    if (Counter == 0x0) {
-      return EFI_NO_RESPONSE;
-    }
-  }
-}
-
-EFI_STATUS
-EfiActivateBmcElog (
-  IN BOOLEAN                            *EnableElog,
-  OUT BOOLEAN                           *ElogStatus
-  )
-/*++
-
-Routine Description:
-
-Arguments:
-
-  This        - Protocol pointer
-  DataType    - indicate event log type
-  EnableElog  - Enable/Disable event log
-  ElogStatus  - return log status
-
-Returns:
-
-  EFI_STATUS
-
---*/
-{
-  EFI_STATUS                           Status;
-  UINT8                                ElogStat;
-  IPMI_SET_BMC_GLOBAL_ENABLES_REQUEST  SetBmcGlobalEnables;
-  IPMI_GET_BMC_GLOBAL_ENABLES_RESPONSE GetBmcGlobalEnables;
-  UINT8                                CompletionCode;
-
-  Status              = EFI_SUCCESS;
-  ElogStat            = 0;
-
-  Status = IpmiGetBmcGlobalEnables (&GetBmcGlobalEnables);
-  if (EFI_ERROR(Status)) {
-    return Status;
-  }
-
-  if (EnableElog == NULL) {
-    *ElogStatus = GetBmcGlobalEnables.GetEnables.Bits.SystemEventLogging;
-  } else {
-    if (Status == EFI_SUCCESS) {
-      if (*EnableElog) {
-        ElogStat = 1;
-      }
-
-      CopyMem (&SetBmcGlobalEnables, (UINT8 *)&GetBmcGlobalEnables + 1, sizeof(UINT8));
-      SetBmcGlobalEnables.SetEnables.Bits.SystemEventLogging = ElogStat;
-
-      Status = IpmiSetBmcGlobalEnables (&SetBmcGlobalEnables, &CompletionCode);
-    }
-  }
-
-  return Status;
-}
-
-EFI_STATUS
-SetElogRedirInstall (
-  VOID
-  )
-/*++
-
-Routine Description:
-
-Arguments:
-
-  None
-
-Returns:
-
-  EFI_SUCCESS
-
---*/
-{
-  BOOLEAN     EnableElog;
-  BOOLEAN     ElogStatus;
-
-  //
-  // Activate the Event Log (This should depend upon Setup).
-  //
-  EfiActivateBmcElog (&EnableElog, &ElogStatus);
-  return EFI_SUCCESS;
-}
-
-EFI_STATUS
-EFIAPI
-InitializeBmcElogLayer (
-  IN EFI_HANDLE             ImageHandle,
-  IN EFI_SYSTEM_TABLE       *SystemTable
-  )
-/*++
-
-Routine Description:
-
-Arguments:
-
-  ImageHandle - ImageHandle of the loaded driver
-  SystemTable - Pointer to the System Table
-
-Returns:
-
-  EFI_STATUS
-
---*/
-{
-  SetElogRedirInstall ();
-
-  CheckIfSelIsFull ();
-
-  return EFI_SUCCESS;
-}
-
-EFI_STATUS
-EFIAPI
-CheckIfSelIsFull (
-  VOID
-  )
-/*++
-
-  Routine Description:
-    This function verifies the BMC SEL is full and When it is reports the error to the Error Manager.
-
-  Arguments:
-    None
-
-  Returns:
-    EFI_SUCCESS
-    EFI_DEVICE_ERROR
-
---*/
-{
-  EFI_STATUS                  Status;
-  UINT8                       SelIsFull;
-  IPMI_GET_SEL_INFO_RESPONSE  SelInfo;
-
-  Status = IpmiGetSelInfo (&SelInfo);
-  if (EFI_ERROR (Status)) {
-    return EFI_DEVICE_ERROR;
-  }
-
-  //
-  // Check the Bit7 of the OperationByte if SEL is OverFlow.
-  //
-  SelIsFull = (SelInfo.OperationSupport & 0x80);
-  DEBUG ((DEBUG_INFO, "SelIsFull - 0x%x\n", SelIsFull));
-
-  return EFI_SUCCESS;
-}
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Common/BmcElogCommon.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Common/BmcElogCommon.c
new file mode 100644
index 000000000000..b0688e3afb6c
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Common/BmcElogCommon.c
@@ -0,0 +1,465 @@
+/** @file
+  BMC Event Log Common functions.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "BmcElogCommon.h"
+
+/**
+  WaitTillClearSel.
+
+  @param ResvId              - Reserved ID
+
+  @retval EFI_SUCCESS
+  @retval EFI_NO_RESPONSE
+
+**/
+EFI_STATUS
+WaitTillClearSel (
+  UINT8  *ResvId
+  )
+{
+  INTN                     Counter;
+  UINT32                   ResponseDataSize;
+  IPMI_CLEAR_SEL_REQUEST   ClearSelRequest;
+  IPMI_CLEAR_SEL_RESPONSE  ClearSelResponse;
+  EFI_STATUS               Status;
+
+  Counter = 0x200;
+  Status  = EFI_SUCCESS;
+  while (TRUE) {
+    ClearSelRequest.Reserve[0] = ResvId[0];
+    ClearSelRequest.Reserve[1] = ResvId[1];
+    ClearSelRequest.AscC       = IPMI_CLEAR_SEL_REQUEST_C_CHAR_ASCII;
+    ClearSelRequest.AscL       = IPMI_CLEAR_SEL_REQUEST_L_CHAR_ASCII;
+    ClearSelRequest.AscR       = IPMI_CLEAR_SEL_REQUEST_R_CHAR_ASCII;
+    ClearSelRequest.Erase      = IPMI_CLEAR_SEL_REQUEST_GET_ERASE_STATUS;
+    ResponseDataSize           = sizeof (ClearSelResponse);
+
+    Status = IpmiSubmitCommand (
+               IPMI_NETFN_STORAGE,
+               IPMI_STORAGE_CLEAR_SEL,
+               (UINT8 *)&ClearSelRequest,
+               sizeof (ClearSelRequest),
+               (UINT8 *)&ClearSelResponse,
+               &ResponseDataSize
+               );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "IpmiSubmitCommand ClearSelRequest Failed %r\n", Status));
+    }
+
+    if ((ClearSelResponse.ErasureProgress & 0xf) == IPMI_CLEAR_SEL_RESPONSE_ERASURE_COMPLETED) {
+      return EFI_SUCCESS;
+    }
+
+    //
+    //  If there is not a response from the BMC controller we need to return and not hang.
+    //
+    --Counter;
+    if (Counter == 0x0) {
+      return EFI_NO_RESPONSE;
+    }
+  }
+}
+
+/**
+  Set Bmc Elog Data.
+
+
+  @param ElogData    - Buffer for log storage
+  @param DataType    - Event Log type
+  @param AlertEvent  - If it is an alert event
+  @param Size        - Log data size
+  @param RecordId    - Indicate which recorder it is
+
+  @retval EFI_STATUS
+
+**/
+EFI_STATUS
+SetBmcElogRecord (
+  IN  UINT8             *ElogData,
+  IN  EFI_SM_ELOG_TYPE  DataType,
+  IN  BOOLEAN           AlertEvent,
+  IN  UINTN             Size,
+  OUT UINT64            *RecordId
+  )
+{
+  EFI_STATUS                                Status;
+  UINT32                                    ResponseDataSize;
+  UINT8                                     EvntMsgResponse;
+  IPMI_PLATFORM_EVENT_MESSAGE_DATA_REQUEST  EvntMsgRequest;
+  IPMI_ADD_SEL_ENTRY_REQUEST                AddSelRequest;
+  IPMI_ADD_SEL_ENTRY_RESPONSE               AddSelResponse;
+
+  Status = EFI_SUCCESS;
+  CopyMem (&AddSelRequest.RecordData, ElogData, Size);
+
+  *RecordId = 0;
+
+  if (AlertEvent) {
+    EvntMsgRequest.GeneratorId  = (UINT8)AddSelRequest.RecordData.GeneratorId;
+    EvntMsgRequest.EvMRevision  = AddSelRequest.RecordData.EvMRevision;
+    EvntMsgRequest.SensorType   = AddSelRequest.RecordData.SensorType;
+    EvntMsgRequest.SensorNumber = AddSelRequest.RecordData.SensorNumber;
+    EvntMsgRequest.EventDirType = AddSelRequest.RecordData.EventDirType;
+    EvntMsgRequest.OEMEvData1   = AddSelRequest.RecordData.OEMEvData1;
+    EvntMsgRequest.OEMEvData2   = AddSelRequest.RecordData.OEMEvData2;
+    EvntMsgRequest.OEMEvData3   = AddSelRequest.RecordData.OEMEvData3;
+
+    ResponseDataSize = sizeof (EvntMsgResponse);
+    Status           = IpmiSubmitCommand (
+                         IPMI_NETFN_SENSOR_EVENT,
+                         IPMI_SENSOR_PLATFORM_EVENT_MESSAGE,
+                         (UINT8 *)&EvntMsgRequest,
+                         sizeof (EvntMsgRequest),
+                         (UINT8 *)&EvntMsgResponse,
+                         &ResponseDataSize
+                         );
+  } else {
+    ResponseDataSize = sizeof (AddSelResponse);
+    Status           = IpmiSubmitCommand (
+                         IPMI_NETFN_STORAGE,
+                         IPMI_STORAGE_ADD_SEL_ENTRY,
+                         (UINT8 *)&AddSelRequest,
+                         sizeof (AddSelRequest),
+                         (UINT8 *)&AddSelResponse,
+                         &ResponseDataSize
+                         );
+
+    if (Status == EFI_SUCCESS) {
+      *RecordId = AddSelResponse.RecordId;
+    }
+  }
+
+  return Status;
+}
+
+/**
+  Get Bmc Elog Data.
+
+  @param ElogData    - Buffer for log data store
+  @param DataType    - Event log type
+  @param Size        - Size of log data
+  @param RecordId    - indicate which recorder it is
+
+  @retval EFI_STATUS
+
+**/
+EFI_STATUS
+GetBmcElogRecord (
+  IN UINT8             *ElogData,
+  IN EFI_SM_ELOG_TYPE  DataType,
+  IN OUT UINTN         *Size,
+  IN OUT UINT64        *RecordId
+  )
+{
+  UINT64                       ReceiveKey;
+  EFI_STATUS                   Status;
+  IPMI_GET_SEL_ENTRY_REQUEST   GetSelEntryRequest;
+  IPMI_GET_SEL_ENTRY_RESPONSE  GetSelEntryResponse;
+  UINT32                       ResponseDataSize;
+
+  Status                          = EFI_SUCCESS;
+  ReceiveKey                      = *RecordId;
+  GetSelEntryRequest.ReserveId[0] = 0;
+  GetSelEntryRequest.ReserveId[1] = 0;
+  GetSelEntryRequest.SelRecID[0]  = (UINT8)ReceiveKey;
+  ReceiveKey                      = DivU64x32 (ReceiveKey, (UINT32)(1 << 8));
+  GetSelEntryRequest.SelRecID[1]  = (UINT8)ReceiveKey;
+  GetSelEntryRequest.Offset       = 0;
+  GetSelEntryRequest.BytesToRead  = IPMI_COMPLETE_SEL_RECORD;
+  ResponseDataSize                = sizeof (GetSelEntryResponse);
+
+  Status = IpmiSubmitCommand (
+             IPMI_NETFN_STORAGE,
+             IPMI_STORAGE_GET_SEL_ENTRY,
+             (UINT8 *)&GetSelEntryRequest,
+             sizeof (GetSelEntryRequest),
+             (UINT8 *)&GetSelEntryResponse,
+             &ResponseDataSize
+             );
+  //
+  // Per IPMI spec, Entire Record is 16 Bytes
+  // If less than 16 bytes pointer is sent return buffer too small
+  //
+  if (Status == EFI_SUCCESS) {
+    if (*Size < (SEL_RECORD_SIZE)) {
+      return EFI_BUFFER_TOO_SMALL;
+    }
+
+    if (GetSelEntryResponse.NextSelRecordId == 0xFFFF) {
+      return EFI_NOT_FOUND;
+    }
+
+    *RecordId = GetSelEntryResponse.NextSelRecordId;
+    CopyMem (ElogData, &GetSelEntryResponse.RecordData, sizeof (GetSelEntryResponse.RecordData));
+    *Size = SEL_RECORD_SIZE;
+  }
+
+  return Status;
+}
+
+/**
+  Erase Bmc Elog Data.
+
+  @param DataType    - Event log type
+  @param RecordId    - return which recorder it is
+
+  @retval EFI_STATUS
+
+**/
+EFI_STATUS
+EraseBmcElogRecord (
+  IN EFI_SM_ELOG_TYPE  DataType,
+  IN OUT UINT64        *RecordId
+  )
+{
+  EFI_STATUS                      Status;
+  UINT64                          ReceiveKey;
+  UINT8                           ResvId[2];
+  BOOLEAN                         SelReserveIdIsSupported;
+  UINT8                           OperationSupport;
+  UINT8                           SelReserveIdvalue;
+  UINT32                          ResponseDataSize;
+  IPMI_GET_SEL_INFO_RESPONSE      GetSelInfoResponse;
+  IPMI_RESERVE_SEL_RESPONSE       ReserveSelResponse;
+  IPMI_DELETE_SEL_ENTRY_REQUEST   DeleteSelRequest;
+  IPMI_DELETE_SEL_ENTRY_RESPONSE  DeleteSelResponse;
+  IPMI_CLEAR_SEL_REQUEST          ClearSelRequest;
+  IPMI_CLEAR_SEL_RESPONSE         ClearSelResponse;
+
+  Status = EFI_SUCCESS;
+
+  //
+  // Before issuing this SEL reservation ID, Check whether this command is supported or not by issuing the
+  // GetSelInfoCommand. If it does not support ResvId should be 0000h
+  //
+  ResponseDataSize = sizeof (GetSelInfoResponse);
+  Status           = IpmiSubmitCommand (
+                       IPMI_NETFN_STORAGE,
+                       IPMI_STORAGE_GET_SEL_INFO,
+                       NULL,
+                       0,
+                       (UINT8 *)&GetSelInfoResponse,
+                       &ResponseDataSize
+                       );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  OperationSupport  = GetSelInfoResponse.OperationSupport;
+  SelReserveIdvalue = (OperationSupport & IPMI_GET_SEL_INFO_OPERATION_SUPPORT_RESERVE_SEL_CMD);
+  if (SelReserveIdvalue == IPMI_GET_SEL_INFO_OPERATION_SUPPORT_RESERVE_SEL_CMD) {
+    SelReserveIdIsSupported = TRUE;
+  } else {
+    SelReserveIdIsSupported = FALSE;
+  }
+
+  //
+  // if SelReserveIdcommand not supported do not issue the RESERVE_SEL_ENTRY command, and set the ResvId value to 0000h
+  //
+
+  //
+  // Get the SEL reservation ID
+  //
+
+  if (SelReserveIdIsSupported) {
+    ResponseDataSize = sizeof (ReserveSelResponse);
+    Status           = IpmiSubmitCommand (
+                         IPMI_NETFN_STORAGE,
+                         IPMI_STORAGE_RESERVE_SEL,
+                         NULL,
+                         0,
+                         (UINT8 *)&ReserveSelResponse,
+                         &ResponseDataSize
+                         );
+
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    ResvId[0] = ReserveSelResponse.ReservationId[0];
+    ResvId[1] = ReserveSelResponse.ReservationId[1];
+  } else {
+    ResvId[0] = 0x00;
+    ResvId[1] = 0x00;
+  }
+
+  //
+  // Clear the SEL
+  //
+  if (RecordId != NULL) {
+    ReceiveKey                         = *RecordId;
+    DeleteSelRequest.ReserveId[0]      = ResvId[0];
+    DeleteSelRequest.ReserveId[1]      = ResvId[1];
+    DeleteSelRequest.RecordToDelete[0] = (UINT8)ReceiveKey;
+    ReceiveKey                         = DivU64x32 (ReceiveKey, (UINT32)(1 << 8));
+    DeleteSelRequest.RecordToDelete[1] = (UINT8)ReceiveKey;
+
+    ResponseDataSize = sizeof (DeleteSelResponse);
+    Status           = IpmiSubmitCommand (
+                         IPMI_NETFN_STORAGE,
+                         IPMI_STORAGE_DELETE_SEL_ENTRY,
+                         (UINT8 *)&DeleteSelRequest,
+                         sizeof (DeleteSelRequest),
+                         (UINT8 *)&DeleteSelResponse,
+                         &ResponseDataSize
+                         );
+  } else {
+    ClearSelRequest.Reserve[0] = ResvId[0];
+    ClearSelRequest.Reserve[1] = ResvId[1];
+    ClearSelRequest.AscC       = IPMI_CLEAR_SEL_REQUEST_C_CHAR_ASCII;
+    ClearSelRequest.AscL       = IPMI_CLEAR_SEL_REQUEST_L_CHAR_ASCII;
+    ClearSelRequest.AscR       = IPMI_CLEAR_SEL_REQUEST_R_CHAR_ASCII;
+    ClearSelRequest.Erase      = IPMI_CLEAR_SEL_REQUEST_INITIALIZE_ERASE;
+    ResponseDataSize           = sizeof (ClearSelResponse);
+
+    Status = IpmiSubmitCommand (
+               IPMI_NETFN_STORAGE,
+               IPMI_STORAGE_CLEAR_SEL,
+               (UINT8 *)&ClearSelRequest,
+               sizeof (ClearSelRequest),
+               (UINT8 *)&ClearSelResponse,
+               &ResponseDataSize
+               );
+  }
+
+  if (Status == EFI_SUCCESS) {
+    if (RecordId == NULL) {
+      WaitTillClearSel (ResvId);
+    }
+  }
+
+  return Status;
+}
+
+/**
+  Activate Bmc Elog.
+
+  @param DataType    - indicate event log type
+  @param EnableElog  - Enable/Disable event log
+  @param ElogStatus  - return log status
+
+  @retval EFI_STATUS
+
+**/
+EFI_STATUS
+ActivateBmcElog (
+  IN  EFI_SM_ELOG_TYPE  DataType,
+  IN  BOOLEAN           *EnableElog,
+  OUT BOOLEAN           *ElogStatus
+  )
+{
+  EFI_STATUS                            Status;
+  UINT8                                 ElogStat;
+  IPMI_GET_BMC_GLOBAL_ENABLES_RESPONSE  GetBmcGlobalResponse;
+  IPMI_SET_BMC_GLOBAL_ENABLES_REQUEST   SetBmcGlobalRequest;
+  UINT8                                 SetBmcGlobalResponse;
+  UINT32                                ResponseDataSize;
+
+  Status   = EFI_SUCCESS;
+  ElogStat = 0;
+
+  ResponseDataSize = sizeof (GetBmcGlobalResponse);
+  Status           = IpmiSubmitCommand (
+                       IPMI_NETFN_APP,
+                       IPMI_APP_GET_BMC_GLOBAL_ENABLES,
+                       NULL,
+                       0,
+                       (UINT8 *)&GetBmcGlobalResponse,
+                       &ResponseDataSize
+                       );
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "IpmiSubmitCommand App Get Bmc Global Enables Failed %r\n", Status));
+  }
+
+  if (EnableElog == NULL) {
+    *ElogStatus = (UINT8)(GetBmcGlobalResponse.GetEnables.Bits.SystemEventLogging);
+  } else {
+    if (Status == EFI_SUCCESS) {
+      if (*EnableElog) {
+        ElogStat = 0x1; // Setting SystemEventLogging
+      }
+
+      SetBmcGlobalRequest.SetEnables.Uint8                   = GetBmcGlobalResponse.GetEnables.Uint8;
+      SetBmcGlobalRequest.SetEnables.Bits.SystemEventLogging = ElogStat;
+
+      ResponseDataSize = sizeof (SetBmcGlobalResponse);
+      Status           = IpmiSubmitCommand (
+                           IPMI_NETFN_APP,
+                           IPMI_APP_SET_BMC_GLOBAL_ENABLES,
+                           (UINT8 *)&SetBmcGlobalRequest,
+                           sizeof (SetBmcGlobalRequest),
+                           (UINT8 *)&SetBmcGlobalResponse,
+                           &ResponseDataSize
+                           );
+
+      if (EFI_ERROR (Status)) {
+        DEBUG ((DEBUG_ERROR, "IpmiSubmitCommand App Set Bmc Global Enables Failed %r\n", Status));
+      }
+    }
+  }
+
+  return Status;
+}
+
+/**
+  This function checks the BMC SEL is full and whether to report the error.
+
+  @retval EFI_SUCCESS
+  @retval EFI_DEVICE_ERROR
+
+**/
+EFI_STATUS
+EFIAPI
+CheckIfSelIsFull (
+  VOID
+  )
+{
+  EFI_STATUS                  Status;
+  UINT32                      ResponseDataSize;
+  UINT8                       OperationSupportByte;
+  UINT8                       SelIsFull;
+  IPMI_GET_SEL_INFO_RESPONSE  GetSelInfoResponse;
+
+  OperationSupportByte = 0;
+  SelIsFull            = 0;
+
+  ResponseDataSize = sizeof (GetSelInfoResponse);
+
+  Status = IpmiSubmitCommand (
+             IPMI_NETFN_STORAGE,
+             IPMI_STORAGE_GET_SEL_INFO,
+             NULL,
+             0,
+             (UINT8 *)&GetSelInfoResponse,
+             &ResponseDataSize
+             );
+
+  if (EFI_ERROR (Status)) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  OperationSupportByte = GetSelInfoResponse.OperationSupport;
+
+  //
+  // Check the Bit7 of the OperationByte if SEL is OverFlow.
+  //
+  SelIsFull = (OperationSupportByte & IPMI_GET_SEL_INFO_OPERATION_SUPPORT_OVERFLOW_FLAG);
+
+  if (SelIsFull == IPMI_GET_SEL_INFO_OPERATION_SUPPORT_OVERFLOW_FLAG) {
+    //
+    // Report the Error code that SEL Log is full
+    //
+    ReportStatusCode (
+      (EFI_ERROR_CODE | EFI_ERROR_MINOR),
+      (SOFTWARE_EFI_BMC | EFI_SW_EC_EVENT_LOG_FULL)
+      );
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Dxe/BmcElog.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Dxe/BmcElog.c
new file mode 100644
index 000000000000..0b1e2f5b1355
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Dxe/BmcElog.c
@@ -0,0 +1,287 @@
+/** @file
+  BMC Event Log functions.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "BmcElog.h"
+
+//
+// Define module globals used to register for notification of when
+// the ELOG REDIR protocol has been produced.
+//
+EFI_EVENT                   mEfiBmcTransEvent;
+EFI_BMC_ELOG_INSTANCE_DATA  *mRedirProtoPrivate;
+
+/**
+  WaitTillErased.
+
+  @param BmcElogPrivateData  - Bmc event log instance
+  @param ResvId              - Reserved ID
+
+  @retval EFI_SUCCESS
+  @retval EFI_NO_RESPONSE
+
+**/
+EFI_STATUS
+WaitTillErased (
+  EFI_BMC_ELOG_INSTANCE_DATA  *BmcElogPrivateData,
+  UINT8                       *ResvId
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = WaitTillClearSel (ResvId);
+  return Status;
+}
+
+/**
+  Efi Set Bmc Elog Data.
+
+  @param This        - Protocol pointer
+  @param ElogData    - Buffer for log storage
+  @param DataType    - Event Log type
+  @param AlertEvent  - If it is an alert event
+  @param Size        - Log data size
+  @param RecordId    - Indicate which recorder it is
+
+  @retval EFI_STATUS
+
+**/
+EFI_STATUS
+EfiSetBmcElogData (
+  IN  EFI_SM_ELOG_REDIR_PROTOCOL  *This,
+  IN  UINT8                       *ElogData,
+  IN  EFI_SM_ELOG_TYPE            DataType,
+  IN  BOOLEAN                     AlertEvent,
+  IN  UINTN                       Size,
+  OUT UINT64                      *RecordId
+  )
+{
+  EFI_BMC_ELOG_INSTANCE_DATA  *BmcElogPrivateData;
+  EFI_STATUS                  Status;
+
+  Status             = EFI_SUCCESS;
+  BmcElogPrivateData = INSTANCE_FROM_EFI_ELOG_REDIR_THIS (This);
+
+  if (DataType >= EfiSmElogMax) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Size > SEL_RECORD_SIZE) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  if (BmcElogPrivateData->DataType == DataType) {
+    Status = SetBmcElogRecord (ElogData, DataType, AlertEvent, Size, RecordId);
+  }
+
+  return Status;
+}
+
+/**
+  Efi Get Bmc Elog Data.
+
+  @param This        - Protocol pointer
+  @param ElogData    - Buffer for log data store
+  @param DataType    - Event log type
+  @param Size        - Size of log data
+  @param RecordId    - indicate which recorder it is
+
+  @retval EFI_STATUS
+
+**/
+EFI_STATUS
+EfiGetBmcElogData (
+  IN EFI_SM_ELOG_REDIR_PROTOCOL  *This,
+  IN OUT UINT8                   *ElogData,
+  IN EFI_SM_ELOG_TYPE            DataType,
+  IN OUT UINTN                   *Size,
+  IN OUT UINT64                  *RecordId
+  )
+{
+  EFI_BMC_ELOG_INSTANCE_DATA  *BmcElogPrivateData;
+  EFI_STATUS                  Status;
+
+  Status             = EFI_SUCCESS;
+  BmcElogPrivateData = INSTANCE_FROM_EFI_ELOG_REDIR_THIS (This);
+
+  if (DataType >= EfiSmElogMax) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (BmcElogPrivateData->DataType == DataType) {
+    Status = GetBmcElogRecord (ElogData, DataType, Size, RecordId);
+  }
+
+  return Status;
+}
+
+/**
+  Efi Erase Bmc Elog Data.
+
+  @param This        - Protocol pointer
+  @param DataType    - Event log type
+  @param RecordId    - return which recorder it is
+
+  @retval EFI_STATUS
+
+**/
+EFI_STATUS
+EfiEraseBmcElogData (
+  IN EFI_SM_ELOG_REDIR_PROTOCOL  *This,
+  IN EFI_SM_ELOG_TYPE            DataType,
+  IN OUT UINT64                  *RecordId
+  )
+{
+  EFI_BMC_ELOG_INSTANCE_DATA  *BmcElogPrivateData;
+  EFI_STATUS                  Status;
+
+  Status             = EFI_SUCCESS;
+  BmcElogPrivateData = INSTANCE_FROM_EFI_ELOG_REDIR_THIS (This);
+
+  if (DataType >= EfiSmElogMax) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (BmcElogPrivateData->DataType == DataType) {
+    Status = EraseBmcElogRecord (DataType, RecordId);
+
+    if (Status == EFI_SUCCESS) {
+      if (RecordId != NULL) {
+        *RecordId = (UINT16)(*((UINT16 *)&BmcElogPrivateData->TempData[0]));
+      }
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Efi Activate Bmc Elog.
+
+  @param This        - Protocol pointer
+  @param DataType    - indicate event log type
+  @param EnableElog  - Enable/Disable event log
+  @param ElogStatus  - return log status
+
+  @retval EFI_STATUS
+
+**/
+EFI_STATUS
+EfiActivateBmcElog (
+  IN EFI_SM_ELOG_REDIR_PROTOCOL  *This,
+  IN EFI_SM_ELOG_TYPE            DataType,
+  IN BOOLEAN                     *EnableElog,
+  OUT BOOLEAN                    *ElogStatus
+  )
+{
+  EFI_BMC_ELOG_INSTANCE_DATA  *BmcElogPrivateData;
+  EFI_STATUS                  Status;
+
+  Status             = EFI_SUCCESS;
+  BmcElogPrivateData = INSTANCE_FROM_EFI_ELOG_REDIR_THIS (This);
+
+  if (DataType >= EfiSmElogMax) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (BmcElogPrivateData->DataType == DataType) {
+    Status = ActivateBmcElog (DataType, EnableElog, ElogStatus);
+  }
+
+  return Status;
+}
+
+/**
+  Set Elog Redir Install.
+
+  @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+SetElogRedirInstall (
+  VOID
+  )
+{
+  EFI_HANDLE  NewHandle;
+  EFI_STATUS  Status;
+  BOOLEAN     EnableElog;
+  BOOLEAN     ElogStatus;
+  UINT16      Instance;
+
+  Status     = EFI_SUCCESS;
+  EnableElog = TRUE;
+  ElogStatus = TRUE;
+  Instance   = 0;
+
+  mRedirProtoPrivate->Signature                 = EFI_ELOG_REDIR_SIGNATURE;
+  mRedirProtoPrivate->DataType                  = EfiElogSmIPMI;
+  mRedirProtoPrivate->BmcElog.ActivateEventLog  = EfiActivateBmcElog;
+  mRedirProtoPrivate->BmcElog.EraseEventlogData = EfiEraseBmcElogData;
+  mRedirProtoPrivate->BmcElog.GetEventLogData   = EfiGetBmcElogData;
+  mRedirProtoPrivate->BmcElog.SetEventLogData   = EfiSetBmcElogData;
+  mRedirProtoPrivate->Instance                  = Instance;
+  //
+  // Now install the Protocol
+  //
+  NewHandle = NULL;
+
+  Status = gBS->InstallProtocolInterface (
+                  &NewHandle,
+                  &gEfiRedirElogProtocolGuid,
+                  EFI_NATIVE_INTERFACE,
+                  &mRedirProtoPrivate->BmcElog
+                  );
+  ASSERT_EFI_ERROR (Status);
+  if (Status != EFI_SUCCESS) {
+    return Status;
+  }
+
+  //
+  // Activate the Event Log (This should depend upon Setup).
+  //
+  EfiActivateBmcElog (&mRedirProtoPrivate->BmcElog, EfiElogSmIPMI, &EnableElog, &ElogStatus);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  InitializeBmcElogLayer.
+
+  @param ImageHandle - ImageHandle of the loaded driver
+  @param SystemTable - Pointer to the System Table
+
+  @retval EFI_STATUS
+
+**/
+EFI_STATUS
+InitializeBmcElogLayer (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = EFI_SUCCESS;
+
+  InitializeIpmiBase ();
+
+  mRedirProtoPrivate = AllocatePool (sizeof (EFI_BMC_ELOG_INSTANCE_DATA));
+  ASSERT (mRedirProtoPrivate != NULL);
+  if (mRedirProtoPrivate == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  SetElogRedirInstall ();
+
+  //
+  // Check if the BMC System Event Log (SEL) is full and whether to report the error.
+  //
+
+  CheckIfSelIsFull ();
+
+  return Status;
+}
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Pei/BmcElog.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Pei/BmcElog.c
new file mode 100644
index 000000000000..f791d872b7a1
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Pei/BmcElog.c
@@ -0,0 +1,297 @@
+/** @file
+  BMC Event Log functions.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "BmcElog.h"
+
+//
+// Define module globals used to register for notification of when
+// the ELOG REDIR protocol has been produced.
+//
+
+EFI_STATUS
+NotifyPeiBmcElogCallback (
+  IN EFI_PEI_SERVICES           **PeiServices,
+  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,
+  IN VOID                       *Ppi
+  );
+
+EFI_PEI_NOTIFY_DESCRIPTOR  mNotifyList[] = {
+  {
+    EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+    &gPeiIpmiTransportPpiGuid,
+    NotifyPeiBmcElogCallback
+  }
+};
+
+/**
+  Efi Set Bmc Elog Data.
+
+  @param This        - Protocol pointer
+  @param ElogData    - Buffer for log storage
+  @param DataType    - Event Log type
+  @param AlertEvent  - If it is an alert event
+  @param Size        - Log data size
+  @param RecordId    - Indicate which recorder it is
+
+  @retval EFI_STATUS
+
+**/
+EFI_STATUS
+EfiSetBmcElogData (
+  IN  EFI_SM_ELOG_REDIR_PPI  *This,
+  IN  UINT8                  *ElogData,
+  IN  EFI_SM_ELOG_TYPE       DataType,
+  IN  BOOLEAN                AlertEvent,
+  IN  UINTN                  Size,
+  OUT UINT64                 *RecordId
+  )
+{
+  EFI_PEI_BMC_ELOG_INSTANCE_DATA  *BmcElogPrivateData;
+  EFI_STATUS                      Status;
+
+  Status             = EFI_SUCCESS;
+  BmcElogPrivateData = INSTANCE_FROM_EFI_PEI_ELOG_REDIR_THIS (This);
+
+  if (DataType >= EfiSmElogMax) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Size > SEL_RECORD_SIZE) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  if (BmcElogPrivateData->DataType == DataType) {
+    Status = SetBmcElogRecord (ElogData, DataType, AlertEvent, Size, RecordId);
+  }
+
+  return Status;
+}
+
+/**
+  Efi Get Bmc Elog Data.
+
+  @param This        - Protocol pointer
+  @param ElogData    - Buffer for log data store
+  @param DataType    - Event log type
+  @param Size        - Size of log data
+  @param RecordId    - indicate which recorder it is
+
+  @retval EFI_STATUS
+
+**/
+EFI_STATUS
+EfiGetBmcElogData (
+  IN EFI_SM_ELOG_REDIR_PPI  *This,
+  IN OUT UINT8              *ElogData,
+  IN EFI_SM_ELOG_TYPE       DataType,
+  IN OUT UINTN              *Size,
+  IN OUT UINT64             *RecordId
+  )
+{
+  EFI_PEI_BMC_ELOG_INSTANCE_DATA  *BmcElogPrivateData;
+  EFI_STATUS                      Status;
+
+  Status             = EFI_SUCCESS;
+  BmcElogPrivateData = INSTANCE_FROM_EFI_PEI_ELOG_REDIR_THIS (This);
+
+  if (DataType >= EfiSmElogMax) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (BmcElogPrivateData->DataType == DataType) {
+    Status = GetBmcElogRecord (ElogData, DataType, Size, RecordId);
+  }
+
+  return Status;
+}
+
+/**
+  Efi Erase Bmc Elog Data.
+
+  @param This        - Protocol pointer
+  @param DataType    - Event log type
+  @param RecordId    - return which recorder it is
+
+  @retval EFI_STATUS
+
+**/
+EFI_STATUS
+EfiEraseBmcElogData (
+  IN EFI_SM_ELOG_REDIR_PPI  *This,
+  IN EFI_SM_ELOG_TYPE       DataType,
+  IN OUT UINT64             *RecordId
+  )
+{
+  EFI_PEI_BMC_ELOG_INSTANCE_DATA  *BmcElogPrivateData;
+  EFI_STATUS                      Status;
+
+  Status             = EFI_SUCCESS;
+  BmcElogPrivateData = INSTANCE_FROM_EFI_PEI_ELOG_REDIR_THIS (This);
+
+  if (DataType >= EfiSmElogMax) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (BmcElogPrivateData->DataType == DataType) {
+    Status = EraseBmcElogRecord (DataType, RecordId);
+
+    if (Status == EFI_SUCCESS) {
+      if (RecordId != NULL) {
+        *RecordId = (UINT16)(*((UINT16 *)&BmcElogPrivateData->TempData[0]));
+      }
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Efi Activate Bmc Elog.
+
+  @param This        - Protocol pointer
+  @param DataType    - indicate event log type
+  @param EnableElog  - Enable/Disable event log
+  @param ElogStatus  - return log status
+
+  @retval EFI_STATUS
+
+**/
+EFI_STATUS
+EfiActivateBmcElog (
+  IN EFI_SM_ELOG_REDIR_PPI  *This,
+  IN EFI_SM_ELOG_TYPE       DataType,
+  IN BOOLEAN                *EnableElog,
+  OUT BOOLEAN               *ElogStatus
+  )
+{
+  EFI_PEI_BMC_ELOG_INSTANCE_DATA  *BmcElogPrivateData;
+  EFI_STATUS                      Status;
+
+  Status             = EFI_SUCCESS;
+  BmcElogPrivateData = INSTANCE_FROM_EFI_PEI_ELOG_REDIR_THIS (This);
+
+  if (DataType >= EfiSmElogMax) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (BmcElogPrivateData->DataType == DataType) {
+    Status = ActivateBmcElog (DataType, EnableElog, ElogStatus);
+  }
+
+  return Status;
+}
+
+/**
+  Set Elog Redir Install.
+
+  @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+SetElogRedirInstall (
+  EFI_PEI_BMC_ELOG_INSTANCE_DATA  *mRedirPeiProtoPrivate
+  )
+{
+  EFI_STATUS  Status;
+  BOOLEAN     EnableElog;
+  BOOLEAN     ElogStatus;
+  UINT16      Instance;
+
+  Status     = EFI_SUCCESS;
+  EnableElog = TRUE;
+  ElogStatus = TRUE;
+  Instance   = 0;
+
+  mRedirPeiProtoPrivate->Signature                    = EFI_PEI_ELOG_REDIR_SIGNATURE;
+  mRedirPeiProtoPrivate->DataType                     = EfiElogSmIPMI;
+  mRedirPeiProtoPrivate->BmcElogPpi.ActivateEventLog  = EfiActivateBmcElog;
+  mRedirPeiProtoPrivate->BmcElogPpi.EraseEventlogData = EfiEraseBmcElogData;
+  mRedirPeiProtoPrivate->BmcElogPpi.GetEventLogData   = EfiGetBmcElogData;
+  mRedirPeiProtoPrivate->BmcElogPpi.SetEventLogData   = EfiSetBmcElogData;
+
+  mRedirPeiProtoPrivate->BmcElog.Guid  = &gPeiRedirElogPpiGuid;
+  mRedirPeiProtoPrivate->BmcElog.Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
+  mRedirPeiProtoPrivate->BmcElog.Ppi   = (VOID *)&mRedirPeiProtoPrivate->BmcElogPpi;
+  mRedirPeiProtoPrivate->Instance      = Instance;
+  //
+  // Now install the Protocol
+  //
+
+  Status = PeiServicesInstallPpi (&mRedirPeiProtoPrivate->BmcElog);
+  ASSERT_EFI_ERROR (Status);
+  if (Status != EFI_SUCCESS) {
+    return Status;
+  }
+
+  //
+  // Activate the Event Log (This should depend upon Setup).
+  //
+  EfiActivateBmcElog (&mRedirPeiProtoPrivate->BmcElogPpi, EfiElogSmIPMI, &EnableElog, &ElogStatus);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  InitializeBmcElogLayer.
+
+  @param ImageHandle - ImageHandle of the loaded driver
+  @param SystemTable - Pointer to the System Table
+
+  @retval EFI_STATUS
+
+**/
+EFI_STATUS
+InitializeBmcElogLayer (
+  IN       EFI_PEI_FILE_HANDLE  FileHandle,
+  IN CONST EFI_PEI_SERVICES     **PeiServices
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = EFI_SUCCESS;
+
+  Status = PeiServicesNotifyPpi (&mNotifyList[0]);
+  return Status;
+}
+
+/**
+  NotifyPeiBmcElogCallback   This notification function is invoked when an instance of the
+  IPMI Transport layer at PEI is produced.
+
+  @param PeiServices      - Pointer to the PEI Services table
+  @param NotifyDescriptor - Pointer to the NotifyPpi Descriptor
+  @param Ppi              - Pointer to the PPI passed during Notify
+
+  @retval EFI_STATUS
+
+**/
+EFI_STATUS
+NotifyPeiBmcElogCallback (
+  IN EFI_PEI_SERVICES           **PeiServices,
+  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,
+  IN VOID                       *Ppi
+  )
+{
+  EFI_STATUS                      Status;
+  EFI_PEI_BMC_ELOG_INSTANCE_DATA  *mRedirPeiProtoPrivate;
+
+  Status = EFI_SUCCESS;
+
+  mRedirPeiProtoPrivate = AllocateZeroPool (sizeof (EFI_PEI_BMC_ELOG_INSTANCE_DATA));
+
+  if (mRedirPeiProtoPrivate == NULL) {
+    DEBUG ((DEBUG_ERROR, "IPMI BMCELog Peim:EFI_OUT_OF_RESOURCES of memory allocation\n"));
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  SetElogRedirInstall (mRedirPeiProtoPrivate);
+
+  CheckIfSelIsFull ();
+
+  return Status;
+}
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Smm/BmcElog.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Smm/BmcElog.c
new file mode 100644
index 000000000000..efaa61f43869
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Smm/BmcElog.c
@@ -0,0 +1,288 @@
+/** @file
+  BMC Event Log functions.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "BmcElog.h"
+
+//
+// Define module globals used to register for notification of when
+// the ELOG REDIR protocol has been produced.
+//
+EFI_EVENT                   mEfiBmcTransEvent;
+EFI_BMC_ELOG_INSTANCE_DATA  *mRedirProtoPrivate;
+
+/**
+  WaitTillErased.
+
+  @param BmcElogPrivateData  - Bmc event log instance
+  @param ResvId              - Reserved ID
+
+  @retval EFI_SUCCESS
+  @retval EFI_NO_RESPONSE
+
+**/
+EFI_STATUS
+WaitTillErased (
+  EFI_BMC_ELOG_INSTANCE_DATA  *BmcElogPrivateData,
+  UINT8                       *ResvId
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = WaitTillClearSel (ResvId);
+  return Status;
+}
+
+/**
+  Efi Set Bmc Elog Data.
+
+  @param This        - Protocol pointer
+  @param ElogData    - Buffer for log storage
+  @param DataType    - Event Log type
+  @param AlertEvent  - If it is an alert event
+  @param Size        - Log data size
+  @param RecordId    - Indicate which recorder it is
+
+  @retval EFI_STATUS
+
+**/
+EFI_STATUS
+EfiSetBmcElogData (
+  IN  EFI_SM_ELOG_REDIR_PROTOCOL  *This,
+  IN  UINT8                       *ElogData,
+  IN  EFI_SM_ELOG_TYPE            DataType,
+  IN  BOOLEAN                     AlertEvent,
+  IN  UINTN                       Size,
+  OUT UINT64                      *RecordId
+  )
+{
+  EFI_BMC_ELOG_INSTANCE_DATA  *BmcElogPrivateData;
+  EFI_STATUS                  Status;
+
+  Status             = EFI_SUCCESS;
+  BmcElogPrivateData = INSTANCE_FROM_EFI_SM_ELOG_REDIR_THIS (This);
+
+  if (DataType >= EfiSmElogMax) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Size > SEL_RECORD_SIZE) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  if (BmcElogPrivateData->DataType == DataType) {
+    Status = SetBmcElogRecord (ElogData, DataType, AlertEvent, Size, RecordId);
+  }
+
+  return Status;
+}
+
+/**
+  Efi Get Bmc Elog Data.
+
+  @param This        - Protocol pointer
+  @param ElogData    - Buffer for log data store
+  @param DataType    - Event log type
+  @param Size        - Size of log data
+  @param RecordId    - indicate which recorder it is
+
+  @retval EFI_STATUS
+
+**/
+EFI_STATUS
+EfiGetBmcElogData (
+  IN EFI_SM_ELOG_REDIR_PROTOCOL  *This,
+  IN OUT UINT8                   *ElogData,
+  IN EFI_SM_ELOG_TYPE            DataType,
+  IN OUT UINTN                   *Size,
+  IN OUT UINT64                  *RecordId
+  )
+{
+  EFI_BMC_ELOG_INSTANCE_DATA  *BmcElogPrivateData;
+  EFI_STATUS                  Status;
+
+  Status             = EFI_SUCCESS;
+  BmcElogPrivateData = INSTANCE_FROM_EFI_SM_ELOG_REDIR_THIS (This);
+
+  if (DataType >= EfiSmElogMax) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (BmcElogPrivateData->DataType == DataType) {
+    Status = GetBmcElogRecord (ElogData, DataType, Size, RecordId);
+  }
+
+  return Status;
+}
+
+/**
+  Efi Erase Bmc Elog Data.
+
+  @param This        - Protocol pointer
+  @param DataType    - Event log type
+  @param RecordId    - return which recorder it is
+
+  @retval EFI_STATUS
+
+**/
+EFI_STATUS
+EfiEraseBmcElogData (
+  IN EFI_SM_ELOG_REDIR_PROTOCOL  *This,
+  IN EFI_SM_ELOG_TYPE            DataType,
+  IN OUT UINT64                  *RecordId
+  )
+{
+  EFI_BMC_ELOG_INSTANCE_DATA  *BmcElogPrivateData;
+  EFI_STATUS                  Status;
+
+  Status             = EFI_SUCCESS;
+  BmcElogPrivateData = INSTANCE_FROM_EFI_SM_ELOG_REDIR_THIS (This);
+
+  if (DataType >= EfiSmElogMax) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (BmcElogPrivateData->DataType == DataType) {
+    Status = EraseBmcElogRecord (DataType, RecordId);
+
+    if (Status == EFI_SUCCESS) {
+      if (RecordId != NULL) {
+        *RecordId = (UINT16)(*((UINT16 *)&BmcElogPrivateData->TempData[0]));
+      }
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Efi Activate Bmc Elog.
+
+  @param This        - Protocol pointer
+  @param DataType    - indicate event log type
+  @param EnableElog  - Enable/Disable event log
+  @param ElogStatus  - return log status
+
+  @retval EFI_STATUS
+
+**/
+EFI_STATUS
+EfiActivateBmcElog (
+  IN EFI_SM_ELOG_REDIR_PROTOCOL  *This,
+  IN EFI_SM_ELOG_TYPE            DataType,
+  IN BOOLEAN                     *EnableElog,
+  OUT BOOLEAN                    *ElogStatus
+  )
+{
+  EFI_BMC_ELOG_INSTANCE_DATA  *BmcElogPrivateData;
+  EFI_STATUS                  Status;
+
+  Status             = EFI_SUCCESS;
+  BmcElogPrivateData = INSTANCE_FROM_EFI_SM_ELOG_REDIR_THIS (This);
+
+  if (DataType >= EfiSmElogMax) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (BmcElogPrivateData->DataType == DataType) {
+    Status = ActivateBmcElog (DataType, EnableElog, ElogStatus);
+  }
+
+  return Status;
+}
+
+/**
+  Set Elog Redir Install.
+
+  @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+SetElogRedirInstall (
+  VOID
+  )
+{
+  EFI_HANDLE  NewHandle;
+  EFI_STATUS  Status;
+  BOOLEAN     EnableElog;
+  BOOLEAN     ElogStatus;
+  UINT16      Instance;
+
+  Status     = EFI_SUCCESS;
+  EnableElog = TRUE;
+  ElogStatus = TRUE;
+  Instance   = 0;
+
+  mRedirProtoPrivate->Signature                 = SM_ELOG_REDIR_SIGNATURE;
+  mRedirProtoPrivate->DataType                  = EfiElogSmIPMI;
+  mRedirProtoPrivate->BmcElog.ActivateEventLog  = (EFI_ACTIVATE_ELOG)EfiActivateBmcElog;
+  mRedirProtoPrivate->BmcElog.EraseEventlogData = (EFI_ERASE_ELOG_DATA)EfiEraseBmcElogData;
+  mRedirProtoPrivate->BmcElog.GetEventLogData   = (EFI_GET_ELOG_DATA)EfiGetBmcElogData;
+  mRedirProtoPrivate->BmcElog.SetEventLogData   = (EFI_SET_ELOG_DATA)EfiSetBmcElogData;
+  mRedirProtoPrivate->Instance                  = Instance;
+  //
+  // Now install the Protocol
+  //
+  NewHandle = NULL;
+  Status    = gSmst->SmmInstallProtocolInterface (
+                       &NewHandle,
+                       &gSmmRedirElogProtocolGuid,
+                       EFI_NATIVE_INTERFACE,
+                       &mRedirProtoPrivate->BmcElog
+                       );
+
+  ASSERT_EFI_ERROR (Status);
+  if (Status != EFI_SUCCESS) {
+    return Status;
+  }
+
+  //
+  // Activate the Event Log (This should depend upon Setup).
+  //
+  EfiActivateBmcElog (&mRedirProtoPrivate->BmcElog, EfiElogSmIPMI, &EnableElog, &ElogStatus);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  InitializeBmcElogLayer.
+
+  @param ImageHandle - ImageHandle of the loaded driver
+  @param SystemTable - Pointer to the System Table
+
+  @retval EFI_STATUS
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeSmBmcElogLayer (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = EFI_SUCCESS;
+
+  gST = SystemTable;
+  gBS = gST->BootServices;
+
+  mRedirProtoPrivate = AllocatePool (sizeof (EFI_BMC_ELOG_INSTANCE_DATA));
+  ASSERT (mRedirProtoPrivate != NULL);
+  if (mRedirProtoPrivate == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  SetElogRedirInstall ();
+  //
+  // Check if the BMC System Event Log (SEL) is full and whether to report the error.
+  //
+
+  CheckIfSelIsFull ();
+
+  return Status;
+}
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Dxe/GenericElog.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Dxe/GenericElog.c
new file mode 100644
index 000000000000..d432b2151664
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Dxe/GenericElog.c
@@ -0,0 +1,576 @@
+/** @file
+  Generic Event Log functions of DXE driver.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "GenericElog.h"
+
+ELOG_MODULE_GLOBAL  *mElogModuleGlobal;
+
+//
+// Define module globals used to register for notification of when
+// the ELOG REDIR protocol has been produced.
+//
+EFI_EVENT  mEfiElogRedirProtocolEvent;
+
+/**
+  Sends the Event-Log data to the destination.
+
+  @param[in] ElogData Pointer to the Event-Log data that needs to be recorded.
+  @param[in] DataType Type of Elog Data that is being recorded.
+  @param[in] AlertEvent This is an indication that the input data type is an Alert.
+  @param[in] DataSize
+  @param[out] RecordId Record ID sent by the target.
+  @param[in] Global The module global variable pointer.
+  @param[in] Virtual If this function is called in virtual mode or physical mode
+
+  @retval EFI_SUCCESS Event-Log was recorded successfully.
+  @retval EFI_OUT_OF_RESOURCES Not enough resources to record data.
+  @retval EFI_UNSUPPORTED The Data Type is unsupported.
+
+**/
+EFI_STATUS
+EfiLibSetElogData (
+  IN  UINT8               *ElogData,
+  IN  EFI_SM_ELOG_TYPE    DataType,
+  IN  BOOLEAN             AlertEvent,
+  IN  UINTN               DataSize,
+  OUT UINT64              *RecordId,
+  IN  ELOG_MODULE_GLOBAL  *Global,
+  IN  BOOLEAN             Virtual
+  )
+{
+  UINT8       Index;
+  VOID        *ElogRedirCommand;
+  EFI_STATUS  Status;
+  EFI_STATUS  RetStatus;
+
+  RetStatus = EFI_UNSUPPORTED;
+
+  if (DataType >= EfiSmElogMax) {
+    RetStatus = EFI_INVALID_PARAMETER;
+    return RetStatus;
+  }
+
+  for (Index = 0; Index < Global->MaxDescriptors; Index++) {
+    if (Global->Redir[Index].Valid) {
+      ElogRedirCommand = Global->Redir[Index].Command[Virtual].SetEventLogData.Function;
+      Status           = (*((EFI_SET_ELOG_DATA *)&ElogRedirCommand))(Global->Redir[Index].Command[Virtual].This, ElogData, DataType, AlertEvent, DataSize, RecordId);
+
+      if (!EFI_ERROR (Status)) {
+        RetStatus = EFI_SUCCESS;
+        break;
+      } else if (Status != EFI_UNSUPPORTED) {
+        RetStatus = Status;
+        break;
+      }
+    }
+  }
+
+  return RetStatus;
+}
+
+/**
+  Add function description.
+
+  @param This        -  add argument description
+  @param ElogData    -  add argument description
+  @param DataType    -  add argument description
+  @param AlertEvent  -  add argument description
+  @param DataSize    -  add argument description
+  @param RecordId    -  add argument description
+
+  @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EfiSetElogData (
+  IN  EFI_SM_ELOG_PROTOCOL  *This,
+  IN  UINT8                 *ElogData,
+  IN  EFI_SM_ELOG_TYPE      DataType,
+  IN  BOOLEAN               AlertEvent,
+  IN  UINTN                 DataSize,
+  OUT UINT64                *RecordId
+  )
+{
+  if (DataType >= EfiSmElogMax) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return EfiLibSetElogData (
+           ElogData,
+           DataType,
+           AlertEvent,
+           DataSize,
+           RecordId,
+           mElogModuleGlobal,
+           FALSE
+           );
+}
+
+/**
+  Gets the Event-Log data from the destination.
+
+  @param[in] ElogData Pointer to the Event-Log data buffer that will contain the data to be retrieved.
+  @param[in] DataType Type of Elog Data that is being recorded.
+  @param[in, out] DataSize
+  @param[in, out] RecordId This is the RecordId of the next record. If ElogData is NULL,
+                       this gives the RecordId of the first record available in the database with the correct DataSize.
+                        A value of 0 on return indicates the last record if the EFI_STATUS indicates a success
+  @param[in] Global The module global variable pointer.
+  @param[in] Virtual If this function is called in virtual mode or physical mode
+
+  @retval EFI_SUCCESS Event-Log was retrieved successfully.
+  @retval EFI_NOT_FOUND Event-Log target not found.
+  @retval EFI_BUFFER_TOO_SMALL Target buffer is too small to retrieve the data.
+  @retval EFI_UNSUPPORTED The Data Type is unsupported
+
+**/
+EFI_STATUS
+EfiLibGetElogData (
+  IN UINT8               *ElogData,
+  IN EFI_SM_ELOG_TYPE    DataType,
+  IN OUT UINTN           *DataSize,
+  IN OUT UINT64          *RecordId,
+  IN ELOG_MODULE_GLOBAL  *Global,
+  IN BOOLEAN             Virtual
+  )
+{
+  UINT8       Index;
+  VOID        *ElogRedirCommand;
+  EFI_STATUS  Status;
+  EFI_STATUS  RetStatus;
+
+  RetStatus = EFI_UNSUPPORTED;
+
+  if (DataType >= EfiSmElogMax) {
+    RetStatus = EFI_INVALID_PARAMETER;
+    return RetStatus;
+  }
+
+  for (Index = 0; Index < Global->MaxDescriptors; Index++) {
+    if (Global->Redir[Index].Valid) {
+      ElogRedirCommand = Global->Redir[Index].Command[Virtual].GetEventLogData.Function;
+      Status           = (*((EFI_GET_ELOG_DATA *)&ElogRedirCommand))(Global->Redir[Index].Command[Virtual].This, ElogData, DataType, DataSize, RecordId);
+
+      if (!EFI_ERROR (Status)) {
+        RetStatus = EFI_SUCCESS;
+        break;
+      } else if (Status != EFI_UNSUPPORTED) {
+        RetStatus = Status;
+        break;
+      }
+    }
+  }
+
+  return RetStatus;
+}
+
+/**
+  Add function description.
+
+  @param This      - Protocol instance pointer.
+  @param ElogData  - Pointer to the Event-Log data buffer that will contain the data to be retrieved.
+  @param DataType  - Type of Elog Data that is being recorded.
+  @param DataSize  - Size of Elog Data in bytes.
+  @param RecordId  - This is the RecordId of the next record. If ElogData is NULL,
+                     this gives the RecordId of the first record available in the database with the correct DataSize.
+                     A value of 0 on return indicates the last record if the EFI_STATUS indicates a success
+
+  @retval EFI_SUCCESS add return values
+
+**/
+EFI_STATUS
+EfiGetElogData (
+  IN EFI_SM_ELOG_PROTOCOL  *This,
+  IN UINT8                 *ElogData,
+  IN EFI_SM_ELOG_TYPE      DataType,
+  IN OUT UINTN             *DataSize,
+  IN OUT UINT64            *RecordId
+  )
+{
+  if (DataType >= EfiSmElogMax) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return EfiLibGetElogData (ElogData, DataType, DataSize, RecordId, mElogModuleGlobal, FALSE);
+}
+
+/**
+  Erases the Event-Log data from the destination.
+
+  @param DataType              - Type of Elog Data that is being Erased.
+  @param RecordId              - This is the RecordId of the data to be erased. If RecordId is NULL, all
+                                 the records on the database are erased if permitted by the target.
+                                 Contains the deleted RecordId on return
+  @param Global                - The module global variable pointer.
+  @param Virtual               - If this function is called in virtual mode or physical mode
+
+  @retval EFI_SUCCESS           - Event-Log was erased successfully
+  @retval EFI_UNSUPPORTED       - The Data Type is unsupported
+  @retval EFI_NOT_FOUND         - Event-Log target not found
+
+**/
+EFI_STATUS
+EfiLibEraseElogData (
+  IN EFI_SM_ELOG_TYPE    DataType,
+  IN OUT UINT64          *RecordId,
+  IN ELOG_MODULE_GLOBAL  *Global,
+  IN BOOLEAN             Virtual
+  )
+{
+  UINT8       Index;
+  VOID        *ElogRedirCommand;
+  EFI_STATUS  Status;
+  EFI_STATUS  RetStatus;
+
+  RetStatus = EFI_UNSUPPORTED;
+
+  if (DataType >= EfiSmElogMax) {
+    RetStatus = EFI_INVALID_PARAMETER;
+    return RetStatus;
+  }
+
+  for (Index = 0; Index < Global->MaxDescriptors; Index++) {
+    if (Global->Redir[Index].Valid) {
+      ElogRedirCommand = Global->Redir[Index].Command[Virtual].EraseEventLogData.Function;
+      Status           = (*((EFI_ERASE_ELOG_DATA *)&ElogRedirCommand))(Global->Redir[Index].Command[Virtual].This, DataType, RecordId);
+
+      if (!EFI_ERROR (Status)) {
+        RetStatus = EFI_SUCCESS;
+        break;
+      } else if (Status != EFI_UNSUPPORTED) {
+        RetStatus = Status;
+        break;
+      }
+    }
+  }
+
+  return RetStatus;
+}
+
+/**
+  Efi Erase Elog Data.
+
+  @param This
+  @param DataType
+  @param RecordId
+
+  @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EfiEraseElogData (
+  IN EFI_SM_ELOG_PROTOCOL  *This,
+  IN EFI_SM_ELOG_TYPE      DataType,
+  IN OUT UINT64            *RecordId
+  )
+{
+  return EfiLibEraseElogData (DataType, RecordId, mElogModuleGlobal, FALSE);
+}
+
+/**
+  This API enables/Disables Event Log.
+
+  @param DataType              - Type of Elog Data that is being Activated.
+  @param EnableElog            - Enables (TRUE) / Disables (FALSE) Event Log. If NULL just returns the
+                                 Current ElogStatus.
+  @param ElogStatus            - Current (New) Status of Event Log. Enabled (TRUE), Disabled (FALSE).
+  @param Global                - The module global variable pointer.
+  @param Virtual               - If this function is called in virtual mode or physical mode
+
+  @retval EFI_SUCCESS           - Event-Log was recorded successfully
+  @retval EFI_UNSUPPORTED       - The Data Type is unsupported
+
+**/
+EFI_STATUS
+EfiLibActivateElog (
+  IN  EFI_SM_ELOG_TYPE  DataType,
+  IN BOOLEAN            *EnableElog,
+  OUT BOOLEAN           *ElogStatus,
+  ELOG_MODULE_GLOBAL    *Global,
+  BOOLEAN               Virtual
+  )
+{
+  UINT8       Index;
+  VOID        *ElogRedirCommand;
+  EFI_STATUS  Status;
+  EFI_STATUS  RetStatus;
+
+  RetStatus = EFI_UNSUPPORTED;
+  if (DataType >= EfiSmElogMax) {
+    RetStatus = EFI_INVALID_PARAMETER;
+    return RetStatus;
+  }
+
+  for (Index = 0; Index < Global->MaxDescriptors; Index++) {
+    if (Global->Redir[Index].Valid) {
+      ElogRedirCommand = Global->Redir[Index].Command[Virtual].ActivateEventLog.Function;
+      Status           = (*((EFI_ACTIVATE_ELOG *)&ElogRedirCommand))(Global->Redir[Index].Command[Virtual].This, DataType, EnableElog, ElogStatus);
+
+      if (!EFI_ERROR (Status)) {
+        RetStatus = EFI_SUCCESS;
+        break;
+      } else if (Status != EFI_UNSUPPORTED) {
+        RetStatus = Status;
+        break;
+      }
+    }
+  }
+
+  return RetStatus;
+}
+
+/**
+  Efi Activate Elog.
+
+  @param This
+  @param DataType
+  @param EnableElog
+  @param ElogStatus
+
+  @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EfiActivateElog (
+  IN EFI_SM_ELOG_PROTOCOL  *This,
+  IN  EFI_SM_ELOG_TYPE     DataType,
+  IN BOOLEAN               *EnableElog,
+  OUT BOOLEAN              *ElogStatus
+  )
+{
+  if (DataType >= EfiSmElogMax) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return EfiLibActivateElog (DataType, EnableElog, ElogStatus, mElogModuleGlobal, FALSE);
+}
+
+/**
+  SetElogRedirInstances.
+
+  @retval EFI_SUCCESS - The Redir instances were successfully set.
+  @retval Other       - Failed to set Redir instances.
+
+**/
+EFI_STATUS
+SetElogRedirInstances (
+  VOID
+  )
+{
+  UINTN                       NumHandles;
+  UINTN                       Index;
+  UINTN                       Instance;
+  UINTN                       EmptyIndex;
+  EFI_HANDLE                  *Buffer;
+  EFI_STATUS                  Status;
+  EFI_SM_ELOG_REDIR_PROTOCOL  *Redir;
+  REDIR_MODULE_PROC           *RedirProc;
+
+  Buffer = NULL;
+
+  //
+  // Check for all IPMI Controllers
+  //
+  Status = gBS->LocateHandleBuffer (
+                  ByProtocol,
+                  &gEfiRedirElogProtocolGuid,
+                  NULL,
+                  &NumHandles,
+                  &Buffer
+                  );
+
+  if (EFI_ERROR (Status) || (NumHandles == 0)) {
+    return EFI_SUCCESS;
+  }
+
+  for (Index = 0; ((Index < NumHandles) && (Index < mElogModuleGlobal->MaxDescriptors)); Index++) {
+    EmptyIndex = mElogModuleGlobal->MaxDescriptors;
+
+    Status = gBS->HandleProtocol (
+                    Buffer[Index],
+                    &gEfiRedirElogProtocolGuid,
+                    (VOID *)&Redir
+                    );
+    if (EFI_ERROR (Status) || (Redir == NULL)) {
+      continue;
+    }
+
+    for (Instance = 0; Instance < mElogModuleGlobal->MaxDescriptors; Instance++) {
+      if (mElogModuleGlobal->Redir[Instance].Valid == FALSE) {
+        if (EmptyIndex >= mElogModuleGlobal->MaxDescriptors) {
+          EmptyIndex = Instance;
+        }
+      } else {
+        if (Redir == mElogModuleGlobal->Redir[Instance].Command->This) {
+          EmptyIndex = mElogModuleGlobal->MaxDescriptors;
+          break;
+          //
+          // FIX: changed continue to break.
+          //
+        }
+      }
+    }
+
+    if (EmptyIndex < mElogModuleGlobal->MaxDescriptors) {
+      RedirProc                                  = (REDIR_MODULE_PROC *)mElogModuleGlobal->Redir[EmptyIndex].Command;
+      mElogModuleGlobal->Redir[EmptyIndex].Valid = TRUE;
+
+      EfiSetFunctionEntry (&RedirProc->ActivateEventLog, *((VOID **)&Redir->ActivateEventLog));
+      EfiSetFunctionEntry (&RedirProc->EraseEventLogData, *((VOID **)&Redir->EraseEventlogData));
+      EfiSetFunctionEntry (&RedirProc->GetEventLogData, *((VOID **)&Redir->GetEventLogData));
+      EfiSetFunctionEntry (&RedirProc->SetEventLogData, *((VOID **)&Redir->SetEventLogData));
+      RedirProc->This = Redir;
+
+      CopyMem (&RedirProc[EFI_ELOG_VIRTUAL], &RedirProc[EFI_ELOG_PHYSICAL], sizeof (REDIR_MODULE_PROC));
+    }
+  }
+
+  if (Buffer != NULL) {
+    FreePool (Buffer);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  This notification function is invoked when an instance of the
+  ELOG REDIR protocol is produced.
+
+  @param Event - The event that occurred
+  @param Context - For EFI compatibility.  Not used.
+
+**/
+VOID
+EFIAPI
+NotifyElogRedirEventCallback (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  )
+{
+  SetElogRedirInstances ();
+}
+
+/**
+  Initialize the generic Elog driver of server management.
+
+  @param ImageHandle  - The image handle of this driver
+  @param SystemTable  - The pointer of EFI_SYSTEM_TABLE
+
+  @retval EFI_SUCCESS - The driver initialized successfully
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeElogLayer (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_HANDLE            NewHandle;
+  EFI_STATUS            Status;
+  EFI_SM_ELOG_PROTOCOL  *ElogProtocol;
+  EFI_EVENT             Event;
+
+  mElogModuleGlobal = AllocateZeroPool (sizeof (ELOG_MODULE_GLOBAL));
+  ASSERT (mElogModuleGlobal != NULL);
+  if (mElogModuleGlobal == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  ElogServiceInitialize (ImageHandle, SystemTable);
+
+  mElogModuleGlobal->MaxDescriptors = MAX_REDIR_DESCRIPTOR;
+
+  //
+  // Check for all IPMI Controllers
+  //
+  SetElogRedirInstances ();
+
+  ElogProtocol = AllocatePool (sizeof (EFI_SM_ELOG_PROTOCOL));
+  ASSERT (ElogProtocol != NULL);
+  if (ElogProtocol == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  ElogProtocol->ActivateEventLog  = EfiActivateElog;
+  ElogProtocol->EraseEventlogData = EfiEraseElogData;
+  ElogProtocol->GetEventLogData   = EfiGetElogData;
+  ElogProtocol->SetEventLogData   = EfiSetElogData;
+
+  NewHandle = NULL;
+  Status    = gBS->InstallProtocolInterface (
+                     &NewHandle,
+                     &gEfiGenericElogProtocolGuid,
+                     EFI_NATIVE_INTERFACE,
+                     ElogProtocol
+                     );
+
+  ASSERT_EFI_ERROR (Status);
+  if (Status != EFI_SUCCESS) {
+    return Status;
+  }
+
+  //
+  // Register to be notified when the ELOG REDIR protocol has been
+  // produced.
+  //
+  Status = gBS->CreateEvent (
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_CALLBACK,
+                  NotifyElogRedirEventCallback,
+                  NULL,
+                  &Event
+                  );
+
+  if (!EFI_ERROR (Status)) {
+    Status = gBS->RegisterProtocolNotify (
+                    &gEfiRedirElogProtocolGuid,
+                    Event,
+                    &mEfiElogRedirProtocolEvent
+                    );
+  }
+
+  return Status;
+}
+
+/**
+  Set the function entry.
+
+  @param FunctionPointer - The destination function pointer
+  @param Function        - The source function pointer
+
+  @retval EFI_SUCCESS - Set the function pointer successfully
+
+**/
+EFI_STATUS
+EfiSetFunctionEntry (
+  IN  FUNCTION_PTR  *FunctionPointer,
+  IN  VOID          *Function
+  )
+{
+  FunctionPointer->Function = (EFI_PLABEL *)Function;
+  return EFI_SUCCESS;
+}
+
+/**
+  Initialize Dxe generic event log.
+
+  @param ImageHandle         - The Image handle of this driver.
+  @param SystemTable         - The pointer of EFI_SYSTEM_TABLE.
+
+  @retval EFI_SUCCESS - The driver successfully initialized
+
+**/
+EFI_STATUS
+ElogServiceInitialize (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  return EFI_SUCCESS;
+}
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Smm/GenericElog.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Smm/GenericElog.c
new file mode 100644
index 000000000000..d6a129a181fb
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Smm/GenericElog.c
@@ -0,0 +1,558 @@
+/** @file
+  Generic Event Log functions of SMM driver.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "GenericElog.h"
+
+ELOG_MODULE_GLOBAL  *mElogModuleGlobal;
+
+//
+// Define module globals used to register for notification of when
+// the ELOG REDIR protocol has been produced.
+//
+EFI_EVENT  mEfiElogRedirProtocolEvent;
+
+/**
+  Sends the Event-Log data to the destination.
+
+  @param ElogData              - Pointer to the Event-Log data that needs to be recorded.
+  @param DataType              - Type of Elog Data that is being recorded.
+  @param AlertEvent            - This is an indication that the input data type is an Alert.
+  @param DataSize              - Size of the data to be logged.
+  @param RecordId              - Record ID sent by the target.
+  @param Global                - The module global variable pointer.
+  @param Virtual               - If this function is called in virtual mode or physical mode
+
+  @retval EFI_SUCCESS            - Event-Log was recorded successfully.
+  @retval EFI_OUT_OF_RESOURCES   - Not enough resources to record data.
+  @retval EFI_UNSUPPORTED        - The Data Type is unsupported.
+
+**/
+EFI_STATUS
+EfiLibSetElogData (
+  IN  UINT8               *ElogData,
+  IN  EFI_SM_ELOG_TYPE    DataType,
+  IN  BOOLEAN             AlertEvent,
+  IN  UINTN               DataSize,
+  OUT UINT64              *RecordId,
+  IN  ELOG_MODULE_GLOBAL  *Global,
+  IN  BOOLEAN             Virtual
+  )
+{
+  UINT8       Index;
+  VOID        *ElogRedirCommand;
+  EFI_STATUS  Status;
+  EFI_STATUS  RetStatus;
+
+  RetStatus = EFI_UNSUPPORTED;
+
+  if (DataType >= EfiSmElogMax) {
+    RetStatus = EFI_INVALID_PARAMETER;
+    return RetStatus;
+  }
+
+  for (Index = 0; Index < Global->MaxDescriptors; Index++) {
+    if (Global->Redir[Index].Valid) {
+      ElogRedirCommand = Global->Redir[Index].Command[Virtual].SetEventLogData.Function;
+      Status           = (*((EFI_SET_ELOG_DATA *)&ElogRedirCommand))(Global->Redir[Index].Command[Virtual].This, ElogData, DataType, AlertEvent, DataSize, RecordId);
+
+      if (!EFI_ERROR (Status)) {
+        RetStatus = EFI_SUCCESS;
+        break;
+      } else if (Status != EFI_UNSUPPORTED) {
+        RetStatus = Status;
+        break;
+      }
+    }
+  }
+
+  return RetStatus;
+}
+
+/**
+  Efi Set Elog Data.
+
+  @param This
+  @param ElogData
+  @param DataType
+  @param AlertEvent
+  @param DataSize
+  @param RecordId
+
+  @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EfiSetElogData (
+  IN  EFI_SM_ELOG_PROTOCOL  *This,
+  IN  UINT8                 *ElogData,
+  IN  EFI_SM_ELOG_TYPE      DataType,
+  IN  BOOLEAN               AlertEvent,
+  IN  UINTN                 DataSize,
+  OUT UINT64                *RecordId
+  )
+{
+  if (DataType >= EfiSmElogMax) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return EfiLibSetElogData (
+           ElogData,
+           DataType,
+           AlertEvent,
+           DataSize,
+           RecordId,
+           mElogModuleGlobal,
+           FALSE
+           );
+}
+
+/**
+  Gets the Event-Log data from the destination.
+
+  @param ElogData              - Pointer to the Event-Log data buffer that will contain the data to be retrieved.
+  @param DataType              - Type of Elog Data that is being recorded.
+  @param DataSize              - Size of the data to be retrieved. .
+  @param RecordId              - This is the RecordId of the next record. If ElogData is NULL,
+                                this gives the RecordId of the first record available in the database with the correct DataSize.
+                                A value of 0 on return indicates the last record if the EFI_STATUS indicates a success
+  @param Global                - The module global variable pointer.
+  @param Virtual               - If this function is called in virtual mode or physical mode
+
+  @retval EFI_SUCCESS           - Event-Log was retrieved successfully.
+  @retval EFI_NOT_FOUND         - Event-Log target not found.
+  @retval EFI_BUFFER_TOO_SMALL  - Target buffer is too small to retrieve the data.
+  @retval EFI_UNSUPPORTED       - The Data Type is unsupported
+
+**/
+EFI_STATUS
+EfiLibGetElogData (
+  IN UINT8               *ElogData,
+  IN EFI_SM_ELOG_TYPE    DataType,
+  IN OUT UINTN           *DataSize,
+  IN OUT UINT64          *RecordId,
+  IN ELOG_MODULE_GLOBAL  *Global,
+  IN BOOLEAN             Virtual
+  )
+{
+  UINT8       Index;
+  VOID        *ElogRedirCommand;
+  EFI_STATUS  Status;
+  EFI_STATUS  RetStatus;
+
+  RetStatus = EFI_UNSUPPORTED;
+
+  if (DataType >= EfiSmElogMax) {
+    RetStatus = EFI_INVALID_PARAMETER;
+    return RetStatus;
+  }
+
+  for (Index = 0; Index < Global->MaxDescriptors; Index++) {
+    if (Global->Redir[Index].Valid) {
+      ElogRedirCommand = Global->Redir[Index].Command[Virtual].GetEventLogData.Function;
+      Status           = (*((EFI_GET_ELOG_DATA *)&ElogRedirCommand))(Global->Redir[Index].Command[Virtual].This, ElogData, DataType, DataSize, RecordId);
+
+      if (!EFI_ERROR (Status)) {
+        RetStatus = EFI_SUCCESS;
+        break;
+      } else if (Status != EFI_UNSUPPORTED) {
+        RetStatus = Status;
+        break;
+      }
+    }
+  }
+
+  return RetStatus;
+}
+
+/**
+  Efi Get Elog Data.
+
+  @param This
+  @param ElogData
+  @param DataType
+  @param DataSize
+  @param RecordId
+
+  @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EfiGetElogData (
+  IN EFI_SM_ELOG_PROTOCOL  *This,
+  IN UINT8                 *ElogData,
+  IN EFI_SM_ELOG_TYPE      DataType,
+  IN OUT UINTN             *DataSize,
+  IN OUT UINT64            *RecordId
+  )
+{
+  if (DataType >= EfiSmElogMax) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return EfiLibGetElogData (ElogData, DataType, DataSize, RecordId, mElogModuleGlobal, FALSE);
+}
+
+/**
+  Erases the Event-Log data from the destination.
+
+  @param DataType              - Type of Elog Data that is being Erased.
+  @param RecordId              - This is the RecordId of the data to be erased. If RecordId is NULL, all
+                                 the records on the database are erased if permitted by the target.
+                                 Contains the deleted RecordId on return
+  @param Global                - The module global variable pointer.
+  @param Virtual               - If this function is called in virtual mode or physical mode
+
+  @retval EFI_SUCCESS           - Event-Log was erased successfully
+  @retval EFI_UNSUPPORTED       - The Data Type is unsupported
+  @retval EFI_NOT_FOUND         - Event-Log target not found
+
+**/
+EFI_STATUS
+EfiLibEraseElogData (
+  IN EFI_SM_ELOG_TYPE    DataType,
+  IN OUT UINT64          *RecordId,
+  IN ELOG_MODULE_GLOBAL  *Global,
+  IN BOOLEAN             Virtual
+  )
+{
+  UINT8       Index;
+  VOID        *ElogRedirCommand;
+  EFI_STATUS  Status;
+  EFI_STATUS  RetStatus;
+
+  RetStatus = EFI_UNSUPPORTED;
+
+  if (DataType >= EfiSmElogMax) {
+    RetStatus = EFI_INVALID_PARAMETER;
+    return RetStatus;
+  }
+
+  for (Index = 0; Index < Global->MaxDescriptors; Index++) {
+    if (Global->Redir[Index].Valid) {
+      ElogRedirCommand = Global->Redir[Index].Command[Virtual].EraseEventLogData.Function;
+      Status           = (*((EFI_ERASE_ELOG_DATA *)&ElogRedirCommand))(Global->Redir[Index].Command[Virtual].This, DataType, RecordId);
+
+      if (!EFI_ERROR (Status)) {
+        RetStatus = EFI_SUCCESS;
+        break;
+      } else if (Status != EFI_UNSUPPORTED) {
+        RetStatus = Status;
+        break;
+      }
+    }
+  }
+
+  return RetStatus;
+}
+
+/**
+  Efi Erase Elog Data
+
+  @param This
+  @param DataType
+  @param RecordId
+
+  @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EfiEraseElogData (
+  IN EFI_SM_ELOG_PROTOCOL  *This,
+  IN EFI_SM_ELOG_TYPE      DataType,
+  IN OUT UINT64            *RecordId
+  )
+{
+  return EfiLibEraseElogData (DataType, RecordId, mElogModuleGlobal, FALSE);
+}
+
+/**
+  This API enables/Disables Event Log.
+
+  @param DataType              - Type of Elog Data that is being Activated.
+  @param EnableElog            - Enables (TRUE) / Disables (FALSE) Event Log. If NULL just returns the
+                                 Current ElogStatus.
+  @param ElogStatus            - Current (New) Status of Event Log. Enabled (TRUE), Disabled (FALSE).
+  @param Global                - The module global variable pointer.
+  @param Virtual               - If this function is called in virtual mode or physical mode
+
+  @retval EFI_SUCCESS           - Event-Log was recorded successfully
+  @retval EFI_UNSUPPORTED       - The Data Type is unsupported
+
+**/
+EFI_STATUS
+EfiLibActivateElog (
+  IN  EFI_SM_ELOG_TYPE  DataType,
+  IN BOOLEAN            *EnableElog,
+  OUT BOOLEAN           *ElogStatus,
+  ELOG_MODULE_GLOBAL    *Global,
+  BOOLEAN               Virtual
+  )
+{
+  UINT8       Index;
+  VOID        *ElogRedirCommand;
+  EFI_STATUS  Status;
+  EFI_STATUS  RetStatus;
+
+  RetStatus = EFI_UNSUPPORTED;
+  if (DataType >= EfiSmElogMax) {
+    RetStatus = EFI_INVALID_PARAMETER;
+    return RetStatus;
+  }
+
+  for (Index = 0; Index < Global->MaxDescriptors; Index++) {
+    if (Global->Redir[Index].Valid) {
+      ElogRedirCommand = Global->Redir[Index].Command[Virtual].ActivateEventLog.Function;
+      Status           = (*((EFI_ACTIVATE_ELOG *)&ElogRedirCommand))(Global->Redir[Index].Command[Virtual].This, DataType, EnableElog, ElogStatus);
+
+      if (!EFI_ERROR (Status)) {
+        RetStatus = EFI_SUCCESS;
+        break;
+      } else if (Status != EFI_UNSUPPORTED) {
+        RetStatus = Status;
+        break;
+      }
+    }
+  }
+
+  return RetStatus;
+}
+
+/**
+  Efi Activate Elog.
+
+  @param This
+  @param DataType
+  @param EnableElog
+  @param ElogStatus
+
+  @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EfiActivateElog (
+  IN EFI_SM_ELOG_PROTOCOL  *This,
+  IN  EFI_SM_ELOG_TYPE     DataType,
+  IN BOOLEAN               *EnableElog,
+  OUT BOOLEAN              *ElogStatus
+  )
+{
+  if (DataType >= EfiSmElogMax) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return EfiLibActivateElog (DataType, EnableElog, ElogStatus, mElogModuleGlobal, FALSE);
+}
+
+/**
+  Set Elog Redir Instances.
+
+  @retval EFI_SUCCESS - The Redir instances were successfully set.
+  @retval Other       - Failed to set Redir instances.
+
+**/
+EFI_STATUS
+SetElogRedirInstances (
+  VOID
+  )
+{
+  UINTN                       NumHandles;
+  UINTN                       Index;
+  UINTN                       Instance;
+  UINTN                       EmptyIndex;
+  EFI_HANDLE                  *Buffer;
+  EFI_STATUS                  Status;
+  EFI_SM_ELOG_REDIR_PROTOCOL  *Redir;
+  REDIR_MODULE_PROC           *RedirProc;
+
+  Buffer = NULL;
+
+  //
+  // Check for all IPMI Controllers
+  //
+  Status = gSmst->SmmLocateHandle (
+                    ByProtocol,
+                    &gSmmRedirElogProtocolGuid,
+                    NULL,
+                    &NumHandles,
+                    Buffer
+                    );
+
+  if (EFI_ERROR (Status) || (NumHandles == 0) || (Buffer == NULL)) {
+    return Status;
+  }
+
+  for (Index = 0; ((Index < NumHandles) && (Index < mElogModuleGlobal->MaxDescriptors)); Index++) {
+    EmptyIndex = mElogModuleGlobal->MaxDescriptors;
+
+    Status = gSmst->SmmHandleProtocol (
+                      Buffer[Index],
+                      &gSmmRedirElogProtocolGuid,
+                      (VOID *)&Redir
+                      );
+    if (EFI_ERROR (Status) || (Redir == NULL)) {
+      continue;
+    }
+
+    for (Instance = 0; Instance < mElogModuleGlobal->MaxDescriptors; Instance++) {
+      if (mElogModuleGlobal->Redir[Instance].Valid == FALSE) {
+        if (EmptyIndex >= mElogModuleGlobal->MaxDescriptors) {
+          EmptyIndex = Instance;
+        }
+      } else {
+        if (Redir == mElogModuleGlobal->Redir[Instance].Command->This) {
+          EmptyIndex = mElogModuleGlobal->MaxDescriptors;
+          break;
+          //
+          // FIX: changed continue to break.
+          //
+        }
+      }
+    }
+
+    if (EmptyIndex < mElogModuleGlobal->MaxDescriptors) {
+      RedirProc                                  = (REDIR_MODULE_PROC *)mElogModuleGlobal->Redir[EmptyIndex].Command;
+      mElogModuleGlobal->Redir[EmptyIndex].Valid = TRUE;
+
+      EfiSetFunctionEntry (&RedirProc->ActivateEventLog, *((VOID **)&Redir->ActivateEventLog));
+      EfiSetFunctionEntry (&RedirProc->EraseEventLogData, *((VOID **)&Redir->EraseEventlogData));
+      EfiSetFunctionEntry (&RedirProc->GetEventLogData, *((VOID **)&Redir->GetEventLogData));
+      EfiSetFunctionEntry (&RedirProc->SetEventLogData, *((VOID **)&Redir->SetEventLogData));
+      RedirProc->This = Redir;
+
+      CopyMem (&RedirProc[EFI_ELOG_VIRTUAL], &RedirProc[EFI_ELOG_PHYSICAL], sizeof (REDIR_MODULE_PROC));
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+    This notification function is invoked when an instance of the
+    ELOG REDIR protocol is produced.
+
+    @param Event - The event that occurred
+    @param Context - For EFI compatibility.  Not used.
+
+**/
+VOID
+EFIAPI
+NotifyElogRedirEventCallback (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  )
+{
+  SetElogRedirInstances ();
+}
+
+/**
+  Initialize the generic Elog driver of server management.
+
+  @param ImageHandle  - The image handle of this driver
+  @param SystemTable  - The pointer of EFI_SYSTEM_TABLE
+
+  @retval EFI_SUCCESS - The driver initialized successfully
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeSmElogLayer (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_HANDLE            NewHandle;
+  EFI_STATUS            Status;
+  EFI_SM_ELOG_PROTOCOL  *ElogProtocol;
+
+  mElogModuleGlobal = AllocatePool (sizeof (ELOG_MODULE_GLOBAL));
+  ASSERT (mElogModuleGlobal != NULL);
+  if (mElogModuleGlobal == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  SmElogServiceInitialize (ImageHandle, SystemTable);
+
+  mElogModuleGlobal->MaxDescriptors = MAX_REDIR_DESCRIPTOR;
+
+  //
+  // Check for all IPMI Controllers
+  //
+  SetElogRedirInstances ();
+
+  ElogProtocol = AllocatePool (sizeof (EFI_SM_ELOG_PROTOCOL));
+  ASSERT (ElogProtocol != NULL);
+  if (ElogProtocol == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  ElogProtocol->ActivateEventLog  = (EFI_ACTIVATE_ELOG)EfiActivateElog;
+  ElogProtocol->EraseEventlogData = (EFI_ERASE_ELOG_DATA)EfiEraseElogData;
+  ElogProtocol->GetEventLogData   = (EFI_GET_ELOG_DATA)EfiGetElogData;
+  ElogProtocol->SetEventLogData   = (EFI_SET_ELOG_DATA)EfiSetElogData;
+
+  NewHandle = NULL;
+  Status    = gSmst->SmmInstallProtocolInterface (
+                       &NewHandle,
+                       &gSmmGenericElogProtocolGuid,
+                       EFI_NATIVE_INTERFACE,
+                       ElogProtocol
+                       );
+
+  ASSERT_EFI_ERROR (Status);
+  if (Status != EFI_SUCCESS) {
+    return Status;
+  }
+
+  //
+  // Register to be notified when the ELOG REDIR protocol has been
+  // produced.
+  //
+  Status = gSmst->SmmRegisterProtocolNotify (
+                    &gSmmRedirElogProtocolGuid,
+                    NULL,
+                    &mEfiElogRedirProtocolEvent
+                    );
+  return Status;
+}
+
+/**
+  Set the function entry.
+
+  @param FunctionPointer - The destination function pointer
+  @param Function        - The source function pointer
+
+  @retval EFI_SUCCESS - Set the function pointer successfully
+
+**/
+EFI_STATUS
+EfiSetFunctionEntry (
+  IN  FUNCTION_PTR  *FunctionPointer,
+  IN  VOID          *Function
+  )
+{
+  FunctionPointer->Function = (EFI_PLABEL *)Function;
+  return EFI_SUCCESS;
+}
+
+/**
+  Entry point of SM Elog service Driver
+
+  @param ImageHandle         - The Image handle of this driver.
+  @param SystemTable         - The pointer of EFI_SYSTEM_TABLE.
+
+  @retval EFI_SUCCESS - The driver successfully initialized
+
+**/
+EFI_STATUS
+SmElogServiceInitialize (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  return EFI_SUCCESS;
+}
-- 
2.39.2.windows.1



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



  reply	other threads:[~2023-10-27 22:38 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-10-27 20:11 [edk2-devel] [PATCH edk2-platforms 0/4] IpmiFeaturePkg: Add server management features Zhen Gong
2023-10-27 20:11 ` Zhen Gong [this message]
2023-10-27 20:11 ` [edk2-devel] [PATCH edk2-platforms 2/4] IpmiFeaturePkg: Add ServerManagementLib Zhen Gong
2023-10-27 20:11 ` [edk2-devel] [PATCH edk2-platforms 3/4] IpmiFeaturePkg: Add ACPI power state drivers Zhen Gong
2023-10-27 20:11 ` [edk2-devel] [PATCH edk2-platforms 4/4] IpmiFeaturePkg: Add FRU drivers Zhen Gong
2023-10-29  1:58 ` [edk2-devel] [PATCH edk2-platforms 0/4] IpmiFeaturePkg: Add server management features Chang, Abner via groups.io
2023-10-29 21:07   ` Zhen Gong

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=151e2cd3461b6c577cd15e0ce862309e409129f0.1698437221.git.zhen.gong@intel.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox