* [edk2-devel] [PATCH edk2-platforms v2 1/4] IpmiFeaturePkg: Add Elog drivers
2023-10-29 20:27 [edk2-devel] [PATCH edk2-platforms v2 0/4] IpmiFeaturePkg: Add server management features Zhen Gong
@ 2023-10-29 20:27 ` Zhen Gong
2023-10-29 20:27 ` [edk2-devel] [PATCH edk2-platforms v2 2/4] IpmiFeaturePkg: Add ServerManagementLib Zhen Gong
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Zhen Gong @ 2023-10-29 20:27 UTC (permalink / raw)
To: devel; +Cc: Zhen Gong
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} | 19 +-
.../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, 3530 insertions(+), 243 deletions(-)
rename Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/{BmcElog.inf => DxeBmcElog.inf} (60%)
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 60%
rename from Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/BmcElog.inf
rename to Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/DxeBmcElog.inf
index 1e7a7658b7b0..7d8db9b633de 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,7 +17,10 @@ [Defines]
ENTRY_POINT = InitializeBmcElogLayer
[Sources]
- BmcElog.c
+ Dxe/BmcElog.c
+ Dxe/BmcElog.h
+ Common/BmcElogCommon.h
+ Common/BmcElogCommon.c
[Packages]
MdePkg/MdePkg.dec
@@ -28,7 +31,13 @@ [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 (#110326): https://edk2.groups.io/g/devel/message/110326
Mute This Topic: https://groups.io/mt/102279905/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [edk2-devel] [PATCH edk2-platforms v2 2/4] IpmiFeaturePkg: Add ServerManagementLib
2023-10-29 20:27 [edk2-devel] [PATCH edk2-platforms v2 0/4] IpmiFeaturePkg: Add server management features Zhen Gong
2023-10-29 20:27 ` [edk2-devel] [PATCH edk2-platforms v2 1/4] IpmiFeaturePkg: Add Elog drivers Zhen Gong
@ 2023-10-29 20:27 ` Zhen Gong
2023-10-29 20:27 ` [edk2-devel] [PATCH edk2-platforms v2 3/4] IpmiFeaturePkg: Add ACPI power state drivers Zhen Gong
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Zhen Gong @ 2023-10-29 20:27 UTC (permalink / raw)
To: devel; +Cc: Zhen Gong
Lightweight lib to support Server Management drivers.
Signed-off-by: Zhen Gong <zhen.gong@intel.com>
---
.../IpmiFeaturePkg/Include/IpmiFeature.dsc | 1 +
.../ServerManagementLib.inf | 35 +
.../ServerManagementLibNull.inf | 38 +
.../Include/Library/ServerMgmtRtLib.h | 147 ++++
.../ServerManagementLib/ServerManagementLib.c | 696 ++++++++++++++++++
.../ServerManagementLibNull.c | 144 ++++
6 files changed, 1061 insertions(+)
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManagementLib/ServerManagementLib.inf
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManagementLibNull/ServerManagementLibNull.inf
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Library/ServerMgmtRtLib.h
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManagementLib/ServerManagementLib.c
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManagementLibNull/ServerManagementLibNull.c
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiFeature.dsc b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiFeature.dsc
index fa98e5672d83..fc9001e98473 100644
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiFeature.dsc
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiFeature.dsc
@@ -51,6 +51,7 @@ [LibraryClasses.common.DXE_DRIVER,LibraryClasses.common.UEFI_DRIVER]
[LibraryClasses.common]
BmcCommonInterfaceLib|IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/BmcCommonInterfaceLib.inf
BtInterfaceLib|IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/BtInterfaceLib/BtInterfaceLib.inf
+ ServerManagementLib|IpmiFeaturePkg/Library/ServerManagementLib/ServerManagementLib.inf
[LibraryClasses.common.DXE_RUNTIME_DRIVER, LibraryClasses.common.DXE_DRIVER]
SsifInterfaceLib|IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInterfaceLib/DxeSsifInterfaceLib.inf
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManagementLib/ServerManagementLib.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManagementLib/ServerManagementLib.inf
new file mode 100644
index 000000000000..25a3a7540762
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManagementLib/ServerManagementLib.inf
@@ -0,0 +1,35 @@
+### @file
+#
+# Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+###
+
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ServerManagementLib
+ FILE_GUID = D43C86F0-7C8B-4992-9593-8CB6FBC66A0A
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x0001000A
+ LIBRARY_CLASS = ServerManagementLib
+
+[Sources]
+ ServerManagementLib.c
+
+[Packages]
+ IpmiFeaturePkg/IpmiFeaturePkg.dec
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ IoLib
+ DebugLib
+ UefiBootServicesTableLib
+
+[Protocols]
+ gEfiGenericElogProtocolGuid
+
+
+
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManagementLibNull/ServerManagementLibNull.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManagementLibNull/ServerManagementLibNull.inf
new file mode 100644
index 000000000000..6b66b44857f3
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManagementLibNull/ServerManagementLibNull.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 = ServerManagementLibNull
+ FILE_GUID = 3AC01DE9-5A96-4df5-A645-ECD092C29AF9
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x0001000A
+ LIBRARY_CLASS = ServerManagementLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources.common]
+ ServerManagementLibNull.c
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ServerPlatformPkg/PlatformPkg.dec
+
+[LibraryClasses]
+ DebugLib
+
+[Protocols]
+
+
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Library/ServerMgmtRtLib.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Library/ServerMgmtRtLib.h
new file mode 100644
index 000000000000..12b2e82f9e6e
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Library/ServerMgmtRtLib.h
@@ -0,0 +1,147 @@
+/** @file
+ Server Management Driver Lib.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _SERVER_MGMT_LIB_H_
+#define _SERVER_MGMT_LIB_H_
+
+#include <Protocol/GenericElog.h>
+
+/**
+ ELOG Library Initializer.
+**/
+
+/**
+ The function will set up a notification on the ELOG protocol. This function is required to be called prior
+ to utilizing the ELOG protocol from within this library.
+ @param None
+
+ @retval EFI_SUCCESS After the notification has been setup.
+ @retval Other Failure in constructor.
+
+**/
+EFI_STATUS
+EfiInitializeGenericElog (
+ VOID
+ );
+
+/**
+
+ This function sends event log data to the destination such as LAN, ICMB, BMC etc.
+ @param[in] ElogData A pointer to the event log data that needs to be recorded
+ @param[in] DataType Type of Elog data that is being recorded. The Elog is redirected based on this
+ parameter.
+ @param[in] AlertEvent An indication that the input data type is an alert. The underlying
+ drivers need to decide if they need to listen to the DataType and send it on
+ an appropriate channel as an alert use of the information.
+ @param[in] DataSize The size of the data to be logged
+ @param[out] RecordId The array of record IDs sent by the target. This can be used to retrieve the
+ records or erase the records.
+
+ @retval EFI_SUCCESS If the data was logged.
+ @retval EFI_INVALID_PARAMETER If the DataType is >= EfiSmElogMax
+ @retval EFI_OUT_OF_RESOURCES If the DataSize is larger than the Elog temp buffer and we cannot log the record
+ @retval EFI_NOT_FOUND The event log target was not found
+ @retval EFI_PROTOCOL_ERROR There was a data formatting error
+
+**/
+EFI_STATUS
+EfiSmSetEventLogData (
+ IN UINT8 *ElogData,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN BOOLEAN AlertEvent,
+ IN UINTN DataSize,
+ OUT UINT64 *RecordId
+ );
+
+/**
+
+ This function gets event log data from the destination dependent on the DataType. The destination
+ can be a remote target such as LAN, ICMB, IPMI, or a FV. The ELOG redir driver will resolve the
+ destination.
+ @param[in] ElogData Pointer to the event log data buffer to contain the data to be retrieved.
+ @param[in] DataType This is the type of Elog data to be gotten. Elog is redirected based upon this
+ information.
+ @param[in, out] DataSize This is the size of the data to be retrieved.
+ @param[in, out] RecordId 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
+ that it was last record if the Status is EFI_SUCCESS.
+
+ @retval EFI_SUCCESS If the event log was retrieved successfully.
+ @retval EFI_NOT_FOUND If the event log target was not found.
+ @retval EFI_NO_RESPONSE If the event log target is not responding. This is done by the redir driver.
+ @retval EFI_INVALID_PARAMETER DataType or another parameter was invalid.
+ @retval EFI_BUFFER_TOO_SMALL The ElogData buffer is too small to be filled with the requested data.
+
+**/
+EFI_STATUS
+EfiSmGetEventLogData (
+ IN UINT8 *ElogData,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN OUT UINTN *DataSize,
+ IN OUT UINT64 *RecordId
+ );
+
+/**
+ This function erases the event log data defined by the DataType. The redir driver associated with
+ the DataType resolves the path to the record.
+
+ @param[in] DataType The type of Elog data that is to be erased.
+ @param[in, out] RecordId The RecordId of the data to be erased. If RecordId is NULL, all records in the
+ database are erased if permitted by the target. RecordId will contain the deleted
+ RecordId on return.
+
+ @retval EFI_SUCCESS The record or collection of records were erased.
+ @retval EFI_NOT_FOUND The event log target was not found.
+ @retval EFI_NO_RESPONSE The event log target was found but did not respond.
+ @retval EFI_INVALID_PARAMETER One of the parameters was invalid.
+
+**/
+EFI_STATUS
+EfiSmEraseEventlogData (
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN OUT UINT64 *RecordId
+ );
+
+/**
+
+ This function enables or disables the event log defined by the DataType.
+ @param[in] DataType The type of Elog data that is being activated.
+ @param[in] EnableElog Enables or disables the event log defined by the DataType. If it is NULL
+ it returns the current status of the DataType log.
+ @param[out] ElogStatus Is the current status of the Event log defined by the DataType. Enabled is
+ TRUE and Disabled is FALSE.
+
+ @retval EFI_SUCCESS If the event log was successfully enabled or disabled.
+ @retval EFI_NOT_FOUND The event log target was not found.
+ @retval EFI_NO_RESPONSE The event log target was found but did not respond.
+ @retval EFI_INVALID_PARAMETER One of the parameters was invalid.
+
+**/
+EFI_STATUS
+EfiSmActivateEventLog (
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN BOOLEAN *EnableElog,
+ OUT BOOLEAN *ElogStatus
+ );
+
+/**
+
+ Return Date and Time from RTC in Unix format which fits in 32 bit format.
+
+ @param[out] NumOfSeconds Pointer to return calculated time.
+
+ @retval EFI_SUCCESS
+ @retval Other EFI status if error occurred.
+
+**/
+EFI_STATUS
+EfiSmGetTimeStamp (
+ OUT UINT32 *NumOfSeconds
+ );
+
+#endif // _SERVER_MGMT_LIB_H_
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManagementLib/ServerManagementLib.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManagementLib/ServerManagementLib.c
new file mode 100644
index 000000000000..66a481fa57b4
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManagementLib/ServerManagementLib.c
@@ -0,0 +1,696 @@
+/** @file
+ Lightweight lib to support EFI Server Management drivers.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/GenericElog.h>
+
+#include <Library/ServerMgmtRtLib.h>
+
+// #include EFI_PROTOCOL_DEPENDENCY (CpuIo)
+
+#define PCAT_RTC_ADDRESS_REGISTER 0x70
+#define PCAT_RTC_DATA_REGISTER 0x71
+
+#define RTC_ADDRESS_SECONDS 0 // R/W Range 0..59
+#define RTC_ADDRESS_MINUTES 2 // R/W Range 0..59
+#define RTC_ADDRESS_HOURS 4 // R/W Range 1..12 or 0..23 Bit 7 is AM/PM
+#define RTC_ADDRESS_DAY_OF_THE_MONTH 7 // R/W Range 1..31
+#define RTC_ADDRESS_MONTH 8 // R/W Range 1..12
+#define RTC_ADDRESS_YEAR 9 // R/W Range 0..99
+#define RTC_ADDRESS_REGISTER_A 10 // R/W[0..6] R0[7]
+#define RTC_ADDRESS_REGISTER_B 11 // R/W
+#define RTC_ADDRESS_REGISTER_C 12 // RO
+#define RTC_ADDRESS_REGISTER_D 13 // RO
+#define RTC_ADDRESS_CENTURY 50 // R/W Range 19..20 Bit 8 is R/W
+
+//
+// Register A
+//
+typedef struct {
+ UINT8 RS : 4; // Rate Selection Bits
+ UINT8 DV : 3; // Divisor
+ UINT8 UIP : 1; // Update in progress
+} RTC_REGISTER_A_BITS;
+
+typedef union {
+ RTC_REGISTER_A_BITS Bits;
+ UINT8 Data;
+} RTC_REGISTER_A;
+
+//
+// Register B
+//
+typedef struct {
+ UINT8 DSE : 1; // 0 - Daylight saving disabled 1 - Daylight savings enabled
+ UINT8 MIL : 1; // 0 - 12 hour mode 1 - 24 hour mode
+ UINT8 DM : 1; // 0 - BCD Format 1 - Binary Format
+ UINT8 SQWE : 1; // 0 - Disable SQWE output 1 - Enable SQWE output
+ UINT8 UIE : 1; // 0 - Update INT disabled 1 - Update INT enabled
+ UINT8 AIE : 1; // 0 - Alarm INT disabled 1 - Alarm INT Enabled
+ UINT8 PIE : 1; // 0 - Periodic INT disabled 1 - Periodic INT Enabled
+ UINT8 SET : 1; // 0 - Normal operation. 1 - Updates inhibited
+} RTC_REGISTER_B_BITS;
+
+typedef union {
+ RTC_REGISTER_B_BITS Bits;
+ UINT8 Data;
+} RTC_REGISTER_B;
+
+//
+// Register D
+//
+typedef struct {
+ UINT8 Reserved : 7; // Read as zero. Can not be written.
+ UINT8 VRT : 1; // Valid RAM and Time
+} RTC_REGISTER_D_BITS;
+
+typedef union {
+ RTC_REGISTER_D_BITS Bits;
+ UINT8 Data;
+} RTC_REGISTER_D;
+
+//
+// Module Globals
+//
+EFI_SM_ELOG_PROTOCOL *mGenericElogProtocol = NULL;
+VOID *mGenericElogRegistration = NULL;
+
+INTN DaysOfMonth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+/**
+ This function is called whenever an instance of ELOG protocol is created. When the function is notified
+ it initializes the module global data.
+
+ @param Event This is used only for EFI compatibility.
+ @param Context This is used only for EFI compatibility.
+
+**/
+VOID
+EFIAPI
+GenericElogNotificationFunction (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+
+ Status = gBS->LocateProtocol (&gEfiGenericElogProtocolGuid, NULL, (VOID **)&mGenericElogProtocol);
+ if (EFI_ERROR (Status)) {
+ mGenericElogProtocol = NULL;
+ }
+}
+
+/**
+ The function will set up a notification on the ELOG protocol. This function is required to be called prior
+ to utilizing the ELOG protocol from within this library.
+
+ @retval EFI_SUCCESS after the notification has been setup.
+**/
+EFI_STATUS
+EfiInitializeGenericElog (
+ VOID
+ )
+{
+ EFI_EVENT Event;
+ EFI_STATUS Status;
+
+ Status = gBS->CreateEvent (EVT_NOTIFY_SIGNAL, TPL_CALLBACK, GenericElogNotificationFunction, NULL, &Event);
+ ASSERT_EFI_ERROR (Status);
+ if (Status != EFI_SUCCESS) {
+ return Status;
+ }
+
+ Status = gBS->RegisterProtocolNotify (&gEfiGenericElogProtocolGuid, Event, &mGenericElogRegistration);
+ ASSERT_EFI_ERROR (Status);
+ if (Status != EFI_SUCCESS) {
+ return Status;
+ }
+
+ gBS->SignalEvent (Event);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function sends event log data to the destination such as LAN, ICMB, BMC etc.
+
+ @param ElogData is a pointer to the event log data that needs to be recorded
+ @param DataType type of Elog data that is being recorded. The Elog is redirected based on this parameter.
+ @param AlertEvent is an indication that the input data type is an alert. The underlying
+ drivers need to decide if they need to listen to the DataType and send it on
+ an appropriate channel as an alert use of the information.
+ @param DataSize is the size of the data to be logged
+ @param RecordId is the array of record IDs sent by the target. This can be used to retrieve the
+ records or erase the records.
+ @retval EFI_SUCCESS - if the data was logged.
+ @retval EFI_INVALID_PARAMETER - if the DataType is >= EfiSmElogMax
+ @retval EFI_NOT_FOUND - the event log target was not found
+ @retval EFI_PROTOCOL_ERROR - there was a data formatting error
+
+**/
+EFI_STATUS
+EfiSmSetEventLogData (
+ IN UINT8 *ElogData,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN BOOLEAN AlertEvent,
+ IN UINTN DataSize,
+ OUT UINT64 *RecordId
+ )
+{
+ //
+ // If the protocol is not found return EFI_NOT_FOUND
+ //
+ if (mGenericElogProtocol == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ return mGenericElogProtocol->SetEventLogData (
+ mGenericElogProtocol,
+ ElogData,
+ DataType,
+ AlertEvent,
+ DataSize,
+ RecordId
+ );
+}
+
+/**
+ This function gets event log data from the destination dependent on the DataType. The destination
+ can be a remote target such as LAN, ICMB, IPMI, or a FV. The ELOG redir driver will resolve the
+ destination.
+
+ @param ElogData - pointer to the event log data buffer to contain the data to be retrieved.
+ @param DataType - this is the type of Elog data to be gotten. Elog is redirected based upon this
+ information.
+ @param DataSize - this is the size of the data to be retrieved.
+ @param RecordId - 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
+ that it was last record if the Status is EFI_SUCCESS.
+
+ @retval EFI_SUCCESS - if the event log was retrieved successfully.
+ @retval EFI_NOT_FOUND - if the event log target was not found.
+ @retval EFI_NO_RESPONSE - if the event log target is not responding. This is done by the redir driver.
+ @retval EFI_INVALID_PARAMETER - DataType or another parameter was invalid.
+ @retval EFI_BUFFER_TOO_SMALL -the ElogData buffer is too small to be filled with the requested data.
+
+**/
+EFI_STATUS
+EfiSmGetEventLogData (
+ IN UINT8 *ElogData,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN OUT UINTN *DataSize,
+ IN OUT UINT64 *RecordId
+ )
+{
+ //
+ // If the protocol is not found return EFI_NOT_FOUND
+ //
+ if (mGenericElogProtocol == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ return mGenericElogProtocol->GetEventLogData (
+ mGenericElogProtocol,
+ ElogData,
+ DataType,
+ DataSize,
+ RecordId
+ );
+}
+
+/**
+ This function erases the event log data defined by the DataType. The redir driver associated with
+ the DataType resolves the path to the record.
+
+ @param DataType - the type of Elog data that is to be erased.
+ @param RecordId - the RecordId of the data to be erased. If RecordId is NULL, all records in the
+ database are erased if permitted by the target. RecordId will contain the deleted
+ RecordId on return.
+
+ @retval EFI_SUCCESS - the record or collection of records were erased.
+ @retval EFI_NOT_FOUND - the event log target was not found.
+ @retval EFI_NO_RESPONSE - the event log target was found but did not respond.
+ @retval EFI_INVALID_PARAMETER - one of the parameters was invalid.
+
+**/
+EFI_STATUS
+EfiSmEraseEventlogData (
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN OUT UINT64 *RecordId
+ )
+{
+ //
+ // If the protocol is not found return EFI_NOT_FOUND
+ //
+ if (mGenericElogProtocol == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ return mGenericElogProtocol->EraseEventlogData (
+ mGenericElogProtocol,
+ DataType,
+ RecordId
+ );
+}
+
+/**
+ This function enables or disables the event log defined by the DataType.
+
+
+ @param DataType - the type of Elog data that is being activated.
+ @param EnableElog - enables or disables the event log defined by the DataType. If it is NULL
+ it returns the current status of the DataType log.
+ @param ElogStatus - is the current status of the Event log defined by the DataType. Enabled is
+ TRUE and Disabled is FALSE.
+
+ @retval EFI_SUCCESS - if the event log was successfully enabled or disabled.
+ @retval EFI_NOT_FOUND - the event log target was not found.
+ @retval EFI_NO_RESPONSE - the event log target was found but did not respond.
+ @retval EFI_INVALID_PARAMETER - one of the parameters was invalid.
+
+**/
+EFI_STATUS
+EfiSmActivateEventLog (
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN BOOLEAN *EnableElog,
+ OUT BOOLEAN *ElogStatus
+ )
+{
+ //
+ // If the protocol is not found return EFI_NOT_FOUND
+ //
+ if (mGenericElogProtocol == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ return mGenericElogProtocol->ActivateEventLog (
+ mGenericElogProtocol,
+ DataType,
+ EnableElog,
+ ElogStatus
+ );
+}
+
+/**
+ This function verifies the leap year
+
+ @param Year year in YYYY format.
+
+ @retval TRUE if the year is a leap year
+
+**/
+STATIC
+BOOLEAN
+IsLeapYear (
+ IN UINT16 Year
+ )
+{
+ if (Year % 4 == 0) {
+ if (Year % 100 == 0) {
+ if (Year % 400 == 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+ } else {
+ return TRUE;
+ }
+ } else {
+ return FALSE;
+ }
+}
+
+/**
+ This function calculates the total number leap days from 1970 to the current year
+
+ @param Time - Current Time
+
+ @retval Returns the number of leap days since the base year, 1970.
+
+**/
+STATIC
+UINTN
+CountNumOfLeapDays (
+ IN EFI_TIME *Time
+ )
+{
+ UINT16 NumOfYear;
+ UINT16 BaseYear;
+ UINT16 Index;
+ UINTN Count;
+
+ Count = 0;
+ BaseYear = 1970;
+ NumOfYear = Time->Year - 1970;
+
+ for (Index = 0; Index <= NumOfYear; Index++) {
+ if (IsLeapYear (BaseYear + Index)) {
+ Count++;
+ }
+ }
+
+ //
+ // If the current year is a leap year but the month is January or February,
+ // then the leap day has not occurred and should not be counted. If it is
+ // February 29, the leap day is accounted for in CalculateNumOfDayPassedThisYear( )
+ //
+ if (IsLeapYear (Time->Year)) {
+ if ((Count > 0) && (Time->Month < 3)) {
+ Count--;
+ }
+ }
+
+ return Count;
+}
+
+/**
+ This function calculates the total number of days passed till the day in a year.
+ If the year is a leap year, an extra day is not added since the number of leap
+ days is calculated in CountNumOfLeapDays.
+
+ @param Time This structure contains detailed information about date and time
+
+ @retval Returns the number of days passed until the input day.
+
+**/
+STATIC
+UINTN
+CalculateNumOfDayPassedThisYear (
+ IN EFI_TIME Time
+ )
+{
+ UINTN Index;
+ UINTN NumOfDays;
+
+ NumOfDays = 0;
+ for (Index = 1; Index < Time.Month; Index++) {
+ NumOfDays += DaysOfMonth[Index - 1];
+ }
+
+ NumOfDays += Time.Day;
+ return NumOfDays;
+}
+
+/**
+ Function converts a BCD to a decimal value.
+
+ @param[in] BcdValue An 8 bit BCD value
+
+ @return The decimal value of the BcdValue
+**/
+STATIC
+UINT8
+BcdToDecimal (
+ IN UINT8 BcdValue
+ )
+{
+ UINTN High;
+ UINTN Low;
+
+ High = BcdValue >> 4;
+ Low = BcdValue - (High << 4);
+
+ return (UINT8)(Low + (High * 10));
+}
+
+//
+// RTC read functions were copied here since we need to get the time
+// in both DXE and runtime code. The PcRtc driver is not currently a
+// dual mode driver, this is more efficient since making PcRtc dual mode
+// would unnecessarily bloat the SMM code space.
+//
+
+/**
+ Read data register and return contents.
+
+ @param Address - Register address to read
+
+ @retval Value of data register contents
+
+**/
+STATIC
+UINT8
+RtcRead (
+ IN UINT8 Address
+ )
+{
+ IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, (UINT8)(Address | (UINT8)(IoRead8 (PCAT_RTC_ADDRESS_REGISTER) & 0x80)));
+ return IoRead8 (PCAT_RTC_DATA_REGISTER);
+}
+
+/**
+ Write data to register address.
+
+ @param Address - Register address to write
+ @param Data - Data to write to register
+
+**/
+STATIC
+VOID
+RtcWrite (
+ IN UINT8 Address,
+ IN UINT8 Data
+ )
+{
+ IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, (UINT8)(Address | (UINT8)(IoRead8 (PCAT_RTC_ADDRESS_REGISTER) & 0x80)));
+ IoWrite8 (PCAT_RTC_DATA_REGISTER, Data);
+}
+
+/**
+ Convert Rtc Time To Efi Time.
+
+ @param Time
+ @param RegisterB
+
+**/
+STATIC
+VOID
+ConvertRtcTimeToEfiTime (
+ IN EFI_TIME *Time,
+ IN RTC_REGISTER_B RegisterB
+ )
+{
+ BOOLEAN Pm;
+
+ if ((Time->Hour) & 0x80) {
+ Pm = TRUE;
+ } else {
+ Pm = FALSE;
+ }
+
+ Time->Hour = (UINT8)(Time->Hour & 0x7f);
+
+ if (RegisterB.Bits.DM == 0) {
+ Time->Year = BcdToDecimal ((UINT8)Time->Year);
+ Time->Month = BcdToDecimal (Time->Month);
+ Time->Day = BcdToDecimal (Time->Day);
+ Time->Hour = BcdToDecimal (Time->Hour);
+ Time->Minute = BcdToDecimal (Time->Minute);
+ Time->Second = BcdToDecimal (Time->Second);
+ }
+
+ //
+ // If time is in 12 hour format, convert it to 24 hour format
+ //
+ if (RegisterB.Bits.MIL == 0) {
+ if (Pm && (Time->Hour < 12)) {
+ Time->Hour = (UINT8)(Time->Hour + 12);
+ }
+
+ if (!Pm && (Time->Hour == 12)) {
+ Time->Hour = 0;
+ }
+ }
+
+ Time->Nanosecond = 0;
+ Time->TimeZone = EFI_UNSPECIFIED_TIMEZONE;
+ Time->Daylight = 0;
+}
+
+/**
+ Test Century Register.
+
+ @retval EFI_SUCCESS
+ @retval EFI_DEVICE_ERROR
+
+**/
+STATIC
+EFI_STATUS
+RtcTestCenturyRegister (
+ VOID
+ )
+{
+ UINT8 Century;
+ UINT8 Temp;
+
+ Century = RtcRead (RTC_ADDRESS_CENTURY);
+
+ //
+ // Always sync-up the Bit7 "semaphore"...this maintains
+ // consistency across the different chips/implementations of
+ // the RTC...
+ //
+ RtcWrite (RTC_ADDRESS_CENTURY, 0x00);
+ Temp = (UINT8)(RtcRead (RTC_ADDRESS_CENTURY) & 0x7f);
+ RtcWrite (RTC_ADDRESS_CENTURY, Century);
+ if ((Temp == 0x19) || (Temp == 0x20)) {
+ return EFI_SUCCESS;
+ }
+
+ return EFI_DEVICE_ERROR;
+}
+
+/**
+ Waits until RTC register A and D show data is valid.
+
+ @param Timeout - Maximum time to wait
+
+ @retval EFI_DEVICE_ERROR
+ @retval EFI_SUCCESS
+
+**/
+STATIC
+EFI_STATUS
+RtcWaitToUpdate (
+ UINTN Timeout
+ )
+{
+ RTC_REGISTER_A RegisterA;
+ RTC_REGISTER_D RegisterD;
+
+ //
+ // See if the RTC is functioning correctly
+ //
+ RegisterD.Data = RtcRead (RTC_ADDRESS_REGISTER_D);
+
+ if (RegisterD.Bits.VRT == 0) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Wait for up to 0.1 seconds for the RTC to be ready.
+ //
+ Timeout = (Timeout / 10) + 1;
+ RegisterA.Data = RtcRead (RTC_ADDRESS_REGISTER_A);
+ while (RegisterA.Bits.UIP == 1 && Timeout > 0) {
+ gBS->Stall (10);
+ RegisterA.Data = RtcRead (RTC_ADDRESS_REGISTER_A);
+ Timeout--;
+ }
+
+ RegisterD.Data = RtcRead (RTC_ADDRESS_REGISTER_D);
+ if ((Timeout == 0) || (RegisterD.Bits.VRT == 0)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get time from RTC.
+
+ @param Time - pointer to time structure
+
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_SUCCESS
+
+**/
+STATIC
+EFI_STATUS
+RtcGetTime (
+ OUT EFI_TIME *Time
+ )
+{
+ RTC_REGISTER_B RegisterB;
+ UINT8 Century;
+ EFI_STATUS Status;
+
+ //
+ // Check parameters for null pointer
+ //
+ if (Time == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Wait for up to 0.1 seconds for the RTC to be updated
+ //
+ Status = RtcWaitToUpdate (100000);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Read Register B
+ //
+ RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);
+
+ //
+ // Get the Time/Date/Daylight Savings values.
+ //
+ Time->Second = RtcRead (RTC_ADDRESS_SECONDS);
+ Time->Minute = RtcRead (RTC_ADDRESS_MINUTES);
+ Time->Hour = RtcRead (RTC_ADDRESS_HOURS);
+ Time->Day = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH);
+ Time->Month = RtcRead (RTC_ADDRESS_MONTH);
+ Time->Year = RtcRead (RTC_ADDRESS_YEAR);
+
+ ConvertRtcTimeToEfiTime (Time, RegisterB);
+
+ if (RtcTestCenturyRegister () == EFI_SUCCESS) {
+ Century = BcdToDecimal ((UINT8)(RtcRead (RTC_ADDRESS_CENTURY) & 0x7f));
+ } else {
+ Century = BcdToDecimal (RtcRead (RTC_ADDRESS_CENTURY));
+ }
+
+ Time->Year = (UINT16)(Century * 100 + Time->Year);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Return Date and Time from RTC in Unix format which fits in 32 bit format.
+
+ @param NumOfSeconds - pointer to return calculated time
+
+ @retval EFI_SUCCESS
+ @retval EFI status if error occurred
+
+**/
+EFI_STATUS
+EfiSmGetTimeStamp (
+ OUT UINT32 *NumOfSeconds
+ )
+{
+ UINT16 NumOfYears;
+ UINTN NumOfLeapDays;
+ UINTN NumOfDays;
+ EFI_TIME Time;
+ EFI_STATUS Status;
+
+ Status = RtcGetTime (&Time);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ NumOfYears = Time.Year - 1970;
+ NumOfLeapDays = CountNumOfLeapDays (&Time);
+ NumOfDays = CalculateNumOfDayPassedThisYear (Time);
+
+ //
+ // Add 365 days for all years. Add additional days for Leap Years. Subtract off current day.
+ //
+ NumOfDays += (NumOfLeapDays + (365 * NumOfYears) - 1);
+
+ *NumOfSeconds = (UINT32)(3600 * 24 * NumOfDays + (Time.Hour * 3600) + (60 * Time.Minute) + Time.Second);
+
+ return EFI_SUCCESS;
+}
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManagementLibNull/ServerManagementLibNull.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManagementLibNull/ServerManagementLibNull.c
new file mode 100644
index 000000000000..7dd27f34878e
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManagementLibNull/ServerManagementLibNull.c
@@ -0,0 +1,144 @@
+/** @file
+ Lightweight lib to support EFI Server Management drivers.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+#include <Library/DebugLib.h>
+#include <Library/ServerMgmtRtLib.h>
+
+/**
+ The function will set up a notification on the ELOG protocol. This function is required to be called prior
+ to utilizing the ELOG protocol from within this library.
+
+ @retval EFI_SUCCESS after the notification has been setup.
+**/
+EFI_STATUS
+EfiInitializeGenericElog (
+ VOID
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ This function sends event log data to the destination such as LAN, ICMB, BMC etc.
+
+ @param ElogData is a pointer to the event log data that needs to be recorded
+ @param DataType type of Elog data that is being recorded. The Elog is redirected based on this parameter.
+ @param AlertEvent is an indication that the input data type is an alert. The underlying
+ drivers need to decide if they need to listen to the DataType and send it on
+ an appropriate channel as an alert use of the information.
+ @param DataSize is the size of the data to be logged
+ @param RecordId is the array of record IDs sent by the target. This can be used to retrieve the
+ records or erase the records.
+ @retval EFI_NOT_FOUND - the event log target was not found
+
+**/
+EFI_STATUS
+EfiSmSetEventLogData (
+ IN UINT8 *ElogData,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN BOOLEAN AlertEvent,
+ IN UINTN DataSize,
+ OUT UINT64 *RecordId
+ )
+{
+ return EFI_NOT_FOUND;
+}
+
+/**
+ This function gets event log data from the destination dependent on the DataType. The destination
+ can be a remote target such as LAN, ICMB, IPMI, or a FV. The ELOG redir driver will resolve the
+ destination.
+
+ @param ElogData - pointer to the event log data buffer to contain the data to be retrieved.
+ @param DataType - this is the type of Elog data to be gotten. Elog is redirected based upon this
+ information.
+ @param DataSize - this is the size of the data to be retrieved.
+ @param RecordId - 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
+ that it was last record if the Status is EFI_SUCCESS.
+
+ @retval EFI_NOT_FOUND - if the event log target was not found.
+
+**/
+EFI_STATUS
+EfiSmGetEventLogData (
+ IN UINT8 *ElogData,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN OUT UINTN *DataSize,
+ IN OUT UINT64 *RecordId
+ )
+{
+ return EFI_NOT_FOUND;
+}
+
+/**
+ This function erases the event log data defined by the DataType. The redir driver associated with
+ the DataType resolves the path to the record.
+
+ @param DataType - the type of Elog data that is to be erased.
+ @param RecordId - the RecordId of the data to be erased. If RecordId is NULL, all records in the
+ database are erased if permitted by the target. RecordId will contain the deleted
+ RecordId on return.
+
+ @retval EFI_SUCCESS - the record or collection of records were erased.
+ @retval EFI_NOT_FOUND - the event log target was not found.
+ @retval EFI_NO_RESPONSE - the event log target was found but did not respond.
+ @retval EFI_INVALID_PARAMETER - one of the parameters was invalid.
+
+**/
+EFI_STATUS
+EfiSmEraseEventlogData (
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN OUT UINT64 *RecordId
+ )
+{
+ return EFI_NOT_FOUND;
+}
+
+/**
+ This function enables or disables the event log defined by the DataType.
+
+
+ @param DataType - the type of Elog data that is being activated.
+ @param EnableElog - enables or disables the event log defined by the DataType. If it is NULL
+ it returns the current status of the DataType log.
+ @param ElogStatus - is the current status of the Event log defined by the DataType. Enabled is
+ TRUE and Disabled is FALSE.
+
+ @retval EFI_NOT_FOUND - the event log target was not found.
+
+**/
+EFI_STATUS
+EfiSmActivateEventLog (
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN BOOLEAN *EnableElog,
+ OUT BOOLEAN *ElogStatus
+ )
+{
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Return Date and Time from RTC in Unix format which fits in 32 bit format.
+
+ @param NumOfSeconds - pointer to return calculated time
+
+ @retval EFI_SUCCESS
+ @retval EFI status if error occurred
+
+**/
+EFI_STATUS
+EfiSmGetTimeStamp (
+ OUT UINT32 *NumOfSeconds
+ )
+{
+ *NumOfSeconds = 0;
+
+ return EFI_NOT_FOUND;
+}
--
2.39.2.windows.1
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#110327): https://edk2.groups.io/g/devel/message/110327
Mute This Topic: https://groups.io/mt/102279906/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [edk2-devel] [PATCH edk2-platforms v2 3/4] IpmiFeaturePkg: Add ACPI power state drivers
2023-10-29 20:27 [edk2-devel] [PATCH edk2-platforms v2 0/4] IpmiFeaturePkg: Add server management features Zhen Gong
2023-10-29 20:27 ` [edk2-devel] [PATCH edk2-platforms v2 1/4] IpmiFeaturePkg: Add Elog drivers Zhen Gong
2023-10-29 20:27 ` [edk2-devel] [PATCH edk2-platforms v2 2/4] IpmiFeaturePkg: Add ServerManagementLib Zhen Gong
@ 2023-10-29 20:27 ` Zhen Gong
2023-10-29 20:27 ` [edk2-devel] [PATCH edk2-platforms v2 4/4] IpmiFeaturePkg: Add FRU drivers Zhen Gong
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Zhen Gong @ 2023-10-29 20:27 UTC (permalink / raw)
To: devel; +Cc: Zhen Gong
Add DXE and SMM drivers that send "Set ACPI Power State" command to BMC.
Signed-off-by: Zhen Gong <zhen.gong@intel.com>
---
.../IpmiFeaturePkg/IpmiFeaturePkg.dec | 1 +
.../IpmiFeaturePkg/Include/IpmiFeature.dsc | 2 +
.../IpmiFeaturePkg/Include/PostMemory.fdf | 2 +
.../BmcAcpiState/BmcAcpiState.inf | 40 ++++
.../BmcAcpiSwChild/BmcAcpiSwChild.inf | 39 ++++
.../BmcAcpiState/BmcAcpiState.h | 26 +++
.../BmcAcpiSwChild/BmcAcpiSwChild.h | 82 ++++++++
.../Include/Protocol/BmcAcpiSwChildPolicy.h | 31 +++
.../BmcAcpiState/BmcAcpiState.c | 93 +++++++++
.../BmcAcpiSwChild/BmcAcpiSwChild.c | 189 ++++++++++++++++++
10 files changed, 505 insertions(+)
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiState/BmcAcpiState.inf
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiSwChild/BmcAcpiSwChild.inf
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiState/BmcAcpiState.h
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiSwChild/BmcAcpiSwChild.h
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/BmcAcpiSwChildPolicy.h
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiState/BmcAcpiState.c
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiSwChild/BmcAcpiSwChild.c
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFeaturePkg.dec b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFeaturePkg.dec
index 22bc4e69be8a..be0a11e2adb1 100644
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFeaturePkg.dec
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFeaturePkg.dec
@@ -75,6 +75,7 @@ [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 }}
+ gEfiBmcAcpiSwChildPolicyProtocolGuid = { 0x89843c0b, 0x5701, 0x4ff6, { 0xa4, 0x73, 0x65, 0x75, 0x99, 0x04, 0xf7, 0x35 } }
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 } }
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiFeature.dsc b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiFeature.dsc
index fc9001e98473..7e663236d9a1 100644
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiFeature.dsc
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiFeature.dsc
@@ -122,6 +122,8 @@ [Components.X64]
IpmiFeaturePkg/GenericIpmi/Dxe/GenericIpmi.inf
IpmiFeaturePkg/Library/SmmIpmiBaseLib/SmmIpmiBaseLib.inf
IpmiFeaturePkg/BmcAcpi/BmcAcpi.inf
+ IpmiFeaturePkg/BmcAcpiState/BmcAcpiState.inf
+ IpmiFeaturePkg/BmcAcpiSwChild/BmcAcpiSwChild.inf
IpmiFeaturePkg/BmcElog/DxeBmcElog.inf
IpmiFeaturePkg/BmcElog/SmmBmcElog.inf
IpmiFeaturePkg/GenericElog/Dxe/GenericElog.inf
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/PostMemory.fdf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/PostMemory.fdf
index f29810bc0b34..9b692f07dcd8 100644
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/PostMemory.fdf
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/PostMemory.fdf
@@ -10,6 +10,8 @@
INF IpmiFeaturePkg/GenericIpmi/Dxe/GenericIpmi.inf
INF IpmiFeaturePkg/IpmiInit/DxeIpmiInit.inf
INF RuleOverride = DRIVER_ACPITABLE IpmiFeaturePkg/BmcAcpi/BmcAcpi.inf
+INF IpmiFeaturePkg/BmcAcpiState/BmcAcpiState.inf
+INF IpmiFeaturePkg/BmcAcpiSwChild/BmcAcpiSwChild.inf
INF IpmiFeaturePkg/BmcElog/DxeBmcElog.inf
INF IpmiFeaturePkg/BmcElog/SmmBmcElog.inf
INF IpmiFeaturePkg/Frb/FrbDxe.inf
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiState/BmcAcpiState.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiState/BmcAcpiState.inf
new file mode 100644
index 000000000000..f1b750d6a20a
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiState/BmcAcpiState.inf
@@ -0,0 +1,40 @@
+### @file
+#
+# Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+###
+
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BmcAcpiState
+ FILE_GUID = 04103e59-48cc-417a-baec-9929c69c20f6
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = BmcAcpiStateEntryPoint
+
+[Sources]
+ BmcAcpiState.c
+ BmcAcpiState.h
+
+[Packages]
+ IpmiFeaturePkg/IpmiFeaturePkg.dec
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ DebugLib
+ UefiDriverEntryPoint
+ UefiBootServicesTableLib
+ IpmiBaseLib
+
+[Protocols]
+ gIpmiTransportProtocolGuid
+
+[Guids]
+ gEfiEventExitBootServicesGuid ## CONSUMES ## Event
+
+[Depex]
+ gIpmiTransportProtocolGuid
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiSwChild/BmcAcpiSwChild.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiSwChild/BmcAcpiSwChild.inf
new file mode 100644
index 000000000000..59a9f77d9f10
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiSwChild/BmcAcpiSwChild.inf
@@ -0,0 +1,39 @@
+### @file
+#
+# Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+###
+
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BmcAcpiSwChild
+ FILE_GUID = BB5BEBD1-CE71-4cd0-9E2F-C07886502661
+ MODULE_TYPE = DXE_SMM_DRIVER
+ PI_SPECIFICATION_VERSION = 0x0001000A
+ VERSION_STRING = 1.0
+ ENTRY_POINT = InitializeBmcAcpiSwChild
+
+[Sources]
+ BmcAcpiSwChild.c
+ BmcAcpiSwChild.h
+
+[Packages]
+ IpmiFeaturePkg/IpmiFeaturePkg.dec
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ DebugLib
+ SmmServicesTableLib
+ ServerManagementLib
+ IpmiBaseLib
+
+[Protocols]
+ gEfiBmcAcpiSwChildPolicyProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+
+[Depex]
+ gSmmIpmiTransportProtocolGuid
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiState/BmcAcpiState.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiState/BmcAcpiState.h
new file mode 100644
index 000000000000..4352652a2bda
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiState/BmcAcpiState.h
@@ -0,0 +1,26 @@
+/** @file
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _ACPI_BMC_STATE_H_
+#define _ACPI_BMC_STATE_H_
+
+//
+// Statements that include other header files
+//
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Guid/EventGroup.h>
+#include <Protocol/IpmiTransportProtocol.h>
+#include <Include/IpmiNetFnAppDefinitions.h>
+#include <IndustryStandard/Ipmi.h>
+#include <Library/IpmiBaseLib.h>
+#include <Protocol/IpmiProtocol.h>
+
+EFI_EVENT mExitBootServicesEvent = NULL;
+
+#endif
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiSwChild/BmcAcpiSwChild.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiSwChild/BmcAcpiSwChild.h
new file mode 100644
index 000000000000..10d687ed2b84
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiSwChild/BmcAcpiSwChild.h
@@ -0,0 +1,82 @@
+/** @file
+ This driver produces the ACPI enable and disable SMI handlers.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _BMC_ACPI_SW_CHILD_H_
+#define _BMC_ACPI_SW_CHILD_H_
+
+//
+// Statements that include other files
+//
+#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 <Library/ServerMgmtRtLib.h>
+#include <Protocol/IpmiTransportProtocol.h>
+#include <Protocol/BmcAcpiSwChildPolicy.h>
+#include <IndustryStandard/Ipmi.h>
+#include <Library/IpmiBaseLib.h>
+
+//
+// Module prototypes
+//
+
+/**
+ This is the standard EFI driver entrypoint. This function initializes
+ the BMC ACPI SW Child protocol.
+
+ @param ImageHandle - ImageHandle of the loaded driver
+ @param SystemTable - Pointer to the System Table
+
+ @retval EFI_SUCCESS - If all services discovered.
+ @retval Other - Failure in constructor.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeBmcAcpiSwChild (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Send the time to the BMC, in the UNIX 32 bit format.
+
+ @retval Status - result of sending the time stamp
+
+**/
+EFI_STATUS
+SyncTimeStamp (
+ VOID
+ );
+
+/**
+ Send a command to BMC to set the present power state.
+
+ @param This
+ @param PowerState
+ @param DeviceState
+
+ @retval EFI_SUCCESS if successful
+ @retval Other than EFI_SUCCESS if not successful
+
+**/
+EFI_STATUS
+SetACPIPowerStateInBMC (
+ IN EFI_BMC_ACPI_SW_CHILD_POLICY_PROTOCOL *This,
+ IN UINT8 PowerState,
+ IN UINT8 DeviceState
+ );
+
+#endif
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/BmcAcpiSwChildPolicy.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/BmcAcpiSwChildPolicy.h
new file mode 100644
index 000000000000..7958f8c63899
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/BmcAcpiSwChildPolicy.h
@@ -0,0 +1,31 @@
+/** @file
+ This protocol produces BmcAcpiSwChildPolicy Protocol.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _BMC_ACPI_SW_CHILD_POLICY_H_
+#define _BMC_ACPI_SW_CHILD_POLICY_H_
+
+typedef struct _EFI_BMC_ACPI_SW_CHILD_POLICY_PROTOCOL EFI_BMC_ACPI_SW_CHILD_POLICY_PROTOCOL;
+
+#define EFI_BMC_ACPI_SW_CHILD_POLICY_PROTOCOL_GUID \
+ { 0x89843c0b, 0x5701, 0x4ff6, 0xa4, 0x73, 0x65, 0x75, 0x99, 0x04, 0xf7, 0x35 }
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SET_ACPI_POWER_STATE_IN_BMC)(
+ IN EFI_BMC_ACPI_SW_CHILD_POLICY_PROTOCOL *This,
+ IN UINT8 PowerState,
+ IN UINT8 DeviceState
+ );
+
+struct _EFI_BMC_ACPI_SW_CHILD_POLICY_PROTOCOL {
+ EFI_SET_ACPI_POWER_STATE_IN_BMC SetACPIPowerStateInBMC;
+};
+
+extern EFI_GUID gEfiBmcAcpiSwChildPolicyProtocolGuid;
+
+#endif
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiState/BmcAcpiState.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiState/BmcAcpiState.c
new file mode 100644
index 000000000000..04fe2d80307e
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiState/BmcAcpiState.c
@@ -0,0 +1,93 @@
+/** @file
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <BmcAcpiState.h>
+
+/**
+ Notification function of Exit Boot Services event group.
+
+ Send a command to BMC to set power state to S0.
+
+ @param Event Event whose notification function is being invoked.
+ @param Context Pointer to the notification function's context.
+
+**/
+VOID
+EFIAPI
+BmcAcpiPowerStateS0Notify (
+ EFI_EVENT Event,
+ VOID *Context
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ IPMI_SET_ACPI_POWER_STATE_REQUEST AcpiPowerStateRequest;
+ UINT8 AcpiPowerStateResponse;
+ UINT32 ResponseDataSize = 0;
+
+ AcpiPowerStateRequest.SystemPowerState.Bits.PowerState = IPMI_SYSTEM_POWER_STATE_S0_G0; // System Power State S0
+ AcpiPowerStateRequest.SystemPowerState.Bits.StateChange = 1;
+ AcpiPowerStateRequest.DevicePowerState.Bits.PowerState = IPMI_DEVICE_POWER_STATE_D0; // Device State State S0
+ AcpiPowerStateRequest.DevicePowerState.Bits.StateChange = 1;
+
+ ResponseDataSize = sizeof (AcpiPowerStateResponse);
+
+ //
+ // Send a command to BMC to set power state to S0.
+ //
+ Status = IpmiSubmitCommand (
+ IPMI_NETFN_APP,
+ IPMI_APP_SET_ACPI_POWERSTATE,
+ (UINT8 *)&AcpiPowerStateRequest,
+ sizeof (IPMI_SET_ACPI_POWER_STATE_REQUEST),
+ (UINT8 *)&AcpiPowerStateResponse,
+ &ResponseDataSize
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "IpmiSubmitCommand App Set Acpi Power State Failed %r\n", Status));
+ }
+}
+
+/**
+
+ Entry point for the Bmc Acpi State Dxe driver.
+ Use this function to replace previous ACPI Enable SMM handler to set BMC ACPI power state.
+
+ @param ImageHandle - Image Handle.
+ @param SystemTable - EFI System Table.
+
+ @retval EFI_SUCCESS - Function has completed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+BmcAcpiStateEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Create an Exit Boot Service to Send a command to BMC to set the present power state
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ BmcAcpiPowerStateS0Notify,
+ NULL,
+ &gEfiEventExitBootServicesGuid,
+ &mExitBootServicesEvent
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Create Exit Boot Services Event Failed\n"));
+ } else {
+ return EFI_SUCCESS;
+ }
+
+ return EFI_UNSUPPORTED;
+}
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiSwChild/BmcAcpiSwChild.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiSwChild/BmcAcpiSwChild.c
new file mode 100644
index 000000000000..ba134db8d50d
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiSwChild/BmcAcpiSwChild.c
@@ -0,0 +1,189 @@
+/** @file
+ This driver publishes a protocol that is used by the ACPI SMM Platform
+ driver to notify the BMC of Power State transitions.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "BmcAcpiSwChild.h"
+
+//
+// Global variables
+//
+EFI_BMC_ACPI_SW_CHILD_POLICY_PROTOCOL mBmcAcpiSwChild;
+
+/**
+ This is the standard EFI driver entrypoint. This function initializes
+ the BMC ACPI SW Child protocol.
+
+ @param ImageHandle - ImageHandle of the loaded driver
+ @param SystemTable - Pointer to the System Table
+
+ @retval EFI_SUCCESS - If all services discovered.
+ @retval Other - Failure in constructor.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeBmcAcpiSwChild (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+
+ Status = EFI_SUCCESS;
+
+ mBmcAcpiSwChild.SetACPIPowerStateInBMC = (EFI_SET_ACPI_POWER_STATE_IN_BMC)SetACPIPowerStateInBMC;
+
+ //
+ // Install protocol
+ //
+ Handle = NULL;
+ Status = gSmst->SmmInstallProtocolInterface (
+ &Handle,
+ &gEfiBmcAcpiSwChildPolicyProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mBmcAcpiSwChild
+ );
+
+ return Status;
+}
+
+/**
+ Send the time to the BMC, in the UNIX 32 bit format.
+
+ @retval Status - result of sending the time stamp
+
+**/
+EFI_STATUS
+SyncTimeStamp (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT32 ResponseDataSize;
+ IPMI_ADD_SEL_ENTRY_REQUEST TimeStampEvtRecord;
+ IPMI_ADD_SEL_ENTRY_RESPONSE AddSelEntryResponse;
+ IPMI_SET_SEL_TIME_REQUEST SelTimeReq;
+ UINT8 SelTimeResponse;
+
+ TimeStampEvtRecord.RecordData.RecordId = 0; // Record Id
+ TimeStampEvtRecord.RecordData.RecordType = IPMI_SEL_SYSTEM_RECORD; // Record Type
+ TimeStampEvtRecord.RecordData.TimeStamp = 0; // Time stamp
+ TimeStampEvtRecord.RecordData.GeneratorId = 0x0003; // GenID:BIOS
+ TimeStampEvtRecord.RecordData.EvMRevision = IPMI_EVM_REVISION; // EVM REV
+ TimeStampEvtRecord.RecordData.SensorType = 0x12; // Sensor Type
+ TimeStampEvtRecord.RecordData.SensorNumber = 0x83; // Sensor No
+ TimeStampEvtRecord.RecordData.EventDirType = IPMI_SENSOR_TYPE_EVENT_CODE_DISCRETE; // Event Dir
+ TimeStampEvtRecord.RecordData.OEMEvData1 = 05; // Sensor specific Offset for Timestamp Clock Synch Event.
+ TimeStampEvtRecord.RecordData.OEMEvData2 = 00; // ED2
+ TimeStampEvtRecord.RecordData.OEMEvData3 = 0xFF; // ED3
+
+ //
+ // Log Timestamp Clock Synch Event 1st pair.
+ //
+ ResponseDataSize = sizeof (AddSelEntryResponse);
+ Status = IpmiSubmitCommand (
+ IPMI_NETFN_STORAGE,
+ IPMI_STORAGE_ADD_SEL_ENTRY,
+ (UINT8 *)&TimeStampEvtRecord,
+ sizeof (TimeStampEvtRecord),
+ (UINT8 *)&AddSelEntryResponse,
+ &ResponseDataSize
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "IpmiSubmitCommand Storage Add SEL Entry Failed %r\n", Status));
+ return Status;
+ }
+
+ Status = EfiSmGetTimeStamp (&SelTimeReq.Timestamp);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ResponseDataSize = sizeof (SelTimeResponse);
+ Status = IpmiSubmitCommand (
+ IPMI_NETFN_STORAGE,
+ IPMI_STORAGE_SET_SEL_TIME,
+ (UINT8 *)&SelTimeReq,
+ sizeof (SelTimeReq),
+ (UINT8 *)&SelTimeResponse,
+ &ResponseDataSize
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "IpmiSubmitCommand Storage Set SEL Time Failed %r\n", Status));
+ return Status;
+ }
+
+ //
+ // Log Timestamp Clock Sync Event 2nd pair.
+ //
+ TimeStampEvtRecord.RecordData.OEMEvData2 = 0x80;
+ ResponseDataSize = sizeof (AddSelEntryResponse);
+ Status = IpmiSubmitCommand (
+ IPMI_NETFN_STORAGE,
+ IPMI_STORAGE_ADD_SEL_ENTRY,
+ (UINT8 *)&TimeStampEvtRecord,
+ sizeof (TimeStampEvtRecord),
+ (UINT8 *)&AddSelEntryResponse,
+ &ResponseDataSize
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "IpmiSubmitCommand Storage Add SEL Entry Failed %r\n", Status));
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Send a command to BMC to set the present power state.
+
+ @param This
+ @param PowerState
+ @param DeviceState
+
+ @retval EFI_SUCCESS if successful
+ @retval Other than EFI_SUCCESS if not successful
+
+**/
+EFI_STATUS
+SetACPIPowerStateInBMC (
+ IN EFI_BMC_ACPI_SW_CHILD_POLICY_PROTOCOL *This,
+ IN UINT8 PowerState,
+ IN UINT8 DeviceState
+ )
+{
+ EFI_STATUS Status;
+ IPMI_SET_ACPI_POWER_STATE_REQUEST AcpiPowerStateRequest;
+ UINT8 AcpiPowerStateResponse;
+ UINT32 ResponseDataSize;
+
+ AcpiPowerStateRequest.SystemPowerState.Bits.PowerState = PowerState;
+ AcpiPowerStateRequest.SystemPowerState.Bits.StateChange = 1;
+ AcpiPowerStateRequest.DevicePowerState.Bits.PowerState = DeviceState;
+ AcpiPowerStateRequest.DevicePowerState.Bits.StateChange = 1;
+
+ ResponseDataSize = sizeof (AcpiPowerStateResponse);
+
+ Status = IpmiSubmitCommand (
+ IPMI_NETFN_APP,
+ IPMI_APP_SET_ACPI_POWERSTATE,
+ (UINT8 *)&AcpiPowerStateRequest,
+ sizeof (AcpiPowerStateRequest),
+ (UINT8 *)&AcpiPowerStateResponse,
+ &ResponseDataSize
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "IpmiSubmitCommand App Set Acpi Power State Failed %r\n", Status));
+ }
+
+ return Status;
+}
--
2.39.2.windows.1
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#110328): https://edk2.groups.io/g/devel/message/110328
Mute This Topic: https://groups.io/mt/102279907/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [edk2-devel] [PATCH edk2-platforms v2 4/4] IpmiFeaturePkg: Add FRU drivers
2023-10-29 20:27 [edk2-devel] [PATCH edk2-platforms v2 0/4] IpmiFeaturePkg: Add server management features Zhen Gong
` (2 preceding siblings ...)
2023-10-29 20:27 ` [edk2-devel] [PATCH edk2-platforms v2 3/4] IpmiFeaturePkg: Add ACPI power state drivers Zhen Gong
@ 2023-10-29 20:27 ` Zhen Gong
2023-11-02 15:47 ` [edk2-devel] [PATCH edk2-platforms v2 0/4] IpmiFeaturePkg: Add server management features Nate DeSimone
2023-11-03 19:06 ` Nate DeSimone
5 siblings, 0 replies; 7+ messages in thread
From: Zhen Gong @ 2023-10-29 20:27 UTC (permalink / raw)
To: devel; +Cc: Zhen Gong
Add GenericFruDriver and generate data based on SMBIOS data.
Signed-off-by: Zhen Gong <zhen.gong@intel.com>
# Conflicts:
# Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFru/IpmiFru.inf
---
.../IpmiFeaturePkg/IpmiFeaturePkg.dec | 4 +
.../IpmiFeaturePkg/Include/IpmiFeature.dsc | 3 +-
.../IpmiFeaturePkg/Include/PostMemory.fdf | 3 +-
.../IpmiFeaturePkg/GenericFru/GenericFru.inf | 42 ++
.../IpmiFeaturePkg/IpmiFru/IpmiFru.inf | 36 --
.../IpmiRedirFru/IpmiRedirFru.inf | 51 ++
.../GenericFru/GenericFruDriver.h | 178 ++++++
.../Include/Protocol/GenericFru.h | 103 ++++
.../Include/Protocol/RedirFru.h | 81 +++
.../IpmiRedirFru/IpmiRedirFru.h | 149 +++++
.../IpmiFeaturePkg/GenericFru/GenericFru.c | 68 +++
.../GenericFru/GenericFruDriver.c | 513 ++++++++++++++++++
.../IpmiFeaturePkg/IpmiFru/IpmiFru.c | 67 ---
.../IpmiFeaturePkg/IpmiRedirFru/FruSmbios.c | 469 ++++++++++++++++
.../IpmiRedirFru/IpmiRedirFru.c | 479 ++++++++++++++++
15 files changed, 2141 insertions(+), 105 deletions(-)
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericFru/GenericFru.inf
delete mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFru/IpmiFru.inf
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRedirFru/IpmiRedirFru.inf
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericFru/GenericFruDriver.h
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/GenericFru.h
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/RedirFru.h
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRedirFru/IpmiRedirFru.h
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericFru/GenericFru.c
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericFru/GenericFruDriver.c
delete mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFru/IpmiFru.c
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRedirFru/FruSmbios.c
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRedirFru/IpmiRedirFru.c
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFeaturePkg.dec b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFeaturePkg.dec
index be0a11e2adb1..d586931a6d6f 100644
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFeaturePkg.dec
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFeaturePkg.dec
@@ -63,6 +63,8 @@ [LibraryClasses]
[Guids]
gIpmiFeaturePkgTokenSpaceGuid = {0xc05283f6, 0xd6a8, 0x48f3, {0x9b, 0x59, 0xfb, 0xca, 0x71, 0x32, 0x0f, 0x12}}
gPeiIpmiHobGuid = {0xcb4d3e13, 0x1e34, 0x4373, {0x8a, 0x81, 0xe9, 0x0, 0x10, 0xf1, 0xdb, 0xa4}}
+ gEfiIpmiFormatFruGuid = { 0x3531fdc6, 0xeae, 0x4cd2, { 0xb0, 0xa6, 0x5f, 0x48, 0xa0, 0xdf, 0xe3, 0x8 } }
+ gEfiSystemTypeFruGuid = { 0xaab16018, 0x679d, 0x4461, { 0xba, 0x20, 0xe7, 0xc, 0xf7, 0x86, 0x6a, 0x9b } }
[Ppis]
gPeiIpmiTransportPpiGuid = {0x7bf5fecc, 0xc5b5, 0x4b25, {0x81, 0x1b, 0xb4, 0xb5, 0xb, 0x28, 0x79, 0xf7}}
@@ -80,6 +82,8 @@ [Protocols]
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 } }
+ gEfiRedirFruProtocolGuid = { 0x28638cfa, 0xea88, 0x456c, { 0x92, 0xa5, 0xf2, 0x49, 0xca, 0x48, 0x85, 0x35 } }
+ gEfiGenericFruProtocolGuid = { 0xc8eebf0e, 0x0e10, 0x47f7, { 0x81, 0xbd, 0x39, 0xdb, 0x75, 0xca, 0x93, 0x9f } }
[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 7e663236d9a1..3ceedb2fa3c4 100644
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiFeature.dsc
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiFeature.dsc
@@ -129,7 +129,8 @@ [Components.X64]
IpmiFeaturePkg/GenericElog/Dxe/GenericElog.inf
IpmiFeaturePkg/GenericElog/Smm/GenericElog.inf
IpmiFeaturePkg/Frb/FrbDxe.inf
- IpmiFeaturePkg/IpmiFru/IpmiFru.inf
+ IpmiFeaturePkg/IpmiRedirFru/IpmiRedirFru.inf
+ IpmiFeaturePkg/GenericFru/GenericFru.inf
IpmiFeaturePkg/IpmiInit/DxeIpmiInit.inf
IpmiFeaturePkg/OsWdt/OsWdt.inf
IpmiFeaturePkg/SolStatus/SolStatus.inf
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/PostMemory.fdf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/PostMemory.fdf
index 9b692f07dcd8..810a041983c1 100644
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/PostMemory.fdf
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/PostMemory.fdf
@@ -15,8 +15,9 @@
INF IpmiFeaturePkg/BmcElog/DxeBmcElog.inf
INF IpmiFeaturePkg/BmcElog/SmmBmcElog.inf
INF IpmiFeaturePkg/Frb/FrbDxe.inf
-INF IpmiFeaturePkg/IpmiFru/IpmiFru.inf
+INF IpmiFeaturePkg/IpmiRedirFru/IpmiRedirFru.inf
INF IpmiFeaturePkg/GenericElog/Dxe/GenericElog.inf
INF IpmiFeaturePkg/GenericElog/Smm/GenericElog.inf
+INF IpmiFeaturePkg/GenericFru/GenericFru.inf
INF IpmiFeaturePkg/OsWdt/OsWdt.inf
INF IpmiFeaturePkg/SolStatus/SolStatus.inf
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericFru/GenericFru.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericFru/GenericFru.inf
new file mode 100644
index 000000000000..f53642b1a476
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericFru/GenericFru.inf
@@ -0,0 +1,42 @@
+### @file
+#
+# Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+###
+
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = GenericFru
+ FILE_GUID = 663FB335-25DE-45b0-A531-DF3627A13D29
+ MODULE_TYPE = DXE_RUNTIME_DRIVER
+ ENTRY_POINT = InitializeSmFruLayer
+
+[Sources]
+ GenericFruDriver.h
+ GenericFruDriver.c
+ GenericFru.c
+
+[Packages]
+ IpmiFeaturePkg/IpmiFeaturePkg.dec
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+ UefiRuntimeLib
+ UefiDriverEntryPoint
+ BaseMemoryLib
+ DebugLib
+
+[Protocols]
+ gEfiGenericFruProtocolGuid ##Produces
+ gEfiRedirFruProtocolGuid ##Consumes
+
+[Guids]
+
+[Depex]
+ gIpmiTransportProtocolGuid
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFru/IpmiFru.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFru/IpmiFru.inf
deleted file mode 100644
index f5778f3468df..000000000000
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFru/IpmiFru.inf
+++ /dev/null
@@ -1,36 +0,0 @@
-### @file
-# Component description file for IPMI FRU.
-#
-# Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>
-#
-# SPDX-License-Identifier: BSD-2-Clause-Patent
-#
-###
-
-[Defines]
- INF_VERSION = 0x00010005
- BASE_NAME = IpmiFru
- FILE_GUID = 3F1D6464-2B4C-4640-BAC4-3DD905D26CDA
- MODULE_TYPE = DXE_DRIVER
- PI_SPECIFICATION_VERSION = 0x0001000A
- VERSION_STRING = 1.0
- ENTRY_POINT = InitializeFru
-
-[Sources]
- IpmiFru.c
-
-[Packages]
- MdePkg/MdePkg.dec
- MdeModulePkg/MdeModulePkg.dec
- IpmiFeaturePkg/IpmiFeaturePkg.dec
-
-[LibraryClasses]
- UefiDriverEntryPoint
- UefiLib
- DebugLib
- UefiBootServicesTableLib
- BaseMemoryLib
- IpmiCommandLib
-
-[Depex]
- TRUE
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRedirFru/IpmiRedirFru.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRedirFru/IpmiRedirFru.inf
new file mode 100644
index 000000000000..24fbc94128da
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRedirFru/IpmiRedirFru.inf
@@ -0,0 +1,51 @@
+### @file
+#
+# Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+###
+
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = IpmiRedirFru
+ FILE_GUID = 3F1D6464-2B4C-4640-BAC4-3DD905D26CDA
+ MODULE_TYPE = DXE_DRIVER
+ PI_SPECIFICATION_VERSION = 0x0001000A
+ VERSION_STRING = 1.0
+ ENTRY_POINT = InitializeSmRedirFruLayer
+
+[Sources]
+ FruSmbios.c
+ IpmiRedirFru.h
+ IpmiRedirFru.c
+
+[Packages]
+ IpmiFeaturePkg/IpmiFeaturePkg.dec
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ DebugLib
+ UefiBootServicesTableLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ UefiLib
+ IpmiBaseLib
+
+[Guids]
+ gEfiIpmiFormatFruGuid
+ gEfiSystemTypeFruGuid
+
+[Protocols]
+ gEfiSmbiosProtocolGuid
+ gEfiRedirFruProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+ gIpmiTransportProtocolGuid
+
+[Depex]
+ gIpmiTransportProtocolGuid AND
+ gEfiHiiDatabaseProtocolGuid AND
+ gEfiLoadedImageProtocolGuid
+
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericFru/GenericFruDriver.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericFru/GenericFruDriver.h
new file mode 100644
index 000000000000..1761e52dc453
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericFru/GenericFruDriver.h
@@ -0,0 +1,178 @@
+/** @file
+ Generic FRU functions.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _EFI_GENEFRU_H_
+#define _EFI_GENEFRU_H_
+
+#include <PiDxe.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiRuntimeLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+
+#include "Protocol/GenericFru.h"
+#include "Protocol/RedirFru.h"
+
+#define EFI_FRU_PHYSICAL 0
+#define EFI_FRU_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_FRU_REDIR_PROTOCOL *This;
+ FUNCTION_PTR GetFruRedirInfo;
+ FUNCTION_PTR GetFruSlotInfo;
+ FUNCTION_PTR GetFruRedirData;
+ FUNCTION_PTR SetFruRedirData;
+} REDIR_FRU_MODULE_PROC;
+
+typedef struct {
+ BOOLEAN Valid;
+ EFI_GUID FruTypeGuid;
+ UINTN StartSlot;
+ UINTN EndSlot;
+ REDIR_FRU_MODULE_PROC Command[2];
+} FRU_REDIR_MODULES;
+
+typedef struct {
+ FRU_REDIR_MODULES Redir[MAX_REDIR_DESCRIPTOR];
+ UINTN MaxDescriptors;
+} FRU_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
+ );
+
+/**
+ Sm Fru Service Initialize.
+
+ @param ImageHandle
+ @param SystemTable
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+SmFruServiceInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Efi Lib Get Fru Info.
+
+ @param FruTypeGuid
+ @param FruInstance
+ @param FruFormatGuid
+ @param DataAccessGranularity
+ @param FruInformationString
+ @param Global
+ @param Virtual
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EfiLibGetFruInfo (
+ IN EFI_GUID *FruTypeGuid,
+ IN UINTN FruInstance,
+ OUT EFI_GUID *FruFormatGuid,
+ OUT UINTN *DataAccessGranularity,
+ OUT CHAR16 **FruInformationString,
+ IN FRU_MODULE_GLOBAL *Global,
+ IN BOOLEAN Virtual
+ );
+
+/**
+ Efi Lib Get Fru Data.
+
+ @param FruTypeGuid
+ @param FruInstance
+ @param FruDataOffset
+ @param FruDataSize
+ @param FruData
+ @param Global
+ @param Virtual
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EfiLibGetFruData (
+ IN EFI_GUID *FruTypeGuid,
+ IN UINTN FruInstance,
+ IN UINTN FruDataOffset,
+ IN UINTN FruDataSize,
+ IN UINT8 *FruData,
+ IN FRU_MODULE_GLOBAL *Global,
+ IN BOOLEAN Virtual
+ );
+
+/**
+ Efi Lib Set Fru Data.
+
+ @param FruTypeGuid
+ @param FruInstance
+ @param FruDataOffset
+ @param FruDataSize
+ @param FruData
+ @param Global
+ @param Virtual
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EfiLibSetFruData (
+ IN EFI_GUID *FruTypeGuid,
+ IN UINTN FruInstance,
+ IN UINTN FruDataOffset,
+ IN UINTN FruDataSize,
+ IN UINT8 *FruData,
+ IN FRU_MODULE_GLOBAL *Global,
+ IN BOOLEAN Virtual
+ );
+
+#endif
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/GenericFru.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/GenericFru.h
new file mode 100644
index 000000000000..7fcc64ba5038
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/GenericFru.h
@@ -0,0 +1,103 @@
+/** @file
+ Generic FRU Protocol as defined in Tiano
+ This code abstracts the generic FRU Protocol
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _GENERIC_FRU_H_
+#define _GENERIC_FRU_H_
+
+#define EFI_SM_FRU_PROTOCOL_GUID \
+ { \
+ 0xc8eebf0e, 0xe10, 0x47f7, 0x81, 0xbd, 0x39, 0xdb, 0x75, 0xca, 0x93, 0x9f \
+ }
+
+typedef struct _EFI_SM_FRU_PROTOCOL EFI_SM_FRU_PROTOCOL;
+
+//
+// Common FRU Types
+//
+#define EFI_CPU_TYPE_FRU_GUID \
+ { \
+ 0xf064c91f, 0x188c, 0x4f56, 0xb7, 0xfd, 0x30, 0xa9, 0xb8, 0x6a, 0x29, 0xf3 \
+ }
+
+#define EFI_MEMORY_TYPE_FRU_GUID \
+ { \
+ 0xd50234f4, 0x6f4b, 0x43e8, 0xa0, 0x13, 0x3c, 0x1e, 0x33, 0xd9, 0xb9, 0xb1 \
+ }
+
+#define EFI_SYSTEM_TYPE_FRU_GUID \
+ { \
+ 0xaab16018, 0x679d, 0x4461, 0xba, 0x20, 0xe7, 0xc, 0xf7, 0x86, 0x6a, 0x9b \
+ }
+
+//
+// Common FRU Formats.
+//
+#define EFI_IPMI_FORMAT_FRU_GUID \
+ { \
+ 0x3531fdc6, 0xeae, 0x4cd2, 0xb0, 0xa6, 0x5f, 0x48, 0xa0, 0xdf, 0xe3, 0x8 \
+ }
+
+#define EFI_DMI_FORMAT_FRU_GUID \
+ { \
+ 0x67ef7a73, 0x2594, 0x4a5e, 0x93, 0xa, 0xe1, 0x66, 0xfa, 0xbc, 0xd2, 0xc8 \
+ }
+
+#define EFI_INTEL_MFG_FORMAT_FRU_GUID \
+ { \
+ 0x79e8c9c7, 0x1152, 0x4f00, 0xb8, 0x31, 0x14, 0xf1, 0xc4, 0x4, 0x1a, 0xe0 \
+ }
+
+//
+// Generic FRU Function Prototypes
+//
+typedef
+EFI_STATUS
+(EFIAPI *EFI_GET_FRU_INFO)(
+ IN EFI_SM_FRU_PROTOCOL *This,
+ IN EFI_GUID *FruTypeGuid,
+ IN UINTN FruInstance,
+ OUT EFI_GUID *FruFormatGuid,
+ OUT UINTN *DataAccessGranularity,
+ OUT CHAR16 **FruInformationString
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_GET_FRU_DATA)(
+ IN EFI_SM_FRU_PROTOCOL *This,
+ IN EFI_GUID *FruTypeGuid,
+ IN UINTN FruInstance,
+ IN UINTN FruDataOffset,
+ IN UINTN FruDataSize,
+ IN UINT8 *FruData
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SET_FRU_DATA)(
+ IN EFI_SM_FRU_PROTOCOL *This,
+ IN EFI_GUID *FruTypeGuid,
+ IN UINTN FruInstance,
+ IN UINTN FruDataOffset,
+ IN UINTN FruDataSize,
+ IN UINT8 *FruData
+ );
+
+//
+// GENERIC FRU PROTOCOL
+//
+typedef struct _EFI_SM_FRU_PROTOCOL {
+ EFI_GET_FRU_INFO GetFruInfo;
+ EFI_GET_FRU_DATA GetFruData;
+ EFI_SET_FRU_DATA SetFruData;
+} EFI_SM_FRU_PROTOCOL;
+
+extern EFI_GUID gEfiGenericFruProtocolGuid;
+
+#endif
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/RedirFru.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/RedirFru.h
new file mode 100644
index 000000000000..30281ba9fa04
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/RedirFru.h
@@ -0,0 +1,81 @@
+/** @file
+ This code abstracts the generic FRU Protocol.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _REDIR_FRU_H_
+#define _REDIR_FRU_H_
+
+typedef struct _EFI_SM_FRU_REDIR_PROTOCOL EFI_SM_FRU_REDIR_PROTOCOL;
+
+#define EFI_SM_FRU_REDIR_PROTOCOL_GUID \
+ { \
+ 0x28638cfa, 0xea88, 0x456c, 0x92, 0xa5, 0xf2, 0x49, 0xca, 0x48, 0x85, 0x35 \
+ }
+
+// {41F49AE4-7FB0-4c54-994E-EA199171B0AC}
+#define EFI_PRE_FRU_SMBIOS_DATA_GUID \
+ { \
+ 0x41f49ae4, 0x7fb0, 0x4c54, 0x99, 0x4e, 0xea, 0x19, 0x91, 0x71, 0xb0, 0xac \
+ }
+
+#define EFI_SM_FRU_REDIR_SIGNATURE SIGNATURE_32 ('f', 'r', 'r', 'x')
+
+//
+// Redir FRU Function Prototypes
+//
+typedef
+EFI_STATUS
+(EFIAPI *EFI_GET_FRU_REDIR_INFO)(
+ IN EFI_SM_FRU_REDIR_PROTOCOL *This,
+ IN UINTN FruSlotNumber,
+ OUT EFI_GUID *FruFormatGuid,
+ OUT UINTN *DataAccessGranularity,
+ OUT CHAR16 **FruInformationString
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_GET_FRU_SLOT_INFO)(
+ IN EFI_SM_FRU_REDIR_PROTOCOL *This,
+ OUT EFI_GUID *FruTypeGuid,
+ OUT UINTN *StartFruSlotNumber,
+ OUT UINTN *NumSlots
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_GET_FRU_REDIR_DATA)(
+ IN EFI_SM_FRU_REDIR_PROTOCOL *This,
+ IN UINTN FruSlotNumber,
+ IN UINTN FruDataOffset,
+ IN UINTN FruDataSize,
+ IN UINT8 *FruData
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SET_FRU_REDIR_DATA)(
+ IN EFI_SM_FRU_REDIR_PROTOCOL *This,
+ IN UINTN FruSlotNumber,
+ IN UINTN FruDataOffset,
+ IN UINTN FruDataSize,
+ IN UINT8 *FruData
+ );
+
+//
+// REDIR FRU PROTOCOL
+//
+struct _EFI_SM_FRU_REDIR_PROTOCOL {
+ EFI_GET_FRU_REDIR_INFO GetFruRedirInfo;
+ EFI_GET_FRU_SLOT_INFO GetFruSlotInfo;
+ EFI_GET_FRU_REDIR_DATA GetFruRedirData;
+ EFI_SET_FRU_REDIR_DATA SetFruRedirData;
+};
+
+extern EFI_GUID gEfiRedirFruProtocolGuid;
+
+#endif
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRedirFru/IpmiRedirFru.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRedirFru/IpmiRedirFru.h
new file mode 100644
index 000000000000..9fd0067973a6
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRedirFru/IpmiRedirFru.h
@@ -0,0 +1,149 @@
+/** @file
+ IPMI Redir Sensor functions.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _EFI_IPMI_REDIR_FRU_H_
+#define _EFI_IPMI_REDIR_FRU_H_
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <Protocol/RedirFru.h>
+#include <Protocol/GenericFru.h>
+#include <Protocol/HiiDatabase.h>
+#include <Protocol/HiiString.h>
+#include <IndustryStandard/SmBios.h>
+#include <Protocol/Smbios.h>
+#include <IndustryStandard/Ipmi.h>
+#include <Library/IpmiBaseLib.h>
+#include <Protocol/IpmiTransportProtocol.h>
+
+#define MAX_FRU_SLOT 20
+
+#define IPMI_RDWR_FRU_FRAGMENT_SIZE 0x10
+
+#define CHASSIS_TYPE_LENGTH 1
+#define CHASSIS_TYPE_OFFSET 2
+#define CHASSIS_PART_NUMBER 3
+
+#define PRODUCT_MFG_OFFSET 3
+#define BOARD_MFG_OFFSET 6
+
+#define SMBIOSTYPE1 1
+#define SMBIOSTYPE2 2
+#define SMBIOSTYPE3 3
+
+#define OFFSET0 0
+#define OFFSET1 1
+#define OFFSET2 2
+#define OFFSET3 3
+#define OFFSET4 4
+#define OFFSET5 5
+#define OFFSET6 6
+#define OFFSET7 7
+#define OFFSET8 8
+#define OFFSET9 9
+
+#define STRING1 1
+#define STRING2 2
+#define STRING3 3
+#define STRING4 4
+#define STRING5 5
+#define STRING6 6
+#define STRING7 7
+#define STRING8 8
+#define STRING9 9
+
+typedef struct {
+ BOOLEAN Valid;
+ IPMI_FRU_DATA_INFO FruDevice;
+} EFI_FRU_DEVICE_INFO;
+
+typedef struct {
+ UINTN Signature;
+ UINT8 MaxFruSlots;
+ UINT8 NumSlots;
+ EFI_FRU_DEVICE_INFO FruDeviceInfo[MAX_FRU_SLOT];
+ EFI_SM_FRU_REDIR_PROTOCOL IpmiRedirFruProtocol;
+} EFI_IPMI_FRU_GLOBAL;
+
+/**
+ Get Fru Redir Data.
+
+ @param This
+ @param FruSlotNumber
+ @param FruDataOffset
+ @param FruDataSize
+ @param FruData
+
+ EFI_STATUS
+
+**/
+EFI_STATUS
+EFIAPI
+EfiGetFruRedirData (
+ IN EFI_SM_FRU_REDIR_PROTOCOL *This,
+ IN UINTN FruSlotNumber,
+ IN UINTN FruDataOffset,
+ IN UINTN FruDataSize,
+ IN UINT8 *FruData
+ );
+
+/**
+ This routine install a notify function listen to gEfiEventReadyToBootGuid.
+
+ @param This - SM Fru Redir protocol
+
+**/
+VOID
+GenerateFruSmbiosData (
+ IN EFI_SM_FRU_REDIR_PROTOCOL *This
+ );
+
+#define INSTANCE_FROM_EFI_SM_IPMI_FRU_THIS(a) \
+ CR (a, \
+ EFI_IPMI_FRU_GLOBAL, \
+ IpmiRedirFruProtocol, \
+ EFI_SM_FRU_REDIR_SIGNATURE \
+ )
+
+/**
+ Do a one byte IO write.
+
+ @param Address - IO address to write
+ @param Data - Data to write to Address
+
+Returns:
+ NONE
+
+**/
+VOID
+IoWrite8 (
+ IN UINT64 Address,
+ IN UINT8 Data
+ );
+
+/**
+ Do a one byte IO read.
+
+ @param Address - IO address to read
+
+ @retval Data read
+
+**/
+UINT8
+IoRead8 (
+ IN UINT64 Address
+ );
+
+#endif
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericFru/GenericFru.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericFru/GenericFru.c
new file mode 100644
index 000000000000..8b91a4dd05bc
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericFru/GenericFru.c
@@ -0,0 +1,68 @@
+/** @file
+ Hooks for Generic FRU.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "GenericFruDriver.h"
+
+//
+// Don't use module globals after the SetVirtualAddress map is signaled
+//
+extern FRU_MODULE_GLOBAL *mFruModuleGlobal;
+
+/**
+ Efi Convert Function.
+
+ @param Function
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EfiConvertFunction (
+ IN FUNCTION_PTR *Function
+ )
+{
+ gRT->ConvertPointer (0x02, (VOID **)&Function->Function);
+ return EFI_SUCCESS;
+}
+
+/**
+ Efi Set Function Entry.
+
+ @param FunctionPointer
+ @param Function
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EfiSetFunctionEntry (
+ IN FUNCTION_PTR *FunctionPointer,
+ IN VOID *Function
+ )
+{
+ FunctionPointer->Function = (EFI_PLABEL *)Function;
+ return EFI_SUCCESS;
+}
+
+/**
+ SmFru Service Initialize.
+
+ @param ImageHandle
+ @param SystemTable
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+SmFruServiceInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ return EFI_SUCCESS;
+}
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericFru/GenericFruDriver.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericFru/GenericFruDriver.c
new file mode 100644
index 000000000000..523630d452f9
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericFru/GenericFruDriver.c
@@ -0,0 +1,513 @@
+/** @file
+ Server Management Generic FRU Driver. Each FRU REDIR driver attaches
+ to the Generic FRU driver which is coded in this section. A Runtime
+ protocol will bind to this and be able to access all the FRU transports
+ as well as their physical layers.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "GenericFruDriver.h"
+
+FRU_MODULE_GLOBAL *mFruModuleGlobal;
+
+//
+// Define module globals used to register for notification of when
+// the FRU REDIR protocol has been produced.
+//
+VOID *mEfiFruRedirProtocolNotifyReg;
+EFI_EVENT mEfiFruRedirProtocolEvent;
+
+/**
+ Efi Lib Get Fru Info.
+
+ @param FruTypeGuid
+ @param FruInstance
+ @param FruFormatGuid
+ @param DataAccessGranularity
+ @param FruInformationString
+ @param Global
+ @param Virtual
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EfiLibGetFruInfo (
+ IN EFI_GUID *FruTypeGuid,
+ IN UINTN FruInstance,
+ OUT EFI_GUID *FruFormatGuid,
+ OUT UINTN *DataAccessGranularity,
+ OUT CHAR16 **FruInformationString,
+ IN FRU_MODULE_GLOBAL *Global,
+ IN BOOLEAN Virtual
+ )
+{
+ UINTN Index;
+ VOID *FruRedirCommand;
+
+ //
+ // Get the FRU Type string first.
+ //
+ for (Index = 0; Index < Global->MaxDescriptors; Index++) {
+ if (Global->Redir[Index].Valid) {
+ if (CompareGuid (&Global->Redir[Index].FruTypeGuid, FruTypeGuid)) {
+ //
+ // We found our target, Now check the format it supports.
+ //
+ FruRedirCommand = Global->Redir[Index].Command[Virtual].GetFruRedirInfo.Function;
+ return (*((EFI_GET_FRU_REDIR_INFO *)&FruRedirCommand))(
+ Global->Redir[Index].Command[Virtual].This,
+ FruInstance,
+ FruFormatGuid,
+ DataAccessGranularity,
+ FruInformationString
+ );
+ }
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Efi Get Fru Info.
+
+ @param This
+ @param FruTypeGuid
+ @param FruInstance
+ @param FruFormatGuid
+ @param DataAccessGranularity
+ @param FruInformationString
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EfiGetFruInfo (
+ IN EFI_SM_FRU_PROTOCOL *This,
+ IN EFI_GUID *FruTypeGuid,
+ IN UINTN FruInstance,
+ OUT EFI_GUID *FruFormatGuid,
+ OUT UINTN *DataAccessGranularity,
+ OUT CHAR16 **FruInformationString
+ )
+{
+ return EfiLibGetFruInfo (
+ FruTypeGuid,
+ FruInstance,
+ FruFormatGuid,
+ DataAccessGranularity,
+ FruInformationString,
+ mFruModuleGlobal,
+ EfiGoneVirtual ()
+ );
+}
+
+/**
+ Efi Lib Get Fru Data.
+
+ @param FruTypeGuid
+ @param FruInstance
+ @param FruDataOffset
+ @param FruDataSize
+ @param FruData
+ @param Global
+ @param Virtual
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EfiLibGetFruData (
+ IN EFI_GUID *FruTypeGuid,
+ IN UINTN FruInstance,
+ IN UINTN FruDataOffset,
+ IN UINTN FruDataSize,
+ IN UINT8 *FruData,
+ IN FRU_MODULE_GLOBAL *Global,
+ IN BOOLEAN Virtual
+ )
+{
+ UINTN Index;
+ VOID *FruRedirCommand;
+
+ //
+ // Get the FRU Type string first.
+ //
+ for (Index = 0; Index < Global->MaxDescriptors; Index++) {
+ if (Global->Redir[Index].Valid) {
+ if (CompareGuid (&Global->Redir[Index].FruTypeGuid, FruTypeGuid)) {
+ //
+ // We found our target, Now check the format it supports.
+ //
+ FruRedirCommand = Global->Redir[Index].Command[Virtual].GetFruRedirData.Function;
+ return (*((EFI_GET_FRU_REDIR_DATA *)&FruRedirCommand))(
+ Global->Redir[Index].Command[Virtual].This,
+ FruInstance,
+ FruDataOffset,
+ FruDataSize,
+ FruData
+ );
+ }
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Efi Get Fru Data.
+
+ @param This
+ @param FruTypeGuid
+ @param FruInstance
+ @param FruDataOffset
+ @param FruDataSize
+ @param FruData
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EfiGetFruData (
+ IN EFI_SM_FRU_PROTOCOL *This,
+ IN EFI_GUID *FruTypeGuid,
+ IN UINTN FruInstance,
+ IN UINTN FruDataOffset,
+ IN UINTN FruDataSize,
+ IN UINT8 *FruData
+ )
+{
+ return EfiLibGetFruData (
+ FruTypeGuid,
+ FruInstance,
+ FruDataOffset,
+ FruDataSize,
+ FruData,
+ mFruModuleGlobal,
+ EfiGoneVirtual ()
+ );
+}
+
+/**
+ Efi Lib Set Fru Data.
+
+ @param FruTypeGuid
+ @param FruInstance
+ @param FruDataOffset
+ @param FruDataSize
+ @param FruData
+ @param Global
+ @param Virtual
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EfiLibSetFruData (
+ IN EFI_GUID *FruTypeGuid,
+ IN UINTN FruInstance,
+ IN UINTN FruDataOffset,
+ IN UINTN FruDataSize,
+ IN UINT8 *FruData,
+ IN FRU_MODULE_GLOBAL *Global,
+ IN BOOLEAN Virtual
+ )
+{
+ UINTN Index;
+ VOID *FruRedirCommand;
+
+ //
+ // Get the FRU Type string first.
+ //
+ for (Index = 0; Index < Global->MaxDescriptors; Index++) {
+ if (Global->Redir[Index].Valid) {
+ if (CompareGuid (&Global->Redir[Index].FruTypeGuid, FruTypeGuid)) {
+ //
+ // We found our target, Now check the format it supports.
+ //
+ FruRedirCommand = Global->Redir[Index].Command[Virtual].SetFruRedirData.Function;
+ return (*((EFI_SET_FRU_REDIR_DATA *)&FruRedirCommand))(
+ Global->Redir[Index].Command[Virtual].This,
+ FruInstance,
+ FruDataOffset,
+ FruDataSize,
+ FruData
+ );
+ }
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Efi Set Fru Data.
+
+ @param This
+ @param FruTypeGuid
+ @param FruInstance
+ @param FruDataOffset
+ @param FruDataSize
+ @param FruData
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EfiSetFruData (
+ IN EFI_SM_FRU_PROTOCOL *This,
+ IN EFI_GUID *FruTypeGuid,
+ IN UINTN FruInstance,
+ IN UINTN FruDataOffset,
+ IN UINTN FruDataSize,
+ IN UINT8 *FruData
+ )
+{
+ return EfiLibSetFruData (
+ FruTypeGuid,
+ FruInstance,
+ FruDataOffset,
+ FruDataSize,
+ FruData,
+ mFruModuleGlobal,
+ EfiGoneVirtual ()
+ );
+}
+
+/**
+ Sm Fru Address Change Event.
+
+ @param Event
+ @param Context
+**/
+VOID
+SmFruAddressChangeEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ UINTN Index;
+ REDIR_FRU_MODULE_PROC *RedirProc;
+
+ //
+ // FRU REDIR Pointer Conversion
+ //
+ for (Index = 0; Index < mFruModuleGlobal->MaxDescriptors; Index++) {
+ if (mFruModuleGlobal->Redir[Index].Valid) {
+ RedirProc = (REDIR_FRU_MODULE_PROC *)&mFruModuleGlobal->Redir[Index].Command[EFI_FRU_VIRTUAL];
+ EfiConvertFunction (&RedirProc->GetFruRedirInfo);
+ EfiConvertFunction (&RedirProc->GetFruSlotInfo);
+ EfiConvertFunction (&RedirProc->GetFruRedirData);
+ EfiConvertFunction (&RedirProc->SetFruRedirData);
+ EfiConvertPointer (0x02, (VOID **)&RedirProc->This);
+ }
+ }
+}
+
+/**
+ Set Fru Redir Instances.
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+SetFruRedirInstances (
+ VOID
+ )
+{
+ UINTN NumHandles;
+ UINTN Index, Instance, EmptyIndex;
+ EFI_HANDLE *Buffer;
+ EFI_STATUS Status;
+ EFI_SM_FRU_REDIR_PROTOCOL *Redir;
+ REDIR_FRU_MODULE_PROC *RedirProc;
+
+ //
+ // Check for all IPMI Controllers
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiRedirFruProtocolGuid,
+ NULL,
+ &NumHandles,
+ &Buffer
+ );
+
+ if (EFI_ERROR (Status) || (NumHandles == 0)) {
+ return EFI_SUCCESS;
+ }
+
+ EmptyIndex = mFruModuleGlobal->MaxDescriptors;
+
+ for (Index = 0; ((Index < NumHandles) && (Index < mFruModuleGlobal->MaxDescriptors)); Index++) {
+ Status = gBS->HandleProtocol (
+ Buffer[Index],
+ &gEfiRedirFruProtocolGuid,
+ (VOID *)&Redir
+ );
+ if (EFI_ERROR (Status) || (Redir == NULL)) {
+ continue;
+ }
+
+ for (Instance = 0; Instance < mFruModuleGlobal->MaxDescriptors; Instance++) {
+ if (mFruModuleGlobal->Redir[Instance].Valid == FALSE) {
+ if (EmptyIndex >= mFruModuleGlobal->MaxDescriptors) {
+ EmptyIndex = Instance;
+ }
+ } else {
+ if (Redir == mFruModuleGlobal->Redir[Instance].Command->This) {
+ EmptyIndex = mFruModuleGlobal->MaxDescriptors;
+ continue;
+ }
+ }
+ }
+
+ if (EmptyIndex < mFruModuleGlobal->MaxDescriptors) {
+ Redir->GetFruSlotInfo (
+ Redir,
+ &mFruModuleGlobal->Redir[EmptyIndex].FruTypeGuid,
+ &mFruModuleGlobal->Redir[EmptyIndex].StartSlot,
+ &mFruModuleGlobal->Redir[EmptyIndex].EndSlot
+ );
+
+ mFruModuleGlobal->Redir[EmptyIndex].EndSlot += mFruModuleGlobal->Redir[EmptyIndex].StartSlot;
+ RedirProc = (REDIR_FRU_MODULE_PROC *)mFruModuleGlobal->Redir[EmptyIndex].Command;
+ mFruModuleGlobal->Redir[EmptyIndex].Valid = TRUE;
+
+ EfiSetFunctionEntry (&RedirProc->GetFruRedirInfo, *((VOID **)&Redir->GetFruRedirInfo));
+ EfiSetFunctionEntry (&RedirProc->GetFruSlotInfo, *((VOID **)&Redir->GetFruSlotInfo));
+ EfiSetFunctionEntry (&RedirProc->GetFruRedirData, *((VOID **)&Redir->GetFruRedirData));
+ EfiSetFunctionEntry (&RedirProc->SetFruRedirData, *((VOID **)&Redir->SetFruRedirData));
+ RedirProc->This = Redir;
+
+ CopyMem (&RedirProc[EFI_FRU_VIRTUAL], &RedirProc[EFI_FRU_PHYSICAL], sizeof (REDIR_FRU_MODULE_PROC));
+ }
+ }
+
+ if (Buffer != NULL) {
+ gBS->FreePool (Buffer);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This notification function is invoked when an instance of the
+ FRU REDIR protocol is produced.
+
+ @param Event - The event that occurred
+ @param Context - For EFI compatibility. Not used.
+
+**/
+VOID
+EFIAPI
+NotifyFruRedirEventCallback (
+ EFI_EVENT Event,
+ VOID *Context
+ )
+{
+ SetFruRedirInstances ();
+}
+
+/**
+ Initialize Sm Fru Layer.
+
+ @param ImageHandle
+ @param SystemTable
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeSmFruLayer (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_HANDLE NewHandle;
+ EFI_STATUS Status;
+ EFI_SM_FRU_PROTOCOL *FruProtocol;
+
+ Status = gBS->AllocatePool (
+ EfiRuntimeServicesData,
+ sizeof (FRU_MODULE_GLOBAL),
+ (VOID **)&mFruModuleGlobal
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ if (Status != EFI_SUCCESS) {
+ return Status;
+ }
+
+ ZeroMem (mFruModuleGlobal, sizeof (FRU_MODULE_GLOBAL));
+
+ SmFruServiceInitialize (ImageHandle, SystemTable);
+
+ mFruModuleGlobal->MaxDescriptors = MAX_REDIR_DESCRIPTOR;
+
+ //
+ // Check for all IPMI Controllers
+ //
+ SetFruRedirInstances ();
+
+ Status = gBS->AllocatePool (
+ EfiRuntimeServicesData,
+ sizeof (EFI_SM_FRU_PROTOCOL),
+ (VOID **)&FruProtocol
+ );
+ ASSERT_EFI_ERROR (Status);
+ if (Status != EFI_SUCCESS) {
+ return Status;
+ }
+
+ ZeroMem (FruProtocol, sizeof (EFI_SM_FRU_PROTOCOL));
+
+ FruProtocol->GetFruInfo = (EFI_GET_FRU_INFO)EfiGetFruInfo;
+ FruProtocol->GetFruData = (EFI_GET_FRU_DATA)EfiGetFruData;
+ FruProtocol->SetFruData = (EFI_SET_FRU_DATA)EfiSetFruData;
+
+ NewHandle = NULL;
+ Status = gBS->InstallProtocolInterface (
+ &NewHandle,
+ &gEfiGenericFruProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ FruProtocol
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ if (Status != EFI_SUCCESS) {
+ return Status;
+ }
+
+ //
+ // Register to be notified when the FRU REDIR protocol has been
+ // produced.
+ //
+
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ NotifyFruRedirEventCallback,
+ NULL,
+ &mEfiFruRedirProtocolEvent
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ if (Status != EFI_SUCCESS) {
+ return Status;
+ }
+
+ Status = gBS->RegisterProtocolNotify (
+ &gEfiRedirFruProtocolGuid,
+ mEfiFruRedirProtocolEvent,
+ &mEfiFruRedirProtocolNotifyReg
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFru/IpmiFru.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFru/IpmiFru.c
deleted file mode 100644
index 58e1fb4d7ef0..000000000000
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFru/IpmiFru.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/** @file
- IPMI FRU Driver.
-
-Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include <Library/BaseLib.h>
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Library/DebugLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/IpmiCommandLib.h>
-#include <IndustryStandard/Ipmi.h>
-
-EFI_STATUS
-EFIAPI
-InitializeFru (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
-/*++
-
-Routine Description:
-
- Initialize SM Redirection Fru Layer
-
-Arguments:
-
- ImageHandle - ImageHandle of the loaded driver
- SystemTable - Pointer to the System Table
-
-Returns:
-
- EFI_STATUS
-
---*/
-{
- EFI_STATUS Status;
- IPMI_GET_DEVICE_ID_RESPONSE ControllerInfo;
- IPMI_GET_FRU_INVENTORY_AREA_INFO_REQUEST GetFruInventoryAreaInfoRequest;
- IPMI_GET_FRU_INVENTORY_AREA_INFO_RESPONSE GetFruInventoryAreaInfoResponse;
-
- //
- // Get all the SDR Records from BMC and retrieve the Record ID from the structure for future use.
- //
- Status = IpmiGetDeviceId (&ControllerInfo);
- if (EFI_ERROR (Status)) {
- DEBUG((DEBUG_ERROR, "!!! IpmiFru IpmiGetDeviceId Status=%x\n", Status));
- return Status;
- }
-
- DEBUG((DEBUG_ERROR, "!!! IpmiFru FruInventorySupport %x\n", ControllerInfo.DeviceSupport.Bits.FruInventorySupport));
-
- if (ControllerInfo.DeviceSupport.Bits.FruInventorySupport) {
- GetFruInventoryAreaInfoRequest.DeviceId = 0;
- Status = IpmiGetFruInventoryAreaInfo (&GetFruInventoryAreaInfoRequest, &GetFruInventoryAreaInfoResponse);
- if (EFI_ERROR (Status)) {
- DEBUG((DEBUG_ERROR, "!!! IpmiFru IpmiGetFruInventoryAreaInfo Status=%x\n", Status));
- return Status;
- }
- DEBUG((DEBUG_ERROR, "!!! IpmiFru InventoryAreaSize=%x\n", GetFruInventoryAreaInfoResponse.InventoryAreaSize));
- }
-
- return EFI_SUCCESS;
-}
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRedirFru/FruSmbios.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRedirFru/FruSmbios.c
new file mode 100644
index 000000000000..bd4b35ba5793
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRedirFru/FruSmbios.c
@@ -0,0 +1,469 @@
+/** @file
+ This code reads the FRU and publishes the data to SMBIOS Type 1,2,3 tables.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef FRUMAXSTRING
+#define FRUMAXSTRING 128
+#endif
+
+#include "IpmiRedirFru.h"
+
+EFI_SM_FRU_REDIR_PROTOCOL *mFruRedirProtocol;
+EFI_SMBIOS_PROTOCOL *mSmbiosProtocol;
+
+extern EFI_GUID gEfiSmbiosProtocolGuid;
+
+/**
+ Fru Str Len.
+
+ @param Str.
+
+ @retval Length.
+
+**/
+UINT8
+FruStrLen (
+ IN CHAR8 *Str
+ )
+{
+ UINT8 Length;
+ CHAR8 *Ptr;
+
+ Length = 0;
+
+ if (Str != NULL) {
+ Ptr = Str;
+ while (*Ptr != '\0') {
+ Length++;
+ Ptr++;
+ }
+ }
+
+ return Length;
+}
+
+/**
+ This routine attempts to get a string out of the FRU at the designated offset in the
+ buffer pointed to by TempPtr. String type is ASCII.
+
+ @param Offset - Offset of string in buffer pointed to by TempPtr, this is updated to the next
+ offset.
+ @param TempPtr - Pointer to a buffer containing the FRU.
+ @param StrPtr - the pointer to a buffer for retrieve the string get from FRU.
+
+**/
+VOID
+GetStringFromFru (
+ IN OUT UINTN *Offset,
+ IN UINT8 *TempPtr,
+ IN OUT UINT8 *StrPtr
+ )
+{
+ UINTN Length;
+ UINT8 *SrcStrPtr;
+
+ if ((Offset == NULL) || (TempPtr == NULL)) {
+ return;
+ }
+
+ Length = 0x3F & TempPtr[*Offset];
+ SrcStrPtr = &TempPtr[*Offset + 1];
+
+ ASSERT (Length < FRUMAXSTRING);
+ if (Length >= FRUMAXSTRING) {
+ return;
+ }
+
+ if (StrPtr != NULL) {
+ if (Length > 0) {
+ CopyMem (StrPtr, SrcStrPtr, Length);
+ StrPtr[Length] = '\0';
+ } else {
+ StrPtr[0] = '\0';
+ }
+ }
+
+ *Offset = *Offset + Length + 1;
+ return;
+}
+
+/**
+ This routine gets the FRU info area specified by the offset and returns it in
+ an allocated buffer. It is the caller's responsibility to free the buffer.
+
+ @param This - SM Fru Redir protocol.
+ @param Offset - Info Area starting offset in multiples of 8 bytes.
+
+ @retval Buffer with FruInfo data or NULL if not found.
+
+**/
+UINT8 *
+GetFruInfoArea (
+ IN EFI_SM_FRU_REDIR_PROTOCOL *This,
+ IN UINTN Offset
+ )
+{
+ EFI_STATUS Status;
+ UINT8 *TempPtr;
+ UINTN Length;
+
+ TempPtr = NULL;
+
+ Offset = Offset * 8;
+ if (Offset > 0) {
+ //
+ // Get Info area length, which is in multiples of 8 bytes
+ //
+ Length = 0;
+ Status = EfiGetFruRedirData (This, 0, (Offset + 1), 1, (UINT8 *)&Length);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "EfiGetFruRedirData returned status %r\n", Status));
+ return NULL;
+ }
+
+ Length = Length * 8;
+
+ if (Length > 0) {
+ TempPtr = AllocateRuntimePool (Length);
+ ASSERT (TempPtr != NULL);
+ if (TempPtr == NULL) {
+ return NULL;
+ }
+
+ Status = EfiGetFruRedirData (This, 0, Offset, Length, TempPtr);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "EfiGetFruRedirData returned status %r\n", Status));
+ return NULL;
+ }
+ }
+ }
+
+ return TempPtr;
+}
+
+/**
+ Type1,2,3 only has one instance in SMBIOS tables for each.
+
+ @param TypeNo - The number of SMBIOS TYPE.
+
+ @retval Record the pointer of SMBIOS TYPE structure.
+
+**/
+UINT8 *
+GetStructureByTypeNo (
+ IN UINT16 TypeNo
+ )
+{
+ EFI_STATUS Status;
+ EFI_SMBIOS_HANDLE SmbiosHandle;
+ EFI_SMBIOS_TABLE_HEADER *Record;
+
+ SmbiosHandle = 0;
+
+ Status = mSmbiosProtocol->GetNext (
+ mSmbiosProtocol,
+ &SmbiosHandle,
+ (EFI_SMBIOS_TYPE *)&TypeNo,
+ &Record,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ return (UINT8 *)Record;
+}
+
+/**
+ Smbios Check Sum.
+
+ @param ChecksumSrc.
+ @param length.
+
+ @retval Record the pointer of SMBIOS TYPE structure.
+
+**/
+UINT8
+SmbiosCheckSum (
+ IN UINT8 *ChecksumSrc,
+ IN UINT8 length
+ )
+{
+ UINT8 Checksum;
+ UINT8 Num;
+
+ Checksum = 0;
+
+ for (Num = 0; Num < length; Num++) {
+ Checksum = Checksum + *ChecksumSrc++;
+ }
+
+ return (0 - Checksum);
+}
+
+/**
+ Dynamic Update Type.
+
+ @param TypeNo.
+ @param StringNo.
+ @param Data.
+
+**/
+VOID
+DynamicUpdateType (
+ IN UINT16 TypeNo,
+ IN UINTN StringNo,
+ IN UINT8 *Data
+ )
+{
+ EFI_STATUS Status;
+ EFI_SMBIOS_HANDLE SmbiosHandle;
+ EFI_SMBIOS_TABLE_HEADER *Record;
+
+ SmbiosHandle = 0;
+
+ Status = mSmbiosProtocol->GetNext (
+ mSmbiosProtocol,
+ &SmbiosHandle,
+ (EFI_SMBIOS_TYPE *)&TypeNo,
+ &Record,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ mSmbiosProtocol->UpdateString (
+ mSmbiosProtocol,
+ &SmbiosHandle,
+ &StringNo,
+ (CHAR8 *)Data
+ );
+}
+
+/**
+ This routine is notified by protocol gEfiEventReadyToBootGuid, and reads
+ strings out of the FRU and populates them into the appropriate Smbios tables.
+
+ @param Event.
+ @param Context.
+
+**/
+VOID
+EFIAPI
+GenerateFruSmbiosType123DataNotified (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+
+ UINT8 *FruHdrPtr;
+ UINT8 FruHdrChksum;
+ IPMI_FRU_COMMON_HEADER FruCommonHeader;
+ UINT8 Num;
+ UINTN Offset;
+ UINT8 *TempPtr;
+ UINT8 TempStr[FRUMAXSTRING];
+
+ UINT8 *TablePtr;
+
+ DEBUG ((DEBUG_INFO, "[FRU SMBIOS]: Generate Fru Smbios Type 1,2,3 Data Notified.\n"));
+ gBS->CloseEvent (Event);
+
+ SetMem ((UINT8 *)(&FruCommonHeader), sizeof (IPMI_FRU_COMMON_HEADER), 0);
+ SetMem (TempStr, FRUMAXSTRING, 0);
+
+ Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **)&mSmbiosProtocol);
+ ASSERT_EFI_ERROR (Status);
+ if (Status != EFI_SUCCESS) {
+ return;
+ }
+
+ Status = EfiGetFruRedirData (mFruRedirProtocol, 0, 0, sizeof (IPMI_FRU_COMMON_HEADER), (UINT8 *)&FruCommonHeader);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "EfiGetFruRedirData returned status %r\n", Status));
+ return;
+ } else {
+ //
+ // Do a validity check on the FRU header, since it may be all 0xFF(s) if
+ // there is no FRU programmed on the system.
+ //
+ FruHdrPtr = (UINT8 *)&FruCommonHeader;
+ for (Num = 0, FruHdrChksum = 0; Num < sizeof (FruCommonHeader); Num++) {
+ FruHdrChksum = (UINT8)(FruHdrChksum +*FruHdrPtr++);
+ }
+
+ if (FruHdrChksum != 0) {
+ DEBUG ((DEBUG_ERROR, "FRU header invalid.\n"));
+ //
+ // The FRU information is bad so nothing need to do.
+ //
+ return;
+ }
+ }
+
+ //
+ // SMBIOS Type 1, Product data
+ //
+ TempPtr = GetFruInfoArea (mFruRedirProtocol, FruCommonHeader.ProductInfoStartingOffset);
+ if (TempPtr != NULL) {
+ //
+ // Get the following fields in the specified order. DO NOT change this order unless the FRU file definition
+ // changes. Offset is initialized and then is incremented to the next field offset in GetStringFromFru.
+ //
+ // Product Manufacturer
+ // Product Name
+ // Product Model Number / System Part Number
+ // Product Version
+ // Product Serial Number
+ // Product Asset Tag
+ //
+ Offset = PRODUCT_MFG_OFFSET;
+ GetStringFromFru (&Offset, TempPtr, TempStr); // MiscSystemManufacturer.SystemManufacturer
+ if (FruStrLen ((CHAR8 *)(TempStr)) != 0) {
+ DynamicUpdateType (SMBIOSTYPE1, STRING1, TempStr);
+ }
+
+ GetStringFromFru (&Offset, TempPtr, TempStr); // MiscSystemManufacturer.SystemProductName
+ if (FruStrLen ((CHAR8 *)(TempStr)) != 0) {
+ DynamicUpdateType (SMBIOSTYPE1, STRING2, TempStr);
+ }
+
+ GetStringFromFru (&Offset, TempPtr, TempStr); // ***********************SystemPartNum
+
+ GetStringFromFru (&Offset, TempPtr, TempStr); // MiscSystemManufacturer.SystemVersion
+ if (FruStrLen ((CHAR8 *)(TempStr)) != 0) {
+ DynamicUpdateType (SMBIOSTYPE1, STRING3, TempStr);
+ }
+
+ GetStringFromFru (&Offset, TempPtr, TempStr); // MiscSystemManufacturer.SystemSerialNumber
+ if (FruStrLen ((CHAR8 *)(TempStr)) != 0) {
+ DynamicUpdateType (SMBIOSTYPE1, STRING4, TempStr);
+ }
+
+ GetStringFromFru (&Offset, TempPtr, TempStr); // ***********************AssetTag
+ if (FruStrLen ((CHAR8 *)(TempStr)) != 0) {
+ DynamicUpdateType (SMBIOSTYPE3, STRING4, TempStr); // NOTICE: this Asset Tag can be used by type 3 table
+ }
+
+ FreePool (TempPtr);
+ }
+
+ //
+ // SMBIOS Type 2, Base Board data
+ //
+ TempPtr = GetFruInfoArea (mFruRedirProtocol, FruCommonHeader.BoardAreaStartingOffset);
+ if (TempPtr != NULL) {
+ //
+ // Get the following fields in the specified order. DO NOT change this order unless the FRU file definition
+ // changes. Offset is initialized and then is incremented to the next field offset in GetStringFromFru.
+ //
+ // Board Manufacturer
+ // Board Product Name
+ // Board Serial Number
+ // Board Part Number
+ // FRU Version Number
+ //
+ Offset = BOARD_MFG_OFFSET;
+ GetStringFromFru (&Offset, TempPtr, TempStr); // MiscBaseBoardManufacturer.BaseBoardManufacturer
+ if (FruStrLen ((CHAR8 *)(TempStr)) != 0) {
+ DynamicUpdateType (SMBIOSTYPE2, STRING1, TempStr);
+ }
+
+ GetStringFromFru (&Offset, TempPtr, TempStr); // MiscBaseBoardManufacturer.BaseBoardProductName
+ if (FruStrLen ((CHAR8 *)(TempStr)) != 0) {
+ DynamicUpdateType (SMBIOSTYPE2, STRING2, TempStr);
+ }
+
+ GetStringFromFru (&Offset, TempPtr, TempStr); // MiscBaseBoardManufacturer.BaseBoardSerialNumber
+ if (FruStrLen ((CHAR8 *)(TempStr)) != 0) {
+ DynamicUpdateType (SMBIOSTYPE2, STRING4, TempStr);
+ }
+
+ GetStringFromFru (&Offset, TempPtr, TempStr); // MiscBaseBoardManufacturer.BoardPartNumber
+ if (FruStrLen ((CHAR8 *)(TempStr)) != 0) {
+ DynamicUpdateType (SMBIOSTYPE2, STRING3, TempStr);
+ }
+
+ GetStringFromFru (&Offset, TempPtr, TempStr); // **************************FRU Version Number
+ if (FruStrLen ((CHAR8 *)(TempStr)) != 0) {
+ DynamicUpdateType (SMBIOSTYPE2, STRING3, TempStr);
+ }
+
+ FreePool (TempPtr);
+ }
+
+ //
+ // SMBIOS Type 3, Chassis data
+ //
+ TempPtr = GetFruInfoArea (mFruRedirProtocol, FruCommonHeader.ChassisInfoStartingOffset);
+ if (TempPtr != NULL) {
+ // special process:
+ TablePtr = GetStructureByTypeNo (SMBIOSTYPE3);
+ ASSERT (TablePtr != NULL);
+ if (TablePtr == NULL) {
+ return;
+ }
+
+ ((SMBIOS_TABLE_TYPE3 *)TablePtr)->Type = TempPtr[CHASSIS_TYPE_OFFSET];
+ //
+ // Get the following fields in the specified order. DO NOT change this order unless the FRU file definition
+ // changes. Offset is initialized and then is incremented to the next field offset in GetStringFromFru.
+ //
+ Offset = CHASSIS_PART_NUMBER;
+ GetStringFromFru (&Offset, TempPtr, TempStr); // MiscChassisManufacturer.ChassisVersion
+ if (FruStrLen ((CHAR8 *)(TempStr)) != 0) {
+ DynamicUpdateType (SMBIOSTYPE3, STRING2, TempStr);
+ }
+
+ GetStringFromFru (&Offset, TempPtr, TempStr); // MiscChassisManufacturer.ChassisSerialNumber
+ if (FruStrLen ((CHAR8 *)(TempStr)) != 0) {
+ DynamicUpdateType (SMBIOSTYPE3, STRING3, TempStr);
+ }
+
+ GetStringFromFru (&Offset, TempPtr, TempStr); // MiscChassisManufacturer.ChassisManufacturer
+ if (FruStrLen ((CHAR8 *)(TempStr)) != 0) {
+ DynamicUpdateType (SMBIOSTYPE3, STRING1, TempStr);
+ }
+
+ FreePool (TempPtr);
+ }
+
+ return;
+}
+
+/**
+ This routine install a notify function listen to ReadyToBoot Event.
+
+ @param This - SM Fru Redir protocol.
+
+**/
+VOID
+GenerateFruSmbiosData (
+ IN EFI_SM_FRU_REDIR_PROTOCOL *This
+ )
+{
+ EFI_EVENT Event;
+ EFI_STATUS Status;
+
+ mFruRedirProtocol = This;
+
+ Status = EfiCreateEventReadyToBootEx (
+ TPL_CALLBACK,
+ GenerateFruSmbiosType123DataNotified,
+ NULL,
+ &Event
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "GenerateFruSmbiosData(): EfiCreateEventReadyToBootEx failed with return value: %r\n", Status));
+ }
+
+ return;
+}
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRedirFru/IpmiRedirFru.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRedirFru/IpmiRedirFru.c
new file mode 100644
index 000000000000..ac3c8ca50022
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRedirFru/IpmiRedirFru.c
@@ -0,0 +1,479 @@
+/** @file
+ Server Management IPMI Redir FRU Driver. This REDIR FRU driver attaches
+ to the Generic FRU driver.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "IpmiRedirFru.h"
+#include <Library/DebugLib.h>
+
+EFI_IPMI_FRU_GLOBAL *mIpmiFruGlobal;
+
+/**
+ Get Empty Fru Slot.
+
+ @retval UINT8
+
+**/
+UINT8
+GetEmptyFruSlot (
+ VOID
+ )
+{
+ UINT8 Num;
+
+ for (Num = 1; Num < mIpmiFruGlobal->MaxFruSlots; Num++) {
+ if (!mIpmiFruGlobal->FruDeviceInfo[Num].Valid) {
+ return Num;
+ }
+ }
+
+ return 0xFF;
+}
+
+/**
+ Get Fru Redir Info.
+
+ @param This
+ @param FruSlotNumber
+ @param FruFormatGuid
+ @param DataAccessGranularity
+ @param FruInformationString
+
+ @retval EFI_NO_MAPPING
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EFIAPI
+EfiGetFruRedirInfo (
+ IN EFI_SM_FRU_REDIR_PROTOCOL *This,
+ IN UINTN FruSlotNumber,
+ OUT EFI_GUID *FruFormatGuid,
+ OUT UINTN *DataAccessGranularity,
+ OUT CHAR16 **FruInformationString
+ )
+{
+ EFI_IPMI_FRU_GLOBAL *FruPrivate;
+
+ FruPrivate = INSTANCE_FROM_EFI_SM_IPMI_FRU_THIS (This);
+
+ if ((FruSlotNumber + 1) > FruPrivate->NumSlots) {
+ return EFI_NO_MAPPING;
+ }
+
+ CopyMem (FruFormatGuid, &gEfiIpmiFormatFruGuid, sizeof (EFI_GUID));
+
+ *DataAccessGranularity = 0x1;
+ *FruInformationString = NULL;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get Fru Slot Info.
+
+ @param This
+ @param FruTypeGuid
+ @param StartFruSlotNumber
+ @param NumSlots
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EFIAPI
+EfiGetFruSlotInfo (
+ IN EFI_SM_FRU_REDIR_PROTOCOL *This,
+ OUT EFI_GUID *FruTypeGuid,
+ OUT UINTN *StartFruSlotNumber,
+ OUT UINTN *NumSlots
+ )
+{
+ EFI_IPMI_FRU_GLOBAL *FruPrivate;
+
+ FruPrivate = NULL;
+
+ FruPrivate = INSTANCE_FROM_EFI_SM_IPMI_FRU_THIS (This);
+
+ CopyMem (FruTypeGuid, &gEfiSystemTypeFruGuid, sizeof (EFI_GUID));
+ *StartFruSlotNumber = 0;
+ *NumSlots = FruPrivate->NumSlots;
+ return EFI_SUCCESS;
+}
+
+/**
+ Get Fru Redir Data.
+
+ @param This
+ @param FruSlotNumber
+ @param FruDataOffset
+ @param FruDataSize
+ @param FruData
+
+ EFI_STATUS
+
+**/
+EFI_STATUS
+EFIAPI
+EfiGetFruRedirData (
+ IN EFI_SM_FRU_REDIR_PROTOCOL *This,
+ IN UINTN FruSlotNumber,
+ IN UINTN FruDataOffset,
+ IN UINTN FruDataSize,
+ IN UINT8 *FruData
+ )
+{
+ EFI_IPMI_FRU_GLOBAL *FruPrivate;
+ UINT32 ResponseDataSize;
+ UINT8 BackupCount;
+ UINT8 PointerOffset;
+ UINT8 DataToCopySize;
+ EFI_STATUS Status = EFI_SUCCESS;
+ IPMI_READ_FRU_DATA_REQUEST ReadFruDataRequest;
+ IPMI_READ_FRU_DATA_RESPONSE *ReadFruDataResponse;
+
+ FruPrivate = NULL;
+ PointerOffset = 0;
+
+ FruPrivate = INSTANCE_FROM_EFI_SM_IPMI_FRU_THIS (This);
+
+ if ((FruSlotNumber + 1) > FruPrivate->NumSlots) {
+ Status = EFI_NO_MAPPING;
+ return Status;
+ }
+
+ if (FruSlotNumber >= sizeof (FruPrivate->FruDeviceInfo) / sizeof (EFI_FRU_DEVICE_INFO)) {
+ Status = EFI_INVALID_PARAMETER;
+ return Status;
+ }
+
+ if (FruPrivate->FruDeviceInfo[FruSlotNumber].FruDevice.Bits.LogicalFruDevice) {
+ //
+ // Create the FRU Read Command for the logical FRU Device.
+ //
+ ReadFruDataRequest.DeviceId = FruPrivate->FruDeviceInfo[FruSlotNumber].FruDevice.Bits.FruDeviceId;
+ ReadFruDataRequest.InventoryOffset = (UINT16)FruDataOffset;
+ ReadFruDataRequest.CountToRead = (UINT8)FruDataSize;
+
+ ReadFruDataResponse = AllocateZeroPool (sizeof (ReadFruDataResponse) + IPMI_RDWR_FRU_FRAGMENT_SIZE);
+
+ if (ReadFruDataResponse == NULL) {
+ DEBUG ((DEBUG_ERROR, " Null Pointer returned by AllocateZeroPool to Read Fru data\n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Collect the data till it is completely retrieved.
+ //
+ while (ReadFruDataRequest.CountToRead != 0) {
+ //
+ // Backup the count, since we are going to perform fragmented reads
+ //
+ BackupCount = ReadFruDataRequest.CountToRead;
+ if (ReadFruDataRequest.CountToRead > IPMI_RDWR_FRU_FRAGMENT_SIZE) {
+ ReadFruDataRequest.CountToRead = IPMI_RDWR_FRU_FRAGMENT_SIZE;
+ }
+
+ ResponseDataSize = sizeof (ReadFruDataResponse) + ReadFruDataRequest.CountToRead;
+
+ Status = IpmiSubmitCommand (
+ IPMI_NETFN_STORAGE,
+ IPMI_STORAGE_READ_FRU_DATA,
+ (UINT8 *)&ReadFruDataRequest,
+ sizeof (ReadFruDataRequest),
+ (UINT8 *)ReadFruDataResponse,
+ &ResponseDataSize
+ );
+
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ DEBUG ((DEBUG_WARN, "%a: WARNING:: IpmiSubmitCommand returned EFI_BUFFER_TOO_SMALL \n", __func__));
+ }
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: IpmiSubmitCommand returned status %r\n", __func__, Status));
+ FreePool (ReadFruDataResponse);
+ return Status;
+ }
+
+ //
+ // If the read FRU command returns a count of 0, then no FRU data was found, so exit.
+ //
+ if (ReadFruDataResponse->CountReturned == 0x00) {
+ Status = EFI_NOT_FOUND;
+ DEBUG ((DEBUG_ERROR, "%a: IpmiSubmitCommand Response data size is 0x0\n", __func__));
+ FreePool (ReadFruDataResponse);
+ return Status;
+ }
+
+ ReadFruDataRequest.CountToRead = BackupCount;
+
+ //
+ // In case of partial retrieval; Data[0] contains the retrieved data size;
+ //
+ if (ReadFruDataRequest.CountToRead >= ReadFruDataResponse->CountReturned) {
+ DataToCopySize = ReadFruDataResponse->CountReturned;
+ ReadFruDataRequest.CountToRead = (UINT8)(ReadFruDataRequest.CountToRead - ReadFruDataResponse->CountReturned); // Remaining Count
+ } else {
+ DEBUG ((
+ DEBUG_WARN,
+ "%a: WARNING Command.Count (%d) is less than response data size (%d) received\n",
+ __func__,
+ ReadFruDataRequest.CountToRead,
+ ReadFruDataResponse->CountReturned
+ ));
+ DataToCopySize = ReadFruDataRequest.CountToRead;
+ ReadFruDataRequest.CountToRead = 0; // Remaining Count
+ }
+
+ ReadFruDataRequest.InventoryOffset = (UINT16)(ReadFruDataRequest.InventoryOffset + DataToCopySize); // Next Offset to retrieve
+
+ if (PointerOffset + DataToCopySize > FruDataSize) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "Insufficient storage supplied to %a, need more than % bytes\n",
+ __func__,
+ PointerOffset + DataToCopySize
+ ));
+ Status = EFI_BUFFER_TOO_SMALL;
+ FreePool (ReadFruDataResponse);
+ return Status;
+ }
+
+ ASSERT (PointerOffset < FruDataSize);
+ ASSERT (PointerOffset + DataToCopySize <= FruDataSize);
+
+ CopyMem (&FruData[PointerOffset], &ReadFruDataResponse->Data[0], DataToCopySize); // Copy the partial data
+ PointerOffset = (UINT8)(PointerOffset + DataToCopySize); // Next offset to the iput pointer.
+ }
+
+ FreePool (ReadFruDataResponse);
+ } else {
+ Status = EFI_UNSUPPORTED;
+ return Status;
+ }
+
+ return Status;
+}
+
+/**
+ Set Fru Redir Data.
+
+ @retval This
+ @retval FruSlotNumber
+ @retval FruDataOffset
+ @retval FruDataSize
+ @retval FruData
+
+ @retval EFI_STATUS
+
+**/
+EFI_STATUS
+EFIAPI
+EfiSetFruRedirData (
+ IN EFI_SM_FRU_REDIR_PROTOCOL *This,
+ IN UINTN FruSlotNumber,
+ IN UINTN FruDataOffset,
+ IN UINTN FruDataSize,
+ IN UINT8 *FruData
+ )
+{
+ EFI_IPMI_FRU_GLOBAL *FruPrivate;
+ UINT8 Count;
+ UINT8 BackupCount;
+ UINT32 ResponseDataSize;
+ UINT8 PointerOffset;
+ UINT8 DataToCopySize;
+ EFI_STATUS Status;
+ IPMI_WRITE_FRU_DATA_REQUEST *WriteFruDataRequest;
+ IPMI_WRITE_FRU_DATA_RESPONSE WriteFruDataResponse;
+
+ FruPrivate = NULL;
+ PointerOffset = 0;
+
+ FruPrivate = INSTANCE_FROM_EFI_SM_IPMI_FRU_THIS (This);
+
+ if ((FruSlotNumber + 1) > FruPrivate->NumSlots) {
+ return EFI_NO_MAPPING;
+ }
+
+ if (FruSlotNumber >= sizeof (FruPrivate->FruDeviceInfo) / sizeof (EFI_FRU_DEVICE_INFO)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (FruPrivate->FruDeviceInfo[FruSlotNumber].FruDevice.Bits.LogicalFruDevice) {
+ WriteFruDataRequest = AllocateZeroPool (sizeof (IPMI_WRITE_FRU_DATA_REQUEST) + IPMI_RDWR_FRU_FRAGMENT_SIZE);
+
+ if (WriteFruDataRequest == NULL) {
+ DEBUG ((DEBUG_ERROR, " Null Pointer returned by AllocateZeroPool to Write Fru data\n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Create the FRU Write Command for the logical FRU Device.
+ //
+ WriteFruDataRequest->DeviceId = FruPrivate->FruDeviceInfo[FruSlotNumber].FruDevice.Bits.FruDeviceId;
+ WriteFruDataRequest->InventoryOffset = (UINT16)FruDataOffset;
+ Count = (UINT8)FruDataSize;
+ PointerOffset = 0;
+
+ //
+ // Collect the data till it is completely retrieved.
+ //
+ while (Count != 0) {
+ //
+ // Backup the count, since we are going to perform fragmented reads
+ //
+ BackupCount = Count;
+ if (Count > IPMI_RDWR_FRU_FRAGMENT_SIZE) {
+ Count = IPMI_RDWR_FRU_FRAGMENT_SIZE;
+ }
+
+ CopyMem (&WriteFruDataRequest->Data[0], &FruData[PointerOffset], Count);
+
+ ResponseDataSize = sizeof (WriteFruDataResponse);
+ Status = IpmiSubmitCommand (
+ IPMI_NETFN_STORAGE,
+ IPMI_STORAGE_WRITE_FRU_DATA,
+ (UINT8 *)WriteFruDataRequest,
+ (sizeof (WriteFruDataRequest) + Count),
+ (UINT8 *)&WriteFruDataResponse,
+ &ResponseDataSize
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: IpmiSubmitCommand returned status %r\n", __func__, Status));
+ FreePool (WriteFruDataRequest);
+ return Status;
+ }
+
+ Count = BackupCount;
+
+ if (Count >= WriteFruDataResponse.CountWritten) {
+ DataToCopySize = Count - WriteFruDataResponse.CountWritten;
+ Count = (UINT8)(Count - WriteFruDataResponse.CountWritten); // Remaining Count
+ } else {
+ DEBUG ((
+ DEBUG_WARN,
+ "%a: WARNING Count (%d) is less than response data size (%d) received\n",
+ __func__,
+ Count,
+ WriteFruDataResponse.CountWritten
+ ));
+ DataToCopySize = Count;
+ Count = 0; // Remaining Count
+ }
+
+ //
+ // In case of partial retrieval; Data[0] contains the retrieved data size;
+ //
+ WriteFruDataRequest->InventoryOffset = (UINT16)(WriteFruDataRequest->InventoryOffset + DataToCopySize); // Next Offset to set
+ PointerOffset = (UINT8)(PointerOffset + DataToCopySize); // Next offset to the iput pointer.
+ }
+
+ FreePool (WriteFruDataRequest);
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Initialize SM Redirection Fru Layer.
+
+ @param ImageHandle - ImageHandle of the loaded driver
+ @param SystemTable - Pointer to the System Table
+
+ @retval EFI_STATUS
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeSmRedirFruLayer (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_HANDLE NewHandle;
+ EFI_STATUS Status;
+ IPMI_GET_DEVICE_ID_RESPONSE GetDeviceIdResponse;
+ UINT32 ResponseDataSize;
+
+ gST = SystemTable;
+ gBS = gST->BootServices;
+
+ //
+ // Initialize Global memory
+ //
+ mIpmiFruGlobal = AllocateRuntimePool (sizeof (EFI_IPMI_FRU_GLOBAL));
+ ASSERT (mIpmiFruGlobal != NULL);
+ if (mIpmiFruGlobal == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ mIpmiFruGlobal->NumSlots = 0;
+ mIpmiFruGlobal->IpmiRedirFruProtocol.GetFruRedirInfo = (EFI_GET_FRU_REDIR_INFO)EfiGetFruRedirInfo;
+ mIpmiFruGlobal->IpmiRedirFruProtocol.GetFruSlotInfo = (EFI_GET_FRU_SLOT_INFO)EfiGetFruSlotInfo;
+ mIpmiFruGlobal->IpmiRedirFruProtocol.GetFruRedirData = (EFI_GET_FRU_REDIR_DATA)EfiGetFruRedirData;
+ mIpmiFruGlobal->IpmiRedirFruProtocol.SetFruRedirData = (EFI_SET_FRU_REDIR_DATA)EfiSetFruRedirData;
+ mIpmiFruGlobal->Signature = EFI_SM_FRU_REDIR_SIGNATURE;
+ mIpmiFruGlobal->MaxFruSlots = MAX_FRU_SLOT;
+ //
+ // Get all the SDR Records from BMC and retrieve the Record ID from the structure for future use.
+ //
+ ResponseDataSize = sizeof (GetDeviceIdResponse);
+ Status = IpmiSubmitCommand (
+ IPMI_NETFN_APP,
+ IPMI_APP_GET_DEVICE_ID,
+ (UINT8 *)NULL,
+ 0,
+ (UINT8 *)&GetDeviceIdResponse,
+ &ResponseDataSize
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "IpmiSubmitCommand Ipmi App Get DeviceId Failed %r\n", Status));
+ return Status;
+ }
+
+ if (GetDeviceIdResponse.DeviceSupport.Bits.FruInventorySupport) {
+ //
+ // Initialize all FRU slots
+ // Add a mandatory FRU Inventory device attached to the controller.
+ //
+ for (mIpmiFruGlobal->NumSlots = 0; mIpmiFruGlobal->NumSlots < mIpmiFruGlobal->MaxFruSlots; mIpmiFruGlobal->NumSlots++) {
+ mIpmiFruGlobal->FruDeviceInfo[mIpmiFruGlobal->NumSlots].Valid = TRUE;
+ ZeroMem (&mIpmiFruGlobal->FruDeviceInfo[mIpmiFruGlobal->NumSlots].FruDevice, sizeof (IPMI_FRU_DATA_INFO));
+ mIpmiFruGlobal->FruDeviceInfo[mIpmiFruGlobal->NumSlots].FruDevice.Bits.LogicalFruDevice = 1;
+ mIpmiFruGlobal->FruDeviceInfo[mIpmiFruGlobal->NumSlots].FruDevice.Bits.FruDeviceId = mIpmiFruGlobal->NumSlots;
+ }
+ }
+
+ //
+ // Install callback for ReadyToBoot event to generate FRU SMBIOS Data
+ //
+
+ GenerateFruSmbiosData (&mIpmiFruGlobal->IpmiRedirFruProtocol);
+
+ //
+ // Install the FRU Ipmi Redir protocol.
+ //
+ NewHandle = NULL;
+ Status = gBS->InstallProtocolInterface (
+ &NewHandle,
+ &gEfiRedirFruProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mIpmiFruGlobal->IpmiRedirFruProtocol
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ if (Status != EFI_SUCCESS) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
--
2.39.2.windows.1
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#110329): https://edk2.groups.io/g/devel/message/110329
Mute This Topic: https://groups.io/mt/102279908/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [edk2-devel] [PATCH edk2-platforms v2 0/4] IpmiFeaturePkg: Add server management features
2023-10-29 20:27 [edk2-devel] [PATCH edk2-platforms v2 0/4] IpmiFeaturePkg: Add server management features Zhen Gong
` (3 preceding siblings ...)
2023-10-29 20:27 ` [edk2-devel] [PATCH edk2-platforms v2 4/4] IpmiFeaturePkg: Add FRU drivers Zhen Gong
@ 2023-11-02 15:47 ` Nate DeSimone
2023-11-03 19:06 ` Nate DeSimone
5 siblings, 0 replies; 7+ messages in thread
From: Nate DeSimone @ 2023-11-02 15:47 UTC (permalink / raw)
To: devel@edk2.groups.io, Gong, Zhen
Good work Zhen!
Reviewed-by: Nate DeSimone <nathaniel.l.desimone@intel.com>
-----Original Message-----
From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Zhen Gong
Sent: Sunday, October 29, 2023 1:28 PM
To: devel@edk2.groups.io
Cc: Gong, Zhen <zhen.gong@intel.com>
Subject: [edk2-devel] [PATCH edk2-platforms v2 0/4] IpmiFeaturePkg: Add server management features
This patch set adds serveral IPMI features to support server management:
BmcAcpiState: A DXE driver to notify BMC of S0 power state.
BmcAcpiSwChild: An SMM driver to notify BMC of ACPI power state changes and add SEL records.
BmcElog: PEI, DXE, and SMM drivers to support BMC event log functions.
GenericElog: DXE and SMM drivers to support generic event log functions.
GenericFru: A runtime driver to support generic FRU functions.
IpmiRedirFru: A DXE driver to support BMC FRU functions and generate data based on SMBIOS data.
ServerManagementLib: A library to provide essential functions for server management drivers.
Notes:
V2:
- Rebased to resolve merge conflict from upstream changes
Zhen Gong (4):
IpmiFeaturePkg: Add Elog drivers
IpmiFeaturePkg: Add ServerManagementLib
IpmiFeaturePkg: Add ACPI power state drivers
IpmiFeaturePkg: Add FRU drivers
.../IpmiFeaturePkg/IpmiFeaturePkg.dec | 10 +
.../IpmiFeaturePkg/Include/IpmiFeature.dsc | 13 +-
.../IpmiFeaturePkg/Include/PostMemory.fdf | 10 +-
.../IpmiFeaturePkg/Include/PreMemory.fdf | 1 +
.../BmcAcpiState/BmcAcpiState.inf | 40 +
.../BmcAcpiSwChild/BmcAcpiSwChild.inf | 39 +
.../BmcElog/{BmcElog.inf => DxeBmcElog.inf} | 19 +-
.../IpmiFeaturePkg/BmcElog/PeiBmcElog.inf | 43 ++
.../IpmiFeaturePkg/BmcElog/SmmBmcElog.inf | 44 ++
.../GenericElog/Dxe/GenericElog.inf | 38 +
.../GenericElog/Smm/GenericElog.inf | 38 +
.../IpmiFeaturePkg/GenericFru/GenericFru.inf | 42 ++
.../IpmiFeaturePkg/IpmiFru/IpmiFru.inf | 36 -
.../IpmiRedirFru/IpmiRedirFru.inf | 51 ++
.../ServerManagementLib.inf | 35 +
.../ServerManagementLibNull.inf | 38 +
.../BmcAcpiState/BmcAcpiState.h | 26 +
.../BmcAcpiSwChild/BmcAcpiSwChild.h | 82 +++
.../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 ++++++
.../GenericFru/GenericFruDriver.h | 178 +++++
.../Include/Library/ServerMgmtRtLib.h | 147 ++++
.../IpmiFeaturePkg/Include/Ppi/GenericElog.h | 84 +++
.../Include/Protocol/BmcAcpiSwChildPolicy.h | 31 +
.../Include/Protocol/GenericElog.h | 99 +++
.../Include/Protocol/GenericFru.h | 103 +++
.../Include/Protocol/RedirFru.h | 81 ++
.../IpmiRedirFru/IpmiRedirFru.h | 149 ++++
.../BmcAcpiState/BmcAcpiState.c | 93 +++
.../BmcAcpiSwChild/BmcAcpiSwChild.c | 189 +++++
.../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 ++++++++++++++
.../IpmiFeaturePkg/GenericFru/GenericFru.c | 68 ++
.../GenericFru/GenericFruDriver.c | 513 +++++++++++++
.../IpmiFeaturePkg/IpmiFru/IpmiFru.c | 67 --
.../IpmiFeaturePkg/IpmiRedirFru/FruSmbios.c | 469 ++++++++++++
.../IpmiRedirFru/IpmiRedirFru.c | 479 ++++++++++++
.../ServerManagementLib/ServerManagementLib.c | 696 ++++++++++++++++++
.../ServerManagementLibNull.c | 144 ++++
48 files changed, 7237 insertions(+), 348 deletions(-) create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiState/BmcAcpiState.inf
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiSwChild/BmcAcpiSwChild.inf
rename Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/{BmcElog.inf => DxeBmcElog.inf} (60%) 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/GenericFru/GenericFru.inf
delete mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFru/IpmiFru.inf
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRedirFru/IpmiRedirFru.inf
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManagementLib/ServerManagementLib.inf
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManagementLibNull/ServerManagementLibNull.inf
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiState/BmcAcpiState.h
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiSwChild/BmcAcpiSwChild.h
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/GenericFru/GenericFruDriver.h
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Library/ServerMgmtRtLib.h
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Ppi/GenericElog.h
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/BmcAcpiSwChildPolicy.h
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/GenericElog.h
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/GenericFru.h
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/RedirFru.h
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRedirFru/IpmiRedirFru.h
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiState/BmcAcpiState.c
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiSwChild/BmcAcpiSwChild.c
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
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericFru/GenericFru.c
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericFru/GenericFruDriver.c
delete mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFru/IpmiFru.c
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRedirFru/FruSmbios.c
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRedirFru/IpmiRedirFru.c
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManagementLib/ServerManagementLib.c
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManagementLibNull/ServerManagementLibNull.c
--
2.39.2.windows.1
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#110559): https://edk2.groups.io/g/devel/message/110559
Mute This Topic: https://groups.io/mt/102279904/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [edk2-devel] [PATCH edk2-platforms v2 0/4] IpmiFeaturePkg: Add server management features
2023-10-29 20:27 [edk2-devel] [PATCH edk2-platforms v2 0/4] IpmiFeaturePkg: Add server management features Zhen Gong
` (4 preceding siblings ...)
2023-11-02 15:47 ` [edk2-devel] [PATCH edk2-platforms v2 0/4] IpmiFeaturePkg: Add server management features Nate DeSimone
@ 2023-11-03 19:06 ` Nate DeSimone
5 siblings, 0 replies; 7+ messages in thread
From: Nate DeSimone @ 2023-11-03 19:06 UTC (permalink / raw)
To: devel@edk2.groups.io, Gong, Zhen
The series has been pushed as 0cedeab~..6d60278
-----Original Message-----
From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Zhen Gong
Sent: Sunday, October 29, 2023 1:28 PM
To: devel@edk2.groups.io
Cc: Gong, Zhen <zhen.gong@intel.com>
Subject: [edk2-devel] [PATCH edk2-platforms v2 0/4] IpmiFeaturePkg: Add server management features
This patch set adds serveral IPMI features to support server management:
BmcAcpiState: A DXE driver to notify BMC of S0 power state.
BmcAcpiSwChild: An SMM driver to notify BMC of ACPI power state changes and add SEL records.
BmcElog: PEI, DXE, and SMM drivers to support BMC event log functions.
GenericElog: DXE and SMM drivers to support generic event log functions.
GenericFru: A runtime driver to support generic FRU functions.
IpmiRedirFru: A DXE driver to support BMC FRU functions and generate data based on SMBIOS data.
ServerManagementLib: A library to provide essential functions for server management drivers.
Notes:
V2:
- Rebased to resolve merge conflict from upstream changes
Zhen Gong (4):
IpmiFeaturePkg: Add Elog drivers
IpmiFeaturePkg: Add ServerManagementLib
IpmiFeaturePkg: Add ACPI power state drivers
IpmiFeaturePkg: Add FRU drivers
.../IpmiFeaturePkg/IpmiFeaturePkg.dec | 10 +
.../IpmiFeaturePkg/Include/IpmiFeature.dsc | 13 +-
.../IpmiFeaturePkg/Include/PostMemory.fdf | 10 +-
.../IpmiFeaturePkg/Include/PreMemory.fdf | 1 +
.../BmcAcpiState/BmcAcpiState.inf | 40 +
.../BmcAcpiSwChild/BmcAcpiSwChild.inf | 39 +
.../BmcElog/{BmcElog.inf => DxeBmcElog.inf} | 19 +-
.../IpmiFeaturePkg/BmcElog/PeiBmcElog.inf | 43 ++
.../IpmiFeaturePkg/BmcElog/SmmBmcElog.inf | 44 ++
.../GenericElog/Dxe/GenericElog.inf | 38 +
.../GenericElog/Smm/GenericElog.inf | 38 +
.../IpmiFeaturePkg/GenericFru/GenericFru.inf | 42 ++
.../IpmiFeaturePkg/IpmiFru/IpmiFru.inf | 36 -
.../IpmiRedirFru/IpmiRedirFru.inf | 51 ++
.../ServerManagementLib.inf | 35 +
.../ServerManagementLibNull.inf | 38 +
.../BmcAcpiState/BmcAcpiState.h | 26 +
.../BmcAcpiSwChild/BmcAcpiSwChild.h | 82 +++
.../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 ++++++
.../GenericFru/GenericFruDriver.h | 178 +++++
.../Include/Library/ServerMgmtRtLib.h | 147 ++++
.../IpmiFeaturePkg/Include/Ppi/GenericElog.h | 84 +++
.../Include/Protocol/BmcAcpiSwChildPolicy.h | 31 +
.../Include/Protocol/GenericElog.h | 99 +++
.../Include/Protocol/GenericFru.h | 103 +++
.../Include/Protocol/RedirFru.h | 81 ++
.../IpmiRedirFru/IpmiRedirFru.h | 149 ++++
.../BmcAcpiState/BmcAcpiState.c | 93 +++
.../BmcAcpiSwChild/BmcAcpiSwChild.c | 189 +++++
.../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 ++++++++++++++
.../IpmiFeaturePkg/GenericFru/GenericFru.c | 68 ++
.../GenericFru/GenericFruDriver.c | 513 +++++++++++++
.../IpmiFeaturePkg/IpmiFru/IpmiFru.c | 67 --
.../IpmiFeaturePkg/IpmiRedirFru/FruSmbios.c | 469 ++++++++++++
.../IpmiRedirFru/IpmiRedirFru.c | 479 ++++++++++++
.../ServerManagementLib/ServerManagementLib.c | 696 ++++++++++++++++++
.../ServerManagementLibNull.c | 144 ++++
48 files changed, 7237 insertions(+), 348 deletions(-) create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiState/BmcAcpiState.inf
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiSwChild/BmcAcpiSwChild.inf
rename Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/{BmcElog.inf => DxeBmcElog.inf} (60%) 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/GenericFru/GenericFru.inf
delete mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFru/IpmiFru.inf
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRedirFru/IpmiRedirFru.inf
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManagementLib/ServerManagementLib.inf
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManagementLibNull/ServerManagementLibNull.inf
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiState/BmcAcpiState.h
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiSwChild/BmcAcpiSwChild.h
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/GenericFru/GenericFruDriver.h
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Library/ServerMgmtRtLib.h
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Ppi/GenericElog.h
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/BmcAcpiSwChildPolicy.h
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/GenericElog.h
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/GenericFru.h
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/RedirFru.h
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRedirFru/IpmiRedirFru.h
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiState/BmcAcpiState.c
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiSwChild/BmcAcpiSwChild.c
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
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericFru/GenericFru.c
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericFru/GenericFruDriver.c
delete mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFru/IpmiFru.c
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRedirFru/FruSmbios.c
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRedirFru/IpmiRedirFru.c
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManagementLib/ServerManagementLib.c
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManagementLibNull/ServerManagementLibNull.c
--
2.39.2.windows.1
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#110666): https://edk2.groups.io/g/devel/message/110666
Mute This Topic: https://groups.io/mt/102279904/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-
^ permalink raw reply [flat|nested] 7+ messages in thread