* [edk2-devel] [PATCH edk2-platforms 1/4] IpmiFeaturePkg: Add Elog drivers
2023-10-27 20:11 [edk2-devel] [PATCH edk2-platforms 0/4] IpmiFeaturePkg: Add server management features Zhen Gong
@ 2023-10-27 20:11 ` Zhen Gong
2023-10-27 20:11 ` [edk2-devel] [PATCH edk2-platforms 2/4] IpmiFeaturePkg: Add ServerManagementLib Zhen Gong
` (3 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Zhen Gong @ 2023-10-27 20:11 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} | 25 +-
.../IpmiFeaturePkg/BmcElog/PeiBmcElog.inf | 43 ++
.../IpmiFeaturePkg/BmcElog/SmmBmcElog.inf | 44 ++
.../GenericElog/Dxe/GenericElog.inf | 38 ++
.../GenericElog/Smm/GenericElog.inf | 38 ++
.../BmcElog/Common/BmcElogCommon.h | 144 +++++
.../IpmiFeaturePkg/BmcElog/Dxe/BmcElog.h | 42 ++
.../IpmiFeaturePkg/BmcElog/Pei/BmcElog.h | 44 ++
.../IpmiFeaturePkg/BmcElog/Smm/BmcElog.h | 43 ++
.../GenericElog/Dxe/GenericElog.h | 194 ++++++
.../GenericElog/Smm/GenericElog.h | 216 +++++++
.../IpmiFeaturePkg/Include/Ppi/GenericElog.h | 84 +++
.../Include/Protocol/GenericElog.h | 99 +++
.../IpmiFeaturePkg/BmcElog/BmcElog.c | 236 -------
.../BmcElog/Common/BmcElogCommon.c | 465 ++++++++++++++
.../IpmiFeaturePkg/BmcElog/Dxe/BmcElog.c | 287 +++++++++
.../IpmiFeaturePkg/BmcElog/Pei/BmcElog.c | 297 +++++++++
.../IpmiFeaturePkg/BmcElog/Smm/BmcElog.c | 288 +++++++++
.../GenericElog/Dxe/GenericElog.c | 576 ++++++++++++++++++
.../GenericElog/Smm/GenericElog.c | 558 +++++++++++++++++
24 files changed, 3535 insertions(+), 244 deletions(-)
rename Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/{BmcElog.inf => DxeBmcElog.inf} (56%)
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/PeiBmcElog.inf
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/SmmBmcElog.inf
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Dxe/GenericElog.inf
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Smm/GenericElog.inf
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Common/BmcElogCommon.h
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Dxe/BmcElog.h
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Pei/BmcElog.h
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Smm/BmcElog.h
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Dxe/GenericElog.h
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Smm/GenericElog.h
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Ppi/GenericElog.h
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/GenericElog.h
delete mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/BmcElog.c
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Common/BmcElogCommon.c
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Dxe/BmcElog.c
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Pei/BmcElog.c
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Smm/BmcElog.c
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Dxe/GenericElog.c
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Smm/GenericElog.c
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFeaturePkg.dec b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFeaturePkg.dec
index 5df71300cbd1..22bc4e69be8a 100644
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFeaturePkg.dec
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFeaturePkg.dec
@@ -67,6 +67,7 @@ [Guids]
[Ppis]
gPeiIpmiTransportPpiGuid = {0x7bf5fecc, 0xc5b5, 0x4b25, {0x81, 0x1b, 0xb4, 0xb5, 0xb, 0x28, 0x79, 0xf7}}
gPeiIpmiTransport2PpiGuid = {0x8122CEBD, 0xF4FD, 0x4EA8, { 0x97, 0x6C, 0xF0, 0x30, 0xAD, 0xDC, 0x4C, 0xB4 }}
+ gPeiRedirElogPpiGuid = { 0x7a7c1591, 0xfc67, 0x4f69, { 0xa3, 0x78, 0xfc, 0x3d, 0x4a, 0xd7, 0x92, 0xf7 } }
[Protocols]
gIpmiTransportProtocolGuid = {0x6bb945e8, 0x3743, 0x433e, {0xb9, 0x0e, 0x29, 0xb3, 0x0d, 0x5d, 0xc6, 0x30}}
@@ -74,6 +75,10 @@ [Protocols]
gEfiVideoPrintProtocolGuid = {0x3dbf3e06, 0x9d0c, 0x40d3, {0xb2, 0x17, 0x45, 0x5f, 0x33, 0x9e, 0x29, 0x09}}
gIpmiTransport2ProtocolGuid = { 0x4A1D0E66, 0x5271, 0x4E22, { 0x83, 0xFE, 0x90, 0x92, 0x1B, 0x74, 0x82, 0x13 }}
gSmmIpmiTransport2ProtocolGuid = { 0x1DBD1503, 0x0A60, 0x4230, { 0xAA, 0xA3, 0x80, 0x16, 0xD8, 0xC3, 0xDE, 0x2F }}
+ gEfiGenericElogProtocolGuid = { 0x59d02fcd, 0x9233, 0x4d34, { 0xbc, 0xfe, 0x87, 0xca, 0x81, 0xd3, 0xdd, 0xa7 } }
+ gSmmGenericElogProtocolGuid = { 0x664ef1f6, 0x19bf, 0x4498, { 0xab, 0x6a, 0xfc, 0x05, 0x72, 0xfb, 0x98, 0x51 } }
+ gEfiRedirElogProtocolGuid = { 0x16d11030, 0x71ba, 0x4e5e, { 0xa9, 0xf9, 0xb4, 0x75, 0xa5, 0x49, 0x4, 0x8a } }
+ gSmmRedirElogProtocolGuid = { 0x79ac2d9c, 0x9216, 0x43c5, { 0xa0, 0x74, 0x0b, 0x45, 0xc7, 0x64, 0x22, 0xc1 } }
[PcdsFeatureFlag]
gIpmiFeaturePkgTokenSpaceGuid.PcdIpmiFeatureEnable|FALSE|BOOLEAN|0xA0000001
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiFeature.dsc b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiFeature.dsc
index 0401974b82e2..fa98e5672d83 100644
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiFeature.dsc
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiFeature.dsc
@@ -57,6 +57,7 @@ [LibraryClasses.common.DXE_RUNTIME_DRIVER, LibraryClasses.common.DXE_DRIVER]
IpmbInterfaceLib|IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/IpmbInterfaceLib/DxeIpmbInterfaceLib.inf
[LibraryClasses.common.DXE_SMM_DRIVER]
+ IpmiBaseLib|IpmiFeaturePkg/Library/SmmIpmiBaseLib/SmmIpmiBaseLib.inf
SsifInterfaceLib|IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInterfaceLib/SmmSsifInterfaceLib.inf
IpmbInterfaceLib|IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/IpmbInterfaceLib/SmmIpmbInterfaceLib.inf
@@ -96,6 +97,7 @@ [Components.IA32]
IpmiFeaturePkg/GenericIpmi/Pei/PeiGenericIpmi.inf
IpmiFeaturePkg/Frb/FrbPei.inf
IpmiFeaturePkg/IpmiInit/PeiIpmiInit.inf
+ IpmiFeaturePkg/BmcElog/PeiBmcElog.inf
#
# Feature DXE Components
@@ -119,7 +121,10 @@ [Components.X64]
IpmiFeaturePkg/GenericIpmi/Dxe/GenericIpmi.inf
IpmiFeaturePkg/Library/SmmIpmiBaseLib/SmmIpmiBaseLib.inf
IpmiFeaturePkg/BmcAcpi/BmcAcpi.inf
- IpmiFeaturePkg/BmcElog/BmcElog.inf
+ IpmiFeaturePkg/BmcElog/DxeBmcElog.inf
+ IpmiFeaturePkg/BmcElog/SmmBmcElog.inf
+ IpmiFeaturePkg/GenericElog/Dxe/GenericElog.inf
+ IpmiFeaturePkg/GenericElog/Smm/GenericElog.inf
IpmiFeaturePkg/Frb/FrbDxe.inf
IpmiFeaturePkg/IpmiFru/IpmiFru.inf
IpmiFeaturePkg/IpmiInit/DxeIpmiInit.inf
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/PostMemory.fdf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/PostMemory.fdf
index e0f3bbe158d9..f29810bc0b34 100644
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/PostMemory.fdf
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/PostMemory.fdf
@@ -10,8 +10,11 @@
INF IpmiFeaturePkg/GenericIpmi/Dxe/GenericIpmi.inf
INF IpmiFeaturePkg/IpmiInit/DxeIpmiInit.inf
INF RuleOverride = DRIVER_ACPITABLE IpmiFeaturePkg/BmcAcpi/BmcAcpi.inf
-INF IpmiFeaturePkg/BmcElog/BmcElog.inf
+INF IpmiFeaturePkg/BmcElog/DxeBmcElog.inf
+INF IpmiFeaturePkg/BmcElog/SmmBmcElog.inf
INF IpmiFeaturePkg/Frb/FrbDxe.inf
INF IpmiFeaturePkg/IpmiFru/IpmiFru.inf
+INF IpmiFeaturePkg/GenericElog/Dxe/GenericElog.inf
+INF IpmiFeaturePkg/GenericElog/Smm/GenericElog.inf
INF IpmiFeaturePkg/OsWdt/OsWdt.inf
INF IpmiFeaturePkg/SolStatus/SolStatus.inf
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/PreMemory.fdf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/PreMemory.fdf
index d214988bd141..ca20546e9aa8 100644
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/PreMemory.fdf
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/PreMemory.fdf
@@ -10,3 +10,4 @@
INF IpmiFeaturePkg/GenericIpmi/Pei/PeiGenericIpmi.inf
INF IpmiFeaturePkg/IpmiInit/PeiIpmiInit.inf
INF IpmiFeaturePkg/Frb/FrbPei.inf
+INF IpmiFeaturePkg/BmcElog/PeiBmcElog.inf
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/BmcElog.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/DxeBmcElog.inf
similarity index 56%
rename from Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/BmcElog.inf
rename to Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/DxeBmcElog.inf
index 388dd2740c69..dce3bc42ce05 100644
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/BmcElog.inf
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/DxeBmcElog.inf
@@ -1,12 +1,12 @@
### @file
-# Component description file for BMC ELOG.
#
-# Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
###
+
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = BmcElog
@@ -17,17 +17,30 @@ [Defines]
ENTRY_POINT = InitializeBmcElogLayer
[Sources]
- BmcElog.c
+ Dxe/BmcElog.c
+ Dxe/BmcElog.h
+ Common/BmcElogCommon.h
+ Common/BmcElogCommon.c
[Packages]
- MdePkg/MdePkg.dec
IpmiFeaturePkg/IpmiFeaturePkg.dec
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
[LibraryClasses]
UefiDriverEntryPoint
DebugLib
UefiBootServicesTableLib
- IpmiCommandLib
+ ReportStatusCodeLib
+ MemoryAllocationLib
+ IpmiBaseLib
+
+[Protocols]
+ gEfiRedirElogProtocolGuid # PROTOCOL ALWAYS_PRODUCED
[Depex]
- TRUE
+ gEfiLoadedImageProtocolGuid AND
+ gIpmiTransportProtocolGuid
+
+
+
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/PeiBmcElog.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/PeiBmcElog.inf
new file mode 100644
index 000000000000..8274033e42e6
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/PeiBmcElog.inf
@@ -0,0 +1,43 @@
+### @file
+#
+# Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+###
+
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BmcElog
+ FILE_GUID = FD2A000E-09EA-4899-B40E-32BE30A58EBD
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ ENTRY_POINT = InitializeBmcElogLayer
+
+[Sources]
+ Pei/BmcElog.c
+ Pei/BmcElog.h
+ Common/BmcElogCommon.h
+ Common/BmcElogCommon.c
+
+[Packages]
+ IpmiFeaturePkg/IpmiFeaturePkg.dec
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ DebugLib
+ ReportStatusCodeLib
+ MemoryAllocationLib
+ PeiServicesLib
+ PeimEntryPoint
+ IpmiBaseLib
+
+[Ppis]
+ gPeiRedirElogPpiGuid # PPI ALWAYS_PRODUCED
+ gPeiIpmiTransportPpiGuid
+
+[Depex]
+ TRUE
+
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/SmmBmcElog.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/SmmBmcElog.inf
new file mode 100644
index 000000000000..d6880f8baa1b
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/SmmBmcElog.inf
@@ -0,0 +1,44 @@
+### @file
+#
+# Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+###
+
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SmBmcElog
+ FILE_GUID = BE29A700-9D5A-4bb9-86B1-D1DB7A05D594
+ MODULE_TYPE = DXE_SMM_DRIVER
+ PI_SPECIFICATION_VERSION = 0x0001000A
+ VERSION_STRING = 1.0
+ ENTRY_POINT = InitializeSmBmcElogLayer
+
+[Sources]
+ Smm/BmcElog.c
+ Smm/BmcElog.h
+ Common/BmcElogCommon.h
+ Common/BmcElogCommon.c
+
+[Packages]
+ IpmiFeaturePkg/IpmiFeaturePkg.dec
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ DebugLib
+ UefiBootServicesTableLib
+ ReportStatusCodeLib
+ SmmServicesTableLib
+ IpmiBaseLib
+
+[Protocols]
+ gSmmRedirElogProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+
+[Depex]
+ gEfiLoadedImageProtocolGuid AND
+ gSmmIpmiTransportProtocolGuid
+
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Dxe/GenericElog.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Dxe/GenericElog.inf
new file mode 100644
index 000000000000..1073d3687d38
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Dxe/GenericElog.inf
@@ -0,0 +1,38 @@
+### @file
+#
+# Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+###
+
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = GenericElog
+ FILE_GUID = FD2D7E66-C5A7-47de-BDCC-4F1B5DC6ADA8
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = InitializeElogLayer
+
+[Sources]
+ GenericElog.c
+ GenericElog.h
+
+[Packages]
+ IpmiFeaturePkg/IpmiFeaturePkg.dec
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ BaseMemoryLib
+ DebugLib
+ UefiBootServicesTableLib
+ MemoryAllocationLib
+
+[Protocols]
+ gEfiGenericElogProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+ gEfiRedirElogProtocolGuid #PROTOCOL ALWAYS_COMSUMED
+
+[Depex]
+ gEfiRedirElogProtocolGuid
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Smm/GenericElog.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Smm/GenericElog.inf
new file mode 100644
index 000000000000..00f4154cdd39
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Smm/GenericElog.inf
@@ -0,0 +1,38 @@
+### @file
+#
+# Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+###
+
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SmGenericElog
+ FILE_GUID = 870B000E-D3AD-4fb2-B846-AB0ADE8799CB
+ MODULE_TYPE = DXE_SMM_DRIVER
+ PI_SPECIFICATION_VERSION = 0x0001000A
+ VERSION_STRING = 1.0
+ ENTRY_POINT = InitializeSmElogLayer
+
+[Sources]
+ GenericElog.c
+ GenericElog.h
+
+[Packages]
+ IpmiFeaturePkg/IpmiFeaturePkg.dec
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ DebugLib
+ SmmServicesTableLib
+
+[Protocols]
+ gSmmGenericElogProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+ gSmmRedirElogProtocolGuid #PROTOCOL ALWAYS_COMSUMED
+
+[Depex]
+ gSmmRedirElogProtocolGuid AND
+ gSmmIpmiTransportProtocolGuid
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Common/BmcElogCommon.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Common/BmcElogCommon.h
new file mode 100644
index 000000000000..23c535d1dd6c
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Common/BmcElogCommon.h
@@ -0,0 +1,144 @@
+/** @file
+ BMC Event Log functions.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _BMCELOG_COMMON_H_
+#define _BMCELOG_COMMON_H_
+
+//
+// Statements that include other files
+//
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/ReportStatusCodeLib.h>
+#include "ServerManagement.h"
+#include <SmStatusCodes.h>
+#include <IndustryStandard/Ipmi.h>
+#include <Library/IpmiBaseLib.h>
+
+#define MAX_TEMP_DATA 160
+#define CLEAR_SEL_COUNTER 0x200
+#define SEL_RECORD_SIZE 0x10 // 16 bytes : Entire SEL Record size
+#define SEL_RECORD_ID_SIZE 0x2 // 2 bytes : SEL Record-ID size
+
+#ifndef _EFI_SM_ELOG_TYPE
+#define _EFI_SM_ELOG_TYPE
+typedef enum {
+ EfiElogSmSMBIOS,
+ EfiElogSmIPMI,
+ EfiElogSmMachineCritical,
+ EfiElogSmASF,
+ EfiElogSmOEM,
+ EfiSmElogMax
+} EFI_SM_ELOG_TYPE;
+#endif
+
+/**
+ WaitTillClearSel.
+
+ @param ResvId Reserved ID
+
+ @retval EFI_SUCCESS
+ @retval EFI_NO_RESPONSE
+
+**/
+EFI_STATUS
+WaitTillClearSel (
+ UINT8 *ResvId
+ );
+
+/**
+ Set Bmc Elog Data.
+
+
+ @param ElogData Buffer for log storage
+ @param DataType Event Log type
+ @param AlertEvent If it is an alert event
+ @param Size Log data size
+ @param RecordId Indicate which recorder it is
+
+ @retval EFI_STATUS
+
+**/
+EFI_STATUS
+SetBmcElogRecord (
+ IN UINT8 *ElogData,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN BOOLEAN AlertEvent,
+ IN UINTN Size,
+ OUT UINT64 *RecordId
+ );
+
+/**
+ Get Bmc Elog Data.
+
+ @param ElogData Buffer for log data store
+ @param DataType Event log type
+ @param Size Size of log data
+ @param RecordId indicate which recorder it is
+
+ @retval EFI_STATUS
+
+**/
+EFI_STATUS
+GetBmcElogRecord (
+ IN UINT8 *ElogData,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN OUT UINTN *Size,
+ IN OUT UINT64 *RecordId
+ );
+
+/**
+ Erase Bmc Elog Data.
+
+ @param This Protocol pointer
+ @param DataType Event log type
+ @param RecordId return which recorder it is
+
+ @retval EFI_STATUS
+
+**/
+EFI_STATUS
+EraseBmcElogRecord (
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN OUT UINT64 *RecordId
+ );
+
+/**
+ Activate Bmc Elog.
+
+ @param DataType indicate event log type
+ @param EnableElog Enable/Disable event log
+ @param ElogStatus return log status
+
+ @retval EFI_STATUS
+
+**/
+EFI_STATUS
+ActivateBmcElog (
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN BOOLEAN *EnableElog,
+ OUT BOOLEAN *ElogStatus
+ );
+
+/**
+ This function verifies the BMC SEL is full and When it is reports the error to the Error Manager.
+
+ @retval EFI_SUCCESS
+ @retval EFI_DEVICE_ERROR
+
+**/
+EFI_STATUS
+EFIAPI
+CheckIfSelIsFull (
+ VOID
+ );
+
+#endif
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Dxe/BmcElog.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Dxe/BmcElog.h
new file mode 100644
index 000000000000..d70261c7c537
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Dxe/BmcElog.h
@@ -0,0 +1,42 @@
+/** @file
+ BMC Event Log functions.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _EFI_BMCELOG_H_
+#define _EFI_BMCELOG_H_
+
+//
+// Statements that include other files
+//
+
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Protocol/IpmiTransportProtocol.h>
+#include <Protocol/GenericElog.h>
+#include "BmcElogCommon.h"
+
+//
+// BMC Elog instance data
+//
+typedef struct {
+ UINTN Signature;
+ SM_COM_ADDRESS ControllerAddress;
+ SM_COM_ADDRESS TargetAddress;
+ UINT16 Instance;
+ EFI_SM_ELOG_TYPE DataType;
+ UINT8 TempData[MAX_TEMP_DATA + 1];
+ EFI_SM_ELOG_REDIR_PROTOCOL BmcElog;
+} EFI_BMC_ELOG_INSTANCE_DATA;
+
+//
+// BMC Elog Instance signature
+//
+#define EFI_ELOG_REDIR_SIGNATURE SIGNATURE_32 ('e', 'e', 'l', 'g')
+
+#define INSTANCE_FROM_EFI_ELOG_REDIR_THIS(a) CR (a, EFI_BMC_ELOG_INSTANCE_DATA, BmcElog, EFI_ELOG_REDIR_SIGNATURE)
+
+#endif
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Pei/BmcElog.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Pei/BmcElog.h
new file mode 100644
index 000000000000..c1b53f3e468d
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Pei/BmcElog.h
@@ -0,0 +1,44 @@
+/** @file
+ BMC Event Log functions.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _EFI_PEIBMCELOG_H_
+#define _EFI_PEIBMCELOG_H_
+
+//
+// Statements that include other files
+//
+
+#include <Ppi/GenericElog.h>
+#include <Ppi/IpmiTransportPpi.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PeiServicesTablePointerLib.h>
+#include <IndustryStandard/Ipmi.h>
+#include "BmcElogCommon.h"
+
+//
+// BMC Elog instance data
+//
+typedef struct {
+ UINTN Signature;
+ SM_COM_ADDRESS ControllerAddress;
+ SM_COM_ADDRESS TargetAddress;
+ UINT16 Instance;
+ EFI_SM_ELOG_TYPE DataType;
+ UINT8 TempData[MAX_TEMP_DATA + 1];
+ EFI_SM_ELOG_REDIR_PPI BmcElogPpi;
+ EFI_PEI_PPI_DESCRIPTOR BmcElog;
+} EFI_PEI_BMC_ELOG_INSTANCE_DATA;
+
+//
+// BMC Elog Instance signature
+//
+#define EFI_PEI_ELOG_REDIR_SIGNATURE SIGNATURE_32 ('e', 'p', 'l', 'g')
+
+#define INSTANCE_FROM_EFI_PEI_ELOG_REDIR_THIS(a) CR (a, EFI_PEI_BMC_ELOG_INSTANCE_DATA, BmcElogPpi, EFI_PEI_ELOG_REDIR_SIGNATURE)
+
+#endif
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Smm/BmcElog.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Smm/BmcElog.h
new file mode 100644
index 000000000000..218af380a229
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Smm/BmcElog.h
@@ -0,0 +1,43 @@
+/** @file
+ BMC Event Log functions.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _SMM_BMCELOG_H_
+#define _SMM_BMCELOG_H_
+
+//
+// Statements that include other files
+//
+
+#include <Library/SmmServicesTableLib.h>
+#include <Library/SmmLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/IpmiTransportProtocol.h>
+#include <Protocol/GenericElog.h>
+#include "BmcElogCommon.h"
+
+//
+// BMC Elog instance data
+//
+typedef struct {
+ UINTN Signature;
+ SM_COM_ADDRESS ControllerAddress;
+ SM_COM_ADDRESS TargetAddress;
+ UINT16 Instance;
+ EFI_SM_ELOG_TYPE DataType;
+ UINT8 TempData[MAX_TEMP_DATA + 1];
+ EFI_SM_ELOG_REDIR_PROTOCOL BmcElog;
+} EFI_BMC_ELOG_INSTANCE_DATA;
+
+//
+// BMC Elog Instance signature
+//
+#define SM_ELOG_REDIR_SIGNATURE SIGNATURE_32 ('e', 'l', 'o', 'f')
+
+#define INSTANCE_FROM_EFI_SM_ELOG_REDIR_THIS(a) CR (a, EFI_BMC_ELOG_INSTANCE_DATA, BmcElog, SM_ELOG_REDIR_SIGNATURE)
+
+#endif //_SMM_BMCELOG_H_
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Dxe/GenericElog.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Dxe/GenericElog.h
new file mode 100644
index 000000000000..460185455648
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Dxe/GenericElog.h
@@ -0,0 +1,194 @@
+/** @file
+ Generic Event Log functions.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _EFI_GENELOG_H_
+#define _EFI_GENELOG_H_
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include "ServerManagement.h"
+
+#include <Protocol/IpmiTransportProtocol.h>
+#include <Protocol/GenericElog.h>
+
+#define EFI_ELOG_PHYSICAL 0
+#define EFI_ELOG_VIRTUAL 1
+#define MAX_REDIR_DESCRIPTOR 10
+
+///
+/// A pointer to a function in IPF points to a plabel.
+///
+typedef struct {
+ UINT64 EntryPoint;
+ UINT64 GP;
+} EFI_PLABEL;
+
+typedef struct {
+ EFI_PLABEL *Function;
+ EFI_PLABEL Plabel;
+} FUNCTION_PTR;
+
+typedef struct {
+ EFI_SM_ELOG_REDIR_PROTOCOL *This;
+ FUNCTION_PTR SetEventLogData;
+ FUNCTION_PTR GetEventLogData;
+ FUNCTION_PTR EraseEventLogData;
+ FUNCTION_PTR ActivateEventLog;
+} REDIR_MODULE_PROC;
+
+typedef struct {
+ BOOLEAN Valid;
+ REDIR_MODULE_PROC Command[2];
+} REDIR_MODULES;
+
+typedef struct {
+ REDIR_MODULES Redir[MAX_REDIR_DESCRIPTOR];
+ UINTN MaxDescriptors;
+} ELOG_MODULE_GLOBAL;
+
+/**
+ Efi Convert Function.
+
+ @param Function
+
+ @retval EFI_SUCCESS
+**/
+EFI_STATUS
+EfiConvertFunction (
+ IN FUNCTION_PTR *Function
+ );
+
+/**
+ Efi Set Function Entry.
+
+ @param FunctionPointer
+ @param Function
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EfiSetFunctionEntry (
+ IN FUNCTION_PTR *FunctionPointer,
+ IN VOID *Function
+ );
+
+/**
+ Elog Service Initialize.
+
+ @param ImageHandle
+ @param SystemTable
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+ElogServiceInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Efi Lib Set Elog Data.
+
+ @param ElogData
+ @param DataType
+ @param AlertEvent
+ @param DataSize
+ @param RecordId
+ @param Global
+ @param Virtual
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EfiLibSetElogData (
+ IN UINT8 *ElogData,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN BOOLEAN AlertEvent,
+ IN UINTN DataSize,
+ OUT UINT64 *RecordId,
+ ELOG_MODULE_GLOBAL *Global,
+ BOOLEAN Virtual
+ );
+
+/**
+ Efi Lib Get Elog Data.
+
+ @param ElogData
+ @param DataType
+ @param DataSize
+ @param RecordId
+ @param Global
+ @param Virtual
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EfiLibGetElogData (
+ IN UINT8 *ElogData,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN OUT UINTN *DataSize,
+ IN OUT UINT64 *RecordId,
+ ELOG_MODULE_GLOBAL *Global,
+ BOOLEAN Virtual
+ );
+
+/**
+ Efi Lib Erase Elog Data.
+
+ @param DataType
+ @param RecordId
+ @param Global
+ @param Virtual
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EfiLibEraseElogData (
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN OUT UINT64 *RecordId,
+ ELOG_MODULE_GLOBAL *Global,
+ BOOLEAN Virtual
+ );
+
+/**
+ This API enables/Disables Event Log.
+
+ @param DataType - Type of Elog Data that is being Activated.
+ @param EnableElog - Enables (TRUE) / Disables (FALSE) Event Log. If NULL just returns the
+ Current ElogStatus.
+ @param ElogStatus - Current (New) Status of Event Log. Enabled (TRUE), Disabled (FALSE).
+ @param Global - The module global variable pointer.
+ @param Virtual - If this function is called in virtual mode or physical mode
+
+ @retval EFI_SUCCESS - Event-Log was recorded successfully
+ @retval EFI_UNSUPPORTED - The Data Type is unsupported
+
+**/
+
+EFI_STATUS
+EfiLibActivateElog (
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN BOOLEAN *EnableElog,
+ OUT BOOLEAN *ElogStatus,
+ ELOG_MODULE_GLOBAL *Global,
+ BOOLEAN Virtual
+ );
+
+#endif //_EFI_GENELOG_H_
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Smm/GenericElog.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Smm/GenericElog.h
new file mode 100644
index 000000000000..ad6530616309
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Smm/GenericElog.h
@@ -0,0 +1,216 @@
+/** @file
+ Generic Event Log functions.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _SMM_GENELOG_H_
+#define _SMM_GENELOG_H_
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/SmmLib.h>
+#include <Library/DebugLib.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include "ServerManagement.h"
+#include <Protocol/IpmiTransportProtocol.h>
+#include <Protocol/GenericElog.h>
+
+#define EFI_ELOG_PHYSICAL 0
+#define EFI_ELOG_VIRTUAL 1
+#define MAX_REDIR_DESCRIPTOR 10
+
+///
+/// A pointer to a function in IPF points to a plabel.
+///
+typedef struct {
+ UINT64 EntryPoint;
+ UINT64 GP;
+} EFI_PLABEL;
+
+typedef struct {
+ EFI_PLABEL *Function;
+ EFI_PLABEL Plabel;
+} FUNCTION_PTR;
+
+typedef struct {
+ EFI_SM_ELOG_REDIR_PROTOCOL *This;
+ FUNCTION_PTR SetEventLogData;
+ FUNCTION_PTR GetEventLogData;
+ FUNCTION_PTR EraseEventLogData;
+ FUNCTION_PTR ActivateEventLog;
+} REDIR_MODULE_PROC;
+
+typedef struct {
+ BOOLEAN Valid;
+ REDIR_MODULE_PROC Command[2];
+} REDIR_MODULES;
+
+typedef struct {
+ REDIR_MODULES Redir[MAX_REDIR_DESCRIPTOR];
+ UINTN MaxDescriptors;
+} ELOG_MODULE_GLOBAL;
+
+/**
+ Efi Convert Function.
+
+ @param Function
+
+ @retval EFI_SUCCESS
+**/
+EFI_STATUS
+EfiConvertFunction (
+ IN FUNCTION_PTR *Function
+ );
+
+/**
+ Set the function entry.
+
+ @param FunctionPointer - The destination function pointer
+ @param Function - The source function pointer
+
+ @retval EFI_SUCCESS - Set the function pointer successfully
+
+**/
+EFI_STATUS
+EfiSetFunctionEntry (
+ IN FUNCTION_PTR *FunctionPointer,
+ IN VOID *Function
+ );
+
+/**
+ Entry point of SM Elog service Driver
+
+ @param ImageHandle - The Image handle of this driver.
+ @param SystemTable - The pointer of EFI_SYSTEM_TABLE.
+
+ @retval EFI_SUCCESS - The driver successfully initialized
+
+**/
+EFI_STATUS
+SmElogServiceInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Sm Redir Address Change Event.
+
+ @param Event
+ @param Context
+
+**/
+VOID
+SmRedirAddressChangeEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+/**
+ Sends the Event-Log data to the destination.
+
+ @param ElogData - Pointer to the Event-Log data that needs to be recorded.
+ @param DataType - Type of Elog Data that is being recorded.
+ @param AlertEvent - This is an indication that the input data type is an Alert.
+ @param DataSize - Data Size.
+ @param RecordId - Record ID sent by the target.
+ @param Global - The module global variable pointer.
+ @param Virtual - If this function is called in virtual mode or physical mode
+
+ @retval EFI_SUCCESS - Event-Log was recorded successfully.
+ @retval EFI_OUT_OF_RESOURCES - Not enough resources to record data.
+ @retval EFI_UNSUPPORTED - The Data Type is unsupported.
+
+**/
+EFI_STATUS
+EfiLibSetElogData (
+ IN UINT8 *ElogData,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN BOOLEAN AlertEvent,
+ IN UINTN DataSize,
+ OUT UINT64 *RecordId,
+ ELOG_MODULE_GLOBAL *Global,
+ BOOLEAN Virtual
+ );
+
+/**
+ Gets the Event-Log data from the destination.
+
+ @param ElogData - Pointer to the Event-Log data buffer that will contain the data to be retrieved.
+ @param DataType - Type of Elog Data that is being recorded.
+ @param DataSize - Data Size.
+ @param RecordId - This is the RecordId of the next record. If ElogData is NULL,
+ this gives the RecordId of the first record available in the database with the correct DataSize.
+ A value of 0 on return indicates the last record if the EFI_STATUS indicates a success
+ @param Global - The module global variable pointer.
+ @param Virtual - If this function is called in virtual mode or physical mode
+
+ @retval EFI_SUCCESS - Event-Log was retrieved successfully.
+ @retval EFI_NOT_FOUND - Event-Log target not found.
+ @retval EFI_BUFFER_TOO_SMALL - Target buffer is too small to retrieve the data.
+ @retval EFI_UNSUPPORTED - The Data Type is unsupported
+
+**/
+EFI_STATUS
+EfiLibGetElogData (
+ IN UINT8 *ElogData,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN OUT UINTN *DataSize,
+ IN OUT UINT64 *RecordId,
+ ELOG_MODULE_GLOBAL *Global,
+ BOOLEAN Virtual
+ );
+
+/**
+ Erases the Event-Log data from the destination.
+
+ @param DataType - Type of Elog Data that is being Erased.
+ @param RecordId - This is the RecordId of the data to be erased. If RecordId is NULL, all
+ the records on the database are erased if permitted by the target.
+ Contains the deleted RecordId on return
+ @param Global - The module global variable pointer.
+ @param Virtual - If this function is called in virtual mode or physical mode
+
+ @retval EFI_SUCCESS - Event-Log was erased successfully
+ @retval EFI_UNSUPPORTED - The Data Type is unsupported
+ @retval EFI_NOT_FOUND - Event-Log target not found
+
+**/
+EFI_STATUS
+EfiLibEraseElogData (
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN OUT UINT64 *RecordId,
+ ELOG_MODULE_GLOBAL *Global,
+ BOOLEAN Virtual
+ );
+
+/**
+ This API enables/Disables Event Log.
+
+ @param DataType - Type of Elog Data that is being Activated.
+ @param EnableElog - Enables (TRUE) / Disables (FALSE) Event Log. If NULL just returns the
+ Current ElogStatus.
+ @param ElogStatus - Current (New) Status of Event Log. Enabled (TRUE), Disabled (FALSE).
+ @param Global - The module global variable pointer.
+ @param Virtual - If this function is called in virtual mode or physical mode
+
+ @retval EFI_SUCCESS - Event-Log was recorded successfully
+ @retval EFI_UNSUPPORTED - The Data Type is unsupported
+
+**/
+EFI_STATUS
+EfiLibActivateElog (
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN BOOLEAN *EnableElog,
+ OUT BOOLEAN *ElogStatus,
+ ELOG_MODULE_GLOBAL *Global,
+ BOOLEAN Virtual
+ );
+
+#endif //_SMM_GENELOG_H_
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Ppi/GenericElog.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Ppi/GenericElog.h
new file mode 100644
index 000000000000..4b3b3ee2af33
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Ppi/GenericElog.h
@@ -0,0 +1,84 @@
+/** @file
+ This code abstracts the generic ELOG Protocol.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _GENERIC_ELOG_H_
+#define _GENERIC_ELOG_H_
+
+#include "ServerManagement.h"
+
+typedef struct _EFI_SM_ELOG_PPI EFI_SM_ELOG_REDIR_PPI;
+
+//
+// Common Defines
+//
+#ifndef _EFI_SM_ELOG_TYPE
+#define _EFI_SM_ELOG_TYPE
+typedef enum {
+ EfiElogSmSMBIOS,
+ EfiElogSmIPMI,
+ EfiElogSmMachineCritical,
+ EfiElogSmASF,
+ EfiElogSmOEM,
+ EfiSmElogMax
+} EFI_SM_ELOG_TYPE;
+#endif
+
+//
+// Generic ELOG Function Prototypes
+//
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SET_ELOG_DATA)(
+ IN EFI_SM_ELOG_REDIR_PPI *This,
+ IN UINT8 *ElogData,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN BOOLEAN AlertEvent,
+ IN UINTN DataSize,
+ OUT UINT64 *RecordId
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_GET_ELOG_DATA)(
+ IN EFI_SM_ELOG_REDIR_PPI *This,
+ IN OUT UINT8 *ElogData,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN OUT UINTN *DataSize,
+ IN OUT UINT64 *RecordId
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_ERASE_ELOG_DATA)(
+ IN EFI_SM_ELOG_REDIR_PPI *This,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN OUT UINT64 *RecordId
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_ACTIVATE_ELOG)(
+ IN EFI_SM_ELOG_REDIR_PPI *This,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN BOOLEAN *EnableElog,
+ OUT BOOLEAN *ElogStatus
+ );
+
+//
+// IPMI TRANSPORT PPI
+//
+struct _EFI_SM_ELOG_PPI {
+ EFI_SET_ELOG_DATA SetEventLogData;
+ EFI_GET_ELOG_DATA GetEventLogData;
+ EFI_ERASE_ELOG_DATA EraseEventlogData;
+ EFI_ACTIVATE_ELOG ActivateEventLog;
+};
+
+extern EFI_GUID gPeiRedirElogPpiGuid;
+
+#endif
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/GenericElog.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/GenericElog.h
new file mode 100644
index 000000000000..19726ff58f0f
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/GenericElog.h
@@ -0,0 +1,99 @@
+/** @file
+ This code abstracts the generic ELOG Protocol.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _GENERIC_ELOG_H_
+#define _GENERIC_ELOG_H_
+
+#include "ServerManagement.h"
+
+#define EFI_SM_ELOG_PROTOCOL_GUID \
+ { \
+ 0x59d02fcd, 0x9233, 0x4d34, 0xbc, 0xfe, 0x87, 0xca, 0x81, 0xd3, 0xdd, 0xa7 \
+ }
+
+#define EFI_SM_ELOG_REDIR_PROTOCOL_GUID \
+ { \
+ 0x16d11030, 0x71ba, 0x4e5e, 0xa9, 0xf9, 0xb4, 0x75, 0xa5, 0x49, 0x4, 0x8a \
+ }
+
+//
+// Common Defines
+//
+#ifndef _EFI_SM_ELOG_TYPE
+#define _EFI_SM_ELOG_TYPE
+typedef enum {
+ EfiElogSmSMBIOS,
+ EfiElogSmIPMI,
+ EfiElogSmMachineCritical,
+ EfiElogSmASF,
+ EfiElogSmOEM,
+ EfiSmElogMax
+} EFI_SM_ELOG_TYPE;
+#endif
+
+typedef struct _EFI_SM_ELOG_PROTOCOL EFI_SM_ELOG_PROTOCOL;
+
+typedef struct _EFI_SM_ELOG_PROTOCOL EFI_SM_ELOG_REDIR_PROTOCOL;
+
+//
+// Generic ELOG Function Prototypes
+//
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SET_ELOG_DATA)(
+ IN EFI_SM_ELOG_PROTOCOL *This,
+ IN UINT8 *ElogData,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN BOOLEAN AlertEvent,
+ IN UINTN DataSize,
+ OUT UINT64 *RecordId
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_GET_ELOG_DATA)(
+ IN EFI_SM_ELOG_PROTOCOL *This,
+ IN OUT UINT8 *ElogData,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN OUT UINTN *DataSize,
+ IN OUT UINT64 *RecordId
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_ERASE_ELOG_DATA)(
+ IN EFI_SM_ELOG_PROTOCOL *This,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN OUT UINT64 *RecordId
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_ACTIVATE_ELOG)(
+ IN EFI_SM_ELOG_PROTOCOL *This,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN BOOLEAN *EnableElog,
+ OUT BOOLEAN *ElogStatus
+ );
+
+//
+// IPMI TRANSPORT PROTOCOL
+//
+struct _EFI_SM_ELOG_PROTOCOL {
+ EFI_SET_ELOG_DATA SetEventLogData;
+ EFI_GET_ELOG_DATA GetEventLogData;
+ EFI_ERASE_ELOG_DATA EraseEventlogData;
+ EFI_ACTIVATE_ELOG ActivateEventLog;
+};
+
+extern EFI_GUID gEfiGenericElogProtocolGuid;
+extern EFI_GUID gEfiRedirElogProtocolGuid;
+extern EFI_GUID gSmmGenericElogProtocolGuid;
+extern EFI_GUID gSmmRedirElogProtocolGuid;
+
+#endif
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/BmcElog.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/BmcElog.c
deleted file mode 100644
index a6d075b19c49..000000000000
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/BmcElog.c
+++ /dev/null
@@ -1,236 +0,0 @@
-/** @file
- BMC Event Log functions.
-
-Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include <Uefi.h>
-#include <Library/BaseLib.h>
-#include <Library/DebugLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/UefiRuntimeServicesTableLib.h>
-#include <Library/IpmiCommandLib.h>
-
-EFI_STATUS
-EFIAPI
-CheckIfSelIsFull (
- VOID
- );
-
-/*++
-
- Routine Description:
- This function verifies the BMC SEL is full and When it is reports the error to the Error Manager.
-
- Arguments:
- None
-
- Returns:
- EFI_SUCCESS
- EFI_DEVICE_ERROR
-
---*/
-EFI_STATUS
-WaitTillErased (
- UINT8 *ResvId
- )
-/*++
-
-Routine Description:
-
-Arguments:
-
- BmcElogPrivateData - Bmc event log instance
- ResvId - Reserved ID
-
-Returns:
-
- EFI_SUCCESS
- EFI_NO_RESPONSE
-
---*/
-{
- INTN Counter;
- IPMI_CLEAR_SEL_REQUEST ClearSel;
- IPMI_CLEAR_SEL_RESPONSE ClearSelResponse;
-
- Counter = 0x200;
- ZeroMem (&ClearSelResponse, sizeof(ClearSelResponse));
-
- while (TRUE) {
- ZeroMem (&ClearSel, sizeof(ClearSel));
- ClearSel.Reserve[0] = ResvId[0];
- ClearSel.Reserve[1] = ResvId[1];
- ClearSel.AscC = 0x43;
- ClearSel.AscL = 0x4C;
- ClearSel.AscR = 0x52;
- ClearSel.Erase = 0x00;
-
- IpmiClearSel (
- &ClearSel,
- &ClearSelResponse
- );
-
- if ((ClearSelResponse.ErasureProgress & 0xf) == 1) {
- return EFI_SUCCESS;
- }
- //
- // If there is not a response from the BMC controller we need to return and not hang.
- //
- --Counter;
- if (Counter == 0x0) {
- return EFI_NO_RESPONSE;
- }
- }
-}
-
-EFI_STATUS
-EfiActivateBmcElog (
- IN BOOLEAN *EnableElog,
- OUT BOOLEAN *ElogStatus
- )
-/*++
-
-Routine Description:
-
-Arguments:
-
- This - Protocol pointer
- DataType - indicate event log type
- EnableElog - Enable/Disable event log
- ElogStatus - return log status
-
-Returns:
-
- EFI_STATUS
-
---*/
-{
- EFI_STATUS Status;
- UINT8 ElogStat;
- IPMI_SET_BMC_GLOBAL_ENABLES_REQUEST SetBmcGlobalEnables;
- IPMI_GET_BMC_GLOBAL_ENABLES_RESPONSE GetBmcGlobalEnables;
- UINT8 CompletionCode;
-
- Status = EFI_SUCCESS;
- ElogStat = 0;
-
- Status = IpmiGetBmcGlobalEnables (&GetBmcGlobalEnables);
- if (EFI_ERROR(Status)) {
- return Status;
- }
-
- if (EnableElog == NULL) {
- *ElogStatus = GetBmcGlobalEnables.GetEnables.Bits.SystemEventLogging;
- } else {
- if (Status == EFI_SUCCESS) {
- if (*EnableElog) {
- ElogStat = 1;
- }
-
- CopyMem (&SetBmcGlobalEnables, (UINT8 *)&GetBmcGlobalEnables + 1, sizeof(UINT8));
- SetBmcGlobalEnables.SetEnables.Bits.SystemEventLogging = ElogStat;
-
- Status = IpmiSetBmcGlobalEnables (&SetBmcGlobalEnables, &CompletionCode);
- }
- }
-
- return Status;
-}
-
-EFI_STATUS
-SetElogRedirInstall (
- VOID
- )
-/*++
-
-Routine Description:
-
-Arguments:
-
- None
-
-Returns:
-
- EFI_SUCCESS
-
---*/
-{
- BOOLEAN EnableElog;
- BOOLEAN ElogStatus;
-
- //
- // Activate the Event Log (This should depend upon Setup).
- //
- EfiActivateBmcElog (&EnableElog, &ElogStatus);
- return EFI_SUCCESS;
-}
-
-EFI_STATUS
-EFIAPI
-InitializeBmcElogLayer (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
-/*++
-
-Routine Description:
-
-Arguments:
-
- ImageHandle - ImageHandle of the loaded driver
- SystemTable - Pointer to the System Table
-
-Returns:
-
- EFI_STATUS
-
---*/
-{
- SetElogRedirInstall ();
-
- CheckIfSelIsFull ();
-
- return EFI_SUCCESS;
-}
-
-EFI_STATUS
-EFIAPI
-CheckIfSelIsFull (
- VOID
- )
-/*++
-
- Routine Description:
- This function verifies the BMC SEL is full and When it is reports the error to the Error Manager.
-
- Arguments:
- None
-
- Returns:
- EFI_SUCCESS
- EFI_DEVICE_ERROR
-
---*/
-{
- EFI_STATUS Status;
- UINT8 SelIsFull;
- IPMI_GET_SEL_INFO_RESPONSE SelInfo;
-
- Status = IpmiGetSelInfo (&SelInfo);
- if (EFI_ERROR (Status)) {
- return EFI_DEVICE_ERROR;
- }
-
- //
- // Check the Bit7 of the OperationByte if SEL is OverFlow.
- //
- SelIsFull = (SelInfo.OperationSupport & 0x80);
- DEBUG ((DEBUG_INFO, "SelIsFull - 0x%x\n", SelIsFull));
-
- return EFI_SUCCESS;
-}
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Common/BmcElogCommon.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Common/BmcElogCommon.c
new file mode 100644
index 000000000000..b0688e3afb6c
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Common/BmcElogCommon.c
@@ -0,0 +1,465 @@
+/** @file
+ BMC Event Log Common functions.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "BmcElogCommon.h"
+
+/**
+ WaitTillClearSel.
+
+ @param ResvId - Reserved ID
+
+ @retval EFI_SUCCESS
+ @retval EFI_NO_RESPONSE
+
+**/
+EFI_STATUS
+WaitTillClearSel (
+ UINT8 *ResvId
+ )
+{
+ INTN Counter;
+ UINT32 ResponseDataSize;
+ IPMI_CLEAR_SEL_REQUEST ClearSelRequest;
+ IPMI_CLEAR_SEL_RESPONSE ClearSelResponse;
+ EFI_STATUS Status;
+
+ Counter = 0x200;
+ Status = EFI_SUCCESS;
+ while (TRUE) {
+ ClearSelRequest.Reserve[0] = ResvId[0];
+ ClearSelRequest.Reserve[1] = ResvId[1];
+ ClearSelRequest.AscC = IPMI_CLEAR_SEL_REQUEST_C_CHAR_ASCII;
+ ClearSelRequest.AscL = IPMI_CLEAR_SEL_REQUEST_L_CHAR_ASCII;
+ ClearSelRequest.AscR = IPMI_CLEAR_SEL_REQUEST_R_CHAR_ASCII;
+ ClearSelRequest.Erase = IPMI_CLEAR_SEL_REQUEST_GET_ERASE_STATUS;
+ ResponseDataSize = sizeof (ClearSelResponse);
+
+ Status = IpmiSubmitCommand (
+ IPMI_NETFN_STORAGE,
+ IPMI_STORAGE_CLEAR_SEL,
+ (UINT8 *)&ClearSelRequest,
+ sizeof (ClearSelRequest),
+ (UINT8 *)&ClearSelResponse,
+ &ResponseDataSize
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "IpmiSubmitCommand ClearSelRequest Failed %r\n", Status));
+ }
+
+ if ((ClearSelResponse.ErasureProgress & 0xf) == IPMI_CLEAR_SEL_RESPONSE_ERASURE_COMPLETED) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // If there is not a response from the BMC controller we need to return and not hang.
+ //
+ --Counter;
+ if (Counter == 0x0) {
+ return EFI_NO_RESPONSE;
+ }
+ }
+}
+
+/**
+ Set Bmc Elog Data.
+
+
+ @param ElogData - Buffer for log storage
+ @param DataType - Event Log type
+ @param AlertEvent - If it is an alert event
+ @param Size - Log data size
+ @param RecordId - Indicate which recorder it is
+
+ @retval EFI_STATUS
+
+**/
+EFI_STATUS
+SetBmcElogRecord (
+ IN UINT8 *ElogData,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN BOOLEAN AlertEvent,
+ IN UINTN Size,
+ OUT UINT64 *RecordId
+ )
+{
+ EFI_STATUS Status;
+ UINT32 ResponseDataSize;
+ UINT8 EvntMsgResponse;
+ IPMI_PLATFORM_EVENT_MESSAGE_DATA_REQUEST EvntMsgRequest;
+ IPMI_ADD_SEL_ENTRY_REQUEST AddSelRequest;
+ IPMI_ADD_SEL_ENTRY_RESPONSE AddSelResponse;
+
+ Status = EFI_SUCCESS;
+ CopyMem (&AddSelRequest.RecordData, ElogData, Size);
+
+ *RecordId = 0;
+
+ if (AlertEvent) {
+ EvntMsgRequest.GeneratorId = (UINT8)AddSelRequest.RecordData.GeneratorId;
+ EvntMsgRequest.EvMRevision = AddSelRequest.RecordData.EvMRevision;
+ EvntMsgRequest.SensorType = AddSelRequest.RecordData.SensorType;
+ EvntMsgRequest.SensorNumber = AddSelRequest.RecordData.SensorNumber;
+ EvntMsgRequest.EventDirType = AddSelRequest.RecordData.EventDirType;
+ EvntMsgRequest.OEMEvData1 = AddSelRequest.RecordData.OEMEvData1;
+ EvntMsgRequest.OEMEvData2 = AddSelRequest.RecordData.OEMEvData2;
+ EvntMsgRequest.OEMEvData3 = AddSelRequest.RecordData.OEMEvData3;
+
+ ResponseDataSize = sizeof (EvntMsgResponse);
+ Status = IpmiSubmitCommand (
+ IPMI_NETFN_SENSOR_EVENT,
+ IPMI_SENSOR_PLATFORM_EVENT_MESSAGE,
+ (UINT8 *)&EvntMsgRequest,
+ sizeof (EvntMsgRequest),
+ (UINT8 *)&EvntMsgResponse,
+ &ResponseDataSize
+ );
+ } else {
+ ResponseDataSize = sizeof (AddSelResponse);
+ Status = IpmiSubmitCommand (
+ IPMI_NETFN_STORAGE,
+ IPMI_STORAGE_ADD_SEL_ENTRY,
+ (UINT8 *)&AddSelRequest,
+ sizeof (AddSelRequest),
+ (UINT8 *)&AddSelResponse,
+ &ResponseDataSize
+ );
+
+ if (Status == EFI_SUCCESS) {
+ *RecordId = AddSelResponse.RecordId;
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Get Bmc Elog Data.
+
+ @param ElogData - Buffer for log data store
+ @param DataType - Event log type
+ @param Size - Size of log data
+ @param RecordId - indicate which recorder it is
+
+ @retval EFI_STATUS
+
+**/
+EFI_STATUS
+GetBmcElogRecord (
+ IN UINT8 *ElogData,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN OUT UINTN *Size,
+ IN OUT UINT64 *RecordId
+ )
+{
+ UINT64 ReceiveKey;
+ EFI_STATUS Status;
+ IPMI_GET_SEL_ENTRY_REQUEST GetSelEntryRequest;
+ IPMI_GET_SEL_ENTRY_RESPONSE GetSelEntryResponse;
+ UINT32 ResponseDataSize;
+
+ Status = EFI_SUCCESS;
+ ReceiveKey = *RecordId;
+ GetSelEntryRequest.ReserveId[0] = 0;
+ GetSelEntryRequest.ReserveId[1] = 0;
+ GetSelEntryRequest.SelRecID[0] = (UINT8)ReceiveKey;
+ ReceiveKey = DivU64x32 (ReceiveKey, (UINT32)(1 << 8));
+ GetSelEntryRequest.SelRecID[1] = (UINT8)ReceiveKey;
+ GetSelEntryRequest.Offset = 0;
+ GetSelEntryRequest.BytesToRead = IPMI_COMPLETE_SEL_RECORD;
+ ResponseDataSize = sizeof (GetSelEntryResponse);
+
+ Status = IpmiSubmitCommand (
+ IPMI_NETFN_STORAGE,
+ IPMI_STORAGE_GET_SEL_ENTRY,
+ (UINT8 *)&GetSelEntryRequest,
+ sizeof (GetSelEntryRequest),
+ (UINT8 *)&GetSelEntryResponse,
+ &ResponseDataSize
+ );
+ //
+ // Per IPMI spec, Entire Record is 16 Bytes
+ // If less than 16 bytes pointer is sent return buffer too small
+ //
+ if (Status == EFI_SUCCESS) {
+ if (*Size < (SEL_RECORD_SIZE)) {
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ if (GetSelEntryResponse.NextSelRecordId == 0xFFFF) {
+ return EFI_NOT_FOUND;
+ }
+
+ *RecordId = GetSelEntryResponse.NextSelRecordId;
+ CopyMem (ElogData, &GetSelEntryResponse.RecordData, sizeof (GetSelEntryResponse.RecordData));
+ *Size = SEL_RECORD_SIZE;
+ }
+
+ return Status;
+}
+
+/**
+ Erase Bmc Elog Data.
+
+ @param DataType - Event log type
+ @param RecordId - return which recorder it is
+
+ @retval EFI_STATUS
+
+**/
+EFI_STATUS
+EraseBmcElogRecord (
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN OUT UINT64 *RecordId
+ )
+{
+ EFI_STATUS Status;
+ UINT64 ReceiveKey;
+ UINT8 ResvId[2];
+ BOOLEAN SelReserveIdIsSupported;
+ UINT8 OperationSupport;
+ UINT8 SelReserveIdvalue;
+ UINT32 ResponseDataSize;
+ IPMI_GET_SEL_INFO_RESPONSE GetSelInfoResponse;
+ IPMI_RESERVE_SEL_RESPONSE ReserveSelResponse;
+ IPMI_DELETE_SEL_ENTRY_REQUEST DeleteSelRequest;
+ IPMI_DELETE_SEL_ENTRY_RESPONSE DeleteSelResponse;
+ IPMI_CLEAR_SEL_REQUEST ClearSelRequest;
+ IPMI_CLEAR_SEL_RESPONSE ClearSelResponse;
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Before issuing this SEL reservation ID, Check whether this command is supported or not by issuing the
+ // GetSelInfoCommand. If it does not support ResvId should be 0000h
+ //
+ ResponseDataSize = sizeof (GetSelInfoResponse);
+ Status = IpmiSubmitCommand (
+ IPMI_NETFN_STORAGE,
+ IPMI_STORAGE_GET_SEL_INFO,
+ NULL,
+ 0,
+ (UINT8 *)&GetSelInfoResponse,
+ &ResponseDataSize
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ OperationSupport = GetSelInfoResponse.OperationSupport;
+ SelReserveIdvalue = (OperationSupport & IPMI_GET_SEL_INFO_OPERATION_SUPPORT_RESERVE_SEL_CMD);
+ if (SelReserveIdvalue == IPMI_GET_SEL_INFO_OPERATION_SUPPORT_RESERVE_SEL_CMD) {
+ SelReserveIdIsSupported = TRUE;
+ } else {
+ SelReserveIdIsSupported = FALSE;
+ }
+
+ //
+ // if SelReserveIdcommand not supported do not issue the RESERVE_SEL_ENTRY command, and set the ResvId value to 0000h
+ //
+
+ //
+ // Get the SEL reservation ID
+ //
+
+ if (SelReserveIdIsSupported) {
+ ResponseDataSize = sizeof (ReserveSelResponse);
+ Status = IpmiSubmitCommand (
+ IPMI_NETFN_STORAGE,
+ IPMI_STORAGE_RESERVE_SEL,
+ NULL,
+ 0,
+ (UINT8 *)&ReserveSelResponse,
+ &ResponseDataSize
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ResvId[0] = ReserveSelResponse.ReservationId[0];
+ ResvId[1] = ReserveSelResponse.ReservationId[1];
+ } else {
+ ResvId[0] = 0x00;
+ ResvId[1] = 0x00;
+ }
+
+ //
+ // Clear the SEL
+ //
+ if (RecordId != NULL) {
+ ReceiveKey = *RecordId;
+ DeleteSelRequest.ReserveId[0] = ResvId[0];
+ DeleteSelRequest.ReserveId[1] = ResvId[1];
+ DeleteSelRequest.RecordToDelete[0] = (UINT8)ReceiveKey;
+ ReceiveKey = DivU64x32 (ReceiveKey, (UINT32)(1 << 8));
+ DeleteSelRequest.RecordToDelete[1] = (UINT8)ReceiveKey;
+
+ ResponseDataSize = sizeof (DeleteSelResponse);
+ Status = IpmiSubmitCommand (
+ IPMI_NETFN_STORAGE,
+ IPMI_STORAGE_DELETE_SEL_ENTRY,
+ (UINT8 *)&DeleteSelRequest,
+ sizeof (DeleteSelRequest),
+ (UINT8 *)&DeleteSelResponse,
+ &ResponseDataSize
+ );
+ } else {
+ ClearSelRequest.Reserve[0] = ResvId[0];
+ ClearSelRequest.Reserve[1] = ResvId[1];
+ ClearSelRequest.AscC = IPMI_CLEAR_SEL_REQUEST_C_CHAR_ASCII;
+ ClearSelRequest.AscL = IPMI_CLEAR_SEL_REQUEST_L_CHAR_ASCII;
+ ClearSelRequest.AscR = IPMI_CLEAR_SEL_REQUEST_R_CHAR_ASCII;
+ ClearSelRequest.Erase = IPMI_CLEAR_SEL_REQUEST_INITIALIZE_ERASE;
+ ResponseDataSize = sizeof (ClearSelResponse);
+
+ Status = IpmiSubmitCommand (
+ IPMI_NETFN_STORAGE,
+ IPMI_STORAGE_CLEAR_SEL,
+ (UINT8 *)&ClearSelRequest,
+ sizeof (ClearSelRequest),
+ (UINT8 *)&ClearSelResponse,
+ &ResponseDataSize
+ );
+ }
+
+ if (Status == EFI_SUCCESS) {
+ if (RecordId == NULL) {
+ WaitTillClearSel (ResvId);
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Activate Bmc Elog.
+
+ @param DataType - indicate event log type
+ @param EnableElog - Enable/Disable event log
+ @param ElogStatus - return log status
+
+ @retval EFI_STATUS
+
+**/
+EFI_STATUS
+ActivateBmcElog (
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN BOOLEAN *EnableElog,
+ OUT BOOLEAN *ElogStatus
+ )
+{
+ EFI_STATUS Status;
+ UINT8 ElogStat;
+ IPMI_GET_BMC_GLOBAL_ENABLES_RESPONSE GetBmcGlobalResponse;
+ IPMI_SET_BMC_GLOBAL_ENABLES_REQUEST SetBmcGlobalRequest;
+ UINT8 SetBmcGlobalResponse;
+ UINT32 ResponseDataSize;
+
+ Status = EFI_SUCCESS;
+ ElogStat = 0;
+
+ ResponseDataSize = sizeof (GetBmcGlobalResponse);
+ Status = IpmiSubmitCommand (
+ IPMI_NETFN_APP,
+ IPMI_APP_GET_BMC_GLOBAL_ENABLES,
+ NULL,
+ 0,
+ (UINT8 *)&GetBmcGlobalResponse,
+ &ResponseDataSize
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "IpmiSubmitCommand App Get Bmc Global Enables Failed %r\n", Status));
+ }
+
+ if (EnableElog == NULL) {
+ *ElogStatus = (UINT8)(GetBmcGlobalResponse.GetEnables.Bits.SystemEventLogging);
+ } else {
+ if (Status == EFI_SUCCESS) {
+ if (*EnableElog) {
+ ElogStat = 0x1; // Setting SystemEventLogging
+ }
+
+ SetBmcGlobalRequest.SetEnables.Uint8 = GetBmcGlobalResponse.GetEnables.Uint8;
+ SetBmcGlobalRequest.SetEnables.Bits.SystemEventLogging = ElogStat;
+
+ ResponseDataSize = sizeof (SetBmcGlobalResponse);
+ Status = IpmiSubmitCommand (
+ IPMI_NETFN_APP,
+ IPMI_APP_SET_BMC_GLOBAL_ENABLES,
+ (UINT8 *)&SetBmcGlobalRequest,
+ sizeof (SetBmcGlobalRequest),
+ (UINT8 *)&SetBmcGlobalResponse,
+ &ResponseDataSize
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "IpmiSubmitCommand App Set Bmc Global Enables Failed %r\n", Status));
+ }
+ }
+ }
+
+ return Status;
+}
+
+/**
+ This function checks the BMC SEL is full and whether to report the error.
+
+ @retval EFI_SUCCESS
+ @retval EFI_DEVICE_ERROR
+
+**/
+EFI_STATUS
+EFIAPI
+CheckIfSelIsFull (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT32 ResponseDataSize;
+ UINT8 OperationSupportByte;
+ UINT8 SelIsFull;
+ IPMI_GET_SEL_INFO_RESPONSE GetSelInfoResponse;
+
+ OperationSupportByte = 0;
+ SelIsFull = 0;
+
+ ResponseDataSize = sizeof (GetSelInfoResponse);
+
+ Status = IpmiSubmitCommand (
+ IPMI_NETFN_STORAGE,
+ IPMI_STORAGE_GET_SEL_INFO,
+ NULL,
+ 0,
+ (UINT8 *)&GetSelInfoResponse,
+ &ResponseDataSize
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ OperationSupportByte = GetSelInfoResponse.OperationSupport;
+
+ //
+ // Check the Bit7 of the OperationByte if SEL is OverFlow.
+ //
+ SelIsFull = (OperationSupportByte & IPMI_GET_SEL_INFO_OPERATION_SUPPORT_OVERFLOW_FLAG);
+
+ if (SelIsFull == IPMI_GET_SEL_INFO_OPERATION_SUPPORT_OVERFLOW_FLAG) {
+ //
+ // Report the Error code that SEL Log is full
+ //
+ ReportStatusCode (
+ (EFI_ERROR_CODE | EFI_ERROR_MINOR),
+ (SOFTWARE_EFI_BMC | EFI_SW_EC_EVENT_LOG_FULL)
+ );
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Dxe/BmcElog.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Dxe/BmcElog.c
new file mode 100644
index 000000000000..0b1e2f5b1355
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Dxe/BmcElog.c
@@ -0,0 +1,287 @@
+/** @file
+ BMC Event Log functions.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "BmcElog.h"
+
+//
+// Define module globals used to register for notification of when
+// the ELOG REDIR protocol has been produced.
+//
+EFI_EVENT mEfiBmcTransEvent;
+EFI_BMC_ELOG_INSTANCE_DATA *mRedirProtoPrivate;
+
+/**
+ WaitTillErased.
+
+ @param BmcElogPrivateData - Bmc event log instance
+ @param ResvId - Reserved ID
+
+ @retval EFI_SUCCESS
+ @retval EFI_NO_RESPONSE
+
+**/
+EFI_STATUS
+WaitTillErased (
+ EFI_BMC_ELOG_INSTANCE_DATA *BmcElogPrivateData,
+ UINT8 *ResvId
+ )
+{
+ EFI_STATUS Status;
+
+ Status = WaitTillClearSel (ResvId);
+ return Status;
+}
+
+/**
+ Efi Set Bmc Elog Data.
+
+ @param This - Protocol pointer
+ @param ElogData - Buffer for log storage
+ @param DataType - Event Log type
+ @param AlertEvent - If it is an alert event
+ @param Size - Log data size
+ @param RecordId - Indicate which recorder it is
+
+ @retval EFI_STATUS
+
+**/
+EFI_STATUS
+EfiSetBmcElogData (
+ IN EFI_SM_ELOG_REDIR_PROTOCOL *This,
+ IN UINT8 *ElogData,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN BOOLEAN AlertEvent,
+ IN UINTN Size,
+ OUT UINT64 *RecordId
+ )
+{
+ EFI_BMC_ELOG_INSTANCE_DATA *BmcElogPrivateData;
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+ BmcElogPrivateData = INSTANCE_FROM_EFI_ELOG_REDIR_THIS (This);
+
+ if (DataType >= EfiSmElogMax) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Size > SEL_RECORD_SIZE) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (BmcElogPrivateData->DataType == DataType) {
+ Status = SetBmcElogRecord (ElogData, DataType, AlertEvent, Size, RecordId);
+ }
+
+ return Status;
+}
+
+/**
+ Efi Get Bmc Elog Data.
+
+ @param This - Protocol pointer
+ @param ElogData - Buffer for log data store
+ @param DataType - Event log type
+ @param Size - Size of log data
+ @param RecordId - indicate which recorder it is
+
+ @retval EFI_STATUS
+
+**/
+EFI_STATUS
+EfiGetBmcElogData (
+ IN EFI_SM_ELOG_REDIR_PROTOCOL *This,
+ IN OUT UINT8 *ElogData,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN OUT UINTN *Size,
+ IN OUT UINT64 *RecordId
+ )
+{
+ EFI_BMC_ELOG_INSTANCE_DATA *BmcElogPrivateData;
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+ BmcElogPrivateData = INSTANCE_FROM_EFI_ELOG_REDIR_THIS (This);
+
+ if (DataType >= EfiSmElogMax) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BmcElogPrivateData->DataType == DataType) {
+ Status = GetBmcElogRecord (ElogData, DataType, Size, RecordId);
+ }
+
+ return Status;
+}
+
+/**
+ Efi Erase Bmc Elog Data.
+
+ @param This - Protocol pointer
+ @param DataType - Event log type
+ @param RecordId - return which recorder it is
+
+ @retval EFI_STATUS
+
+**/
+EFI_STATUS
+EfiEraseBmcElogData (
+ IN EFI_SM_ELOG_REDIR_PROTOCOL *This,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN OUT UINT64 *RecordId
+ )
+{
+ EFI_BMC_ELOG_INSTANCE_DATA *BmcElogPrivateData;
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+ BmcElogPrivateData = INSTANCE_FROM_EFI_ELOG_REDIR_THIS (This);
+
+ if (DataType >= EfiSmElogMax) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BmcElogPrivateData->DataType == DataType) {
+ Status = EraseBmcElogRecord (DataType, RecordId);
+
+ if (Status == EFI_SUCCESS) {
+ if (RecordId != NULL) {
+ *RecordId = (UINT16)(*((UINT16 *)&BmcElogPrivateData->TempData[0]));
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Efi Activate Bmc Elog.
+
+ @param This - Protocol pointer
+ @param DataType - indicate event log type
+ @param EnableElog - Enable/Disable event log
+ @param ElogStatus - return log status
+
+ @retval EFI_STATUS
+
+**/
+EFI_STATUS
+EfiActivateBmcElog (
+ IN EFI_SM_ELOG_REDIR_PROTOCOL *This,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN BOOLEAN *EnableElog,
+ OUT BOOLEAN *ElogStatus
+ )
+{
+ EFI_BMC_ELOG_INSTANCE_DATA *BmcElogPrivateData;
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+ BmcElogPrivateData = INSTANCE_FROM_EFI_ELOG_REDIR_THIS (This);
+
+ if (DataType >= EfiSmElogMax) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BmcElogPrivateData->DataType == DataType) {
+ Status = ActivateBmcElog (DataType, EnableElog, ElogStatus);
+ }
+
+ return Status;
+}
+
+/**
+ Set Elog Redir Install.
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+SetElogRedirInstall (
+ VOID
+ )
+{
+ EFI_HANDLE NewHandle;
+ EFI_STATUS Status;
+ BOOLEAN EnableElog;
+ BOOLEAN ElogStatus;
+ UINT16 Instance;
+
+ Status = EFI_SUCCESS;
+ EnableElog = TRUE;
+ ElogStatus = TRUE;
+ Instance = 0;
+
+ mRedirProtoPrivate->Signature = EFI_ELOG_REDIR_SIGNATURE;
+ mRedirProtoPrivate->DataType = EfiElogSmIPMI;
+ mRedirProtoPrivate->BmcElog.ActivateEventLog = EfiActivateBmcElog;
+ mRedirProtoPrivate->BmcElog.EraseEventlogData = EfiEraseBmcElogData;
+ mRedirProtoPrivate->BmcElog.GetEventLogData = EfiGetBmcElogData;
+ mRedirProtoPrivate->BmcElog.SetEventLogData = EfiSetBmcElogData;
+ mRedirProtoPrivate->Instance = Instance;
+ //
+ // Now install the Protocol
+ //
+ NewHandle = NULL;
+
+ Status = gBS->InstallProtocolInterface (
+ &NewHandle,
+ &gEfiRedirElogProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mRedirProtoPrivate->BmcElog
+ );
+ ASSERT_EFI_ERROR (Status);
+ if (Status != EFI_SUCCESS) {
+ return Status;
+ }
+
+ //
+ // Activate the Event Log (This should depend upon Setup).
+ //
+ EfiActivateBmcElog (&mRedirProtoPrivate->BmcElog, EfiElogSmIPMI, &EnableElog, &ElogStatus);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ InitializeBmcElogLayer.
+
+ @param ImageHandle - ImageHandle of the loaded driver
+ @param SystemTable - Pointer to the System Table
+
+ @retval EFI_STATUS
+
+**/
+EFI_STATUS
+InitializeBmcElogLayer (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ InitializeIpmiBase ();
+
+ mRedirProtoPrivate = AllocatePool (sizeof (EFI_BMC_ELOG_INSTANCE_DATA));
+ ASSERT (mRedirProtoPrivate != NULL);
+ if (mRedirProtoPrivate == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ SetElogRedirInstall ();
+
+ //
+ // Check if the BMC System Event Log (SEL) is full and whether to report the error.
+ //
+
+ CheckIfSelIsFull ();
+
+ return Status;
+}
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Pei/BmcElog.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Pei/BmcElog.c
new file mode 100644
index 000000000000..f791d872b7a1
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Pei/BmcElog.c
@@ -0,0 +1,297 @@
+/** @file
+ BMC Event Log functions.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "BmcElog.h"
+
+//
+// Define module globals used to register for notification of when
+// the ELOG REDIR protocol has been produced.
+//
+
+EFI_STATUS
+NotifyPeiBmcElogCallback (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ );
+
+EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList[] = {
+ {
+ EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+ &gPeiIpmiTransportPpiGuid,
+ NotifyPeiBmcElogCallback
+ }
+};
+
+/**
+ Efi Set Bmc Elog Data.
+
+ @param This - Protocol pointer
+ @param ElogData - Buffer for log storage
+ @param DataType - Event Log type
+ @param AlertEvent - If it is an alert event
+ @param Size - Log data size
+ @param RecordId - Indicate which recorder it is
+
+ @retval EFI_STATUS
+
+**/
+EFI_STATUS
+EfiSetBmcElogData (
+ IN EFI_SM_ELOG_REDIR_PPI *This,
+ IN UINT8 *ElogData,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN BOOLEAN AlertEvent,
+ IN UINTN Size,
+ OUT UINT64 *RecordId
+ )
+{
+ EFI_PEI_BMC_ELOG_INSTANCE_DATA *BmcElogPrivateData;
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+ BmcElogPrivateData = INSTANCE_FROM_EFI_PEI_ELOG_REDIR_THIS (This);
+
+ if (DataType >= EfiSmElogMax) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Size > SEL_RECORD_SIZE) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (BmcElogPrivateData->DataType == DataType) {
+ Status = SetBmcElogRecord (ElogData, DataType, AlertEvent, Size, RecordId);
+ }
+
+ return Status;
+}
+
+/**
+ Efi Get Bmc Elog Data.
+
+ @param This - Protocol pointer
+ @param ElogData - Buffer for log data store
+ @param DataType - Event log type
+ @param Size - Size of log data
+ @param RecordId - indicate which recorder it is
+
+ @retval EFI_STATUS
+
+**/
+EFI_STATUS
+EfiGetBmcElogData (
+ IN EFI_SM_ELOG_REDIR_PPI *This,
+ IN OUT UINT8 *ElogData,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN OUT UINTN *Size,
+ IN OUT UINT64 *RecordId
+ )
+{
+ EFI_PEI_BMC_ELOG_INSTANCE_DATA *BmcElogPrivateData;
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+ BmcElogPrivateData = INSTANCE_FROM_EFI_PEI_ELOG_REDIR_THIS (This);
+
+ if (DataType >= EfiSmElogMax) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BmcElogPrivateData->DataType == DataType) {
+ Status = GetBmcElogRecord (ElogData, DataType, Size, RecordId);
+ }
+
+ return Status;
+}
+
+/**
+ Efi Erase Bmc Elog Data.
+
+ @param This - Protocol pointer
+ @param DataType - Event log type
+ @param RecordId - return which recorder it is
+
+ @retval EFI_STATUS
+
+**/
+EFI_STATUS
+EfiEraseBmcElogData (
+ IN EFI_SM_ELOG_REDIR_PPI *This,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN OUT UINT64 *RecordId
+ )
+{
+ EFI_PEI_BMC_ELOG_INSTANCE_DATA *BmcElogPrivateData;
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+ BmcElogPrivateData = INSTANCE_FROM_EFI_PEI_ELOG_REDIR_THIS (This);
+
+ if (DataType >= EfiSmElogMax) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BmcElogPrivateData->DataType == DataType) {
+ Status = EraseBmcElogRecord (DataType, RecordId);
+
+ if (Status == EFI_SUCCESS) {
+ if (RecordId != NULL) {
+ *RecordId = (UINT16)(*((UINT16 *)&BmcElogPrivateData->TempData[0]));
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Efi Activate Bmc Elog.
+
+ @param This - Protocol pointer
+ @param DataType - indicate event log type
+ @param EnableElog - Enable/Disable event log
+ @param ElogStatus - return log status
+
+ @retval EFI_STATUS
+
+**/
+EFI_STATUS
+EfiActivateBmcElog (
+ IN EFI_SM_ELOG_REDIR_PPI *This,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN BOOLEAN *EnableElog,
+ OUT BOOLEAN *ElogStatus
+ )
+{
+ EFI_PEI_BMC_ELOG_INSTANCE_DATA *BmcElogPrivateData;
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+ BmcElogPrivateData = INSTANCE_FROM_EFI_PEI_ELOG_REDIR_THIS (This);
+
+ if (DataType >= EfiSmElogMax) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BmcElogPrivateData->DataType == DataType) {
+ Status = ActivateBmcElog (DataType, EnableElog, ElogStatus);
+ }
+
+ return Status;
+}
+
+/**
+ Set Elog Redir Install.
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+SetElogRedirInstall (
+ EFI_PEI_BMC_ELOG_INSTANCE_DATA *mRedirPeiProtoPrivate
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN EnableElog;
+ BOOLEAN ElogStatus;
+ UINT16 Instance;
+
+ Status = EFI_SUCCESS;
+ EnableElog = TRUE;
+ ElogStatus = TRUE;
+ Instance = 0;
+
+ mRedirPeiProtoPrivate->Signature = EFI_PEI_ELOG_REDIR_SIGNATURE;
+ mRedirPeiProtoPrivate->DataType = EfiElogSmIPMI;
+ mRedirPeiProtoPrivate->BmcElogPpi.ActivateEventLog = EfiActivateBmcElog;
+ mRedirPeiProtoPrivate->BmcElogPpi.EraseEventlogData = EfiEraseBmcElogData;
+ mRedirPeiProtoPrivate->BmcElogPpi.GetEventLogData = EfiGetBmcElogData;
+ mRedirPeiProtoPrivate->BmcElogPpi.SetEventLogData = EfiSetBmcElogData;
+
+ mRedirPeiProtoPrivate->BmcElog.Guid = &gPeiRedirElogPpiGuid;
+ mRedirPeiProtoPrivate->BmcElog.Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
+ mRedirPeiProtoPrivate->BmcElog.Ppi = (VOID *)&mRedirPeiProtoPrivate->BmcElogPpi;
+ mRedirPeiProtoPrivate->Instance = Instance;
+ //
+ // Now install the Protocol
+ //
+
+ Status = PeiServicesInstallPpi (&mRedirPeiProtoPrivate->BmcElog);
+ ASSERT_EFI_ERROR (Status);
+ if (Status != EFI_SUCCESS) {
+ return Status;
+ }
+
+ //
+ // Activate the Event Log (This should depend upon Setup).
+ //
+ EfiActivateBmcElog (&mRedirPeiProtoPrivate->BmcElogPpi, EfiElogSmIPMI, &EnableElog, &ElogStatus);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ InitializeBmcElogLayer.
+
+ @param ImageHandle - ImageHandle of the loaded driver
+ @param SystemTable - Pointer to the System Table
+
+ @retval EFI_STATUS
+
+**/
+EFI_STATUS
+InitializeBmcElogLayer (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ Status = PeiServicesNotifyPpi (&mNotifyList[0]);
+ return Status;
+}
+
+/**
+ NotifyPeiBmcElogCallback This notification function is invoked when an instance of the
+ IPMI Transport layer at PEI is produced.
+
+ @param PeiServices - Pointer to the PEI Services table
+ @param NotifyDescriptor - Pointer to the NotifyPpi Descriptor
+ @param Ppi - Pointer to the PPI passed during Notify
+
+ @retval EFI_STATUS
+
+**/
+EFI_STATUS
+NotifyPeiBmcElogCallback (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ )
+{
+ EFI_STATUS Status;
+ EFI_PEI_BMC_ELOG_INSTANCE_DATA *mRedirPeiProtoPrivate;
+
+ Status = EFI_SUCCESS;
+
+ mRedirPeiProtoPrivate = AllocateZeroPool (sizeof (EFI_PEI_BMC_ELOG_INSTANCE_DATA));
+
+ if (mRedirPeiProtoPrivate == NULL) {
+ DEBUG ((DEBUG_ERROR, "IPMI BMCELog Peim:EFI_OUT_OF_RESOURCES of memory allocation\n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ SetElogRedirInstall (mRedirPeiProtoPrivate);
+
+ CheckIfSelIsFull ();
+
+ return Status;
+}
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Smm/BmcElog.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Smm/BmcElog.c
new file mode 100644
index 000000000000..efaa61f43869
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Smm/BmcElog.c
@@ -0,0 +1,288 @@
+/** @file
+ BMC Event Log functions.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "BmcElog.h"
+
+//
+// Define module globals used to register for notification of when
+// the ELOG REDIR protocol has been produced.
+//
+EFI_EVENT mEfiBmcTransEvent;
+EFI_BMC_ELOG_INSTANCE_DATA *mRedirProtoPrivate;
+
+/**
+ WaitTillErased.
+
+ @param BmcElogPrivateData - Bmc event log instance
+ @param ResvId - Reserved ID
+
+ @retval EFI_SUCCESS
+ @retval EFI_NO_RESPONSE
+
+**/
+EFI_STATUS
+WaitTillErased (
+ EFI_BMC_ELOG_INSTANCE_DATA *BmcElogPrivateData,
+ UINT8 *ResvId
+ )
+{
+ EFI_STATUS Status;
+
+ Status = WaitTillClearSel (ResvId);
+ return Status;
+}
+
+/**
+ Efi Set Bmc Elog Data.
+
+ @param This - Protocol pointer
+ @param ElogData - Buffer for log storage
+ @param DataType - Event Log type
+ @param AlertEvent - If it is an alert event
+ @param Size - Log data size
+ @param RecordId - Indicate which recorder it is
+
+ @retval EFI_STATUS
+
+**/
+EFI_STATUS
+EfiSetBmcElogData (
+ IN EFI_SM_ELOG_REDIR_PROTOCOL *This,
+ IN UINT8 *ElogData,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN BOOLEAN AlertEvent,
+ IN UINTN Size,
+ OUT UINT64 *RecordId
+ )
+{
+ EFI_BMC_ELOG_INSTANCE_DATA *BmcElogPrivateData;
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+ BmcElogPrivateData = INSTANCE_FROM_EFI_SM_ELOG_REDIR_THIS (This);
+
+ if (DataType >= EfiSmElogMax) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Size > SEL_RECORD_SIZE) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (BmcElogPrivateData->DataType == DataType) {
+ Status = SetBmcElogRecord (ElogData, DataType, AlertEvent, Size, RecordId);
+ }
+
+ return Status;
+}
+
+/**
+ Efi Get Bmc Elog Data.
+
+ @param This - Protocol pointer
+ @param ElogData - Buffer for log data store
+ @param DataType - Event log type
+ @param Size - Size of log data
+ @param RecordId - indicate which recorder it is
+
+ @retval EFI_STATUS
+
+**/
+EFI_STATUS
+EfiGetBmcElogData (
+ IN EFI_SM_ELOG_REDIR_PROTOCOL *This,
+ IN OUT UINT8 *ElogData,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN OUT UINTN *Size,
+ IN OUT UINT64 *RecordId
+ )
+{
+ EFI_BMC_ELOG_INSTANCE_DATA *BmcElogPrivateData;
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+ BmcElogPrivateData = INSTANCE_FROM_EFI_SM_ELOG_REDIR_THIS (This);
+
+ if (DataType >= EfiSmElogMax) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BmcElogPrivateData->DataType == DataType) {
+ Status = GetBmcElogRecord (ElogData, DataType, Size, RecordId);
+ }
+
+ return Status;
+}
+
+/**
+ Efi Erase Bmc Elog Data.
+
+ @param This - Protocol pointer
+ @param DataType - Event log type
+ @param RecordId - return which recorder it is
+
+ @retval EFI_STATUS
+
+**/
+EFI_STATUS
+EfiEraseBmcElogData (
+ IN EFI_SM_ELOG_REDIR_PROTOCOL *This,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN OUT UINT64 *RecordId
+ )
+{
+ EFI_BMC_ELOG_INSTANCE_DATA *BmcElogPrivateData;
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+ BmcElogPrivateData = INSTANCE_FROM_EFI_SM_ELOG_REDIR_THIS (This);
+
+ if (DataType >= EfiSmElogMax) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BmcElogPrivateData->DataType == DataType) {
+ Status = EraseBmcElogRecord (DataType, RecordId);
+
+ if (Status == EFI_SUCCESS) {
+ if (RecordId != NULL) {
+ *RecordId = (UINT16)(*((UINT16 *)&BmcElogPrivateData->TempData[0]));
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Efi Activate Bmc Elog.
+
+ @param This - Protocol pointer
+ @param DataType - indicate event log type
+ @param EnableElog - Enable/Disable event log
+ @param ElogStatus - return log status
+
+ @retval EFI_STATUS
+
+**/
+EFI_STATUS
+EfiActivateBmcElog (
+ IN EFI_SM_ELOG_REDIR_PROTOCOL *This,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN BOOLEAN *EnableElog,
+ OUT BOOLEAN *ElogStatus
+ )
+{
+ EFI_BMC_ELOG_INSTANCE_DATA *BmcElogPrivateData;
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+ BmcElogPrivateData = INSTANCE_FROM_EFI_SM_ELOG_REDIR_THIS (This);
+
+ if (DataType >= EfiSmElogMax) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BmcElogPrivateData->DataType == DataType) {
+ Status = ActivateBmcElog (DataType, EnableElog, ElogStatus);
+ }
+
+ return Status;
+}
+
+/**
+ Set Elog Redir Install.
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+SetElogRedirInstall (
+ VOID
+ )
+{
+ EFI_HANDLE NewHandle;
+ EFI_STATUS Status;
+ BOOLEAN EnableElog;
+ BOOLEAN ElogStatus;
+ UINT16 Instance;
+
+ Status = EFI_SUCCESS;
+ EnableElog = TRUE;
+ ElogStatus = TRUE;
+ Instance = 0;
+
+ mRedirProtoPrivate->Signature = SM_ELOG_REDIR_SIGNATURE;
+ mRedirProtoPrivate->DataType = EfiElogSmIPMI;
+ mRedirProtoPrivate->BmcElog.ActivateEventLog = (EFI_ACTIVATE_ELOG)EfiActivateBmcElog;
+ mRedirProtoPrivate->BmcElog.EraseEventlogData = (EFI_ERASE_ELOG_DATA)EfiEraseBmcElogData;
+ mRedirProtoPrivate->BmcElog.GetEventLogData = (EFI_GET_ELOG_DATA)EfiGetBmcElogData;
+ mRedirProtoPrivate->BmcElog.SetEventLogData = (EFI_SET_ELOG_DATA)EfiSetBmcElogData;
+ mRedirProtoPrivate->Instance = Instance;
+ //
+ // Now install the Protocol
+ //
+ NewHandle = NULL;
+ Status = gSmst->SmmInstallProtocolInterface (
+ &NewHandle,
+ &gSmmRedirElogProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mRedirProtoPrivate->BmcElog
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ if (Status != EFI_SUCCESS) {
+ return Status;
+ }
+
+ //
+ // Activate the Event Log (This should depend upon Setup).
+ //
+ EfiActivateBmcElog (&mRedirProtoPrivate->BmcElog, EfiElogSmIPMI, &EnableElog, &ElogStatus);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ InitializeBmcElogLayer.
+
+ @param ImageHandle - ImageHandle of the loaded driver
+ @param SystemTable - Pointer to the System Table
+
+ @retval EFI_STATUS
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeSmBmcElogLayer (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ gST = SystemTable;
+ gBS = gST->BootServices;
+
+ mRedirProtoPrivate = AllocatePool (sizeof (EFI_BMC_ELOG_INSTANCE_DATA));
+ ASSERT (mRedirProtoPrivate != NULL);
+ if (mRedirProtoPrivate == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ SetElogRedirInstall ();
+ //
+ // Check if the BMC System Event Log (SEL) is full and whether to report the error.
+ //
+
+ CheckIfSelIsFull ();
+
+ return Status;
+}
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Dxe/GenericElog.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Dxe/GenericElog.c
new file mode 100644
index 000000000000..d432b2151664
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Dxe/GenericElog.c
@@ -0,0 +1,576 @@
+/** @file
+ Generic Event Log functions of DXE driver.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "GenericElog.h"
+
+ELOG_MODULE_GLOBAL *mElogModuleGlobal;
+
+//
+// Define module globals used to register for notification of when
+// the ELOG REDIR protocol has been produced.
+//
+EFI_EVENT mEfiElogRedirProtocolEvent;
+
+/**
+ Sends the Event-Log data to the destination.
+
+ @param[in] ElogData Pointer to the Event-Log data that needs to be recorded.
+ @param[in] DataType Type of Elog Data that is being recorded.
+ @param[in] AlertEvent This is an indication that the input data type is an Alert.
+ @param[in] DataSize
+ @param[out] RecordId Record ID sent by the target.
+ @param[in] Global The module global variable pointer.
+ @param[in] Virtual If this function is called in virtual mode or physical mode
+
+ @retval EFI_SUCCESS Event-Log was recorded successfully.
+ @retval EFI_OUT_OF_RESOURCES Not enough resources to record data.
+ @retval EFI_UNSUPPORTED The Data Type is unsupported.
+
+**/
+EFI_STATUS
+EfiLibSetElogData (
+ IN UINT8 *ElogData,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN BOOLEAN AlertEvent,
+ IN UINTN DataSize,
+ OUT UINT64 *RecordId,
+ IN ELOG_MODULE_GLOBAL *Global,
+ IN BOOLEAN Virtual
+ )
+{
+ UINT8 Index;
+ VOID *ElogRedirCommand;
+ EFI_STATUS Status;
+ EFI_STATUS RetStatus;
+
+ RetStatus = EFI_UNSUPPORTED;
+
+ if (DataType >= EfiSmElogMax) {
+ RetStatus = EFI_INVALID_PARAMETER;
+ return RetStatus;
+ }
+
+ for (Index = 0; Index < Global->MaxDescriptors; Index++) {
+ if (Global->Redir[Index].Valid) {
+ ElogRedirCommand = Global->Redir[Index].Command[Virtual].SetEventLogData.Function;
+ Status = (*((EFI_SET_ELOG_DATA *)&ElogRedirCommand))(Global->Redir[Index].Command[Virtual].This, ElogData, DataType, AlertEvent, DataSize, RecordId);
+
+ if (!EFI_ERROR (Status)) {
+ RetStatus = EFI_SUCCESS;
+ break;
+ } else if (Status != EFI_UNSUPPORTED) {
+ RetStatus = Status;
+ break;
+ }
+ }
+ }
+
+ return RetStatus;
+}
+
+/**
+ Add function description.
+
+ @param This - add argument description
+ @param ElogData - add argument description
+ @param DataType - add argument description
+ @param AlertEvent - add argument description
+ @param DataSize - add argument description
+ @param RecordId - add argument description
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EfiSetElogData (
+ IN EFI_SM_ELOG_PROTOCOL *This,
+ IN UINT8 *ElogData,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN BOOLEAN AlertEvent,
+ IN UINTN DataSize,
+ OUT UINT64 *RecordId
+ )
+{
+ if (DataType >= EfiSmElogMax) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EfiLibSetElogData (
+ ElogData,
+ DataType,
+ AlertEvent,
+ DataSize,
+ RecordId,
+ mElogModuleGlobal,
+ FALSE
+ );
+}
+
+/**
+ Gets the Event-Log data from the destination.
+
+ @param[in] ElogData Pointer to the Event-Log data buffer that will contain the data to be retrieved.
+ @param[in] DataType Type of Elog Data that is being recorded.
+ @param[in, out] DataSize
+ @param[in, out] RecordId This is the RecordId of the next record. If ElogData is NULL,
+ this gives the RecordId of the first record available in the database with the correct DataSize.
+ A value of 0 on return indicates the last record if the EFI_STATUS indicates a success
+ @param[in] Global The module global variable pointer.
+ @param[in] Virtual If this function is called in virtual mode or physical mode
+
+ @retval EFI_SUCCESS Event-Log was retrieved successfully.
+ @retval EFI_NOT_FOUND Event-Log target not found.
+ @retval EFI_BUFFER_TOO_SMALL Target buffer is too small to retrieve the data.
+ @retval EFI_UNSUPPORTED The Data Type is unsupported
+
+**/
+EFI_STATUS
+EfiLibGetElogData (
+ IN UINT8 *ElogData,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN OUT UINTN *DataSize,
+ IN OUT UINT64 *RecordId,
+ IN ELOG_MODULE_GLOBAL *Global,
+ IN BOOLEAN Virtual
+ )
+{
+ UINT8 Index;
+ VOID *ElogRedirCommand;
+ EFI_STATUS Status;
+ EFI_STATUS RetStatus;
+
+ RetStatus = EFI_UNSUPPORTED;
+
+ if (DataType >= EfiSmElogMax) {
+ RetStatus = EFI_INVALID_PARAMETER;
+ return RetStatus;
+ }
+
+ for (Index = 0; Index < Global->MaxDescriptors; Index++) {
+ if (Global->Redir[Index].Valid) {
+ ElogRedirCommand = Global->Redir[Index].Command[Virtual].GetEventLogData.Function;
+ Status = (*((EFI_GET_ELOG_DATA *)&ElogRedirCommand))(Global->Redir[Index].Command[Virtual].This, ElogData, DataType, DataSize, RecordId);
+
+ if (!EFI_ERROR (Status)) {
+ RetStatus = EFI_SUCCESS;
+ break;
+ } else if (Status != EFI_UNSUPPORTED) {
+ RetStatus = Status;
+ break;
+ }
+ }
+ }
+
+ return RetStatus;
+}
+
+/**
+ Add function description.
+
+ @param This - Protocol instance pointer.
+ @param ElogData - Pointer to the Event-Log data buffer that will contain the data to be retrieved.
+ @param DataType - Type of Elog Data that is being recorded.
+ @param DataSize - Size of Elog Data in bytes.
+ @param RecordId - This is the RecordId of the next record. If ElogData is NULL,
+ this gives the RecordId of the first record available in the database with the correct DataSize.
+ A value of 0 on return indicates the last record if the EFI_STATUS indicates a success
+
+ @retval EFI_SUCCESS add return values
+
+**/
+EFI_STATUS
+EfiGetElogData (
+ IN EFI_SM_ELOG_PROTOCOL *This,
+ IN UINT8 *ElogData,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN OUT UINTN *DataSize,
+ IN OUT UINT64 *RecordId
+ )
+{
+ if (DataType >= EfiSmElogMax) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EfiLibGetElogData (ElogData, DataType, DataSize, RecordId, mElogModuleGlobal, FALSE);
+}
+
+/**
+ Erases the Event-Log data from the destination.
+
+ @param DataType - Type of Elog Data that is being Erased.
+ @param RecordId - This is the RecordId of the data to be erased. If RecordId is NULL, all
+ the records on the database are erased if permitted by the target.
+ Contains the deleted RecordId on return
+ @param Global - The module global variable pointer.
+ @param Virtual - If this function is called in virtual mode or physical mode
+
+ @retval EFI_SUCCESS - Event-Log was erased successfully
+ @retval EFI_UNSUPPORTED - The Data Type is unsupported
+ @retval EFI_NOT_FOUND - Event-Log target not found
+
+**/
+EFI_STATUS
+EfiLibEraseElogData (
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN OUT UINT64 *RecordId,
+ IN ELOG_MODULE_GLOBAL *Global,
+ IN BOOLEAN Virtual
+ )
+{
+ UINT8 Index;
+ VOID *ElogRedirCommand;
+ EFI_STATUS Status;
+ EFI_STATUS RetStatus;
+
+ RetStatus = EFI_UNSUPPORTED;
+
+ if (DataType >= EfiSmElogMax) {
+ RetStatus = EFI_INVALID_PARAMETER;
+ return RetStatus;
+ }
+
+ for (Index = 0; Index < Global->MaxDescriptors; Index++) {
+ if (Global->Redir[Index].Valid) {
+ ElogRedirCommand = Global->Redir[Index].Command[Virtual].EraseEventLogData.Function;
+ Status = (*((EFI_ERASE_ELOG_DATA *)&ElogRedirCommand))(Global->Redir[Index].Command[Virtual].This, DataType, RecordId);
+
+ if (!EFI_ERROR (Status)) {
+ RetStatus = EFI_SUCCESS;
+ break;
+ } else if (Status != EFI_UNSUPPORTED) {
+ RetStatus = Status;
+ break;
+ }
+ }
+ }
+
+ return RetStatus;
+}
+
+/**
+ Efi Erase Elog Data.
+
+ @param This
+ @param DataType
+ @param RecordId
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EfiEraseElogData (
+ IN EFI_SM_ELOG_PROTOCOL *This,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN OUT UINT64 *RecordId
+ )
+{
+ return EfiLibEraseElogData (DataType, RecordId, mElogModuleGlobal, FALSE);
+}
+
+/**
+ This API enables/Disables Event Log.
+
+ @param DataType - Type of Elog Data that is being Activated.
+ @param EnableElog - Enables (TRUE) / Disables (FALSE) Event Log. If NULL just returns the
+ Current ElogStatus.
+ @param ElogStatus - Current (New) Status of Event Log. Enabled (TRUE), Disabled (FALSE).
+ @param Global - The module global variable pointer.
+ @param Virtual - If this function is called in virtual mode or physical mode
+
+ @retval EFI_SUCCESS - Event-Log was recorded successfully
+ @retval EFI_UNSUPPORTED - The Data Type is unsupported
+
+**/
+EFI_STATUS
+EfiLibActivateElog (
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN BOOLEAN *EnableElog,
+ OUT BOOLEAN *ElogStatus,
+ ELOG_MODULE_GLOBAL *Global,
+ BOOLEAN Virtual
+ )
+{
+ UINT8 Index;
+ VOID *ElogRedirCommand;
+ EFI_STATUS Status;
+ EFI_STATUS RetStatus;
+
+ RetStatus = EFI_UNSUPPORTED;
+ if (DataType >= EfiSmElogMax) {
+ RetStatus = EFI_INVALID_PARAMETER;
+ return RetStatus;
+ }
+
+ for (Index = 0; Index < Global->MaxDescriptors; Index++) {
+ if (Global->Redir[Index].Valid) {
+ ElogRedirCommand = Global->Redir[Index].Command[Virtual].ActivateEventLog.Function;
+ Status = (*((EFI_ACTIVATE_ELOG *)&ElogRedirCommand))(Global->Redir[Index].Command[Virtual].This, DataType, EnableElog, ElogStatus);
+
+ if (!EFI_ERROR (Status)) {
+ RetStatus = EFI_SUCCESS;
+ break;
+ } else if (Status != EFI_UNSUPPORTED) {
+ RetStatus = Status;
+ break;
+ }
+ }
+ }
+
+ return RetStatus;
+}
+
+/**
+ Efi Activate Elog.
+
+ @param This
+ @param DataType
+ @param EnableElog
+ @param ElogStatus
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EfiActivateElog (
+ IN EFI_SM_ELOG_PROTOCOL *This,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN BOOLEAN *EnableElog,
+ OUT BOOLEAN *ElogStatus
+ )
+{
+ if (DataType >= EfiSmElogMax) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EfiLibActivateElog (DataType, EnableElog, ElogStatus, mElogModuleGlobal, FALSE);
+}
+
+/**
+ SetElogRedirInstances.
+
+ @retval EFI_SUCCESS - The Redir instances were successfully set.
+ @retval Other - Failed to set Redir instances.
+
+**/
+EFI_STATUS
+SetElogRedirInstances (
+ VOID
+ )
+{
+ UINTN NumHandles;
+ UINTN Index;
+ UINTN Instance;
+ UINTN EmptyIndex;
+ EFI_HANDLE *Buffer;
+ EFI_STATUS Status;
+ EFI_SM_ELOG_REDIR_PROTOCOL *Redir;
+ REDIR_MODULE_PROC *RedirProc;
+
+ Buffer = NULL;
+
+ //
+ // Check for all IPMI Controllers
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiRedirElogProtocolGuid,
+ NULL,
+ &NumHandles,
+ &Buffer
+ );
+
+ if (EFI_ERROR (Status) || (NumHandles == 0)) {
+ return EFI_SUCCESS;
+ }
+
+ for (Index = 0; ((Index < NumHandles) && (Index < mElogModuleGlobal->MaxDescriptors)); Index++) {
+ EmptyIndex = mElogModuleGlobal->MaxDescriptors;
+
+ Status = gBS->HandleProtocol (
+ Buffer[Index],
+ &gEfiRedirElogProtocolGuid,
+ (VOID *)&Redir
+ );
+ if (EFI_ERROR (Status) || (Redir == NULL)) {
+ continue;
+ }
+
+ for (Instance = 0; Instance < mElogModuleGlobal->MaxDescriptors; Instance++) {
+ if (mElogModuleGlobal->Redir[Instance].Valid == FALSE) {
+ if (EmptyIndex >= mElogModuleGlobal->MaxDescriptors) {
+ EmptyIndex = Instance;
+ }
+ } else {
+ if (Redir == mElogModuleGlobal->Redir[Instance].Command->This) {
+ EmptyIndex = mElogModuleGlobal->MaxDescriptors;
+ break;
+ //
+ // FIX: changed continue to break.
+ //
+ }
+ }
+ }
+
+ if (EmptyIndex < mElogModuleGlobal->MaxDescriptors) {
+ RedirProc = (REDIR_MODULE_PROC *)mElogModuleGlobal->Redir[EmptyIndex].Command;
+ mElogModuleGlobal->Redir[EmptyIndex].Valid = TRUE;
+
+ EfiSetFunctionEntry (&RedirProc->ActivateEventLog, *((VOID **)&Redir->ActivateEventLog));
+ EfiSetFunctionEntry (&RedirProc->EraseEventLogData, *((VOID **)&Redir->EraseEventlogData));
+ EfiSetFunctionEntry (&RedirProc->GetEventLogData, *((VOID **)&Redir->GetEventLogData));
+ EfiSetFunctionEntry (&RedirProc->SetEventLogData, *((VOID **)&Redir->SetEventLogData));
+ RedirProc->This = Redir;
+
+ CopyMem (&RedirProc[EFI_ELOG_VIRTUAL], &RedirProc[EFI_ELOG_PHYSICAL], sizeof (REDIR_MODULE_PROC));
+ }
+ }
+
+ if (Buffer != NULL) {
+ FreePool (Buffer);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This notification function is invoked when an instance of the
+ ELOG REDIR protocol is produced.
+
+ @param Event - The event that occurred
+ @param Context - For EFI compatibility. Not used.
+
+**/
+VOID
+EFIAPI
+NotifyElogRedirEventCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ SetElogRedirInstances ();
+}
+
+/**
+ Initialize the generic Elog driver of server management.
+
+ @param ImageHandle - The image handle of this driver
+ @param SystemTable - The pointer of EFI_SYSTEM_TABLE
+
+ @retval EFI_SUCCESS - The driver initialized successfully
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeElogLayer (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_HANDLE NewHandle;
+ EFI_STATUS Status;
+ EFI_SM_ELOG_PROTOCOL *ElogProtocol;
+ EFI_EVENT Event;
+
+ mElogModuleGlobal = AllocateZeroPool (sizeof (ELOG_MODULE_GLOBAL));
+ ASSERT (mElogModuleGlobal != NULL);
+ if (mElogModuleGlobal == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ElogServiceInitialize (ImageHandle, SystemTable);
+
+ mElogModuleGlobal->MaxDescriptors = MAX_REDIR_DESCRIPTOR;
+
+ //
+ // Check for all IPMI Controllers
+ //
+ SetElogRedirInstances ();
+
+ ElogProtocol = AllocatePool (sizeof (EFI_SM_ELOG_PROTOCOL));
+ ASSERT (ElogProtocol != NULL);
+ if (ElogProtocol == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ElogProtocol->ActivateEventLog = EfiActivateElog;
+ ElogProtocol->EraseEventlogData = EfiEraseElogData;
+ ElogProtocol->GetEventLogData = EfiGetElogData;
+ ElogProtocol->SetEventLogData = EfiSetElogData;
+
+ NewHandle = NULL;
+ Status = gBS->InstallProtocolInterface (
+ &NewHandle,
+ &gEfiGenericElogProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ ElogProtocol
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ if (Status != EFI_SUCCESS) {
+ return Status;
+ }
+
+ //
+ // Register to be notified when the ELOG REDIR protocol has been
+ // produced.
+ //
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ NotifyElogRedirEventCallback,
+ NULL,
+ &Event
+ );
+
+ if (!EFI_ERROR (Status)) {
+ Status = gBS->RegisterProtocolNotify (
+ &gEfiRedirElogProtocolGuid,
+ Event,
+ &mEfiElogRedirProtocolEvent
+ );
+ }
+
+ return Status;
+}
+
+/**
+ Set the function entry.
+
+ @param FunctionPointer - The destination function pointer
+ @param Function - The source function pointer
+
+ @retval EFI_SUCCESS - Set the function pointer successfully
+
+**/
+EFI_STATUS
+EfiSetFunctionEntry (
+ IN FUNCTION_PTR *FunctionPointer,
+ IN VOID *Function
+ )
+{
+ FunctionPointer->Function = (EFI_PLABEL *)Function;
+ return EFI_SUCCESS;
+}
+
+/**
+ Initialize Dxe generic event log.
+
+ @param ImageHandle - The Image handle of this driver.
+ @param SystemTable - The pointer of EFI_SYSTEM_TABLE.
+
+ @retval EFI_SUCCESS - The driver successfully initialized
+
+**/
+EFI_STATUS
+ElogServiceInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ return EFI_SUCCESS;
+}
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Smm/GenericElog.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Smm/GenericElog.c
new file mode 100644
index 000000000000..d6a129a181fb
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Smm/GenericElog.c
@@ -0,0 +1,558 @@
+/** @file
+ Generic Event Log functions of SMM driver.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "GenericElog.h"
+
+ELOG_MODULE_GLOBAL *mElogModuleGlobal;
+
+//
+// Define module globals used to register for notification of when
+// the ELOG REDIR protocol has been produced.
+//
+EFI_EVENT mEfiElogRedirProtocolEvent;
+
+/**
+ Sends the Event-Log data to the destination.
+
+ @param ElogData - Pointer to the Event-Log data that needs to be recorded.
+ @param DataType - Type of Elog Data that is being recorded.
+ @param AlertEvent - This is an indication that the input data type is an Alert.
+ @param DataSize - Size of the data to be logged.
+ @param RecordId - Record ID sent by the target.
+ @param Global - The module global variable pointer.
+ @param Virtual - If this function is called in virtual mode or physical mode
+
+ @retval EFI_SUCCESS - Event-Log was recorded successfully.
+ @retval EFI_OUT_OF_RESOURCES - Not enough resources to record data.
+ @retval EFI_UNSUPPORTED - The Data Type is unsupported.
+
+**/
+EFI_STATUS
+EfiLibSetElogData (
+ IN UINT8 *ElogData,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN BOOLEAN AlertEvent,
+ IN UINTN DataSize,
+ OUT UINT64 *RecordId,
+ IN ELOG_MODULE_GLOBAL *Global,
+ IN BOOLEAN Virtual
+ )
+{
+ UINT8 Index;
+ VOID *ElogRedirCommand;
+ EFI_STATUS Status;
+ EFI_STATUS RetStatus;
+
+ RetStatus = EFI_UNSUPPORTED;
+
+ if (DataType >= EfiSmElogMax) {
+ RetStatus = EFI_INVALID_PARAMETER;
+ return RetStatus;
+ }
+
+ for (Index = 0; Index < Global->MaxDescriptors; Index++) {
+ if (Global->Redir[Index].Valid) {
+ ElogRedirCommand = Global->Redir[Index].Command[Virtual].SetEventLogData.Function;
+ Status = (*((EFI_SET_ELOG_DATA *)&ElogRedirCommand))(Global->Redir[Index].Command[Virtual].This, ElogData, DataType, AlertEvent, DataSize, RecordId);
+
+ if (!EFI_ERROR (Status)) {
+ RetStatus = EFI_SUCCESS;
+ break;
+ } else if (Status != EFI_UNSUPPORTED) {
+ RetStatus = Status;
+ break;
+ }
+ }
+ }
+
+ return RetStatus;
+}
+
+/**
+ Efi Set Elog Data.
+
+ @param This
+ @param ElogData
+ @param DataType
+ @param AlertEvent
+ @param DataSize
+ @param RecordId
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EfiSetElogData (
+ IN EFI_SM_ELOG_PROTOCOL *This,
+ IN UINT8 *ElogData,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN BOOLEAN AlertEvent,
+ IN UINTN DataSize,
+ OUT UINT64 *RecordId
+ )
+{
+ if (DataType >= EfiSmElogMax) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EfiLibSetElogData (
+ ElogData,
+ DataType,
+ AlertEvent,
+ DataSize,
+ RecordId,
+ mElogModuleGlobal,
+ FALSE
+ );
+}
+
+/**
+ Gets the Event-Log data from the destination.
+
+ @param ElogData - Pointer to the Event-Log data buffer that will contain the data to be retrieved.
+ @param DataType - Type of Elog Data that is being recorded.
+ @param DataSize - Size of the data to be retrieved. .
+ @param RecordId - This is the RecordId of the next record. If ElogData is NULL,
+ this gives the RecordId of the first record available in the database with the correct DataSize.
+ A value of 0 on return indicates the last record if the EFI_STATUS indicates a success
+ @param Global - The module global variable pointer.
+ @param Virtual - If this function is called in virtual mode or physical mode
+
+ @retval EFI_SUCCESS - Event-Log was retrieved successfully.
+ @retval EFI_NOT_FOUND - Event-Log target not found.
+ @retval EFI_BUFFER_TOO_SMALL - Target buffer is too small to retrieve the data.
+ @retval EFI_UNSUPPORTED - The Data Type is unsupported
+
+**/
+EFI_STATUS
+EfiLibGetElogData (
+ IN UINT8 *ElogData,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN OUT UINTN *DataSize,
+ IN OUT UINT64 *RecordId,
+ IN ELOG_MODULE_GLOBAL *Global,
+ IN BOOLEAN Virtual
+ )
+{
+ UINT8 Index;
+ VOID *ElogRedirCommand;
+ EFI_STATUS Status;
+ EFI_STATUS RetStatus;
+
+ RetStatus = EFI_UNSUPPORTED;
+
+ if (DataType >= EfiSmElogMax) {
+ RetStatus = EFI_INVALID_PARAMETER;
+ return RetStatus;
+ }
+
+ for (Index = 0; Index < Global->MaxDescriptors; Index++) {
+ if (Global->Redir[Index].Valid) {
+ ElogRedirCommand = Global->Redir[Index].Command[Virtual].GetEventLogData.Function;
+ Status = (*((EFI_GET_ELOG_DATA *)&ElogRedirCommand))(Global->Redir[Index].Command[Virtual].This, ElogData, DataType, DataSize, RecordId);
+
+ if (!EFI_ERROR (Status)) {
+ RetStatus = EFI_SUCCESS;
+ break;
+ } else if (Status != EFI_UNSUPPORTED) {
+ RetStatus = Status;
+ break;
+ }
+ }
+ }
+
+ return RetStatus;
+}
+
+/**
+ Efi Get Elog Data.
+
+ @param This
+ @param ElogData
+ @param DataType
+ @param DataSize
+ @param RecordId
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EfiGetElogData (
+ IN EFI_SM_ELOG_PROTOCOL *This,
+ IN UINT8 *ElogData,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN OUT UINTN *DataSize,
+ IN OUT UINT64 *RecordId
+ )
+{
+ if (DataType >= EfiSmElogMax) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EfiLibGetElogData (ElogData, DataType, DataSize, RecordId, mElogModuleGlobal, FALSE);
+}
+
+/**
+ Erases the Event-Log data from the destination.
+
+ @param DataType - Type of Elog Data that is being Erased.
+ @param RecordId - This is the RecordId of the data to be erased. If RecordId is NULL, all
+ the records on the database are erased if permitted by the target.
+ Contains the deleted RecordId on return
+ @param Global - The module global variable pointer.
+ @param Virtual - If this function is called in virtual mode or physical mode
+
+ @retval EFI_SUCCESS - Event-Log was erased successfully
+ @retval EFI_UNSUPPORTED - The Data Type is unsupported
+ @retval EFI_NOT_FOUND - Event-Log target not found
+
+**/
+EFI_STATUS
+EfiLibEraseElogData (
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN OUT UINT64 *RecordId,
+ IN ELOG_MODULE_GLOBAL *Global,
+ IN BOOLEAN Virtual
+ )
+{
+ UINT8 Index;
+ VOID *ElogRedirCommand;
+ EFI_STATUS Status;
+ EFI_STATUS RetStatus;
+
+ RetStatus = EFI_UNSUPPORTED;
+
+ if (DataType >= EfiSmElogMax) {
+ RetStatus = EFI_INVALID_PARAMETER;
+ return RetStatus;
+ }
+
+ for (Index = 0; Index < Global->MaxDescriptors; Index++) {
+ if (Global->Redir[Index].Valid) {
+ ElogRedirCommand = Global->Redir[Index].Command[Virtual].EraseEventLogData.Function;
+ Status = (*((EFI_ERASE_ELOG_DATA *)&ElogRedirCommand))(Global->Redir[Index].Command[Virtual].This, DataType, RecordId);
+
+ if (!EFI_ERROR (Status)) {
+ RetStatus = EFI_SUCCESS;
+ break;
+ } else if (Status != EFI_UNSUPPORTED) {
+ RetStatus = Status;
+ break;
+ }
+ }
+ }
+
+ return RetStatus;
+}
+
+/**
+ Efi Erase Elog Data
+
+ @param This
+ @param DataType
+ @param RecordId
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EfiEraseElogData (
+ IN EFI_SM_ELOG_PROTOCOL *This,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN OUT UINT64 *RecordId
+ )
+{
+ return EfiLibEraseElogData (DataType, RecordId, mElogModuleGlobal, FALSE);
+}
+
+/**
+ This API enables/Disables Event Log.
+
+ @param DataType - Type of Elog Data that is being Activated.
+ @param EnableElog - Enables (TRUE) / Disables (FALSE) Event Log. If NULL just returns the
+ Current ElogStatus.
+ @param ElogStatus - Current (New) Status of Event Log. Enabled (TRUE), Disabled (FALSE).
+ @param Global - The module global variable pointer.
+ @param Virtual - If this function is called in virtual mode or physical mode
+
+ @retval EFI_SUCCESS - Event-Log was recorded successfully
+ @retval EFI_UNSUPPORTED - The Data Type is unsupported
+
+**/
+EFI_STATUS
+EfiLibActivateElog (
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN BOOLEAN *EnableElog,
+ OUT BOOLEAN *ElogStatus,
+ ELOG_MODULE_GLOBAL *Global,
+ BOOLEAN Virtual
+ )
+{
+ UINT8 Index;
+ VOID *ElogRedirCommand;
+ EFI_STATUS Status;
+ EFI_STATUS RetStatus;
+
+ RetStatus = EFI_UNSUPPORTED;
+ if (DataType >= EfiSmElogMax) {
+ RetStatus = EFI_INVALID_PARAMETER;
+ return RetStatus;
+ }
+
+ for (Index = 0; Index < Global->MaxDescriptors; Index++) {
+ if (Global->Redir[Index].Valid) {
+ ElogRedirCommand = Global->Redir[Index].Command[Virtual].ActivateEventLog.Function;
+ Status = (*((EFI_ACTIVATE_ELOG *)&ElogRedirCommand))(Global->Redir[Index].Command[Virtual].This, DataType, EnableElog, ElogStatus);
+
+ if (!EFI_ERROR (Status)) {
+ RetStatus = EFI_SUCCESS;
+ break;
+ } else if (Status != EFI_UNSUPPORTED) {
+ RetStatus = Status;
+ break;
+ }
+ }
+ }
+
+ return RetStatus;
+}
+
+/**
+ Efi Activate Elog.
+
+ @param This
+ @param DataType
+ @param EnableElog
+ @param ElogStatus
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EfiActivateElog (
+ IN EFI_SM_ELOG_PROTOCOL *This,
+ IN EFI_SM_ELOG_TYPE DataType,
+ IN BOOLEAN *EnableElog,
+ OUT BOOLEAN *ElogStatus
+ )
+{
+ if (DataType >= EfiSmElogMax) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EfiLibActivateElog (DataType, EnableElog, ElogStatus, mElogModuleGlobal, FALSE);
+}
+
+/**
+ Set Elog Redir Instances.
+
+ @retval EFI_SUCCESS - The Redir instances were successfully set.
+ @retval Other - Failed to set Redir instances.
+
+**/
+EFI_STATUS
+SetElogRedirInstances (
+ VOID
+ )
+{
+ UINTN NumHandles;
+ UINTN Index;
+ UINTN Instance;
+ UINTN EmptyIndex;
+ EFI_HANDLE *Buffer;
+ EFI_STATUS Status;
+ EFI_SM_ELOG_REDIR_PROTOCOL *Redir;
+ REDIR_MODULE_PROC *RedirProc;
+
+ Buffer = NULL;
+
+ //
+ // Check for all IPMI Controllers
+ //
+ Status = gSmst->SmmLocateHandle (
+ ByProtocol,
+ &gSmmRedirElogProtocolGuid,
+ NULL,
+ &NumHandles,
+ Buffer
+ );
+
+ if (EFI_ERROR (Status) || (NumHandles == 0) || (Buffer == NULL)) {
+ return Status;
+ }
+
+ for (Index = 0; ((Index < NumHandles) && (Index < mElogModuleGlobal->MaxDescriptors)); Index++) {
+ EmptyIndex = mElogModuleGlobal->MaxDescriptors;
+
+ Status = gSmst->SmmHandleProtocol (
+ Buffer[Index],
+ &gSmmRedirElogProtocolGuid,
+ (VOID *)&Redir
+ );
+ if (EFI_ERROR (Status) || (Redir == NULL)) {
+ continue;
+ }
+
+ for (Instance = 0; Instance < mElogModuleGlobal->MaxDescriptors; Instance++) {
+ if (mElogModuleGlobal->Redir[Instance].Valid == FALSE) {
+ if (EmptyIndex >= mElogModuleGlobal->MaxDescriptors) {
+ EmptyIndex = Instance;
+ }
+ } else {
+ if (Redir == mElogModuleGlobal->Redir[Instance].Command->This) {
+ EmptyIndex = mElogModuleGlobal->MaxDescriptors;
+ break;
+ //
+ // FIX: changed continue to break.
+ //
+ }
+ }
+ }
+
+ if (EmptyIndex < mElogModuleGlobal->MaxDescriptors) {
+ RedirProc = (REDIR_MODULE_PROC *)mElogModuleGlobal->Redir[EmptyIndex].Command;
+ mElogModuleGlobal->Redir[EmptyIndex].Valid = TRUE;
+
+ EfiSetFunctionEntry (&RedirProc->ActivateEventLog, *((VOID **)&Redir->ActivateEventLog));
+ EfiSetFunctionEntry (&RedirProc->EraseEventLogData, *((VOID **)&Redir->EraseEventlogData));
+ EfiSetFunctionEntry (&RedirProc->GetEventLogData, *((VOID **)&Redir->GetEventLogData));
+ EfiSetFunctionEntry (&RedirProc->SetEventLogData, *((VOID **)&Redir->SetEventLogData));
+ RedirProc->This = Redir;
+
+ CopyMem (&RedirProc[EFI_ELOG_VIRTUAL], &RedirProc[EFI_ELOG_PHYSICAL], sizeof (REDIR_MODULE_PROC));
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This notification function is invoked when an instance of the
+ ELOG REDIR protocol is produced.
+
+ @param Event - The event that occurred
+ @param Context - For EFI compatibility. Not used.
+
+**/
+VOID
+EFIAPI
+NotifyElogRedirEventCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ SetElogRedirInstances ();
+}
+
+/**
+ Initialize the generic Elog driver of server management.
+
+ @param ImageHandle - The image handle of this driver
+ @param SystemTable - The pointer of EFI_SYSTEM_TABLE
+
+ @retval EFI_SUCCESS - The driver initialized successfully
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeSmElogLayer (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_HANDLE NewHandle;
+ EFI_STATUS Status;
+ EFI_SM_ELOG_PROTOCOL *ElogProtocol;
+
+ mElogModuleGlobal = AllocatePool (sizeof (ELOG_MODULE_GLOBAL));
+ ASSERT (mElogModuleGlobal != NULL);
+ if (mElogModuleGlobal == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ SmElogServiceInitialize (ImageHandle, SystemTable);
+
+ mElogModuleGlobal->MaxDescriptors = MAX_REDIR_DESCRIPTOR;
+
+ //
+ // Check for all IPMI Controllers
+ //
+ SetElogRedirInstances ();
+
+ ElogProtocol = AllocatePool (sizeof (EFI_SM_ELOG_PROTOCOL));
+ ASSERT (ElogProtocol != NULL);
+ if (ElogProtocol == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ElogProtocol->ActivateEventLog = (EFI_ACTIVATE_ELOG)EfiActivateElog;
+ ElogProtocol->EraseEventlogData = (EFI_ERASE_ELOG_DATA)EfiEraseElogData;
+ ElogProtocol->GetEventLogData = (EFI_GET_ELOG_DATA)EfiGetElogData;
+ ElogProtocol->SetEventLogData = (EFI_SET_ELOG_DATA)EfiSetElogData;
+
+ NewHandle = NULL;
+ Status = gSmst->SmmInstallProtocolInterface (
+ &NewHandle,
+ &gSmmGenericElogProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ ElogProtocol
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ if (Status != EFI_SUCCESS) {
+ return Status;
+ }
+
+ //
+ // Register to be notified when the ELOG REDIR protocol has been
+ // produced.
+ //
+ Status = gSmst->SmmRegisterProtocolNotify (
+ &gSmmRedirElogProtocolGuid,
+ NULL,
+ &mEfiElogRedirProtocolEvent
+ );
+ return Status;
+}
+
+/**
+ Set the function entry.
+
+ @param FunctionPointer - The destination function pointer
+ @param Function - The source function pointer
+
+ @retval EFI_SUCCESS - Set the function pointer successfully
+
+**/
+EFI_STATUS
+EfiSetFunctionEntry (
+ IN FUNCTION_PTR *FunctionPointer,
+ IN VOID *Function
+ )
+{
+ FunctionPointer->Function = (EFI_PLABEL *)Function;
+ return EFI_SUCCESS;
+}
+
+/**
+ Entry point of SM Elog service Driver
+
+ @param ImageHandle - The Image handle of this driver.
+ @param SystemTable - The pointer of EFI_SYSTEM_TABLE.
+
+ @retval EFI_SUCCESS - The driver successfully initialized
+
+**/
+EFI_STATUS
+SmElogServiceInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ return EFI_SUCCESS;
+}
--
2.39.2.windows.1
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#110229): https://edk2.groups.io/g/devel/message/110229
Mute This Topic: https://groups.io/mt/102231766/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [edk2-devel] [PATCH edk2-platforms 2/4] IpmiFeaturePkg: Add ServerManagementLib
2023-10-27 20:11 [edk2-devel] [PATCH edk2-platforms 0/4] IpmiFeaturePkg: Add server management features Zhen Gong
2023-10-27 20:11 ` [edk2-devel] [PATCH edk2-platforms 1/4] IpmiFeaturePkg: Add Elog drivers Zhen Gong
@ 2023-10-27 20:11 ` Zhen Gong
2023-10-27 20:11 ` [edk2-devel] [PATCH edk2-platforms 3/4] IpmiFeaturePkg: Add ACPI power state drivers Zhen Gong
` (2 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Zhen Gong @ 2023-10-27 20:11 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 (#110230): https://edk2.groups.io/g/devel/message/110230
Mute This Topic: https://groups.io/mt/102231767/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 3/4] IpmiFeaturePkg: Add ACPI power state drivers
2023-10-27 20:11 [edk2-devel] [PATCH edk2-platforms 0/4] IpmiFeaturePkg: Add server management features Zhen Gong
2023-10-27 20:11 ` [edk2-devel] [PATCH edk2-platforms 1/4] IpmiFeaturePkg: Add Elog drivers Zhen Gong
2023-10-27 20:11 ` [edk2-devel] [PATCH edk2-platforms 2/4] IpmiFeaturePkg: Add ServerManagementLib Zhen Gong
@ 2023-10-27 20:11 ` Zhen Gong
2023-10-27 20:11 ` [edk2-devel] [PATCH edk2-platforms 4/4] IpmiFeaturePkg: Add FRU drivers Zhen Gong
2023-10-29 1:58 ` [edk2-devel] [PATCH edk2-platforms 0/4] IpmiFeaturePkg: Add server management features Chang, Abner via groups.io
4 siblings, 0 replies; 7+ messages in thread
From: Zhen Gong @ 2023-10-27 20:11 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 (#110231): https://edk2.groups.io/g/devel/message/110231
Mute This Topic: https://groups.io/mt/102231768/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 4/4] IpmiFeaturePkg: Add FRU drivers
2023-10-27 20:11 [edk2-devel] [PATCH edk2-platforms 0/4] IpmiFeaturePkg: Add server management features Zhen Gong
` (2 preceding siblings ...)
2023-10-27 20:11 ` [edk2-devel] [PATCH edk2-platforms 3/4] IpmiFeaturePkg: Add ACPI power state drivers Zhen Gong
@ 2023-10-27 20:11 ` Zhen Gong
2023-10-29 1:58 ` [edk2-devel] [PATCH edk2-platforms 0/4] IpmiFeaturePkg: Add server management features Chang, Abner via groups.io
4 siblings, 0 replies; 7+ messages in thread
From: Zhen Gong @ 2023-10-27 20:11 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>
---
.../IpmiFeaturePkg/IpmiFeaturePkg.dec | 4 +
.../IpmiFeaturePkg/Include/IpmiFeature.dsc | 3 +-
.../IpmiFeaturePkg/Include/PostMemory.fdf | 3 +-
.../IpmiFeaturePkg/GenericFru/GenericFru.inf | 42 ++
.../IpmiFeaturePkg/IpmiFru/IpmiFru.inf | 35 --
.../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(+), 104 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 322f061a0fff..000000000000
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFru/IpmiFru.inf
+++ /dev/null
@@ -1,35 +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
- 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 (#110232): https://edk2.groups.io/g/devel/message/110232
Mute This Topic: https://groups.io/mt/102231769/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 0/4] IpmiFeaturePkg: Add server management features
2023-10-27 20:11 [edk2-devel] [PATCH edk2-platforms 0/4] IpmiFeaturePkg: Add server management features Zhen Gong
` (3 preceding siblings ...)
2023-10-27 20:11 ` [edk2-devel] [PATCH edk2-platforms 4/4] IpmiFeaturePkg: Add FRU drivers Zhen Gong
@ 2023-10-29 1:58 ` Chang, Abner via groups.io
2023-10-29 21:07 ` Zhen Gong
4 siblings, 1 reply; 7+ messages in thread
From: Chang, Abner via groups.io @ 2023-10-29 1:58 UTC (permalink / raw)
To: devel@edk2.groups.io, zhen.gong@intel.com
[AMD Official Use Only - General]
Hi Gong,
Please note that your code may have conflict as IpmiCommandLib was removed (please check https://edk2.groups.io/g/devel/message/109510), now we are using the one under MdeModulePKg.
Second, I had cleaned up those server management feature drivers and migrated those to under ManageabilityPkg with Issac RB, please check commit ID from b6a5124e to d6f18259. That would be not good if Intel keeps updating IpmiFeaturePkg. As those drivers are higher level applications on top of transport, It shouldn't have a problem to just update the changes against ManageabilityPkg. Is there any issues Intel met if uses IPMI feature drivers from Manageability? If yes, we can address the issue instead of making them diverging.
Thanks
Abner
> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Zhen
> Gong via groups.io
> Sent: Saturday, October 28, 2023 4:11 AM
> To: devel@edk2.groups.io
> Cc: Zhen Gong <zhen.gong@intel.com>
> Subject: [edk2-devel] [PATCH edk2-platforms 0/4] IpmiFeaturePkg: Add
> server management features
>
> Caution: This message originated from an External Source. Use proper caution
> when opening attachments, clicking links, or responding.
>
>
> 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.
>
>
> 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} | 25 +-
> .../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 | 35 -
> .../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, 7242 insertions(+), 348 deletions(-)
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiState/Bmc
> AcpiState.inf
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiSwChild/B
> mcAcpiSwChild.inf
> rename
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/{BmcElog.i
> nf => DxeBmcElog.inf} (56%)
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/PeiBmcElo
> g.inf
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/SmmBmc
> Elog.inf
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Dxe/Ge
> nericElog.inf
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Smm/
> GenericElog.inf
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericFru/Generic
> Fru.inf
> delete mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFru/IpmiFru.inf
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRedirFru/IpmiR
> edirFru.inf
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerMana
> gementLib/ServerManagementLib.inf
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerMana
> gementLibNull/ServerManagementLibNull.inf
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiState/Bmc
> AcpiState.h
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiSwChild/B
> mcAcpiSwChild.h
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Common/
> BmcElogCommon.h
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Dxe/BmcE
> log.h
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Pei/BmcEl
> og.h
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Smm/Bmc
> Elog.h
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Dxe/Ge
> nericElog.h
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Smm/
> GenericElog.h
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericFru/Generic
> FruDriver.h
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Library/Ser
> verMgmtRtLib.h
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Ppi/Generic
> Elog.h
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/B
> mcAcpiSwChildPolicy.h
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/G
> enericElog.h
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/G
> enericFru.h
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/R
> edirFru.h
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRedirFru/IpmiR
> edirFru.h
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiState/Bmc
> AcpiState.c
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiSwChild/B
> mcAcpiSwChild.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/BmcE
> log.c
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Pei/BmcEl
> og.c
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Smm/Bmc
> Elog.c
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Dxe/Ge
> nericElog.c
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Smm/
> GenericElog.c
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericFru/Generic
> Fru.c
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericFru/Generic
> FruDriver.c
> delete mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFru/IpmiFru.c
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRedirFru/FruS
> mbios.c
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRedirFru/IpmiR
> edirFru.c
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerMana
> gementLib/ServerManagementLib.c
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerMana
> gementLibNull/ServerManagementLibNull.c
>
> --
> 2.39.2.windows.1
>
>
>
>
>
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#110254): https://edk2.groups.io/g/devel/message/110254
Mute This Topic: https://groups.io/mt/102231765/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 0/4] IpmiFeaturePkg: Add server management features
2023-10-29 1:58 ` [edk2-devel] [PATCH edk2-platforms 0/4] IpmiFeaturePkg: Add server management features Chang, Abner via groups.io
@ 2023-10-29 21:07 ` Zhen Gong
0 siblings, 0 replies; 7+ messages in thread
From: Zhen Gong @ 2023-10-29 21:07 UTC (permalink / raw)
To: devel@edk2.groups.io, Chang, Abner
Hi Abner,
Thanks for the heads-up.
I caught your commit right before submitting the patch. MdeModulePKg is already consumed by all libraries referencing the header.
However there's a merge conflict now and I just sent out a v2 version to address it.
Regarding to the migration to ManageabilityPkg, we have evaluated whether to adopt it directly.
Given the long time frame of silicon development, we are not going to make big changes for current platforms.
And we chose to keep using IpmiFeaturePkg and upstream drivers with minimum changes required for now.
The decision is more about lifecycle management, other than technical standpoint.
Going forward, we will re-evaluate the open and bring it to newer platforms.
Thanks,
Zhen
-----Original Message-----
From: Chang, Abner <Abner.Chang@amd.com>
Sent: Saturday, October 28, 2023 6:59 PM
To: devel@edk2.groups.io; Gong, Zhen <zhen.gong@intel.com>
Subject: RE: [edk2-devel] [PATCH edk2-platforms 0/4] IpmiFeaturePkg: Add server management features
[AMD Official Use Only - General]
Hi Gong,
Please note that your code may have conflict as IpmiCommandLib was removed (please check https://edk2.groups.io/g/devel/message/109510), now we are using the one under MdeModulePKg.
Second, I had cleaned up those server management feature drivers and migrated those to under ManageabilityPkg with Issac RB, please check commit ID from b6a5124e to d6f18259. That would be not good if Intel keeps updating IpmiFeaturePkg. As those drivers are higher level applications on top of transport, It shouldn't have a problem to just update the changes against ManageabilityPkg. Is there any issues Intel met if uses IPMI feature drivers from Manageability? If yes, we can address the issue instead of making them diverging.
Thanks
Abner
> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Zhen
> Gong via groups.io
> Sent: Saturday, October 28, 2023 4:11 AM
> To: devel@edk2.groups.io
> Cc: Zhen Gong <zhen.gong@intel.com>
> Subject: [edk2-devel] [PATCH edk2-platforms 0/4] IpmiFeaturePkg: Add
> server management features
>
> Caution: This message originated from an External Source. Use proper
> caution when opening attachments, clicking links, or responding.
>
>
> 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.
>
>
> 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} | 25 +-
> .../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 | 35 -
> .../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, 7242 insertions(+), 348 deletions(-) create mode
> 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiState/Bmc
> AcpiState.inf
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiSwChild/B
> mcAcpiSwChild.inf
> rename
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/{BmcElog.i
> nf => DxeBmcElog.inf} (56%)
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/PeiBmcElo
> g.inf
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/SmmBmc
> Elog.inf
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Dxe/Ge
> nericElog.inf
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Smm/
> GenericElog.inf
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericFru/Generic
> Fru.inf
> delete mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFru/IpmiFru.inf
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRedirFru/IpmiR
> edirFru.inf
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerMana
> gementLib/ServerManagementLib.inf
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerMana
> gementLibNull/ServerManagementLibNull.inf
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiState/Bmc
> AcpiState.h
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiSwChild/B
> mcAcpiSwChild.h
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Common/
> BmcElogCommon.h
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Dxe/BmcE
> log.h
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Pei/BmcEl
> og.h
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Smm/Bmc
> Elog.h
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Dxe/Ge
> nericElog.h
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Smm/
> GenericElog.h
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericFru/Generic
> FruDriver.h
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Library/Ser
> verMgmtRtLib.h
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Ppi/Generic
> Elog.h
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/B
> mcAcpiSwChildPolicy.h
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/G
> enericElog.h
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/G
> enericFru.h
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/R
> edirFru.h
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRedirFru/IpmiR
> edirFru.h
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiState/Bmc
> AcpiState.c
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiSwChild/B
> mcAcpiSwChild.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/BmcE
> log.c
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Pei/BmcEl
> og.c
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Smm/Bmc
> Elog.c
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Dxe/Ge
> nericElog.c
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Smm/
> GenericElog.c
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericFru/Generic
> Fru.c
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericFru/Generic
> FruDriver.c
> delete mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFru/IpmiFru.c
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRedirFru/FruS
> mbios.c
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRedirFru/IpmiR
> edirFru.c
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerMana
> gementLib/ServerManagementLib.c
> create mode 100644
> Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerMana
> gementLibNull/ServerManagementLibNull.c
>
> --
> 2.39.2.windows.1
>
>
>
>
>
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#110330): https://edk2.groups.io/g/devel/message/110330
Mute This Topic: https://groups.io/mt/102231765/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