From: "Isaac Oram" <isaac.w.oram@intel.com>
To: Arun K <arunk@ami.com>, "devel@edk2.groups.io" <devel@edk2.groups.io>
Cc: "Desimone, Nathaniel L" <nathaniel.l.desimone@intel.com>,
"Ramkumar Krishnamoorthi" <ramkumark@ami.com>,
"Gao, Liming" <gaoliming@byosoft.com.cn>
Subject: Re: [edk2-devel][edk2-platforms][PATCH V3-3] IpmiFeaturePkg:Provided multiple IPMI interface support in Library
Date: Tue, 13 Jun 2023 01:44:50 +0000 [thread overview]
Message-ID: <SA1PR11MB5801ED0D4F220E73ED6303BAD055A@SA1PR11MB5801.namprd11.prod.outlook.com> (raw)
In-Reply-To: <21b9dc3c5e81b4eba7bcb535d69b35d990590e5b.1686573103.git.arunk@ami.com>
The new library function comment blocks have lots of issues mismatching parameters.
Some of the prior issues with coding style. Indents, (, { etc.
This does not seem like the patch series supports git bisect. The first two patches don't build without the third patch.
One thing that is not clear to me is if multiple interfaces are supposed to be supported/enabled at the same time. It seems like sometimes an action is done for each one if enabled, and other times just the first one enabled will perform an action and return. It seems like there is a PCD PcdDefaultSystemInterface to control which interface is enabled. But there doesn't seem to be any error checking. E.G. if I select KCS and have it disabled via PcdKcsInterfaceSupport, this seems like an invalid configuration and there is no build error.
I would suggest that more comments be added to the various PCD describing expected uses and combinations.
I would also request adding details to the edk2-platforms\Features\Intel\OutOfBandManagement\IpmiFeaturePkg\Readme.md describing libraries and their configuration. There are library and configuration sections exactly for explaining these kinds of design options supported and how to configure.
Regards,
Isaac
-----Original Message-----
From: Arun K <arunk@ami.com>
Sent: Monday, June 12, 2023 5:54 AM
To: devel@edk2.groups.io; Arun K <arunk@ami.com>
Cc: Oram, Isaac W <isaac.w.oram@intel.com>; Desimone, Nathaniel L <nathaniel.l.desimone@intel.com>; Ramkumar Krishnamoorthi <ramkumark@ami.com>; Gao, Liming <gaoliming@byosoft.com.cn>
Subject: [edk2-devel][edk2-platforms][PATCH V3-3] IpmiFeaturePkg:Provided multiple IPMI interface support in Library
Created IpmiTransport2 PPI/Protocol to support multiple
IPMI BMC Interface support such as KCS/BT/SSIF with 2 API's
IpmiSubmitCommand2 & IpmiSubmitCommand2Ex.
IpmiSubmitCommand2 - This API use the default interface
(PcdDefaultSystemInterface) to send IPMI command.
IpmiSubmitCommand2Ex - This API use the specific interface type
to send IPMI command which is passed as an argument.
Cc: Isaac Oram <isaac.w.oram@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Signed-off-by: Arun K <arunk@ami.com>
---
.../GenericIpmi/Pei/PeiIpmiHooks.c | 351 +++++++++++
.../GenericIpmi/Pei/PeiIpmiHooks.h | 213 +++++++
.../Include/IpmiNetFnAppDefinitions.h | 239 ++++++++
.../Include/IpmiTransport2Definitions.h | 153 +++++
.../Include/Library/BmcCommonInterfaceLib.h | 200 ++++++
.../Include/Library/BtInterfaceLib.h | 83 +++
.../Include/Library/IpmbInterfaceLib.h | 92 +++
.../Include/Library/SsifInterfaceLib.h | 165 +++++
.../Include/Ppi/IpmiTransport2Ppi.h | 23 +
.../Include/Protocol/IpmiTransport2Protocol.h | 30 +
.../BmcCommonInterfaceLib.c | 228 +++++++
.../BmcCommonInterfaceLib.inf | 26 +
.../BtInterfaceLib/BtInterfaceLib.c | 570 ++++++++++++++++++
.../BtInterfaceLib/BtInterfaceLib.inf | 39 ++
.../IpmbInterfaceLib/DxeIpmbInterfaceLib.c | 94 +++
.../IpmbInterfaceLib/DxeIpmbInterfaceLib.inf | 38 ++
.../IpmbInterfaceLib/IpmbInterfaceLibCommon.c | 351 +++++++++++
.../IpmbInterfaceLib/PeiIpmbInterfaceLib.c | 100 +++
.../IpmbInterfaceLib/PeiIpmbInterfaceLib.inf | 38 ++
.../IpmbInterfaceLib/SmmIpmbInterfaceLib.c | 94 +++
.../IpmbInterfaceLib/SmmIpmbInterfaceLib.inf | 37 ++
.../SsifInterfaceLib/DxeSsifInterfaceLib.c | 131 ++++
.../SsifInterfaceLib/DxeSsifInterfaceLib.inf | 40 ++
.../SsifInterfaceLib/PeiSsifInterfaceLib.c | 123 ++++
.../SsifInterfaceLib/PeiSsifInterfaceLib.inf | 41 ++
.../SsifInterfaceLib/SmmSsifInterfaceLib.c | 148 +++++
.../SsifInterfaceLib/SmmSsifInterfaceLib.inf | 40 ++
.../SsifInterfaceLib/SsifInterfaceLibCommon.c | 546 +++++++++++++++++
28 files changed, 4233 insertions(+)
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiHooks.c
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiHooks.h
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiNetFnAppDefinitions.h
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiTransport2Definitions.h
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Library/BmcCommonInterfaceLib.h
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Library/BtInterfaceLib.h
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Library/IpmbInterfaceLib.h
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Library/SsifInterfaceLib.h
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Ppi/IpmiTransport2Ppi.h
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/IpmiTransport2Protocol.h
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/BmcCommonInterfaceLib.c
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/BmcCommonInterfaceLib.inf
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/BtInterfaceLib/BtInterfaceLib.c
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/BtInterfaceLib/BtInterfaceLib.inf
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/IpmbInterfaceLib/DxeIpmbInterfaceLib.c
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/IpmbInterfaceLib/DxeIpmbInterfaceLib.inf
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/IpmbInterfaceLib/IpmbInterfaceLibCommon.c
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/IpmbInterfaceLib/PeiIpmbInterfaceLib.c
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/IpmbInterfaceLib/PeiIpmbInterfaceLib.inf
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/IpmbInterfaceLib/SmmIpmbInterfaceLib.c
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/IpmbInterfaceLib/SmmIpmbInterfaceLib.inf
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInterfaceLib/DxeSsifInterfaceLib.c
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInterfaceLib/DxeSsifInterfaceLib.inf
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInterfaceLib/PeiSsifInterfaceLib.c
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInterfaceLib/PeiSsifInterfaceLib.inf
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInterfaceLib/SmmSsifInterfaceLib.c
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInterfaceLib/SmmSsifInterfaceLib.inf
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInterfaceLib/SsifInterfaceLibCommon.c
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiHooks.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiHooks.c
new file mode 100644
index 0000000000..bd17cc4a35
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiHooks.c
@@ -0,0 +1,351 @@
+/** @file
+ IPMI common hook functions
+
+ @copyright
+ Copyright 1999 - 2021 Intel Corporation. <BR>
+ Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <ServerManagement.h>
+#include <PeiIpmiHooks.h>
+
+EFI_STATUS
+PeiIpmiSendCommand (
+ IN PEI_IPMI_TRANSPORT_PPI *This,
+ IN UINT8 NetFunction,
+ IN UINT8 Lun,
+ IN UINT8 Command,
+ IN UINT8 *CommandData,
+ IN UINT32 CommandDataSize,
+ IN OUT UINT8 *ResponseData,
+ IN OUT UINT32 *ResponseDataSize
+ )
+/*++
+
+Routine Description:
+
+ Send Ipmi Command in the right mode: HECI or KCS, to the
+ appropiate device, ME or BMC.
+
+Arguments:
+
+ This - Pointer to IPMI protocol instance
+ NetFunction - Net Function of command to send
+ Lun - LUN of command to send
+ Command - IPMI command to send
+ CommandData - Pointer to command data buffer, if needed
+ CommandDataSize - Size of command data buffer
+ ResponseData - Pointer to response data buffer
+ ResponseDataSize - Pointer to response data buffer size
+
+Returns:
+
+ EFI_INVALID_PARAMETER - One of the input values is bad
+ EFI_DEVICE_ERROR - IPMI command failed
+ EFI_BUFFER_TOO_SMALL - Response buffer is too small
+ EFI_UNSUPPORTED - Command is not supported by BMC
+ EFI_SUCCESS - Command completed successfully
+
+--*/
+{
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // This Will be unchanged ( BMC/KCS style )
+ //
+ return PeiIpmiSendCommandToBmc (
+ This,
+ NetFunction,
+ Lun,
+ Command,
+ CommandData,
+ (UINT8) CommandDataSize,
+ ResponseData,
+ (UINT8 *) ResponseDataSize,
+ NULL
+ );
+} // IpmiSendCommand()
+
+EFI_STATUS
+PeiIpmiSendCommand2 (
+ IN IPMI_TRANSPORT2 *This,
+ IN UINT8 NetFunction,
+ IN UINT8 Lun,
+ IN UINT8 Command,
+ IN UINT8 *CommandData,
+ IN UINT32 CommandDataSize,
+ IN OUT UINT8 *ResponseData,
+ IN OUT UINT32 *ResponseDataSize
+ )
+/*++
+
+Routine Description:
+
+ This API use the default interface (PcdDefaultSystemInterface) to send IPMI command
+ in the right mode to the appropiate device, ME or BMC.
+
+Arguments:
+
+ This - Pointer to IPMI protocol instance
+ NetFunction - Net Function of command to send
+ Lun - LUN of command to send
+ Command - IPMI command to send
+ CommandData - Pointer to command data buffer, if needed
+ CommandDataSize - Size of command data buffer
+ ResponseData - Pointer to response data buffer
+ ResponseDataSize - Pointer to response data buffer size
+
+Returns:
+
+ EFI_INVALID_PARAMETER - One of the input values is bad
+ EFI_DEVICE_ERROR - IPMI command failed
+ EFI_BUFFER_TOO_SMALL - Response buffer is too small
+ EFI_UNSUPPORTED - Command is not supported by BMC
+ EFI_SUCCESS - Command completed successfully
+
+--*/
+{
+ PEI_IPMI_BMC_INSTANCE_DATA *PeiIpmiInstance;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PeiIpmiInstance = INSTANCE_FROM_PEI_IPMI_TRANSPORT2_THIS(This);
+
+#if KcsInterfaceSupport
+ if ((PeiIpmiInstance->IpmiTransport2Ppi.InterfaceType == SysInterfaceKcs) &&
+ (PeiIpmiInstance->IpmiTransport2Ppi.Interface.KcsInterfaceState == IpmiInterfaceInitialized)) {
+
+ return PeiIpmiSendCommand (
+ &PeiIpmiInstance->IpmiTransportPpi,
+ NetFunction,
+ Lun,
+ Command,
+ CommandData,
+ CommandDataSize,
+ ResponseData,
+ ResponseDataSize
+ );
+ }
+#endif
+
+#if BtInterfaceSupport
+ if ((PeiIpmiInstance->IpmiTransport2Ppi.InterfaceType == SysInterfaceBt) &&
+ (PeiIpmiInstance->IpmiTransport2Ppi.Interface.Bt.InterfaceState == IpmiInterfaceInitialized)) {
+
+ return IpmiBtSendCommandToBmc (
+ &PeiIpmiInstance->IpmiTransport2Ppi,
+ NetFunction,
+ Lun,
+ Command,
+ CommandData,
+ (UINT8) CommandDataSize,
+ ResponseData,
+ (UINT8*) ResponseDataSize,
+ NULL
+ );
+ }
+#endif
+
+#if SsifInterfaceSupport
+ if ((PeiIpmiInstance->IpmiTransport2Ppi.InterfaceType == SysInterfaceSsif) &&
+ (PeiIpmiInstance->IpmiTransport2Ppi.Interface.Ssif.InterfaceState == IpmiInterfaceInitialized)) {
+ return IpmiSsifSendCommandToBmc (
+ &PeiIpmiInstance->IpmiTransport2Ppi,
+ NetFunction,
+ Lun,
+ Command,
+ CommandData,
+ (UINT8) CommandDataSize,
+ ResponseData,
+ (UINT8*) ResponseDataSize,
+ NULL
+ );
+ }
+#endif
+
+#if IpmbInterfaceSupport
+ if ((PeiIpmiInstance->IpmiTransport2Ppi.InterfaceType == SysInterfaceIpmb) &&
+ (PeiIpmiInstance->IpmiTransport2Ppi.Interface.Ipmb.InterfaceState == IpmiInterfaceInitialized)) {
+ return IpmiIpmbSendCommandToBmc (
+ &PeiIpmiInstance->IpmiTransport2Ppi,
+ NetFunction,
+ Lun,
+ Command,
+ CommandData,
+ (UINT8) CommandDataSize,
+ ResponseData,
+ (UINT8*) ResponseDataSize,
+ NULL
+ );
+ }
+#endif
+ return EFI_UNSUPPORTED;
+} // IpmiSendCommand()
+
+EFI_STATUS
+PeiIpmiSendCommand2Ex (
+ IN IPMI_TRANSPORT2 *This,
+ IN UINT8 NetFunction,
+ IN UINT8 Lun,
+ IN UINT8 Command,
+ IN UINT8 *CommandData,
+ IN UINT32 CommandDataSize,
+ IN OUT UINT8 *ResponseData,
+ IN OUT UINT32 *ResponseDataSize,
+ IN SYSTEM_INTERFACE_TYPE InterfaceType
+ )
+{
+/*++
+Routine Description:
+
+ This API use the specific interface type to send IPMI command
+ in the right mode to the appropiate device, ME or BMC.
+
+Arguments:
+
+ This - Pointer to IPMI protocol instance
+ NetFunction - Net Function of command to send
+ Lun - LUN of command to send
+ Command - IPMI command to send
+ CommandData - Pointer to command data buffer, if needed
+ CommandDataSize - Size of command data buffer
+ ResponseData - Pointer to response data buffer
+ ResponseDataSize - Pointer to response data buffer size
+ InterfaceType - BMC Interface type.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - One of the input values is bad
+ EFI_DEVICE_ERROR - IPMI command failed
+ EFI_BUFFER_TOO_SMALL - Response buffer is too small
+ EFI_UNSUPPORTED - Command is not supported by BMC
+ EFI_SUCCESS - Command completed successfully
+
+--*/
+
+ PEI_IPMI_BMC_INSTANCE_DATA *PeiIpmiInstance;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PeiIpmiInstance = INSTANCE_FROM_PEI_IPMI_TRANSPORT2_THIS(This);
+
+#if KcsInterfaceSupport
+ if ((InterfaceType == SysInterfaceKcs) &&
+ (PeiIpmiInstance->IpmiTransport2Ppi.Interface.KcsInterfaceState == IpmiInterfaceInitialized)) {
+
+ return PeiIpmiSendCommand (
+ &PeiIpmiInstance->IpmiTransportPpi,
+ NetFunction,
+ Lun,
+ Command,
+ CommandData,
+ CommandDataSize,
+ ResponseData,
+ ResponseDataSize
+ );
+ }
+#endif
+
+#if BtInterfaceSupport
+
+ if ((InterfaceType == SysInterfaceBt) &&
+ (PeiIpmiInstance->IpmiTransport2Ppi.Interface.Bt.InterfaceState == IpmiInterfaceInitialized)) {
+
+ return IpmiBtSendCommandToBmc (
+ &PeiIpmiInstance->IpmiTransport2Ppi,
+ NetFunction,
+ Lun,
+ Command,
+ CommandData,
+ (UINT8) CommandDataSize,
+ ResponseData,
+ (UINT8*) ResponseDataSize,
+ NULL
+ );
+ }
+#endif
+
+#if SsifInterfaceSupport
+
+ if ((InterfaceType == SysInterfaceSsif) &&
+ (PeiIpmiInstance->IpmiTransport2Ppi.Interface.Ssif.InterfaceState == IpmiInterfaceInitialized)) {
+
+ return IpmiSsifSendCommandToBmc (
+ &PeiIpmiInstance->IpmiTransport2Ppi,
+ NetFunction,
+ Lun,
+ Command,
+ CommandData,
+ (UINT8) CommandDataSize,
+ ResponseData,
+ (UINT8*) ResponseDataSize,
+ NULL
+ );
+ }
+#endif
+
+#if IpmbInterfaceSupport
+ if ((InterfaceType == SysInterfaceIpmb) &&
+ (PeiIpmiInstance->IpmiTransport2Ppi.Interface.Ipmb.InterfaceState == IpmiInterfaceInitialized)) {
+
+ return IpmiIpmbSendCommandToBmc (
+ &PeiIpmiInstance->IpmiTransport2Ppi,
+ NetFunction,
+ Lun,
+ Command,
+ CommandData,
+ (UINT8) CommandDataSize,
+ ResponseData,
+ (UINT8*) ResponseDataSize,
+ NULL
+ );
+ }
+#endif
+
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+PeiIpmiBmcStatus (
+ IN PEI_IPMI_TRANSPORT_PPI *This,
+ OUT BMC_STATUS *BmcStatus,
+ OUT SM_COM_ADDRESS *ComAddress,
+ IN VOID *Context
+ )
+/*++
+
+Routine Description:
+
+ Updates the BMC status and returns the Com Address
+
+Arguments:
+
+ This - Pointer to IPMI protocol instance
+ BmcStatus - BMC status
+ ComAddress - Com Address
+
+Returns:
+
+ EFI_SUCCESS - Success
+
+--*/
+{
+
+ if ((This == NULL) || (BmcStatus == NULL) || (ComAddress == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return IpmiBmcStatus (
+ This,
+ BmcStatus,
+ ComAddress,
+ NULL
+ );
+}
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiHooks.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiHooks.h
new file mode 100644
index 0000000000..bba61d1e45
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiHooks.h
@@ -0,0 +1,213 @@
+/** @file
+ IPMI common hook functions head file
+
+ @copyright
+ Copyright 2016 - 2021 Intel Corporation. <BR>
+ Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _IPMI_HOOKS_H
+#define _IPMI_HOOKS_H
+
+#include <Ppi/IpmiTransportPpi.h>
+#include <Ppi/IpmiTransport2Ppi.h>
+#include <Library/BtInterfaceLib.h>
+#include <Library/SsifInterfaceLib.h>
+#include <Library/IpmbInterfaceLib.h>
+#include <PeiIpmiBmcDef.h>
+#include <PeiIpmiBmc.h>
+
+//
+// Internal(hook) function list
+//
+
+EFI_STATUS
+PeiIpmiSendCommand (
+ IN PEI_IPMI_TRANSPORT_PPI *This,
+ IN UINT8 NetFunction,
+ IN UINT8 Lun,
+ IN UINT8 Command,
+ IN UINT8 *CommandData,
+ IN UINT32 CommandDataSize,
+ IN OUT UINT8 *ResponseData,
+ IN OUT UINT32 *ResponseDataSize
+ )
+/*++
+
+Routine Description:
+
+ Send Ipmi Command in the right mode: HECI or KCS, to the
+ appropiate device, ME or BMC.
+
+Arguments:
+
+ This - Pointer to IPMI protocol instance
+ NetFunction - Net Function of command to send
+ Lun - LUN of command to send
+ Command - IPMI command to send
+ CommandData - Pointer to command data buffer, if needed
+ CommandDataSize - Size of command data buffer
+ ResponseData - Pointer to response data buffer
+ ResponseDataSize - Pointer to response data buffer size
+
+Returns:
+
+ EFI_INVALID_PARAMETER - One of the input values is bad
+ EFI_DEVICE_ERROR - IPMI command failed
+ EFI_BUFFER_TOO_SMALL - Response buffer is too small
+ EFI_UNSUPPORTED - Command is not supported by BMC
+ EFI_SUCCESS - Command completed successfully
+
+--*/
+;
+
+EFI_STATUS
+PeiIpmiSendCommand2 (
+ IN IPMI_TRANSPORT2 *This,
+ IN UINT8 NetFunction,
+ IN UINT8 Lun,
+ IN UINT8 Command,
+ IN UINT8 *CommandData,
+ IN UINT32 CommandDataSize,
+ IN OUT UINT8 *ResponseData,
+ IN OUT UINT32 *ResponseDataSize
+ )
+/*++
+
+Routine Description:
+
+ This API use the default interface (PcdDefaultSystemInterface) to send IPMI command
+ in the right mode to the appropiate device, ME or BMC.
+
+Arguments:
+
+ This - Pointer to IPMI protocol instance
+ NetFunction - Net Function of command to send
+ Lun - LUN of command to send
+ Command - IPMI command to send
+ CommandData - Pointer to command data buffer, if needed
+ CommandDataSize - Size of command data buffer
+ ResponseData - Pointer to response data buffer
+ ResponseDataSize - Pointer to response data buffer size
+
+Returns:
+
+ EFI_INVALID_PARAMETER - One of the input values is bad
+ EFI_DEVICE_ERROR - IPMI command failed
+ EFI_BUFFER_TOO_SMALL - Response buffer is too small
+ EFI_UNSUPPORTED - Command is not supported by BMC
+ EFI_SUCCESS - Command completed successfully
+
+--*/
+;
+
+
+EFI_STATUS
+PeiIpmiSendCommand2Ex (
+ IN IPMI_TRANSPORT2 *This,
+ IN UINT8 NetFunction,
+ IN UINT8 Lun,
+ IN UINT8 Command,
+ IN UINT8 *CommandData,
+ IN UINT32 CommandDataSize,
+ IN OUT UINT8 *ResponseData,
+ IN OUT UINT32 *ResponseDataSize,
+ IN SYSTEM_INTERFACE_TYPE InterfaceType
+ );
[Isaac] There is inconsistent place of semicolons in this file.
+
+EFI_STATUS
+PeiIpmiSendCommandToBMC (
+ IN PEI_IPMI_TRANSPORT_PPI *This,
+ IN UINT8 NetFunction,
+ IN UINT8 Lun,
+ IN UINT8 Command,
+ IN UINT8 *CommandData,
+ IN UINT8 CommandDataSize,
+ IN OUT UINT8 *ResponseData,
+ IN OUT UINT8 *ResponseDataSize,
+ IN VOID *Context
+ )
+/*++
+Routine Description:
+
+ This API use the specific interface type to send IPMI command
+ in the right mode to the appropiate device, ME or BMC.
+
+Arguments:
+
+ This - Pointer to IPMI protocol instance
+ NetFunction - Net Function of command to send
+ Lun - LUN of command to send
+ Command - IPMI command to send
+ CommandData - Pointer to command data buffer, if needed
+ CommandDataSize - Size of command data buffer
+ ResponseData - Pointer to response data buffer
+ ResponseDataSize - Pointer to response data buffer size
+ InterfaceType - BMC Interface type.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - One of the input values is bad
+ EFI_DEVICE_ERROR - IPMI command failed
+ EFI_BUFFER_TOO_SMALL - Response buffer is too small
+ EFI_UNSUPPORTED - Command is not supported by BMC
+ EFI_SUCCESS - Command completed successfully
+
+--*/
+;
+
+EFI_STATUS
+PeiIpmiBmcStatus (
+ IN PEI_IPMI_TRANSPORT_PPI *This,
+ OUT BMC_STATUS *BmcStatus,
[Isaac] There are two instances like the preceding line that are not vertically aligned with other parameters.
+ OUT SM_COM_ADDRESS *ComAddress,
+ IN VOID *Context
+ )
+/*++
+
+Routine Description:
+
+ Updates the BMC status and returns the Com Address
+
+Arguments:
+
+ This - Pointer to IPMI protocol instance
+ BmcStatus - BMC status
+ ComAddress - Com Address
+ Context - Context
+
+Returns:
+
+ EFI_SUCCESS - Success
+
+--*/
+;
+
+EFI_STATUS
+IpmiBmcStatus (
+ IN PEI_IPMI_TRANSPORT_PPI *This,
+ OUT BMC_STATUS *BmcStatus,
+ OUT SM_COM_ADDRESS *ComAddress,
+ IN VOID *Context
+ )
+/*++
+
+Routine Description:
+
+ Updates the BMC status and returns the Com Address
+
+Arguments:
+
+ This - Pointer to IPMI protocol instance
+ BmcStatus - BMC status
+ ComAddress - Com Address
+ Context - Context
+
+Returns:
+
+ EFI_SUCCESS - Success
+
+--*/
+;
+#endif
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiNetFnAppDefinitions.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiNetFnAppDefinitions.h
new file mode 100644
index 0000000000..ebc98c856a
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiNetFnAppDefinitions.h
@@ -0,0 +1,239 @@
+
+/** @file IpmiNetFnAppDefinitions.h
+ Ipmi NetFn Application additional commands and its structures.
+
+ @copyright
+ Copyright 2016 - 2021 Intel Corporation. <BR>
+ Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _IPMI_NETFN_APP_DEFINITIONS_H_
+#define _IPMI_NETFN_APP_DEFINITIONS_H_
+
+#include <IndustryStandard/IpmiNetFnApp.h>
+
+#define IPMI_SPEC_VERSION_1_5 0x51
+#define IPMI_SPEC_VERSION_2_0 0x02
+#define IPMI_APP_SELFTEST_RESERVED 0xFF
+
+#pragma pack(1)
+/**
+ Get Bmc global enables command response.
+*/
+typedef struct {
+ /// Completion code.
+ UINT8 CompletionCode;
+ UINT8 ReceiveMsgQueueInterrupt : 1; ///< Receive Message Queue Interrupt.
+ UINT8 EventMsgBufferFullInterrupt : 1; ///< Event Message Buffer Full Interrupt.
+ UINT8 EventMsgBuffer : 1; ///< Event Message Buffer.
+ UINT8 SystemEventLogging : 1; ///< System Event Logging.
+ UINT8 Reserved : 1; ///< Reserved.
+ UINT8 OEM0 : 1; ///< OEM0 interrupt.
+ UINT8 OEM1 : 1; ///< OEM1 interrupt.
+ UINT8 OEM2 : 1; ///< OEM2 interrupt.
+} GET_BMC_GLOBAL_ENABLES_RESPONSE;
+
+/**
+ Channel access type.
+ */
+typedef enum {
+ ChannelAccessTypeReserved0, ///< Reserved0
+ ChannelAccessTypeNonVolatile, ///< NonVolatile
+ ChannelAccessTypePresentVolatileSetting, ///< PresentVolatileSetting
+ ChannelAccessTypeReserved1 ///< Reserved1
+} CHANNEL_ACCESS_TYPE;
+
+/**
+ Channel access modes.
+*/
+typedef enum {
+ ChannelAccessModeDisabled, ///< Disabled Channel Access Mode.
+ ChannelAccessModePreBootOnly, ///< Pre-Boot Only Channel Access Mode.
+ ChannelAccessModeAlwaysAvailable, ///< Always Available Channel Access Mode.
+ ChannelAccessModeShared ///< Shared Channel Access Mode.
+} CHANNEL_ACCESS_MODES;
+
+/**
+ SSIF read/write support.
+*/
+typedef enum {
+ SsifSinglePartRw, ///< Single Part read-write.
+ SsifMultiPartRw, ///< Multi Part read-write.
+ SsifMultiPartRwWithMiddle, ///< Multi Part read-write With Middle.
+ SsifReserved ///< Reserved.
+} SSIF_READ_WRITE_SUPPORT;
+
+/**
+ Channnel states.
+*/
+typedef enum {
+ DisbleChannel = 0, ///< Disble Channel.
+ EnableChannel, ///< Enable Channel.
+ GetChannelState, ///< Get Channel State.
+ ChannelStateReserved ///< Channel State Reserved.
+} CHANNEL_STATE;
+
+/**
+ Enable message channel command request structure.
+*/
+typedef struct {
+ UINT8 ChannelNumber : 4; /// Channel Number.
+ UINT8 Reserved1 : 4; ///< Reserved.
+ UINT8 ChannelState : 2; ///< Channel State.
+ UINT8 Reserved2 : 6; ///< Reserved.
+} IPMI_ENABLE_MESSAGE_CHANNEL_REQUEST;
+
+/**
+ Enable message channel command response structure.
+*/
+typedef struct {
+ UINT8 CompletionCode; /// Completion code.
+ UINT8 ChannelNumber : 4; ///< Channel Number.
+ UINT8 Reserved1 : 4; ///< Reserved.
+ UINT8 ChannelState : 1; ///< Channel State.
+ UINT8 Reserved2 : 7; ///< Reserved.
+} IPMI_ENABLE_MESSAGE_CHANNEL_RESPONSE;
+
+/**
+ Set System Info Parameters Command.
+*/
+#define IPMI_APP_SET_SYSTEM_INFO 0x58
+
+/**
+ System Info String Encoding.
+*/
+typedef enum {
+ SysInfoAscii, ///< Ascii
+ SysInfoUtf8, ///< Utf8
+ SysInfoUnicode ///< Unicode
+} SYSTEM_INFO_STRING_ENCODING;
+
+/**
+ System parameter selector.
+*/
+typedef enum {
+ SysInfoSetInProgress, ///< SetInProgress.
+ SysInfoFirmwareVersion, ///< FirmwareVersion.
+ SysInfoSystemName, ///< SystemName.
+ SysInfoPrimaryOsName, ///< PrimaryOsName.
+ SysInfoPresentOsName, ///< PresentOsName.
+ SysInfoPresentOsVersion, ///< PresentOsVersion.
+ SysInfoBmcUrl, ///< BmcUrl.
+ SysInfoHyperviserUrl, ///< HyperviserUrl.
+} SYSTEM_INFO_PARAMETER_SELECTOR;
+
+/**
+ System info set state.
+*/
+typedef enum {
+ SysInfoStateSetComplete, ///< SetComplete.
+ SysInfoStateSetInProgress, ///< SetInProgress.
+ SysInfoStateCommitWrite, ///< StateCommitWrite.
+ SysInfoStateReserved, ///< StateReserved.
+} SYSTEM_INFO_SET_STATE;
+
+/**
+ Set system info parameter command request Structure.
+*/
+typedef struct {
+ UINT8 ParamSelector; /// Parameter selector.
+ UINT8 SetSelector; ///< Data 1
+ UINT8 Data[16]; ///< Data 2:17
+} SET_SYSTEM_INFO_REQUEST;
+
+/**
+ Get System Info Parameters Command.
+*/
+#define IPMI_APP_GET_SYSTEM_INFO 0x59
+
+/**
+ Get system info Command request Structure.
+*/
+typedef struct {
+ UINT8 Reserved : 7; /// Reserved.
+ UINT8 GetParam : 1; ///< Get Parameter.
+ UINT8 ParamSelector; ///< Parameter Selector.
+ UINT8 SetSelector; ///< Set selector.
+ UINT8 BlockSelector; ///< Block selector.
+} GET_SYSTEM_INFO_REQUEST;
+
+/**
+ Get system info command response Structure.
+*/
+typedef struct {
+ UINT8 CompletionCode; /// Completion code.
+ UINT8 ParamRevision; /// Parameter Revision
+ union {
+ struct {
+ UINT8 State : 2; ///< State.
+ UINT8 Reserved : 6; ///< Reserved.
+ }Progress;
+ UINT8 SetSelector; ///< Set Selector.
+ }Data1;
+ UINT8 Data[16]; ///< Data 2:17.
+} GET_SYSTEM_INFO_RESPONSE;
+
+/**
+ Get system Guid Command response Structure.
+*/
+typedef struct {
+ UINT8 CompletionCode; /// Completion code.
+ UINT8 Node[6]; ///< Node.
+ UINT8 Clock[2]; ///< Clock.
+ UINT16 Time_High; ///< Time High.
+ UINT16 Time_Mid; ///< Time Middle.
+ UINT32 Time_Low; ///< Time Low.
+} GET_SYSTEM_GUID_RESPONSE;
+
+/**
+ Get Bt interface Capability Command response Structure.
+*/
+typedef struct {
+ UINT8 CompletionCode; /// Completion code.
+ UINT8 OutstaningReq; ///<Number of outstanding requests supported.
+ UINT8 InputBuffSize; ///<Input (request) buffer message size in bytes.
+ UINT8 OutputBuffSize; ///<Output (response) buffer message size in bytes.
+ UINT8 BmcReqToResTime; ///<BMC Request-to-Response time, in seconds.
+ UINT8 RecommandedRetires; ///<Recommended retries (1 based
+} IPMI_BT_INTERFACE_CAPABILITY_RES;
+
+/**
+ Get System interface Capability Command request Structure.
+*/
+typedef struct {
+ UINT8 SystemInterfaceType:4; /// System Interface Type 0h = SSIF,1h = KCS ,2h = SMIC.
+ UINT8 Reserved:4; ///< Reserved.
+} IPMI_GET_SYSTEM_INTERFACE_CAPABILITY_REQ;
+
+/**
+ Get System interface Capability Command response Structure.
+*/
+typedef struct {
+ UINT8 CompletionCode; /// Completion code.
+ UINT8 Reserved; ///< Reserved.
+ UINT8 SsifVersion : 3; ///< Ssif Version.
+ UINT8 PecSupport : 1; ///< Pec Support.
+ UINT8 Reserved1 : 2; ///< Reserved.
+ UINT8 TransactionSupport : 2; ///< Transaction Support.
+ UINT8 InputMessageSize; ///< Input Message Size.
+ UINT8 OutputMessageSize; ///< Output Message Size.
+} IPMI_GET_SYSTEM_INTERFACE_CAPABILITY_RES;
+
+/**
+ Get BMC global Enable Command response Structure.
+*/
+typedef struct {
+ UINT8 CompletionCode; /// Completion code.
+ UINT8 ReceiveMsgQueueInterrupt : 1; ///< Receive Message Queue Interrupt Enable bit.
+ UINT8 EventMsgBufferFullInterrupt : 1; ///< Event Message Buffer Full Interrupt Enable bit.
+ UINT8 EventMsgBuffer : 1; ///< Event Message Buffer Enable bit.
+ UINT8 SystemEventLogging : 1; ///< System Event Logging Enable bit.
+ UINT8 Reserved : 1; ///< Reserved.
+ UINT8 OEM0 : 1; ///< oem0 Enable bit.
+ UINT8 OEM1 : 1; ///< oem1 Enable bit.
+ UINT8 OEM2 : 1; ///< Oem2 Enable bit.
+} IPMI_BMC_GLOBAL_ENABLES_RES;
+#pragma pack()
+
+#endif // #ifndef _IPMI_NETFN_APP_DEFINITIONS_H_
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiTransport2Definitions.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiTransport2Definitions.h
new file mode 100644
index 0000000000..c62cf9e0e0
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiTransport2Definitions.h
@@ -0,0 +1,153 @@
+/** @file IpmiTransport2Definitions.h
+ Bmc Common interface library functions.
+
+ @copyright
+ Copyright 2016 - 2021 Intel Corporation. <BR>
+ Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _IPMI_TRANSPORT2_DEFINITIONS_H_
+#define _IPMI_TRANSPORT2_DEFINITIONS_H_
+
+typedef struct _IPMI_TRANSPORT2 IPMI_TRANSPORT2;
+
+/** @internal
+ BT Interface.
+*/
+typedef struct {
+ UINT8 InterfaceState; /// Interface state.
+ UINT16 CtrlPort; ///< Control port.
+ UINT16 ComBuffer; ///< Communication buffer port.
+ UINT16 IntMaskPort; ///< Interrupt mask port.
+ UINTN MmioBaseAddress; ///< Mmio base address.
+ UINTN BaseAddressRange; ///< Mmio base address range to
+ ///< differentiate port address.
+ UINT8 AccessType; ///< Access type - IO or MMIO.
+ UINT32 BtRetryCount; ///< Delay counter for retry.
+ UINT8 BtSoftErrorCount; ///< Soft error count.
+ BOOLEAN BtTransportLocked; ///< Interface lock.
+ UINT8 HosttoBmcBufferSize; ///< Host to Bmc Buffer Size.
+ UINT8 BmctoHostBufferSize; ///< Bmc to Host Buffer Size.
+} BT_SYSTEM_INTERFACE;
+
+/** @internal
+ SSIF Interface.
+*/
+typedef struct {
+ UINT8 InterfaceState; /// Interface state.
+ EFI_GUID SsifInterfaceApiGuid; ///< Smbus instance guid.
+ UINTN SsifInterfaceApiPtr; ///< Smbus instance pointer.
+ UINT8 RwSupport; ///< Read-write support.
+ UINT16 SsifRetryCounter; ///< Retry counter.
+ BOOLEAN PecSupport; ///< Packet Error Check support.
+ BOOLEAN SmbAlertSupport; ///< Smbus alert support.
+ UINT8 SsifSoftErrorCount; ///< Soft error count.
+ BOOLEAN SsifTransportLocked; ///< Interface lock.
+} SSIF_SYSTEM_INTERFACE;
+
+/** @internal
+ IPMB Interface.
+*/
+typedef struct {
+ /// Interface state.
+ UINT8 InterfaceState;
+ EFI_GUID IpmbInterfaceApiGuid; ///< Ipmb instance guid.
+ UINTN IpmbInterfaceApiPtr; ///< Ipmb instance pointer.
+ UINT8 IpmbSoftErrorCount; ///< Soft error count.
+ BOOLEAN IpmbTransportLocked; ///< Interface lock.
+} IPMB_SYSTEM_INTERFACE;
+
+/** @internal
+ System Interface.
+*/
+typedef struct {
+ UINT8 KcsInterfaceState;
+ BT_SYSTEM_INTERFACE Bt; ///< Bt interface.
+ SSIF_SYSTEM_INTERFACE Ssif; ///< Ssif interface.
+ IPMB_SYSTEM_INTERFACE Ipmb;
+} IPMI_SYSTEM_INTERFACE;
+
+/** @inrernal
[Isaac] Typo above
+ Ipmi Interface Access Type.
+*/
+typedef enum {
+ IpmiMmioAccess, ///< Mmio Access.
+ IpmiIoAccess ///< Io Access.
+} IPMI_ACCESS_TYPE;
+
+/** @internal
+ Host to BMC Interface Type.
+*/
+typedef enum {
+ SysInterfaceUnknown, ///< Unknown interface type.
+ SysInterfaceKcs, ///< Kcs interface.
+ SysInterfaceSmic, ///< Smic interface.
+ SysInterfaceBt, ///< Bt interface.
+ SysInterfaceSsif, ///< Ssif interface.
+ SysInterfaceIpmb, ///< Ipmb interface.
+ SysInterfaceMax ///< Maximum interface type.
+} SYSTEM_INTERFACE_TYPE;
+
+/** @internal
+ BMC Interface status.
+*/
+typedef enum {
+ BmcStatusOk, ///< Bmc status Ok.
+ BmcStatusSoftFail, ///< Bmc status Soft fail.
+ BmcStatusHardFail, ///< Bmc status Hard fail.
+ BmcStatusUpdateInProgress ///< Bmc status Update in progress.
+} BMC_INTERFACE_STATUS;
+
+/** @internal
+ Ipmi Interface state.
+*/
+typedef enum {
+ IpmiInterfaceNotReady, ///< Interface Not Ready.
+ IpmiInterfaceInitialized, ///< Interface Initialized.
+ IpmiInterfaceInitError, ///< Interface Initialization Error.
+} IPMI_INTERFACE_STATE;
+
+//
+// IPMI Function Prototypes
+//
+typedef
+EFI_STATUS
+(EFIAPI *IPMI_SEND_COMMAND2) (
+ IN IPMI_TRANSPORT2 *This,
+ IN UINT8 NetFunction,
+ IN UINT8 Lun,
+ IN UINT8 Command,
+ IN UINT8 *CommandData,
+ IN UINT32 CommandDataSize,
+ OUT UINT8 *ResponseData,
+ OUT UINT32 *ResponseDataSize
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *IPMI_SEND_COMMAND2Ex) (
+ IN IPMI_TRANSPORT2 *This,
+ IN UINT8 NetFunction,
+ IN UINT8 Lun,
+ IN UINT8 Command,
+ IN UINT8 *CommandData,
+ IN UINT32 CommandDataSize,
+ OUT UINT8 *ResponseData,
+ OUT UINT32 *ResponseDataSize,
+ IN SYSTEM_INTERFACE_TYPE InterfaceType
+ );
+
+
+struct _IPMI_TRANSPORT2 {
+ UINT64 Revision;
+ IPMI_SEND_COMMAND2 IpmiSubmitCommand2;
+ IPMI_SEND_COMMAND2Ex IpmiSubmitCommand2Ex;
+ IPMI_SYSTEM_INTERFACE Interface; ///< System interface.
+ SYSTEM_INTERFACE_TYPE InterfaceType; ///< Bmc Interface Type.
+ BMC_INTERFACE_STATUS IpmiTransport2BmcStatus;
+ EFI_HANDLE IpmiHandle;
+ UINT8 CompletionCode;
+};
+
+#endif
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Library/BmcCommonInterfaceLib.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Library/BmcCommonInterfaceLib.h
new file mode 100644
index 0000000000..49cb1e6008
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Library/BmcCommonInterfaceLib.h
@@ -0,0 +1,200 @@
+
+/** @file BmcCommonInterfaceLib.h
+ Bmc Common interface library functions.
+
+ @copyright
+ Copyright 2016 - 2021 Intel Corporation. <BR>
+ Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _BMC_COMMON_INTERFACE_LIB_H_
+#define _BMC_COMMON_INTERFACE_LIB_H_
+
+#include <IndustryStandard/IpmiNetFnApp.h>
+#include <IpmiTransport2Definitions.h>
+#include <ServerManagement.h>
+
+#define IPMI_APP_SELFTEST_RESERVED 0xFF
+
+#define IPMI_GET_SET_IN_PROGRESS_RETRY_COUNT 10
+#define IPMI_BIT_CLEAR 0
+#define IPMI_SELECTOR_NONE 0
+#define IPMI_CLEAR_FLAG 0
+#define IPMI_SET_FLAG 1
+#define IPMI_STALL 1000
+#define MIN_TO_100MS 60 * 10
+#define MAX_BMC_CMD_FAIL_COUNT 10
+
+// Completion code macros.
+#define IPMI_COMPLETION_CODE_SUCCESS 0x00
+#define IPMI_COMPLETION_CODE_DEVICE_SPECIFIC_START 0x01
+#define IPMI_COMPLETION_CODE_DEVICE_SPECIFIC_END 0x7E
+#define IPMI_COMPLETION_CODE_COMMAND_SPECIFIC_START 0x80
+#define IPMI_COMPLETION_CODE_COMMAND_SPECIFIC_END 0xBE
+#define IPMI_MAX_SOFT_COUNT 10
+
+#define IPMI_MAX_BT_CMD_DATA_SIZE 0xFF
+
+#define IPMI_ERROR_COMPLETION_CODE(a) !((a == IPMI_COMPLETION_CODE_SUCCESS) || \
+ ((a >= IPMI_COMPLETION_CODE_DEVICE_SPECIFIC_START) && \
+ (a <= IPMI_COMPLETION_CODE_DEVICE_SPECIFIC_END)) || \
+ ((a >= IPMI_COMPLETION_CODE_COMMAND_SPECIFIC_START) && \
+ (a <= IPMI_COMPLETION_CODE_COMMAND_SPECIFIC_END)) \
+ )
+
+#define KcsInterfaceSupport FixedPcdGet8 (PcdKcsInterfaceSupport) == 1
+#define BtInterfaceSupport FixedPcdGet8 (PcdBtInterfaceSupport) == 1
+#define SsifInterfaceSupport FixedPcdGet8 (PcdSsifInterfaceSupport) == 1
+#define IpmbInterfaceSupport FixedPcdGet8 (PcdIpmbInterfaceSupport) == 1
+
+/**
+ Read 8 bit data from BMC port based on access type.
+
+ @param[in] AccessType Specifies MMIO or IO access.
+ @param[in] Address Specifies Address to read.
+
+ @return UINT8 Data read.
+
+**/
+UINT8
+IpmiBmcRead8 (
+ IN UINT8 AccessType,
+ IN UINTN Address
+);
+
+/**
+ Write 8 bit data to BMC port based on access type.
+
+ @param[in] AccessType Specifies MMIO or IO access.
+ @param[in] Address Specifies Address to write.
+ @param[in] Data Specifies data to be written.
+
+ @return Data written.
+
+**/
+UINT8
+IpmiBmcWrite8 (
+ IN UINT8 AccessType,
+ IN UINTN Address,
+ IN UINT8 Data
+);
+
+/**
+ Acquire the lock to use the IPMI transport.
+
+ @param[out] Lock Pointer to Lock.
+
+ @return VOID Returns nothing.
+
+**/
+VOID
+IpmiTransportAcquireLock (
+ OUT BOOLEAN *Lock
+);
+
+
+/**
+ Release the lock of IPMI transport.
+
+ @param[out] Lock Pointer to Lock.
+
+ @return VOID Returns nothing.
+
+**/
+VOID
+IpmiTransportReleaseLock (
+ OUT BOOLEAN *Lock
+);
+
+
+/**
+ Returns the Lock state of IPMI transport.
+
+ @param[in] Lock Pointer to Lock.
+
+ @retval TRUE IPMI transport is in lock state.
+ @retval FALSE IPMI transport is in release state.
+
+*/
+BOOLEAN
+IpmiIsIpmiTransportlocked (
+ IN BOOLEAN *Lock
+);
+
+/**
+ Updates the SoftErrorCount of specific interface based on the BMC Error input.
+
+ @param[in] BmcError BMC Error.
+ @param[in, out] Interface Interface pointer to update soft error count.
+ @param[in] InterfaceType Interface type to communicate.
+
+ @retval EFI_SUCCESS Updated SoftErrorCount of specific interface.
+ @retval EFI_INVALID_PARAMETER Invalid Interface pointer or Interface type.
+
+**/
+EFI_STATUS
+IpmiUpdateSoftErrorCount (
+ IN UINT8 BmcError,
+ IN OUT IPMI_SYSTEM_INTERFACE *Interface,
+ IN SYSTEM_INTERFACE_TYPE InterfaceType
+ );
+
+/**
+ Execute the Self Test command with specific interface
+
+ @param IpmiInstance IpmiInstance Data structure pointer.
+ @param InterfaceType Interface Type
+ @param[in] InterfaceType Interface type to communicate.
+
+ @return EFI_STATUS Return Status
+**/
+EFI_STATUS
+CheckSelfTestByInterfaceType (
+ IN OUT IPMI_TRANSPORT2 *IpmiTransport2,
+ IN OUT BMC_INTERFACE_STATUS *BmcStatus,
+ IN SYSTEM_INTERFACE_TYPE InterfaceType
+ );
+
+/**
+ Initialize BT interface specific data.
+
+ @param[in, out] Interface System interface pointer.
+
+ @retval EFI_SUCCESS Interface is successfully initialized.
+ @retval Others Return status while initializing interface.
+
+**/
+EFI_STATUS
+InitBtInterfaceData (
+ IN OUT IPMI_TRANSPORT2 *IpmiTransport2
+ );
+
+/**
+ Initialize SSIF interface specific data.
+
+ @param[in, out] Interface System interface pointer.
+
+ @retval EFI_SUCCESS Interface is successfully initialized.
+ @retval Others Return status while initializing interface.
+
+**/
+EFI_STATUS
+InitSsifInterfaceData (
+ IN OUT IPMI_TRANSPORT2 *IpmiTransport2
+ );
+
+/** @internal
+ Initialize IPMB interface specific data.
+
+ @param[in, out] Interface System interface pointer.
+
+ @retval EFI_SUCCESS Interface is successfully initialized.
+ @retval Others Error status while initializing interface.
+
+**/
+EFI_STATUS
+InitIpmbInterfaceData (
+ IN OUT IPMI_TRANSPORT2 *IpmiTransport2
+ );
+#endif
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Library/BtInterfaceLib.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Library/BtInterfaceLib.h
new file mode 100644
index 0000000000..183bfdda69
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Library/BtInterfaceLib.h
@@ -0,0 +1,83 @@
+
+/** @file BtInterfaceLib.h
+ BT interface common macros and declarations.
+
+ @copyright
+ Copyright 2016 - 2021 Intel Corporation. <BR>
+ Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _BT_INTERFACE_LIB_H_
+#define _BT_INTERFACE_LIB_H_
+
+#include <Protocol/IpmiTransport2Protocol.h>
+#include <Include/IpmiNetFnAppDefinitions.h>
+
+#define IPMI_MAX_BT_CMD_DATA_SIZE 0xFF
+#define IPMI_CLR_WR_PTR_BIT 0x01
+#define IPMI_CLR_RD_PTR_BIT 0x02
+#define IPMI_H2B_ATN_BIT 0x04
+#define IPMI_B2H_ATN_BIT 0x08
+#define IPMI_H_BUSY 0x40
+#define IPMI_B_BUSY_BIT 0x80
+
+/**
+ BT interface send command implementation.
+
+ @param[in] Interface Pointer to System interface.
+ @param[in] NetFunction Net function of the command.
+ @param[in] Lun Logical Unit Number of the command.
+ @param[in] Command Command to be sent to BMC.
+ @param[in] CommandData Command data to be sent along with
+ Command.
+ @param[in] CommandDataSize Command Data size.
+ @param[out] ResponseData Pointer to the response data buffer.
+ @param[in, out] ResponseDataSize Pointer to the response data size.
+ @param[out] CompletionCode Pointer to completion code.
+ @param[in] InterfaceType Interface type.
+ @param[in] Context NULL here.
+
+ @retval EFI_UNSUPPORTED Interface type is not supported.
+ @retval EFI_NOT_READY Interface is not initialized.
+ @retval EFI_ACCESS_DENIED Interface is locked.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_BAD_BUFFER_SIZE Invalid buffer size.
+ @retval EFI_DEVICE_ERROR Error completion code or data size
+ retrieved is small.
+ @retval EFI_BUFFER_TOO_SMALL Buffer is too small to update response
+ data.
+ @retval EFI_SUCCESS Command sent successfully.
+ @return Others Error status returned from BMC while
+ executing the command.
+
+**/
+EFI_STATUS
+EFIAPI
+IpmiBtSendCommandToBmc (
[Isaac] The function parameters do not match the function description comment block above.
+ IN IPMI_TRANSPORT2 *This,
+ IN UINT8 NetFunction,
+ IN UINT8 Lun,
+ IN UINT8 Command,
+ IN UINT8 *CommandData,
+ IN UINT8 CommandDataSize,
+ IN OUT UINT8 *ResponseData,
+ IN OUT UINT8 *ResponseDataSize,
+ IN VOID *Context
+ );
+
+/**
+ Execute the Get BT Interface Capability command and update the input
+ and output buffer value of Ipmi Instance.
+
+ @param IpmiInstance Data structure pointer.
+
+ @retval VOID
+**/
+
+VOID
+GetBtInterfaceCapability (
[Isaac] Parameters don't match function description.
+ IN OUT IPMI_TRANSPORT2 *IpmiTransport2
+ );
+
+#endif
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Library/IpmbInterfaceLib.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Library/IpmbInterfaceLib.h
new file mode 100644
index 0000000000..5fc1176130
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Library/IpmbInterfaceLib.h
@@ -0,0 +1,92 @@
+
+/** @file IpmbInterfaceLib.h
+ IPMB interface common function declarations and macros.
+
+*/
+
+#ifndef _IPMB_INTERFACE_LIB_H_
+#define _IPMB_INTERFACE_LIB_H_
+
+#include <Pi/PiI2c.h>
+#include <Protocol/IpmiTransport2Protocol.h>
+#include <Include/IpmiNetFnAppDefinitions.h>
+
+#define IPMI_MAX_IPMB_CMD_DATA_SIZE 0xFF
+#define IPMI_READ_FLAG 1
+#define IPMI_WRITE_FLAG 0
+#define IPMI_SEQ_NO 0 // IPMB Message Sequence Number.
+
+/** @internal
+ Locate I2c Ppi/Protocol instance and initialize interface pointer.
+
+ @param[in, out] Interface System interface pointer.
+
+ @return EFI_STATUS Status returned from functions used.
+
+**/
+EFI_STATUS
+IpmiGetI2cApiPtr (
+ IN OUT IPMI_TRANSPORT2 *IpmiTransport2
+);
+
+/** @internal
+ Send Ipmi command through Ipmb interface.
+
+ @param[in] Interface Pointer to System interface.
+ @param[in] SlaveAddress I2C device slave address.
+ @param[in] RequestPacket Pointer to an EFI_I2C_REQUEST_PACKET
+ structure describing the I2C transaction.
+
+ @return EFI_STATUS Status of the Send I2c command.
+
+**/
+EFI_STATUS
+IpmiI2cSendCommand (
+ IN IPMI_SYSTEM_INTERFACE *Interface,
+ IN UINTN SlaveAddress,
+ IN EFI_I2C_REQUEST_PACKET *RequestPacket
+ );
+
+/** @internal
+ IPMB interface send command implementation.
+
+ @param[in] Interface Pointer to System interface.
+ @param[in] NetFunction Net function of the command.
+ @param[in] Lun Logical Unit Number of the command.
+ @param[in] Command Command to be sent to BMC.
+ @param[in] CommandData Command data to be sent along with
+ Command.
+ @param[in] CommandDataSize Command Data size.
+ @param[out] ResponseData Pointer to the response data buffer.
+ @param[in, out] ResponseDataSize Pointer to the response data size.
+ @param[out] CompletionCode Pointer to completion code.
+ @param[in] InterfaceType Interface type.
+ @param[in] Context NULL here.
+
+ @retval EFI_UNSUPPORTED Interface type is not supported.
+ @retval EFI_NOT_READY Interface is not initialized.
+ @retval EFI_ACCESS_DENIED Interface is locked.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_BAD_BUFFER_SIZE Invalid buffer size.
+ @retval EFI_DEVICE_ERROR Error completion code or data size
+ retrieved is small.
+ @retval EFI_BUFFER_TOO_SMALL Buffer is too small to update response
+ data.
+ @retval EFI_SUCCESS Command sent successfully.
+ @return Others Error status returned from BMC while
+ executing the command.
+
+**/
+EFI_STATUS
+IpmiIpmbSendCommandToBmc (
+ IN IPMI_TRANSPORT2 *This,
+ IN UINT8 NetFunction,
+ IN UINT8 Lun,
+ IN UINT8 Command,
+ IN UINT8 *CommandData,
+ IN UINT8 CommandDataSize,
+ OUT UINT8 *ResponseData,
+ IN OUT UINT8 *ResponseDataSize,
+ IN VOID *Context );
+
+#endif // #ifndef _IPMB_INTERFACE_LIB_H
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Library/SsifInterfaceLib.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Library/SsifInterfaceLib.h
new file mode 100644
index 0000000000..992e057385
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Library/SsifInterfaceLib.h
@@ -0,0 +1,165 @@
+
+/** @file SsifInterfaceLib.h
+ SSIF interface common function declarations and macros.
+
+ @copyright
+ Copyright 2016 - 2021 Intel Corporation. <BR>
+ Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _SSIF_INTERFACE_LIB_H
+#define _SSIF_INTERFACE_LIB_H
+
+#include <Protocol/SmbusHc.h>
+#include <Library/BmcCommonInterfaceLib.h>
+#include <Protocol/IpmiTransport2Protocol.h>
+#include <Include/IpmiNetFnAppDefinitions.h>
+
+#define IPMI_MAX_SSIF_CMD_DATA_SIZE 0xFF
+#define IPMI_SMBUS_BLOCK_LENGTH 0x20
+
+// Smbus Write Commands.
+#define IPMI_SMBUS_SINGLE_WRITE_CMD 0x2
+#define IPMI_SMBUS_MULTI_WRITE_START_CMD 0x6
+#define IPMI_SMBUS_MULTI_WRITE_MIDDLE_CMD 0x7
+#define IPMI_SMBUS_MULTI_WRITE_END_CMD 0x8
+
+// Smbus Read Commands.
+#define IPMI_SMBUS_SINGLE_READ_CMD 0x3
+#define IPMI_SMBUS_MULTI_READ_START_CMD SMBUS_SINGLE_READ_CMD
+#define IPMI_SMBUS_MULTI_READ_MIDDLE_CMD 0x9
+#define IPMI_SMBUS_MULTI_READ_END_CMD 0x9
+#define IPMI_SMBUS_MULTI_READ_RETRY_CMD 0xA
+
+#define IPMI_MULTI_READ_ZEROTH_STRT_BIT 0x0
+#define IPMI_MULTI_READ_FIRST_STRT_BIT 0x1
+
+
+/**
+ Check the SMBUS alert pin status function
+
+ @param VOID Nothing.
+
+ @retval TRUE Alert pin status is set.
+ @retval FALSE Alert pin status is not set.
+
+**/
+typedef BOOLEAN (SSIF_ALERT_PIN_CHECK) (
+ VOID
+);
+
+/**
+ Execute the Get System Interface Capability command and update the RwSupport
+ and PecSupport of Ipmi Instance.
+
+ @param IpmiInstance Ipmi Instance Data structure pointer.
+
+ @return EFI_STATUS Return Status
+
+**/
+VOID
+GetSystemInterfaceCapability (
+ IN OUT IPMI_TRANSPORT2 *IpmiTransport2
+ );
+
+/**
+ Execute the Get Global Enable command to get receive message queue interrupt.
+
+ @return VOID
+
+**/
+VOID
+GetGlobalEnables (
+ IN OUT IPMI_TRANSPORT2 *IpmiTransport2
+);
+
+/**
+ Locate Smbus instance and initialize interface pointer.
+
+ @param[in, out] Interface System interface pointer.
+
+ @return EFI_STATUS Status returned while locating smbus instance.
+
+**/
+EFI_STATUS
+IpmiGetSmbusApiPtr (
+ IN OUT IPMI_TRANSPORT2 *IpmiTransport2
+);
+
+/**
+ Send Ipmi command through Smbus instance.
+
+ @param[in] Interface Pointer to System interface.
+ @param[in] SlaveAddress The SMBUS hardware address.
+ @param[in] Command This command is transmitted by the SMBus
+ host controller to the SMBus slave device.
+ @param[in] Operation Operation to be performed.
+ @param[in] PecCheck Defines if Packet Error Code (PEC)
+ checking is required for this operation.
+ @param[in, out] Length Signifies the number of bytes that this
+ operation will do.
+ @param[in, out] Buffer Contains the value of data to execute to
+ the SMBus slave device. The length of
+ this buffer is identified by Length.
+
+ @retval EFI_NOT_FOUND Smbus instance is not found.
+ @retval Others Return status of the Smbus Execute operation.
+
+**/
+EFI_STATUS
+IpmiSmbusSendCommand (
+ IN IPMI_SYSTEM_INTERFACE *Interface,
+ IN EFI_SMBUS_DEVICE_ADDRESS SlaveAddress,
+ IN EFI_SMBUS_DEVICE_COMMAND Command,
+ IN EFI_SMBUS_OPERATION Operation,
+ IN BOOLEAN PecCheck,
+ IN OUT UINTN *Length,
+ IN OUT VOID *Buffer
+);
+
+/**
+ Ssif interface send command implementation.
+
+ @param[in] Interface Pointer to System interface.
+ @param[in] NetFunction Net function of the command.
+ @param[in] Lun Logical Unit Number of the command.
+ @param[in] Command Command to be sent to BMC.
+ @param[in] CommandData Command data to be sent along with
+ Command.
+ @param[in] CommandDataSize Command Data size.
+ @param[out] ResponseData Pointer to the response data buffer.
+ @param[in, out] ResponseDataSize Pointer to the response data size.
+ @param[out] CompletionCode Pointer to completion code.
+ @param[in] InterfaceType Interface type.
+ @param[in] Context NULL here.
+
+ @retval EFI_UNSUPPORTED Interface type is not supported.
+ @retval EFI_NOT_READY Interface is not initialized.
+ @retval EFI_ACCESS_DENIED Interface is locked.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_BAD_BUFFER_SIZE Invalid buffer size.
+ @retval EFI_DEVICE_ERROR Error completion code or data size
+ retrieved is small.
+ @retval EFI_BUFFER_TOO_SMALL Buffer is too small to update response
+ data.
+ @retval EFI_SUCCESS Command sent successfully.
+ @return Others Error status returned from BMC while
+ executing the command.
+
+**/
+EFI_STATUS
+EFIAPI
+IpmiSsifSendCommandToBmc (
+ IN IPMI_TRANSPORT2 *This,
+ IN UINT8 NetFunction,
+ IN UINT8 Lun,
+ IN UINT8 Command,
+ IN UINT8 *CommandData,
+ IN UINT8 CommandDataSize,
+ IN OUT UINT8 *ResponseData,
+ IN OUT UINT8 *ResponseDataSize,
+ IN VOID *Context
+);
+
+#endif
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Ppi/IpmiTransport2Ppi.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Ppi/IpmiTransport2Ppi.h
new file mode 100644
index 0000000000..e977dd2526
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Ppi/IpmiTransport2Ppi.h
@@ -0,0 +1,23 @@
+/** @file
+ IPMI Ttransport2 PPI Header File.
+
+ @copyright
+ Copyright 2016 - 2021 Intel Corporation. <BR>
+ Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _IPMI_TRANSPORT2_PPI_H_
+#define _IPMI_TRANSPORT2_PPI_H_
+
+#include <IpmiTransport2Definitions.h>
+#include <Library/BmcCommonInterfaceLib.h>
+
+#define PEI_IPMI_TRANSPORT2_PPI_GUID \
+ { \
+ 0x8122CEBD, 0xF4FD, 0x4EA8, 0x97, 0x6C, 0xF0, 0x30, 0xAD, 0xDC, 0x4C, 0xB4 \
+ }
+
+extern EFI_GUID gPeiIpmiTransport2PpiGuid;
+
+#endif
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/IpmiTransport2Protocol.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/IpmiTransport2Protocol.h
new file mode 100644
index 0000000000..b4186df303
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/IpmiTransport2Protocol.h
@@ -0,0 +1,30 @@
+
+/** @file IpmiTransport2Protocol.h
+ IpmiTransport2 Protocol Header File.
+
+ @copyright
+ Copyright 2016 - 2021 Intel Corporation. <BR>
+ Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _IPMI2_TRANSPORT2_PROTO_H_
+#define _IPMI2_TRANSPORT2_PROTO_H_
+
+#include <IpmiTransport2Definitions.h>
+#include <Library/BmcCommonInterfaceLib.h>
+
+#define IPMI_TRANSPORT2_PROTOCOL_GUID \
+ { \
+ 0x4a1d0e66, 0x5271, 0x4e22, { 0x83, 0xfe, 0x90, 0x92, 0x1b, 0x74, 0x82, 0x13 } \
+ }
+
+#define SMM_IPMI_TRANSPORT2_PROTOCOL_GUID \
+ { \
+ 0x1dbd1503, 0xa60, 0x4230, { 0xaa, 0xa3, 0x80, 0x16, 0xd8, 0xc3, 0xde, 0x2f } \
+ }
+
+extern EFI_GUID gIpmiTransport2ProtocolGuid;
+extern EFI_GUID gSmmIpmiTransport2ProtocolGuid;
+
+#endif
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/BmcCommonInterfaceLib.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/BmcCommonInterfaceLib.c
new file mode 100644
index 0000000000..086582cf0e
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/BmcCommonInterfaceLib.c
@@ -0,0 +1,228 @@
+/** @file BmcCommonInterfaceLib.c
+ BmcCommonInterfaceLib generic functions for all interfaces.
+
+ @copyright
+ Copyright 2016 - 2021 Intel Corporation. <BR>
+ Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/BmcCommonInterfaceLib.h>
+
+/**
+ Read 8 bit data from BMC port based on access type.
+
+ @param[in] AccessType Specifies MMIO or IO access.
+ @param[in] Address Specifies Address to read.
+
+ @return UINT8 Data read.
+
+**/
+UINT8
+IpmiBmcRead8 (
+ IN UINT8 AccessType,
+ IN UINTN Address
+)
+{
+ if (AccessType == IpmiIoAccess) {
+ return IoRead8 (Address);
+ } else {
+ return MmioRead8 (Address);
+ }
+}
+
+/**
+ Write 8 bit data to BMC port based on access type.
+
+ @param[in] AccessType Specifies MMIO or IO access.
+ @param[in] Address Specifies Address to write.
+ @param[in] Data Specifies data to be written.
+
+ @return Data written.
+
+**/
+UINT8
+IpmiBmcWrite8 (
+ IN UINT8 AccessType,
+ IN UINTN Address,
+ IN UINT8 Data
+)
+{
+ if (AccessType == IpmiIoAccess) {
+ return IoWrite8 (
+ Address,
+ Data );
+ } else {
+ return MmioWrite8 (
+ Address,
+ Data );
+ }
+}
+
+/**
+ Acquire the lock to use the IPMI transport.
+
+ @param[out] Lock Pointer to Lock.
+
+ @return VOID Returns nothing.
+
+**/
+VOID
+IpmiTransportAcquireLock (
+ OUT BOOLEAN *Lock
+)
+{
+ *Lock = TRUE;
+}
+
+/**
+ Release the lock of IPMI transport.
+
+ @param[out] Lock Pointer to Lock.
+
+ @return VOID Returns nothing.
+
+**/
+VOID
+IpmiTransportReleaseLock (
+ OUT BOOLEAN *Lock
+)
+{
+ *Lock = FALSE;
+}
+
+/**
+ Returns the Lock state of IPMI transport.
+
+ @param[in] Lock Pointer to Lock.
+
+ @retval TRUE IPMI transport is in lock state.
+ @retval FALSE IPMI transport is in release state.
+
+*/
+BOOLEAN
+IpmiIsIpmiTransportlocked (
+ IN BOOLEAN *Lock
+)
+{
+ return *Lock;
+}
+
+/** @internal
+ Updates the SoftErrorCount of specific interface based on the BMC Error input.
+
+ @param[in] BmcError BMC Error.
+ @param[in, out] Interface Interface pointer to update soft error count.
+ @param[in] InterfaceType Interface type to communicate.
+
+ @retval EFI_SUCCESS Updated SoftErrorCount of specific interface.
+ @retval EFI_INVALID_PARAMETER Invalid Interface pointer or Interface type.
+
+**/
+EFI_STATUS
+IpmiUpdateSoftErrorCount (
+ IN UINT8 BmcError,
+ IN OUT IPMI_SYSTEM_INTERFACE *Interface,
+ IN SYSTEM_INTERFACE_TYPE InterfaceType
+ )
+{
+ UINT8 Errors[] = {0xC0, 0xC3, 0xC4, 0xC9, 0xCE, 0xCF, 0xFF, 0x00};
+ UINT8 Index = 0;
+
+ if ((Interface == NULL) || (InterfaceType <= SysInterfaceUnknown) ||
+ (InterfaceType >= SysInterfaceMax)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ while (Errors[Index] != 0) {
+
+ if (Errors[Index] == BmcError) {
+
+ switch (InterfaceType) {
+
+ case SysInterfaceBt:
+ Interface->Bt.BtSoftErrorCount++;
+ break;
+
+ case SysInterfaceSsif:
+ Interface->Ssif.SsifSoftErrorCount++;
+ break;
+
+ default :
+ break;
+ }
+ }
+ Index++;
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Updates the SoftErrorCount of specific interface based on the BMC Error input.
+
+ @param[in] BmcError BMC Error.
+ @param[in, out] Interface Interface pointer to update soft error count.
+ @param[in] InterfaceType Interface type to communicate.
+
+ @retval EFI_SUCCESS Updated SoftErrorCount of specific interface.
+ @retval EFI_INVALID_PARAMETER Invalid Interface pointer or Interface type.
+
+**/
+EFI_STATUS
+CheckSelfTestByInterfaceType (
+ IN OUT IPMI_TRANSPORT2 *IpmiTransport2,
+ IN OUT BMC_INTERFACE_STATUS *BmcStatus,
+ IN SYSTEM_INTERFACE_TYPE InterfaceType
+ )
+{
+ EFI_STATUS Status;
+ IPMI_SELF_TEST_RESULT_RESPONSE BstStatus;
+ UINT32 ResponseDataSize;
+
+ if (IpmiTransport2 == NULL || BmcStatus == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ResponseDataSize = sizeof(IPMI_SELF_TEST_RESULT_RESPONSE);
+
+ Status = IpmiTransport2->IpmiSubmitCommand2Ex (
+ IpmiTransport2,
+ IPMI_NETFN_APP,
+ BMC_LUN,
+ IPMI_APP_GET_SELFTEST_RESULTS,
+ NULL,
+ 0,
+ (UINT8 *)&BstStatus,
+ &ResponseDataSize,
+ InterfaceType);
+ if (EFI_ERROR(Status)) {
+ *BmcStatus = BmcStatusHardFail;
+ return Status;
+ }
+
+ if (BstStatus.CompletionCode == IPMI_COMPLETION_CODE_SUCCESS) {
+ /* Check the self test results. Cases 55h - 58h are Ipmi defined
+ test results. Additional Cases are device specific test results.*/
+ switch (BstStatus.Result) {
+ case IPMI_APP_SELFTEST_NO_ERROR: // 0x55
+ case IPMI_APP_SELFTEST_NOT_IMPLEMENTED: // 0x56
+ case IPMI_APP_SELFTEST_RESERVED: // 0xFF
+ *BmcStatus = BmcStatusOk;
+ break;
+
+ case IPMI_APP_SELFTEST_ERROR: // 0x57
+ *BmcStatus = BmcStatusSoftFail;
+ break;
+
+ default: // 0x58 and Other Device Specific Hardware Error.
+ *BmcStatus = BmcStatusHardFail;
+ break;
+ }
+ }
+
+ return Status;
+}
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/BmcCommonInterfaceLib.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/BmcCommonInterfaceLib.inf
new file mode 100644
index 0000000000..33bb360c41
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/BmcCommonInterfaceLib.inf
@@ -0,0 +1,26 @@
+## @file BmcCommonInterfaceLib.inf
+#
+# INF description file for BmcCommonInterfaceLib Library.
+#
+# @copyright
+# Copyright 2016 - 2021 Intel Corporation. <BR>
+# Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BmcCommonInterfaceLib
+ FILE_GUID = D86308F8-5246-4B2F-AC25-E3D17170D6EF
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.1
+ LIBRARY_CLASS = BmcCommonInterfaceLib
+
+[Sources]
+ BmcCommonInterfaceLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IpmiFeaturePkg/IpmiFeaturePkg.dec
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/BtInterfaceLib/BtInterfaceLib.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/BtInterfaceLib/BtInterfaceLib.c
new file mode 100644
index 0000000000..a83620cfaf
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/BtInterfaceLib/BtInterfaceLib.c
@@ -0,0 +1,570 @@
+/** @file BtInterfaceLib.c
+ BT Transport implementation library functions.
+
+ @copyright
+ Copyright 2016 - 2021 Intel Corporation. <BR>
+ Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Uefi/UefiBaseType.h>
+#include <Library/DebugLib.h>
+#include <Library/TimerLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BmcCommonInterfaceLib.h>
+#include <Library/BtInterfaceLib.h>
+
+#define IPMI_BT_DELAY_PER_RETRY FixedPcdGet32 (PcdBtDelayPerRetry)
+
+/**
+ Get the BT interface port addresses based on access type.
+
+ @param[in] Interface Pointer to System interface.
+ @param[out] BtCtrlPort Pointer to Bt control port.
+ @param[out] BtComBufferPort Pointer to Bt communication buffer port.
+
+ @return VOID Nothing.
+
+**/
+VOID
+GetBtPortAddresses (
+ IN IPMI_SYSTEM_INTERFACE *Interface,
+ OUT UINTN *BtCtrlPort,
+ OUT UINTN *BtComBufferPort
+ )
+{
+ // Update Bt Ports based on Interface AccessType.
+ if (Interface->Bt.AccessType == IpmiIoAccess) {
+ *BtCtrlPort = (UINTN) Interface->Bt.CtrlPort;
+ *BtComBufferPort = (UINTN) Interface->Bt.ComBuffer;
+ } else {
+ *BtCtrlPort = Interface->Bt.MmioBaseAddress;
+ *BtComBufferPort = *BtCtrlPort + Interface->Bt.BaseAddressRange;
+ }
+}
+
+/**
+ Sends the command to BT interface BMC port.
+
+ @param[in] Interface Pointer to System interface.
+ @param[in] Context NULL here.
+ @param[in] Data Pointer to command data that will be sent to BMC
+ along with Command.
+ @param[in] DataSize Size of the command data.
+
+ @retval EFI_NOT_READY Interface is not ready to send data.
+ @retval EFI_SUCCESS Command sent to BMC successfully.
+
+**/
+EFI_STATUS
+SendDataToBtBmcPort (
+ IN IPMI_SYSTEM_INTERFACE *Interface,
+ IN VOID *Context,
+ IN UINT8 *Data,
+ IN UINT8 DataSize
+ )
+{
+ UINT8 BtCntlData;
+ UINT8 Index;
+ UINT32 Retry;
+ UINTN BtCtrlPort;
+ UINTN BtComBufferPort;
+ IPMI_ACCESS_TYPE AccessType;
+ UINT8 TempDataSize;
+ BOOLEAN MultipleDataSend;
+ UINT32 BtRetryCount;
+
+ MultipleDataSend = FALSE;
+ BtRetryCount = Interface->Bt.BtRetryCount;
+ AccessType = Interface->Bt.AccessType;
+
+ // Get Bt Ports addresses.
+ GetBtPortAddresses (
+ Interface,
+ &BtCtrlPort,
+ &BtComBufferPort );
+
+ do {
+ /* Wait for B_BUSY bit to clear (BMC ready to accept a request).
+ Default delay for each retry is 15 micro seconds.*/
+ for (Retry = 0; Retry < BtRetryCount; Retry++) {
+ BtCntlData = IpmiBmcRead8 (
+ AccessType,
+ BtCtrlPort );
+ if (!(BtCntlData & IPMI_B_BUSY_BIT)) {
+ break;
+ }
+ MicroSecondDelay (IPMI_BT_DELAY_PER_RETRY);
+ }
+
+ if (Retry == BtRetryCount) {
+ return EFI_TIMEOUT;
+ }
+
+ // Wait for H2B_ATN bit to clear (Acknowledgment of previous commands).
+ for (Retry = 0; Retry < BtRetryCount; Retry++) {
+ BtCntlData = IpmiBmcRead8 (
+ AccessType,
+ BtCtrlPort );
+ if (!(BtCntlData & IPMI_H2B_ATN_BIT)) {
+ break;
+ }
+ MicroSecondDelay (IPMI_BT_DELAY_PER_RETRY);
+ }
+
+ if (Retry == BtRetryCount) {
+ return EFI_TIMEOUT;
+ }
+
+ // Set CLR_WR_PTR.
+ BtCntlData = IPMI_CLR_WR_PTR_BIT;
+ IpmiBmcWrite8 (
+ AccessType,
+ BtCtrlPort,
+ BtCntlData );
+
+ if (DataSize > Interface->Bt.HosttoBmcBufferSize ) {
+ TempDataSize = Interface->Bt.HosttoBmcBufferSize;
+ MultipleDataSend = TRUE;
+ } else {
+ TempDataSize = DataSize;
+ MultipleDataSend = FALSE;
+ }
+
+ // Send each message byte out (write data to HOST2BMC buffer).
+ for (Index = 0; Index < TempDataSize; Index++) {
+ IpmiBmcWrite8 (
+ AccessType,
+ BtComBufferPort,
+ *(Data + Index) );
+ }
+
+ // Set H2B_ATN bit to inform BMC that data is available.
+ BtCntlData = IPMI_H2B_ATN_BIT;
+ IpmiBmcWrite8 (
+ AccessType,
+ BtCtrlPort,
+ BtCntlData );
+
+ //Command data size greater than available Input buffer size.
+ if (MultipleDataSend) {
+ Data = Data + TempDataSize;
+ DataSize -= TempDataSize;
+
+ for (Retry = 0; Retry < BtRetryCount; Retry++) {
+ BtCntlData = IpmiBmcRead8 (
+ AccessType,
+ BtCtrlPort );
+ if ((BtCntlData & IPMI_B_BUSY_BIT)) {
+ break;
+ }
+ MicroSecondDelay (IPMI_BT_DELAY_PER_RETRY);
+ }
+
+ if (Retry == BtRetryCount) {
+ return EFI_TIMEOUT;
+ }
+ }
+ } while (MultipleDataSend);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Receives the Data from BT interface BMC port.
+
+ @param[in] Interface Pointer to System interface.
+ @param[in] Context NULL here.
+ @param[out] Data Pointer to response data that is received from BMC.
+ @param[out] DataSize Size of the response data.
+
+ @retval EFI_NOT_READY Interface is not ready to receive data.
+ @retval EFI_SUCCESS Data received from BMC successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+
+**/
+EFI_STATUS
+ReceiveBmcDataFromBtPort (
+ IN IPMI_SYSTEM_INTERFACE *Interface,
+ IN VOID *Context,
+ OUT UINT8 *Data,
+ OUT UINT8 *DataSize
+ )
+{
+ UINT8 BtCntlData;
+ UINT8 Length ;
+ UINT8 TempDataSize;
+ UINT8 Index;
+ UINT32 Retry;
+ UINTN BtCtrlPort;
+ UINTN BtComBufferPort;
+ IPMI_ACCESS_TYPE AccessType;
+ BOOLEAN MultipleDataReceive;
+ UINT32 BtRetryCount;
+
+ Length = 0;
+ MultipleDataReceive = FALSE;
+ BtRetryCount = Interface->Bt.BtRetryCount;
+ AccessType = Interface->Bt.AccessType;
+
+ // Get Bt Ports addresses.
+ GetBtPortAddresses (
+ Interface,
+ &BtCtrlPort,
+ &BtComBufferPort );
+ do {
+ /* Wait for B2H_ATN bit to be set,signaling data is available for host.
+ Default delay for each retry is 15 micro seconds.*/
+ for (Retry = 0; Retry < BtRetryCount; Retry++) {
+ BtCntlData = IpmiBmcRead8 (
+ AccessType,
+ BtCtrlPort );
+ if (BtCntlData & IPMI_B2H_ATN_BIT) {
+ break;
+ }
+ MicroSecondDelay (IPMI_BT_DELAY_PER_RETRY);
+ }
+
+ if (Retry == BtRetryCount) {
+ return EFI_TIMEOUT;
+ }
+
+ // Set H_BUSY bit, indicating host is in process of reading data from interface.
+ BtCntlData = IpmiBmcRead8 (
+ AccessType,
+ BtCtrlPort );
+ if (!(BtCntlData & IPMI_H_BUSY )) {
+ BtCntlData = IPMI_H_BUSY; // most bits are rw1c, so clear them.
+ IpmiBmcWrite8 (
+ AccessType,
+ BtCtrlPort,
+ BtCntlData );
+ }
+
+ // Clear B2H_ATN bit,to acknowledge receipt of message response.
+ BtCntlData = IPMI_B2H_ATN_BIT; // Most bits are rw1c, so clear them.
+ IpmiBmcWrite8 (
+ AccessType,
+ BtCtrlPort,
+ BtCntlData );
+
+ // Set CLR_RD_PTR bit.
+ BtCntlData = IPMI_CLR_RD_PTR_BIT; // Most bits are rw1c, so clear them.
+ IpmiBmcWrite8 (
+ AccessType,
+ BtCtrlPort,
+ BtCntlData );
+
+ if (!Length){
+ // Read the data bytes from BMC.
+ Length = IpmiBmcRead8 (
+ AccessType,
+ BtComBufferPort );
+ if (Length == 0x00) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ IpmiBmcWrite8 (
+ AccessType,
+ BtCtrlPort,
+ BtCntlData );
+
+ *DataSize = Length;
+ //Increment Length to include length field
+ Length++;
+ }
+
+ if (Length > Interface->Bt.BmctoHostBufferSize) {
+ TempDataSize = Interface->Bt.BmctoHostBufferSize;
+ MultipleDataReceive = TRUE;
+ } else {
+ TempDataSize = Length;
+ MultipleDataReceive = FALSE;
+ }
+
+ for (Index = 0; Index < TempDataSize; Index++) {
+ *(Data + Index) = IpmiBmcRead8 (
+ AccessType,
+ BtComBufferPort );
+ }
+
+ // Clear H_BUSY bit indicating host is done reading data from BMC.
+ BtCntlData = IpmiBmcRead8 (
+ AccessType,
+ BtCtrlPort );
+ if (BtCntlData & IPMI_H_BUSY) {
+ BtCntlData = IPMI_H_BUSY; // Most bits are rw1c, so clear them.
+ IpmiBmcWrite8 (
+ AccessType,
+ BtCtrlPort,
+ BtCntlData );
+ }
+
+ if (MultipleDataReceive) {
+ Data = Data + TempDataSize;
+ Length -= TempDataSize;
+ }
+ } while (MultipleDataReceive);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ BT interface send command implementation.
+
+ @param[in] Interface Pointer to System interface.
+ @param[in] NetFunction Net function of the command.
+ @param[in] Lun Logical Unit Number of the command.
+ @param[in] Command Command to be sent to BMC.
+ @param[in] CommandData Command data to be sent along with
+ Command.
+ @param[in] CommandDataSize Command Data size.
+ @param[out] ResponseData Pointer to the response data buffer.
+ @param[in, out] ResponseDataSize Pointer to the response data size.
+ @param[out] CompletionCode Pointer to completion code.
+ @param[in] InterfaceType Interface type.
+ @param[in] Context NULL here.
+
+ @retval EFI_UNSUPPORTED Interface type is not supported.
+ @retval EFI_NOT_READY Interface is not initialized.
+ @retval EFI_ACCESS_DENIED Interface is locked.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_BAD_BUFFER_SIZE Invalid buffer size.
+ @retval EFI_DEVICE_ERROR Error completion code or data size
+ retrieved is small.
+ @retval EFI_BUFFER_TOO_SMALL Buffer is too small to update response
+ data.
+ @retval EFI_SUCCESS Command sent successfully.
+ @return Others Error status returned from BMC while
+ executing the command.
+
+**/
+EFI_STATUS
+EFIAPI
+IpmiBtSendCommandToBmc (
+ IN IPMI_TRANSPORT2 *This,
+ IN UINT8 NetFunction,
+ IN UINT8 Lun,
+ IN UINT8 Command,
+ IN UINT8 *CommandData,
+ IN UINT8 CommandDataSize,
+ IN OUT UINT8 *ResponseData,
+ IN OUT UINT8 *ResponseDataSize,
+ IN VOID *Context
+ )
+{
+
+ UINT8 DataSize;
+ EFI_STATUS Status;
+ UINT8 Seq;
+ UINT8 CmdDataBuffer[IPMI_MAX_BT_CMD_DATA_SIZE];
+ IPMI_SYSTEM_INTERFACE Interface;
+
+ Seq = 0;
+ Interface = This->Interface;
+
+ if (Interface.Bt.InterfaceState != IpmiInterfaceInitialized) {
+ return EFI_NOT_READY;
+ }
+
+ if (((CommandData == NULL) && (CommandDataSize != 0)) || (This == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((ResponseDataSize == NULL) || ((ResponseData == NULL) && *ResponseDataSize)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (IpmiIsIpmiTransportlocked (&Interface.Bt.BtTransportLocked)) {
+ return EFI_ACCESS_DENIED;
+ } else {
+ IpmiTransportAcquireLock (&Interface.Bt.BtTransportLocked);
+ }
+
+ CmdDataBuffer[0] = (UINT8)CommandDataSize + 0x03;
+ CmdDataBuffer[1] = (UINT8) ((NetFunction << 2) | (Lun & 0xfc));
+ CmdDataBuffer[2] = Seq;
+ CmdDataBuffer[3] = Command;
+
+ if (CommandDataSize > 0) {
+ if (CommandData == NULL) {
+ IpmiTransportReleaseLock (&Interface.Bt.BtTransportLocked);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (CommandDataSize <= (IPMI_MAX_BT_CMD_DATA_SIZE - 4) ) {
+ CopyMem (
+ &CmdDataBuffer[4],
+ CommandData,
+ CommandDataSize );
+ } else {
+ IpmiTransportReleaseLock (&Interface.Bt.BtTransportLocked);
+ return EFI_BAD_BUFFER_SIZE;
+ }
+ }
+
+ Status = SendDataToBtBmcPort (
+ &Interface,
+ Context,
+ CmdDataBuffer,
+ (UINT8)(CommandDataSize + 4));
+
+ if (Status != EFI_SUCCESS) {
+ Interface.Bt.BtSoftErrorCount++;
+ IpmiTransportReleaseLock (&Interface.Bt.BtTransportLocked);
+ return Status;
+ }
+
+ DataSize = IPMI_MAX_BT_CMD_DATA_SIZE;
+
+ Status = ReceiveBmcDataFromBtPort (
+ &Interface,
+ Context,
+ CmdDataBuffer,
+ &DataSize);
+
+ if (Status != EFI_SUCCESS) {
+ Interface.Bt.BtSoftErrorCount++;
+ IpmiTransportReleaseLock (&Interface.Bt.BtTransportLocked);
+ return Status;
+ }
+
+ if (IPMI_ERROR_COMPLETION_CODE(CmdDataBuffer[4])) {
+
+ IpmiUpdateSoftErrorCount (
+ CmdDataBuffer[4],
+ &Interface,
+ This->InterfaceType );
+
+ // Write completion code into return buffer if ipmi command returns an error.
+ if (*ResponseDataSize) {
+ if (ResponseData) {
+ *ResponseData = CmdDataBuffer[4];
+ }
+ *ResponseDataSize = 1;
+ }
+ IpmiTransportReleaseLock (&Interface.Bt.BtTransportLocked);
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (DataSize < 4) {
+ IpmiTransportReleaseLock (&Interface.Bt.BtTransportLocked);
+ return EFI_DEVICE_ERROR;
+ }
+
+ if ((DataSize - 3) > *((UINT8 *)ResponseDataSize)) {
+ *ResponseDataSize = (UINT8) (DataSize - 3);
+ IpmiTransportReleaseLock (&Interface.Bt.BtTransportLocked);
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ // Copying the response data into ResponseData buffer.
+ CopyMem (
+ ResponseData,
+ &CmdDataBuffer[4],
+ (DataSize - 3) );
+ *ResponseDataSize = (UINT8) (DataSize - 3);
+
+ IpmiTransportReleaseLock (&Interface.Bt.BtTransportLocked);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Execute the Get BT Interface Capability command and update the input
+ and output buffer value of Ipmi Instance.
+
+ @param IpmiInstance Data structure pointer.
+
+ @retval VOID
+**/
+
+VOID
+GetBtInterfaceCapability (
+ IN OUT IPMI_TRANSPORT2 *IpmiTransport2
+ )
+{
+ EFI_STATUS Status;
+ IPMI_BT_INTERFACE_CAPABILITY_RES Responsedata;
+ UINT32 ResponseSize;
+
+ ResponseSize = sizeof(IPMI_BT_INTERFACE_CAPABILITY_RES);
+
+ Status = IpmiTransport2->IpmiSubmitCommand2 (
+ IpmiTransport2,
+ IPMI_NETFN_APP,
+ BMC_LUN,
+ IPMI_APP_GET_BT_INTERFACE_CAPABILITY,
+ NULL,
+ 0,
+ (UINT8*) &Responsedata,
+ &ResponseSize );
+
+ if (EFI_ERROR(Status) || Responsedata.CompletionCode) {
+ DEBUG ((DEBUG_ERROR, " IPMI_APP_GET_BT_INTERFACE_CAPABILITY Status: %r Completion code: %x\n", Status, Responsedata.CompletionCode));
+ return;
+ }
+
+ IpmiTransport2->Interface.Bt.HosttoBmcBufferSize = Responsedata.InputBuffSize;
+ IpmiTransport2->Interface.Bt.BmctoHostBufferSize = Responsedata.OutputBuffSize;
+
+ DEBUG ((DEBUG_ERROR, " InputBuffSize:%x OutBuffSize%x BtRetry %x Status %r \n",IpmiTransport2->Interface.Bt.HosttoBmcBufferSize,IpmiTransport2->Interface.Bt.BmctoHostBufferSize,Responsedata.RecommandedRetires, Status));
+
+ return;
+}
+
+
+/**
+ Initialize BT interface specific data.
+
+ @param[in, out] Interface System interface pointer.
+
+ @retval EFI_SUCCESS Interface is successfully initialized.
+ @retval Others Return status while initializing interface.
+
+**/
+EFI_STATUS
+InitBtInterfaceData (
+ IN OUT IPMI_TRANSPORT2 *IpmiTransport2
+ )
+{
+ BMC_INTERFACE_STATUS BmcStatus;
+ EFI_STATUS Status;
+
+ if (IpmiTransport2->Interface.Bt.InterfaceState == IpmiInterfaceInitialized) {
+ return EFI_SUCCESS;
+ }
+
+ IpmiTransport2->Interface.Bt.CtrlPort = FixedPcdGet16 (PcdBtControlPort); // BT Control Port
+ IpmiTransport2->Interface.Bt.ComBuffer = FixedPcdGet16 (PcdBtBufferPort); // BT Buffer Port
+ IpmiTransport2->Interface.Bt.IntMaskPort = FixedPcdGet16 (PcdBtInterruptMaskPort); // BT IntMask Port
+ IpmiTransport2->Interface.Bt.BtRetryCount = FixedPcdGet32 (PcdBtCommandRetryCounter); // BT retry count
+ IpmiTransport2->Interface.Bt.HosttoBmcBufferSize = FixedPcdGet8 (PcdBtBufferSize); // Host to Bmc Buffer Size.
+ IpmiTransport2->Interface.Bt.BmctoHostBufferSize = FixedPcdGet8 (PcdBtBufferSize); // Bmc to Host Buffer Size.
+
+ if (FixedPcdGet8 (PcdIpmiDefaultAccessType)) {
+ IpmiTransport2->Interface.Bt.AccessType = IpmiIoAccess;
+ IpmiTransport2->Interface.Bt.MmioBaseAddress = 0;
+ IpmiTransport2->Interface.Bt.BaseAddressRange = 0;
+ } else {
+ IpmiTransport2->Interface.Bt.AccessType = IpmiMmioAccess;
+ IpmiTransport2->Interface.Bt.MmioBaseAddress = FixedPcdGet64(PcdMmioBaseAddress);
+ IpmiTransport2->Interface.Bt.BaseAddressRange = FixedPcdGet64(PcdBaseAddressRange);
+ }
+
+ IpmiTransportReleaseLock (&IpmiTransport2->Interface.Bt.BtTransportLocked);
+ IpmiTransport2->Interface.Bt.InterfaceState = IpmiInterfaceInitialized;
+
+ Status = CheckSelfTestByInterfaceType(
+ IpmiTransport2,
+ &BmcStatus,
+ SysInterfaceBt);
+ if (EFI_ERROR (Status) || (BmcStatus == BmcStatusHardFail)) {
+ IpmiTransport2->Interface.Bt.InterfaceState = IpmiInterfaceInitError;
+ return Status;
+ }
+
+ GetBtInterfaceCapability (IpmiTransport2);
+
+ return Status;
+}
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/BtInterfaceLib/BtInterfaceLib.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/BtInterfaceLib/BtInterfaceLib.inf
new file mode 100644
index 0000000000..1dd4386204
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/BtInterfaceLib/BtInterfaceLib.inf
@@ -0,0 +1,39 @@
+## @file BtInterfaceLib.inf
+#
+# INF description file for BtInterfaceLib common library.
+#
+# @copyright
+# Copyright 2016 - 2021 Intel Corporation. <BR>
+# Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BtInterfaceLib
+ FILE_GUID = DAFB6AEE-0275-45E4-A33C-E3348149C5BF
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.1
+ LIBRARY_CLASS = BtInterfaceLib
+
+[Sources]
+ BtInterfaceLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IpmiFeaturePkg/IpmiFeaturePkg.dec
+
+[LibraryClasses]
+ TimerLib
+ BmcCommonInterfaceLib
+
+[Pcd]
+ gIpmiFeaturePkgTokenSpaceGuid.PcdBtCommandRetryCounter
+ gIpmiFeaturePkgTokenSpaceGuid.PcdBtControlPort
+ gIpmiFeaturePkgTokenSpaceGuid.PcdBtBufferPort
+ gIpmiFeaturePkgTokenSpaceGuid.PcdBtDelayPerRetry
+ gIpmiFeaturePkgTokenSpaceGuid.PcdBtInterruptMaskPort
+ gIpmiFeaturePkgTokenSpaceGuid.PcdBtBufferSize
+ gIpmiFeaturePkgTokenSpaceGuid.PcdBaseAddressRange
+ gIpmiFeaturePkgTokenSpaceGuid.PcdMmioBaseAddress
+ gIpmiFeaturePkgTokenSpaceGuid.PcdIpmiDefaultAccessType
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/IpmbInterfaceLib/DxeIpmbInterfaceLib.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/IpmbInterfaceLib/DxeIpmbInterfaceLib.c
new file mode 100644
index 0000000000..c0d5ff02c8
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/IpmbInterfaceLib/DxeIpmbInterfaceLib.c
@@ -0,0 +1,94 @@
+/** @file DxeIpmbInterfaceLib.c
+ IPMB Transport Dxe phase Implementation library functions.
+
+ @copyright
+ Copyright 2016 - 2021 Intel Corporation. <BR>
+ Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/BmcCommonInterfaceLib.h>
+#include <Library/IpmbInterfaceLib.h>
+#include <Protocol/IpmiTransport2Protocol.h>
+#include <Protocol/I2cMaster.h>
+
+/** @internal
+ Send Ipmi command through Ipmb interface.
+
+ @param[in] Interface Pointer to System interface.
+ @param[in] SlaveAddress I2C device slave address.
+ @param[in] RequestPacket Pointer to an EFI_I2C_REQUEST_PACKET
+ structure describing the I2C transaction.
+
+ @return EFI_STATUS Status of the Send I2c command.
+
+**/
+EFI_STATUS
+IpmiI2cSendCommand (
+ IN IPMI_SYSTEM_INTERFACE *Interface,
+ IN UINTN SlaveAddress,
+ IN EFI_I2C_REQUEST_PACKET *RequestPacket
+ )
+{
+ EFI_STATUS Status = EFI_NOT_FOUND;
+ EFI_I2C_MASTER_PROTOCOL *I2cMasterTransmit = NULL;
+
+ I2cMasterTransmit = (EFI_I2C_MASTER_PROTOCOL *)Interface->Ipmb.IpmbInterfaceApiPtr;
+
+ if (I2cMasterTransmit != NULL) {
+ Status = I2cMasterTransmit->StartRequest (
+ I2cMasterTransmit,
+ SlaveAddress,
+ RequestPacket,
+ NULL,
+ NULL );
+ }
+
+ DEBUG ((DEBUG_INFO, "I2cMasterTransmit->StartRequest Status = %r\n", Status));
+ return Status;
+}
+
+/** @internal
+ Locate I2c Ppi/Protocol instance and initialize interface pointer.
+
+ @param[in, out] Interface System interface pointer.
+
+ @return EFI_STATUS Status returned from functions used.
+
+**/
+EFI_STATUS
+IpmiGetI2cApiPtr (
+ IN OUT IPMI_TRANSPORT2 *IpmiTransport2
+ )
+{
+ EFI_STATUS Status;
+ EFI_I2C_MASTER_PROTOCOL *I2cMasterTransmit = NULL;
+ BMC_INTERFACE_STATUS BmcStatus;
+
+ IpmiTransport2->Interface.Ipmb.IpmbInterfaceApiGuid = gEfiI2cMasterProtocolGuid;
+
+ // Locate the I2C DXE Protocol for Communication.
+ Status = gBS->LocateProtocol (
+ &gEfiI2cMasterProtocolGuid,
+ NULL,
+ (VOID **)&I2cMasterTransmit );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ IpmiTransport2->Interface.Ipmb.InterfaceState = IpmiInterfaceInitialized;
+ IpmiTransport2->Interface.Ipmb.IpmbInterfaceApiPtr = (UINTN)I2cMasterTransmit;
+
+ Status = CheckSelfTestByInterfaceType(
+ IpmiTransport2,
+ &BmcStatus,
+ SysInterfaceIpmb);
+ if (EFI_ERROR (Status) || (BmcStatus == BmcStatusHardFail)) {
+ IpmiTransport2->Interface.Ipmb.InterfaceState = IpmiInterfaceInitError;
+ }
+ return Status;
+}
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/IpmbInterfaceLib/DxeIpmbInterfaceLib.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/IpmbInterfaceLib/DxeIpmbInterfaceLib.inf
new file mode 100644
index 0000000000..641d7213d4
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/IpmbInterfaceLib/DxeIpmbInterfaceLib.inf
@@ -0,0 +1,38 @@
+## @file DxeIpmbInterfaceLib.inf
+#
+# INF description file for IpmbInterfaceLib Library for DXE and UEFI drivers.
+#
+# @copyright
+# Copyright 2016 - 2021 Intel Corporation. <BR>
+# Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = DxeIpmbInterfaceLib
+ FILE_GUID = 9068B213-4E53-427E-863C-8C7423509035
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.1
+ LIBRARY_CLASS = IpmbInterfaceLib | DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_DRIVER UEFI_APPLICATION
+
+[Sources]
+ DxeIpmbInterfaceLib.c
+ IpmbInterfaceLibCommon.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IpmiFeaturePkg/IpmiFeaturePkg.dec
+
+[LibraryClasses]
+ DebugLib
+ BaseMemoryLib
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+ BmcCommonInterfaceLib
+
+[Protocols]
+ gEfiI2cMasterProtocolGuid
+
+[Pcd]
+ gIpmiFeaturePkgTokenSpaceGuid.PcdBmcSlaveAddress
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/IpmbInterfaceLib/IpmbInterfaceLibCommon.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/IpmbInterfaceLib/IpmbInterfaceLibCommon.c
new file mode 100644
index 0000000000..fd0be85aa5
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/IpmbInterfaceLib/IpmbInterfaceLibCommon.c
@@ -0,0 +1,351 @@
+/** @file IpmbInterfaceLibCommon.c
+ IPMB Transport implementation common library functions.
+
+ @copyright
+ Copyright 2016 - 2021 Intel Corporation. <BR>
+ Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BmcCommonInterfaceLib.h>
+#include <Library/IpmbInterfaceLib.h>
+
+#define IPMI_BMC_SLAVE_ADDRESS FixedPcdGet32 (PcdBmcSlaveAddress)
+/** @internal
+ Verify the data integrity using checksum of BMC response data.
+
+ @param[in] ResponseData Response data from BMC.
+ @param[in] ResponseSize Data size of response data.
+
+ @retval EFI_SUCCESS Data integrity is valid.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+
+**/
+EFI_STATUS
+CheckDataValidity (
+ IN UINT8 *ResponseData,
+ IN UINT8 ResponseSize )
+{
+ UINT8 Index;
+ UINT8 CheckSum = 0;
+ UINT8 DataSum = 0;
+
+ // Calculate header checksum.
+ for (Index = 0; Index < 2; Index++) {
+ DataSum += ResponseData[Index];
+ }
+
+ // Verify header checksum.
+ CheckSum = (UINT8) (0x100 - DataSum);
+ if (CheckSum != ResponseData[2]) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DataSum = 0;
+
+ // Calculate information checksum.
+ for (Index = 3; Index < (ResponseSize - 1); Index++) {
+ DataSum += ResponseData[Index];
+ }
+
+ // Verify information checksum.
+ CheckSum = (UINT8) (0x100 - DataSum);
+ if (CheckSum != ResponseData[ResponseSize - 1]) {
+ return EFI_INVALID_PARAMETER;
+ }
+ return EFI_SUCCESS;
+}
+
+/** @internal
+ Sends the command/data to Ipmb interface.
+
+ @param[in] Interface Pointer to System interface.
+ @param[in] Context NULL here.
+ @param[in] Data Pointer to command data that will be sent to BMC
+ along with Command.
+ @param[in] DataSize Size of the command data.
+
+ @return EFI_STATUS Status returned from I2C send command.
+
+**/
+EFI_STATUS
+SendDataToIpmbBmcPort (
+ IN IPMI_SYSTEM_INTERFACE *Interface,
+ IN VOID *Context,
+ IN UINT8 *Data,
+ IN UINT8 DataSize )
+{
+ EFI_STATUS Status;
+ EFI_I2C_REQUEST_PACKET Packet;
+
+ // Pack command data.
+ Packet.Operation[0].Buffer = Data;
+ Packet.Operation[0].LengthInBytes = DataSize;
+ Packet.Operation[0].Flags = IPMI_WRITE_FLAG;
+
+ // Call the StartRequest function.
+ Status = IpmiI2cSendCommand (
+ Interface,
+ IPMI_BMC_SLAVE_ADDRESS,
+ &Packet );
+
+ return Status;
+}
+
+/** @internal
+ Receives the data from Ipmb interface.
+
+ @param[in] Interface Pointer to System interface.
+ @param[in] Context NULL here.
+ @param[out] Data Pointer to response data that is received from BMC.
+ @param[out] DataSize Size of the response data.
+
+ @return EFI_STATUS Status returned from I2C send command.
+
+**/
+EFI_STATUS
+ReceiveBmcDataFromIpmbPort (
+ IN IPMI_SYSTEM_INTERFACE *Interface,
+ IN VOID *Context,
+ OUT UINT8 *Data,
+ OUT UINT8 *DataSize )
+{
+ EFI_STATUS Status;
+ EFI_I2C_REQUEST_PACKET Packet;
+
+ // Pack command data.
+ Packet.Operation[0].Buffer = Data;
+ Packet.Operation[0].Flags = IPMI_READ_FLAG;
+
+ // Call the StartRequest function.
+ Status = IpmiI2cSendCommand (
+ Interface,
+ IPMI_BMC_SLAVE_ADDRESS,
+ &Packet );
+
+ if (!EFI_ERROR(Status)) {
+ *DataSize = (UINT8)Packet.Operation[0].LengthInBytes;
+ }
+ return Status;
+}
+
+/** @internal
+ IPMB interface send command implementation.
+
+ @param[in] Interface Pointer to System interface.
+ @param[in] NetFunction Net function of the command.
+ @param[in] Lun Logical Unit Number of the command.
+ @param[in] Command Command to be sent to BMC.
+ @param[in] CommandData Command data to be sent along with
+ Command.
+ @param[in] CommandDataSize Command Data size.
+ @param[out] ResponseData Pointer to the response data buffer.
+ @param[in, out] ResponseDataSize Pointer to the response data size.
+ @param[out] CompletionCode Pointer to completion code.
+ @param[in] InterfaceType Interface type.
+ @param[in] Context NULL here.
+
+ @retval EFI_UNSUPPORTED Interface type is not supported.
+ @retval EFI_NOT_READY Interface is not initialized.
+ @retval EFI_ACCESS_DENIED Interface is locked.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_BAD_BUFFER_SIZE Invalid buffer size.
+ @retval EFI_DEVICE_ERROR Error completion code or data size
+ retrieved is small.
+ @retval EFI_BUFFER_TOO_SMALL Buffer is too small to update response
+ data.
+ @retval EFI_SUCCESS Command sent successfully.
+ @return Others Error status returned from BMC while
+ executing the command.
+
+**/
+EFI_STATUS
+IpmiIpmbSendCommandToBmc (
+ IN IPMI_TRANSPORT2 *This,
+ IN UINT8 NetFunction,
+ IN UINT8 Lun,
+ IN UINT8 Command,
+ IN UINT8 *CommandData,
+ IN UINT8 CommandDataSize,
+ OUT UINT8 *ResponseData,
+ IN OUT UINT8 *ResponseDataSize,
+ IN VOID *Context )
+{
+ EFI_STATUS Status;
+ UINT8 DataSize;
+ UINT8 DataSum = 0;
+ UINT8 CheckSum = 0;
+ UINT8 Index;
+ UINT8 CmdDataBuffer[IPMI_MAX_IPMB_CMD_DATA_SIZE];
+ IPMI_SYSTEM_INTERFACE Interface;
+
+ Interface = This->Interface;
+
+ if (Interface.Ipmb.InterfaceState != IpmiInterfaceInitialized) {
+ return EFI_NOT_READY;
+ }
+
+ if (!ResponseDataSize || (!ResponseData && *ResponseDataSize)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (IpmiIsIpmiTransportlocked (&Interface.Ipmb.IpmbTransportLocked)) {
+ return EFI_ACCESS_DENIED;
+ } else {
+ IpmiTransportAcquireLock (&Interface.Ipmb.IpmbTransportLocked);
+ }
+
+ if (Interface.Ipmb.IpmbSoftErrorCount >= MAX_BMC_CMD_FAIL_COUNT) {
+ IpmiTransportReleaseLock (&Interface.Ipmb.IpmbTransportLocked);
+ return EFI_NOT_READY;
+ }
+
+ /* Request Packet format.
+ | Slave Address | Netfun/Lun | CheckSum (Check Sum of previous data)
+ | Slave Address | Seq No | Command | Data 1..N
+ | CheckSum (Check Sum of previous data).*/
+ CmdDataBuffer[0] = IPMI_BMC_SLAVE_ADDRESS;
+ CmdDataBuffer[1] = (UINT8) ((NetFunction << 2) | (Lun & 0x03));
+
+ DataSum += CmdDataBuffer[1] + IPMI_BMC_SLAVE_ADDRESS;
+ CheckSum = (UINT8) (0x100 - DataSum);
+ DataSum = 0;
+
+ CmdDataBuffer[2] = CheckSum;
+
+ CmdDataBuffer[3] = IPMI_BMC_SLAVE_ADDRESS;
+ DataSum += IPMI_BMC_SLAVE_ADDRESS;
+
+ CmdDataBuffer[4] = IPMI_SEQ_NO;
+ DataSum += IPMI_SEQ_NO;
+
+ CmdDataBuffer[5] = Command;
+ DataSum += Command;
+
+ if (CommandDataSize > 0) {
+ if (CommandData == NULL) {
+ IpmiTransportReleaseLock (&Interface.Ipmb.IpmbTransportLocked);
+ return EFI_INVALID_PARAMETER;
+ }
+ //Last data will be Checksum so limiting the Max command data to < IPMI_MAX_IPMB_CMD_DATA_SIZE - 6
+ if (CommandDataSize < (IPMI_MAX_IPMB_CMD_DATA_SIZE - 6)) {
+ CopyMem (
+ &CmdDataBuffer[6],
+ CommandData,
+ CommandDataSize );
+ } else {
+ IpmiTransportReleaseLock (&Interface.Ipmb.IpmbTransportLocked);
+ return EFI_BAD_BUFFER_SIZE;
+ }
+ for(Index = 0; Index < CommandDataSize; Index++) {
+ DataSum += CmdDataBuffer[6 + Index];
+ }
+ }
+ CheckSum = (UINT8) (0x100 - DataSum); // Find the checksum for the packing data.
+ CmdDataBuffer[6] = CheckSum; // Update the checksum.
+
+ if ((Status = SendDataToIpmbBmcPort (
+ &Interface,
+ Context,
+ CmdDataBuffer,
+ (UINT8) (CommandDataSize + 7) ) ) != EFI_SUCCESS) {
+ Interface.Ipmb.IpmbSoftErrorCount++;
+ IpmiTransportReleaseLock (&Interface.Ipmb.IpmbTransportLocked);
+ return Status;
+ }
+
+ DataSize = IPMI_MAX_IPMB_CMD_DATA_SIZE;
+ if ((Status = ReceiveBmcDataFromIpmbPort (
+ &Interface,
+ Context,
+ CmdDataBuffer,
+ &DataSize )) != EFI_SUCCESS) {
+ Interface.Ipmb.IpmbSoftErrorCount++;
+ IpmiTransportReleaseLock (&Interface.Ipmb.IpmbTransportLocked);
+ return Status;
+ }
+
+ /* Response Packet format.
+ | Slave Address | Netfun/Lun | CheckSum (Check Sum of previous data)
+ | Slave Address | Seq No | Command | Completion code| Data 1..N
+ | CheckSum (Check Sum of previous data).*/
+
+ // Calculate and verify checksum.
+ Status = CheckDataValidity (
+ CmdDataBuffer,
+ DataSize );
+ if (EFI_ERROR(Status)) {
+ IpmiTransportReleaseLock (&Interface.Ipmb.IpmbTransportLocked);
+ return Status;
+ }
+
+ if (IPMI_ERROR_COMPLETION_CODE(CmdDataBuffer[6])) {
+ IpmiUpdateSoftErrorCount (
+ CmdDataBuffer[6],
+ &Interface,
+ This->InterfaceType );
+ // Write completion code into return buffer if an IPMI command returns an error
+ if (*ResponseDataSize) {
+ if (ResponseData) {
+ *ResponseData = CmdDataBuffer[6];
+ }
+ *ResponseDataSize = 1;
+ }
+ IpmiTransportReleaseLock (&Interface.Ipmb.IpmbTransportLocked);
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (DataSize < 8) {
+ IpmiTransportReleaseLock (&Interface.Ipmb.IpmbTransportLocked);
+ return EFI_DEVICE_ERROR;
+ }
+ if ((DataSize - 7) > *((UINT8 *)ResponseDataSize)) {
+ *ResponseDataSize = (UINT8) (DataSize - 7);
+ IpmiTransportReleaseLock (&Interface.Ipmb.IpmbTransportLocked);
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ // Copying the response data into ResponseData buffer.
+ CopyMem (
+ ResponseData,
+ &CmdDataBuffer[6],
+ (DataSize - 7) );
+ *ResponseDataSize = (UINT8) (DataSize - 7);
+
+ IpmiTransportReleaseLock (&Interface.Ipmb.IpmbTransportLocked);
+ return EFI_SUCCESS;
+}
+
+/** @internal
+ Initialize IPMB interface specific data.
+
+ @param[in, out] Interface System interface pointer.
+
+ @retval EFI_SUCCESS Interface is successfully initialized.
+ @retval Others Error status while initializing interface.
+
+**/
+EFI_STATUS
+InitIpmbInterfaceData (
+ IN OUT IPMI_TRANSPORT2 *IpmiTransport2
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ if (IpmiTransport2->Interface.Ipmb.InterfaceState == IpmiInterfaceInitialized) {
+ return Status;
+ }
+
+ Status = IpmiGetI2cApiPtr (IpmiTransport2);
+
+ if (EFI_ERROR(Status)) {
+ IpmiTransport2->Interface.Ipmb.InterfaceState = IpmiInterfaceInitError;
+ return Status;
+ }
+
+ IpmiTransportReleaseLock (&IpmiTransport2->Interface.Ipmb.IpmbTransportLocked);
+ IpmiTransport2->Interface.Ipmb.InterfaceState = IpmiInterfaceInitialized;
+ return Status;
+}
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/IpmbInterfaceLib/PeiIpmbInterfaceLib.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/IpmbInterfaceLib/PeiIpmbInterfaceLib.c
new file mode 100644
index 0000000000..e4db0b4b13
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/IpmbInterfaceLib/PeiIpmbInterfaceLib.c
@@ -0,0 +1,100 @@
+/** @file PeiIpmbInterfaceLib.c
+ IPMB Transport Pei phase implementation library functions.
+
+ @copyright
+ Copyright 2016 - 2021 Intel Corporation. <BR>
+ Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/HobLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PeiServicesTablePointerLib.h>
+#include <Library/BmcCommonInterfaceLib.h>
+#include <Library/IpmbInterfaceLib.h>
+#include <Ppi/I2cMaster.h>
+
+/** @internal
+ Send Ipmi command through Ipmb interface.
+
+ @param[in] Interface Pointer to System interface.
+ @param[in] SlaveAddress I2C device slave address.
+ @param[in] RequestPacket Pointer to an EFI_I2C_REQUEST_PACKET
+ structure describing the I2C transaction.
+
+ @return EFI_STATUS Status of the Send I2c command.
+
+**/
+EFI_STATUS
+IpmiI2cSendCommand (
+ IN IPMI_SYSTEM_INTERFACE *Interface,
+ IN UINTN SlaveAddress,
+ IN EFI_I2C_REQUEST_PACKET *RequestPacket )
[Isaac] Put ) on a new line
+{
+ EFI_STATUS Status = EFI_NOT_FOUND;
+ EFI_PEI_I2C_MASTER_PPI *I2cMasterTransmit = NULL;
+
+ I2cMasterTransmit = (EFI_PEI_I2C_MASTER_PPI *)Interface->Ipmb.IpmbInterfaceApiPtr;
+
+ if (I2cMasterTransmit != NULL) {
+ Status = I2cMasterTransmit->StartRequest (
+ I2cMasterTransmit,
+ SlaveAddress,
+ RequestPacket );
+ }
+
+ DEBUG ((DEBUG_INFO, "%a I2cMasterTransmit->StartRequest Status = %r\n", __FUNCTION__, Status));
+
+ return Status;
+}
+
+/** @internal
+ Locate I2c Ppi/Protocol instance and initialize interface pointer.
+
+ @param[in, out] Interface System interface pointer.
+
+ @return EFI_STATUS Status returned from functions used.
+
+**/
+EFI_STATUS
+IpmiGetI2cApiPtr (
+ IN OUT IPMI_TRANSPORT2 *IpmiTransport2
+)
+{
+ EFI_STATUS Status;
+ CONST EFI_PEI_SERVICES **PeiServices;
+ EFI_PEI_I2C_MASTER_PPI *I2cMasterTransmit = NULL;
+ BMC_INTERFACE_STATUS BmcStatus;
+
+ PeiServices = GetPeiServicesTablePointer ();
+
+ IpmiTransport2->Interface.Ipmb.IpmbInterfaceApiGuid = gEfiPeiI2cMasterPpiGuid;
+
+ // Locate the I2C PPI for Communication.
+ Status = (*PeiServices)->LocatePpi (
+ PeiServices,
+ &gEfiPeiI2cMasterPpiGuid,
+ 0,
+ NULL,
+ (VOID **)&I2cMasterTransmit );
+
+ DEBUG ((DEBUG_INFO, "%a (*PeiServices)->LocatePpi gEfiPeiI2cMasterPpiGuid Status = %r\n", __FUNCTION__, Status));
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ IpmiTransport2->Interface.Ipmb.InterfaceState = IpmiInterfaceInitialized;
+ IpmiTransport2->Interface.Ipmb.IpmbInterfaceApiPtr = (UINTN)I2cMasterTransmit;
+
+ Status = CheckSelfTestByInterfaceType(
+ IpmiTransport2,
+ &BmcStatus,
+ SysInterfaceIpmb);
+
+ if (EFI_ERROR (Status) || (BmcStatus == BmcStatusHardFail)) {
+ IpmiTransport2->Interface.Ipmb.InterfaceState = IpmiInterfaceInitError;
+ }
+
+ return Status;
+}
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/IpmbInterfaceLib/PeiIpmbInterfaceLib.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/IpmbInterfaceLib/PeiIpmbInterfaceLib.inf
new file mode 100644
index 0000000000..85b19d74c8
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/IpmbInterfaceLib/PeiIpmbInterfaceLib.inf
@@ -0,0 +1,38 @@
+## @file PeiIpmbInterfaceLib.inf
+#
+# INF description file for IpmbInterfacePeiLib Library for PEIMs.
+#
+# @copyright
+# Copyright 2016 - 2021 Intel Corporation. <BR>
+# Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PeiIpmbInterfaceLib
+ FILE_GUID = 843DBE4E-4750-4335-9094-58645D897D62
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.1
+ LIBRARY_CLASS = IpmbInterfaceLib | PEIM
+
+[Sources]
+ PeiIpmbInterfaceLib.c
+ IpmbInterfaceLibCommon.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IpmiFeaturePkg/IpmiFeaturePkg.dec
+
+[LibraryClasses]
+ HobLib
+ DebugLib
+ BaseMemoryLib
+ PeiServicesTablePointerLib
+ BmcCommonInterfaceLib
+
+[Ppis]
+ gEfiPeiI2cMasterPpiGuid
+
+[Pcd]
+ gIpmiFeaturePkgTokenSpaceGuid.PcdBmcSlaveAddress
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/IpmbInterfaceLib/SmmIpmbInterfaceLib.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/IpmbInterfaceLib/SmmIpmbInterfaceLib.c
new file mode 100644
index 0000000000..2293e3154a
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/IpmbInterfaceLib/SmmIpmbInterfaceLib.c
@@ -0,0 +1,94 @@
+/** @file SmmIpmbInterfaceLib.c
+ IPMB Transport Smm phase implementation library functions.
+
+ @copyright
+ Copyright 2016 - 2021 Intel Corporation. <BR>
+ Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/DebugLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Library/BmcCommonInterfaceLib.h>
+#include <Library/IpmbInterfaceLib.h>
+#include <Protocol/I2cMaster.h>
+
+/** @internal
+ Send Ipmi command through Ipmb interface.
+
+ @param[in] Interface Pointer to System interface.
+ @param[in] SlaveAddress I2C device slave address.
+ @param[in] RequestPacket Pointer to an EFI_I2C_REQUEST_PACKET
+ structure describing the I2C transaction.
+
+ @return EFI_STATUS Status of the Send I2c command.
+
+**/
+EFI_STATUS
+IpmiI2cSendCommand (
+ IN IPMI_SYSTEM_INTERFACE *Interface,
+ IN UINTN SlaveAddress,
+ IN EFI_I2C_REQUEST_PACKET *RequestPacket )
[Isaac] Put ) on a new line
+{
+ EFI_STATUS Status = EFI_NOT_FOUND;
+ EFI_I2C_MASTER_PROTOCOL *I2cMasterTransmit = NULL;
+
+ I2cMasterTransmit = (EFI_I2C_MASTER_PROTOCOL *)Interface->Ipmb.IpmbInterfaceApiPtr;
+
+ if (I2cMasterTransmit != NULL) {
+ Status = I2cMasterTransmit->StartRequest (
+ I2cMasterTransmit,
+ SlaveAddress,
+ RequestPacket,
+ NULL,
+ NULL );
+ }
+
+ DEBUG ((DEBUG_INFO, "%a I2cMasterTransmit->StartRequest Status = %r\n", __FUNCTION__, Status));
+
+ return Status;
+}
+
+/** @internal
+ Locate I2c Ppi/Protocol instance and initialize interface pointer.
+
+ @param[in, out] Interface System interface pointer.
+
+ @return EFI_STATUS Status returned from functions used.
+
+**/
+EFI_STATUS
+IpmiGetI2cApiPtr (
+ IN OUT IPMI_TRANSPORT2 *IpmiTransport2
+)
+{
+ EFI_STATUS Status;
+ EFI_I2C_MASTER_PROTOCOL *I2cMasterTransmit = NULL;
+ BMC_INTERFACE_STATUS BmcStatus;
+
+ IpmiTransport2->Interface.Ipmb.IpmbInterfaceApiGuid = gEfiI2cMasterProtocolGuid;
+
+ // Locate the I2C SMM Protocol for Communication.
+ Status = gSmst->SmmLocateProtocol (
+ &gEfiI2cMasterProtocolGuid,
+ NULL,
+ (VOID **)&I2cMasterTransmit );
+
+ DEBUG ((DEBUG_INFO, "%a SmmLocateProtocol gEfiI2cMasterProtocolGuid Status = %r\n", __FUNCTION__, Status));
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ IpmiTransport2->Interface.Ipmb.InterfaceState = IpmiInterfaceInitialized;
+ IpmiTransport2->Interface.Ipmb.IpmbInterfaceApiPtr = (UINTN)I2cMasterTransmit;
+
+ Status = CheckSelfTestByInterfaceType(
+ IpmiTransport2,
+ &BmcStatus,
+ SysInterfaceIpmb);
+ if (EFI_ERROR (Status) || (BmcStatus == BmcStatusHardFail)) {
+ IpmiTransport2->Interface.Ipmb.InterfaceState = IpmiInterfaceInitError;
+ }
+ return Status;
+}
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/IpmbInterfaceLib/SmmIpmbInterfaceLib.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/IpmbInterfaceLib/SmmIpmbInterfaceLib.inf
new file mode 100644
index 0000000000..2d3c089ef2
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/IpmbInterfaceLib/SmmIpmbInterfaceLib.inf
@@ -0,0 +1,37 @@
+## @file SmmAmiIpmbInterfaceLib.inf
+#
+# INF description file for SmmAmiIpmbInterfaceLib Library for DXE SMM drivers.
+#
+# @copyright
+# Copyright 2016 - 2021 Intel Corporation. <BR>
+# Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SmmIpmbInterfaceLib
+ FILE_GUID = C39F9DC3-37C7-41C1-BE05-8C1524493947
+ MODULE_TYPE = DXE_SMM_DRIVER
+ VERSION_STRING = 1.1
+ LIBRARY_CLASS = IpmbInterfaceLib | DXE_SMM_DRIVER
+
+[Sources]
+ SmmIpmbInterfaceLib.c
+ IpmbInterfaceLibCommon.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IpmiFeaturePkg/IpmiFeaturePkg.dec
+
+[LibraryClasses]
+ DebugLib
+ BaseMemoryLib
+ SmmServicesTableLib
+ BmcCommonInterfaceLib
+
+[Protocols]
+ gEfiI2cMasterProtocolGuid
+
+[Pcd]
+ gIpmiFeaturePkgTokenSpaceGuid.PcdBmcSlaveAddress
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInterfaceLib/DxeSsifInterfaceLib.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInterfaceLib/DxeSsifInterfaceLib.c
new file mode 100644
index 0000000000..60b2b8e016
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInterfaceLib/DxeSsifInterfaceLib.c
@@ -0,0 +1,131 @@
+/** @file DxeSsifInterfaceLib.c
+ SSIF Transport Dxe phase Implementation library functions.
+
+ @copyright
+ Copyright 2016 - 2021 Intel Corporation. <BR>
+ Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BmcCommonInterfaceLib.h>
+#include <Library/SsifInterfaceLib.h>
+#include <Protocol/IpmiTransport2Protocol.h>
+#include <Protocol/SmbusHc.h>
+
+/**
+ Send Ipmi command through Smbus instance.
+
+ @param[in] Interface Pointer to System interface.
+ @param[in] SlaveAddress The SMBUS hardware address.
+ @param[in] Command This command is transmitted by the SMBus
+ host controller to the SMBus slave device.
+ @param[in] Operation Operation to be performed.
+ @param[in] PecCheck Defines if Packet Error Code (PEC)
+ checking is required for this operation.
+ @param[in, out] Length Signifies the number of bytes that this
+ operation will do.
+ @param[in, out] Buffer Contains the value of data to execute to
+ the SMBus slave device. The length of
+ this buffer is identified by Length.
+
+ @retval EFI_NOT_FOUND Smbus instance is not found.
+ @retval Others Return status of the Smbus Execute operation.
+
+**/
+EFI_STATUS
+IpmiSmbusSendCommand (
+ IN IPMI_SYSTEM_INTERFACE *Interface,
+ IN EFI_SMBUS_DEVICE_ADDRESS SlaveAddress,
+ IN EFI_SMBUS_DEVICE_COMMAND Command,
+ IN EFI_SMBUS_OPERATION Operation,
+ IN BOOLEAN PecCheck,
+ IN OUT UINTN *Length,
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ EFI_SMBUS_HC_PROTOCOL *EfiSmbusHcProtocol;
+
+ Status = EFI_NOT_FOUND;
+ EfiSmbusHcProtocol = (EFI_SMBUS_HC_PROTOCOL *)Interface->Ssif.SsifInterfaceApiPtr;
+
+ if (EfiSmbusHcProtocol != NULL) {
+ Status = EfiSmbusHcProtocol->Execute (
+ EfiSmbusHcProtocol,
+ SlaveAddress,
+ Command,
+ Operation,
+ PecCheck,
+ Length,
+ Buffer );
+ }
+
+ DEBUG ((DEBUG_INFO, "EfiSmbusHcProtocol->Execute Status = %r\n", Status));
+ return Status;
+}
+
+/**
+ Locate Smbus instance and initialize interface pointer.
+
+ @param[in, out] Interface System interface pointer.
+
+ @return EFI_STATUS Status returned while locating smbus instance.
+
+**/
+EFI_STATUS
+IpmiGetSmbusApiPtr (
+ IN OUT IPMI_TRANSPORT2 *IpmiTransport2
+ )
+{
+ EFI_STATUS Status;
+ EFI_SMBUS_HC_PROTOCOL *EfiSmbusHcProtocol;
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+ UINTN Index;
+ BMC_INTERFACE_STATUS BmcStatus;
+
+ IpmiTransport2->Interface.Ssif.SsifInterfaceApiGuid = gEfiSmbusHcProtocolGuid;
+
+ Status = gBS->LocateHandleBuffer(
+ ByProtocol,
+ &gEfiSmbusHcProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ for (Index = 0; Index < HandleCount; Index++) {
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiSmbusHcProtocolGuid,
+ (VOID **)&EfiSmbusHcProtocol );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ IpmiTransport2->Interface.Ssif.InterfaceState = IpmiInterfaceInitialized;
+ IpmiTransport2->Interface.Ssif.SsifInterfaceApiPtr = (UINTN)EfiSmbusHcProtocol;
+
+ Status = CheckSelfTestByInterfaceType(
+ IpmiTransport2,
+ &BmcStatus,
+ SysInterfaceSsif);
+ if (EFI_ERROR (Status) || (BmcStatus == BmcStatusHardFail)) {
+ IpmiTransport2->Interface.Ssif.InterfaceState = IpmiInterfaceInitError;
+ continue;
+ }
+
+ GetSystemInterfaceCapability (IpmiTransport2);
+ GetGlobalEnables (IpmiTransport2);
+ break;
+ }
+
+ FreePool(HandleBuffer);
+ return Status;
+}
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInterfaceLib/DxeSsifInterfaceLib.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInterfaceLib/DxeSsifInterfaceLib.inf
new file mode 100644
index 0000000000..d9120b220c
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInterfaceLib/DxeSsifInterfaceLib.inf
@@ -0,0 +1,40 @@
+## @file DxeSsifInterfaceLib.inf
+#
+# INF description file for SsifInterfaceLib Library for DXE and UEFI drivers.
+#
+# @copyright
+# Copyright 2016 - 2021 Intel Corporation. <BR>
+# Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = DxeSsifInterfaceLib
+ FILE_GUID = AD66E7C3-FE13-4849-970E-118347FFE857
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.1
+ LIBRARY_CLASS = SsifInterfaceLib | DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_DRIVER UEFI_APPLICATION
+
+[Sources]
+ DxeSsifInterfaceLib.c
+ SsifInterfaceLibCommon.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IpmiFeaturePkg/IpmiFeaturePkg.dec
+
+[LibraryClasses]
+ UefiLib
+ MemoryAllocationLib
+ BmcCommonInterfaceLib
+
+[Protocols]
+ gEfiSmbusHcProtocolGuid
+
+[Pcd]
+ gIpmiFeaturePkgTokenSpaceGuid.PcdSsifSlaveAddress
+ gIpmiFeaturePkgTokenSpaceGuid.PcdSsifRequestRetriesDelay
+ gIpmiFeaturePkgTokenSpaceGuid.PcdSsifCommandtRetryCounter
+ gIpmiFeaturePkgTokenSpaceGuid.PcdSsifRequestRetriesDelay
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInterfaceLib/PeiSsifInterfaceLib.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInterfaceLib/PeiSsifInterfaceLib.c
new file mode 100644
index 0000000000..0cb7e4afd1
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInterfaceLib/PeiSsifInterfaceLib.c
@@ -0,0 +1,123 @@
+/** @file PeiSsifInterfaceLib.c
+ SSIF Transport Pei phase Implementation library functions.
+
+ @copyright
+ Copyright 2016 - 2021 Intel Corporation. <BR>
+ Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/HobLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PeiServicesTablePointerLib.h>
+#include <Library/BmcCommonInterfaceLib.h>
+#include <Library/SsifInterfaceLib.h>
+#include <Ppi/Smbus2.h>
+
+/**
+ Send Ipmi command through Smbus instance.
+
+ @param[in] Interface Pointer to System interface.
+ @param[in] SlaveAddress The SMBUS hardware address.
+ @param[in] Command This command is transmitted by the SMBus
+ host controller to the SMBus slave device.
+ @param[in] Operation Operation to be performed.
+ @param[in] PecCheck Defines if Packet Error Code (PEC)
+ checking is required for this operation.
+ @param[in, out] Length Signifies the number of bytes that this
+ operation will do.
+ @param[in, out] Buffer Contains the value of data to execute to
+ the SMBus slave device. The length of
+ this buffer is identified by Length.
+
+ @retval EFI_NOT_FOUND Smbus instance is not found.
+ @retval Others Return status of the Smbus Execute operation.
+
+**/
+EFI_STATUS
+IpmiSmbusSendCommand (
+ IN IPMI_SYSTEM_INTERFACE *Interface,
+ IN EFI_SMBUS_DEVICE_ADDRESS SlaveAddress,
+ IN EFI_SMBUS_DEVICE_COMMAND Command,
+ IN EFI_SMBUS_OPERATION Operation,
+ IN BOOLEAN PecCheck,
+ IN OUT UINTN *Length,
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ EFI_PEI_SMBUS2_PPI *EfiPeiSmbus2Ppi;
+
+ Status = EFI_NOT_FOUND;
+ EfiPeiSmbus2Ppi = (EFI_PEI_SMBUS2_PPI *)Interface->Ssif.SsifInterfaceApiPtr;
+
+ if (EfiPeiSmbus2Ppi != NULL) {
+ Status = EfiPeiSmbus2Ppi->Execute (
+ EfiPeiSmbus2Ppi,
+ SlaveAddress,
+ Command,
+ Operation,
+ PecCheck,
+ Length,
+ Buffer );
+ }
+
+ DEBUG ((DEBUG_INFO, "%a EfiPeiSmbus2Ppi->Execute Status = %r\n", __FUNCTION__, Status));
+ return Status;
+}
+
+/**
+ Locate Smbus instance and initialize interface pointer.
+
+ @param[in, out] Interface System interface pointer.
+
+ @return EFI_STATUS Status returned while locating smbus instance.
+
+**/
+EFI_STATUS
+IpmiGetSmbusApiPtr (
+ IN OUT IPMI_TRANSPORT2 *IpmiTransport2
+)
+{
+ EFI_STATUS Status;
+ UINTN Instance;
+ CONST EFI_PEI_SERVICES **PeiServices;
+ EFI_PEI_SMBUS2_PPI *EfiPeiSmbus2Ppi;
+ BMC_INTERFACE_STATUS BmcStatus;
+
+ PeiServices = GetPeiServicesTablePointer ();
+
+ IpmiTransport2->Interface.Ssif.SsifInterfaceApiGuid = gEfiPeiSmbus2PpiGuid;
+
+ // Traverse all Smbus2 PPI instances and find the right instance for SSIF.
+ for (Instance = 0; ; Instance++) {
+ // Locate the Smbus Ppi.
+ Status = (*PeiServices)->LocatePpi (
+ PeiServices,
+ &gEfiPeiSmbus2PpiGuid,
+ Instance,
+ NULL,
+ (VOID **)&EfiPeiSmbus2Ppi );
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ IpmiTransport2->Interface.Ssif.InterfaceState = IpmiInterfaceInitialized;
+ IpmiTransport2->Interface.Ssif.SsifInterfaceApiPtr = (UINTN)EfiPeiSmbus2Ppi;
+
+ Status = CheckSelfTestByInterfaceType(
+ IpmiTransport2,
+ &BmcStatus,
+ SysInterfaceSsif);
+ if (EFI_ERROR (Status) || (BmcStatus == BmcStatusHardFail)) {
+ IpmiTransport2->Interface.Ssif.InterfaceState = IpmiInterfaceInitError;
+ continue;
+ }
+
+ GetSystemInterfaceCapability (IpmiTransport2);
+ GetGlobalEnables (IpmiTransport2);
+ break;
+ }
+
+ return Status;
+}
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInterfaceLib/PeiSsifInterfaceLib.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInterfaceLib/PeiSsifInterfaceLib.inf
new file mode 100644
index 0000000000..b3aad43671
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInterfaceLib/PeiSsifInterfaceLib.inf
@@ -0,0 +1,41 @@
+## @file PeiSsifInterfaceLib.inf
+#
+# INF description file for SsifInterfaceLib Library for PEIMs.
+#
+# @copyright
+# Copyright 2016 - 2021 Intel Corporation. <BR>
+# Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PeiSsifInterfaceLib
+ FILE_GUID = EDA631E3-DC66-4120-BADF-B6BA73B6ABD4
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.1
+ LIBRARY_CLASS = SsifInterfaceLib | PEIM
+
+[Sources]
+ PeiSsifInterfaceLib.c
+ SsifInterfaceLibCommon.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IpmiFeaturePkg/IpmiFeaturePkg.dec
+
+[LibraryClasses]
+ DebugLib
+ TimerLib
+ BaseMemoryLib
+ PeiServicesTablePointerLib
+ BmcCommonInterfaceLib
+
+[Ppis]
+ gEfiPeiSmbus2PpiGuid
+
+[Pcd]
+ gIpmiFeaturePkgTokenSpaceGuid.PcdSsifSlaveAddress
+ gIpmiFeaturePkgTokenSpaceGuid.PcdSsifRequestRetriesDelay
+ gIpmiFeaturePkgTokenSpaceGuid.PcdSsifCommandtRetryCounter
+ gIpmiFeaturePkgTokenSpaceGuid.PcdSsifRequestRetriesDelay
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInterfaceLib/SmmSsifInterfaceLib.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInterfaceLib/SmmSsifInterfaceLib.c
new file mode 100644
index 0000000000..4fb4a889ed
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInterfaceLib/SmmSsifInterfaceLib.c
@@ -0,0 +1,148 @@
+/** @file SmmSsifInterfaceLib.c
+ SSIF Transport SMM phase Implementation library functions.
+
+ @copyright
+ Copyright 2016 - 2021 Intel Corporation. <BR>
+ Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/DebugLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Library/BmcCommonInterfaceLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/SsifInterfaceLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/IpmiTransport2Protocol.h>
+#include <Protocol/SmbusHc.h>
+
+/**
+ Send Ipmi command through Smbus instance.
+
+ @param[in] Interface Pointer to System interface.
+ @param[in] SlaveAddress The SMBUS hardware address.
+ @param[in] Command This command is transmitted by the SMBus
+ host controller to the SMBus slave device.
+ @param[in] Operation Operation to be performed.
+ @param[in] PecCheck Defines if Packet Error Code (PEC)
+ checking is required for this operation.
+ @param[in, out] Length Signifies the number of bytes that this
+ operation will do.
+ @param[in, out] Buffer Contains the value of data to execute to
+ the SMBus slave device. The length of
+ this buffer is identified by Length.
+
+ @retval EFI_NOT_FOUND Smbus instance is not found.
+ @retval Others Return status of the Smbus Execute operation.
+
+**/
+EFI_STATUS
+IpmiSmbusSendCommand (
+ IN IPMI_SYSTEM_INTERFACE *Interface,
+ IN EFI_SMBUS_DEVICE_ADDRESS SlaveAddress,
+ IN EFI_SMBUS_DEVICE_COMMAND Command,
+ IN EFI_SMBUS_OPERATION Operation,
+ IN BOOLEAN PecCheck,
+ IN OUT UINTN *Length,
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ EFI_SMBUS_HC_PROTOCOL *EfiSmbusHcProtocol;
+
+ Status = EFI_NOT_FOUND;
+ EfiSmbusHcProtocol = (EFI_SMBUS_HC_PROTOCOL *)Interface->Ssif.SsifInterfaceApiPtr;
+
+ if (EfiSmbusHcProtocol != NULL) {
+ Status = EfiSmbusHcProtocol->Execute (
+ EfiSmbusHcProtocol,
+ SlaveAddress,
+ Command,
+ Operation,
+ PecCheck,
+ Length,
+ Buffer );
+ }
+
+ DEBUG ((DEBUG_INFO, "%a EfiSmbusHcProtocol->Execute Status = %r\n", __FUNCTION__, Status));
+
+ return Status;
+}
+
+/**
+ Locate Smbus instance and initialize interface pointer.
+
+ @param[in, out] Interface System interface pointer.
+
+ @return EFI_STATUS Status returned while locating smbus instance.
+
+**/
+EFI_STATUS
+IpmiGetSmbusApiPtr (
+ IN OUT IPMI_TRANSPORT2 *IpmiTransport2
+)
+{
+ EFI_STATUS Status;
+ EFI_SMBUS_HC_PROTOCOL *EfiSmbusHcProtocol;
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer = NULL;
+ UINTN Index;
+ BMC_INTERFACE_STATUS BmcStatus;
+
+ IpmiTransport2->Interface.Ssif.SsifInterfaceApiGuid = gEfiSmbusHcProtocolGuid;
+ HandleCount = 0;
+
+ Status = gSmst->SmmLocateHandle (
+ ByProtocol,
+ &gEfiSmbusHcProtocolGuid,
+ NULL,
+ &HandleCount,
+ HandleBuffer );
+ if (EFI_ERROR (Status) && Status == EFI_BUFFER_TOO_SMALL) {
+ // Allocate memory for Handle buffer
+ HandleBuffer = AllocateZeroPool (HandleCount);
+ if (HandleBuffer == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ Status = gSmst->SmmLocateHandle (
+ ByProtocol,
+ &gEfiSmbusHcProtocolGuid,
+ NULL,
+ &HandleCount,
+ HandleBuffer );
+ if (EFI_ERROR (Status)) {
+ // Free HandleBuffer memory
+ FreePool(HandleBuffer);
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ for (Index = 0; Index < HandleCount; Index++) {
+ Status = gSmst->SmmHandleProtocol (
+ HandleBuffer[Index],
+ &gEfiSmbusHcProtocolGuid,
+ (VOID **)&EfiSmbusHcProtocol );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+ IpmiTransport2->Interface.Ssif.InterfaceState = IpmiInterfaceInitialized;
+ IpmiTransport2->Interface.Ssif.SsifInterfaceApiPtr = (UINTN)EfiSmbusHcProtocol;
+
+ Status = CheckSelfTestByInterfaceType(
+ IpmiTransport2,
+ &BmcStatus,
+ SysInterfaceSsif);
+ if (EFI_ERROR (Status) || (BmcStatus == BmcStatusHardFail)) {
+ IpmiTransport2->Interface.Ssif.InterfaceState = IpmiInterfaceInitError;
+ continue;
+ }
+
+ GetSystemInterfaceCapability (IpmiTransport2);
+ GetGlobalEnables (IpmiTransport2);
+ break;
+ }
+
+ FreePool(HandleBuffer);
+ return Status;
+}
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInterfaceLib/SmmSsifInterfaceLib.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInterfaceLib/SmmSsifInterfaceLib.inf
new file mode 100644
index 0000000000..a7e25647e2
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInterfaceLib/SmmSsifInterfaceLib.inf
@@ -0,0 +1,40 @@
+## @file SmmSsifInterfaceLib.inf
+#
+# INF description file for SsifInterfaceLib Library for DXE SMM drivers.
+#
+# @copyright
+# Copyright 2016 - 2021 Intel Corporation. <BR>
+# Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SmmSsifInterfaceLib
+ FILE_GUID = DB817B63-FA26-44FA-BF84-8D48596F982B
+ MODULE_TYPE = DXE_SMM_DRIVER
+ VERSION_STRING = 1.1
+ LIBRARY_CLASS = SsifInterfaceLib | DXE_SMM_DRIVER
+
+[Sources]
+ SmmSsifInterfaceLib.c
+ SsifInterfaceLibCommon.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IpmiFeaturePkg/IpmiFeaturePkg.dec
+
+[LibraryClasses]
+ SmmServicesTableLib
+ MemoryAllocationLib
+ BmcCommonInterfaceLib
+
+[Protocols]
+ gEfiSmbusHcProtocolGuid
+
+[Pcd]
+ gIpmiFeaturePkgTokenSpaceGuid.PcdSsifSlaveAddress
+ gIpmiFeaturePkgTokenSpaceGuid.PcdSsifRequestRetriesDelay
+ gIpmiFeaturePkgTokenSpaceGuid.PcdSsifCommandtRetryCounter
+ gIpmiFeaturePkgTokenSpaceGuid.PcdSsifRequestRetriesDelay
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInterfaceLib/SsifInterfaceLibCommon.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInterfaceLib/SsifInterfaceLibCommon.c
new file mode 100644
index 0000000000..5b6feb194f
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInterfaceLib/SsifInterfaceLibCommon.c
@@ -0,0 +1,546 @@
+/** @file SsifInterfaceLibCommon.c
+ SSIF Transport Implementation common functions and variables.
+
+ @copyright
+ Copyright 2016 - 2021 Intel Corporation. <BR>
+ Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/DebugLib.h>
+#include <Library/TimerLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BmcCommonInterfaceLib.h>
+#include <Library/SsifInterfaceLib.h>
+
+SSIF_ALERT_PIN_CHECK *gSsifAlertPinCheckHookList[] =
+{
+ NULL
+};
+
+/**
+ Check the SMBUS alert pin status function
+
+ @param VOID Nothing.
+
+ @retval TRUE Alert pin status is set.
+ @retval FALSE Alert pin status is not set.
+
+**/
+BOOLEAN
+CheckAlertPinHook (
+ VOID
+ )
+{
+ BOOLEAN CheckAlertSignal = FALSE;
+ UINTN Index;
+
+ for (Index = 0; gSsifAlertPinCheckHookList[Index]; Index++) {
+ CheckAlertSignal = gSsifAlertPinCheckHookList[Index]();
+ }
+
+ return CheckAlertSignal;
+}
+
+/**
+ Sends the command/data to Ssif interface.
+
+ @param[in] Interface Pointer to System interface.
+ @param[in] Context NULL here.
+ @param[in] Data Pointer to command data that will be sent to BMC
+ along with Command.
+ @param[in] DataSize Size of the command data.
+
+ @return EFI_STATUS Status returned from Smbus send command.
+
+**/
+EFI_STATUS
+SendDataToSsifBmcPort (
+ IN IPMI_SYSTEM_INTERFACE *Interface,
+ IN VOID *Context,
+ IN UINT8 *Data,
+ IN UINT8 DataSize
+ )
+{
+ EFI_STATUS Status;
+ EFI_SMBUS_DEVICE_ADDRESS BmcAddress;
+ UINTN IpmiWriteCommand;
+ UINT8 IpmiData[IPMI_SMBUS_BLOCK_LENGTH];
+ UINTN DataLength;
+ UINT8 DataIndex;
+ BOOLEAN PECSupport;
+ UINT8 RetryCount;
+ UINT8 OriginalDataSize;
+
+ DataLength = DataSize;
+ DataIndex = 0;
+ RetryCount = 0;
+ OriginalDataSize = DataSize;
+ PECSupport = Interface->Ssif.PecSupport;
+ BmcAddress.SmbusDeviceAddress = FixedPcdGet16 (PcdSsifSlaveAddress);
+ ZeroMem (IpmiData, sizeof(IpmiData));
+
+ do {
+ if (OriginalDataSize == DataSize) {
+ if (DataSize <= IPMI_SMBUS_BLOCK_LENGTH) {
+ // Working single writes start.
+ DataLength = DataSize;
+ IpmiWriteCommand = IPMI_SMBUS_SINGLE_WRITE_CMD;
+ CopyMem (
+ IpmiData,
+ &Data[DataIndex*IPMI_SMBUS_BLOCK_LENGTH],
+ DataLength );
+ } else {
+ // Working multi-part writes start.
+ IpmiWriteCommand = IPMI_SMBUS_MULTI_WRITE_START_CMD;
+ DataLength = IPMI_SMBUS_BLOCK_LENGTH;
+ CopyMem (
+ IpmiData,
+ &Data[DataIndex*IPMI_SMBUS_BLOCK_LENGTH],
+ DataLength );
+ }
+ } else {
+ if (DataSize > IPMI_SMBUS_BLOCK_LENGTH) {
+ // Working multi-part writes middle.
+ IpmiWriteCommand = IPMI_SMBUS_MULTI_WRITE_MIDDLE_CMD;
+ DataLength = IPMI_SMBUS_BLOCK_LENGTH;
+ CopyMem (
+ IpmiData,
+ &Data[DataIndex*IPMI_SMBUS_BLOCK_LENGTH],
+ DataLength );
+ } else {
+ // Working multi-part writes end.
+ IpmiWriteCommand = IPMI_SMBUS_MULTI_WRITE_END_CMD;
+ DataLength = DataSize;
+ CopyMem (
+ IpmiData,
+ &Data[DataIndex*IPMI_SMBUS_BLOCK_LENGTH],
+ DataLength );
+ }
+ }
+
+ Status = IpmiSmbusSendCommand (
+ Interface,
+ BmcAddress,
+ IpmiWriteCommand,
+ EfiSmbusWriteBlock,
+ PECSupport,
+ &DataLength,
+ IpmiData );
+ if (!EFI_ERROR(Status)) {
+ if (DataSize >= IPMI_SMBUS_BLOCK_LENGTH) {
+ RetryCount = 0;
+ DataSize -= IPMI_SMBUS_BLOCK_LENGTH;
+ DataIndex++;
+ } else {
+ DataSize = 0;
+ }
+ } else {
+ if (RetryCount == Interface->Ssif.SsifRetryCounter) {
+ break;
+ } else {
+ RetryCount++;
+ // Failed retries delay about 60ms to 250ms.
+ MicroSecondDelay (FixedPcdGet32 (PcdSsifRequestRetriesDelay));
+ /* If the Multi-part write fails, then try to write the
+ data from the beginning.*/
+ if (IpmiWriteCommand != IPMI_SMBUS_SINGLE_WRITE_CMD) {
+ DataSize = OriginalDataSize;
+ DataIndex = 0;
+ }
+ }
+ }
+
+ } while (DataSize);
+ return Status;
+}
+
+/**
+ Receives the Data from BMC port
+
+ @param[in] Interface Pointer to System interface.
+ @param[in] Context NULL here.
+ @param[out] Data Pointer to response data that is received from
+ BMC.
+ @param[out] DataSize Size of the response data.
+
+ @retval EFI_SUCCESS Data received from BMC successfully.
+ @retval Others Status of the Receiving data to BMC port.
+
+ @return EFI_STATUS Status returned from Smbus send command.
+
+**/
+EFI_STATUS
+ReceiveBmcDataFromSsifPort (
+ IN IPMI_SYSTEM_INTERFACE *Interface,
+ IN VOID *Context,
+ OUT UINT8 *Data,
+ OUT UINT8 *DataSize
+ )
+{
+ EFI_STATUS Status;
+ EFI_SMBUS_DEVICE_ADDRESS BmcAddress;
+ UINTN IpmiReadCommand;
+ UINT8 IpmiData[IPMI_SMBUS_BLOCK_LENGTH];
+ UINTN DataLength;
+ BOOLEAN PECSupport;
+ UINT8 RetryCount;
+ UINT8 OriginalDataSize;
+
+ DataLength = *DataSize;
+ RetryCount = 0;
+ OriginalDataSize = *DataSize;
+ PECSupport = Interface->Ssif.PecSupport;
+ BmcAddress.SmbusDeviceAddress = FixedPcdGet16 (PcdSsifSlaveAddress);
+ IpmiReadCommand = IPMI_SMBUS_SINGLE_READ_CMD;
+
+ while (RetryCount <= Interface->Ssif.SsifRetryCounter) {
+
+ Status = IpmiSmbusSendCommand (
+ Interface,
+ BmcAddress,
+ IpmiReadCommand,
+ EfiSmbusReadBlock,
+ PECSupport,
+ &DataLength,
+ (VOID *)IpmiData );
+ if (EFI_ERROR(Status)) {
+ RetryCount++;
+ // Failed retries delay about 60ms to 250ms.
+ MicroSecondDelay (FixedPcdGet32 (PcdSsifRequestRetriesDelay));
+ /* If the Multi-part Read command fails, then try to read the
+ data from the beginning.*/
+ if (IpmiReadCommand != IPMI_SMBUS_SINGLE_READ_CMD) {
+ IpmiReadCommand = IPMI_SMBUS_SINGLE_READ_CMD;
+ }
+ DataLength = OriginalDataSize;
+ continue;
+ }
+
+ if (IpmiReadCommand == IPMI_SMBUS_SINGLE_READ_CMD) {
+ if ((IpmiData[0] == IPMI_MULTI_READ_ZEROTH_STRT_BIT) &&
+ (IpmiData[1] == IPMI_MULTI_READ_FIRST_STRT_BIT)) {
+ // Working multi-part reads start.
+ CopyMem (
+ Data,
+ &IpmiData[2],
+ DataLength-2 );
+ *DataSize = (UINT8)DataLength-2;
+ IpmiReadCommand = IPMI_SMBUS_MULTI_READ_MIDDLE_CMD;
+ } else {
+ // Working single reads start.
+ CopyMem (
+ Data,
+ IpmiData,
+ DataLength );
+ *DataSize = (UINT8)DataLength;
+ break;
+ }
+ } else {
+ if(IpmiData[0] == 0xFF) {
+ // Working multi-part reads end.
+ CopyMem (
+ &Data[*DataSize],
+ &IpmiData[1],
+ DataLength-1 );
+ *DataSize += (UINT8)DataLength-1;
+ break;
+ } else {
+ // Working multi-part reads middle.
+ CopyMem (
+ &Data[*DataSize],
+ &IpmiData[1],
+ DataLength-1 );
+ *DataSize += (UINT8)DataLength-1;
+ IpmiReadCommand = IPMI_SMBUS_MULTI_READ_MIDDLE_CMD;
+ }
+ }
+ }
+
+ return Status;
+}
+
+/** @internal
+ SSIF interface Ipmi send command Implementation
+
+ @param[in] Interface Pointer to System interface.
+ @param[in] NetFunction Net function of the command.
+ @param[in] Lun Logical Unit Number of the command.
+ @param[in] Command Command to be sent to BMC.
+ @param[in] CommandData Command data to be sent along with
+ Command.
+ @param[in] CommandDataSize Command Data size.
+ @param[out] ResponseData Pointer to the response data buffer.
+ @param[in, out] ResponseDataSize Pointer to the response data size.
+ @param[out] CompletionCode Pointer to completion code.
+ @param[in] InterfaceType Interface type.
+ @param[in] Context NULL here.
+
+ @retval EFI_UNSUPPORTED Interface type is not supported.
+ @retval EFI_NOT_READY Interface is not initialized.
+ @retval EFI_ACCESS_DENIED Interface is locked.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_BAD_BUFFER_SIZE Invalid buffer size.
+ @retval EFI_DEVICE_ERROR Error completion code or data size
+ retrieved is small.
+ @retval EFI_BUFFER_TOO_SMALL Buffer is too small to update
+ response data.
+ @retval EFI_SUCCESS Command sent successfully.
+ @return Others Error status returned from BMC while
+ executing the command.
+
+**/
+EFI_STATUS
+EFIAPI
+IpmiSsifSendCommandToBmc (
+ IN IPMI_TRANSPORT2 *This,
+ IN UINT8 NetFunction,
+ IN UINT8 Lun,
+ IN UINT8 Command,
+ IN UINT8 *CommandData,
+ IN UINT8 CommandDataSize,
+ IN OUT UINT8 *ResponseData,
+ IN OUT UINT8 *ResponseDataSize,
+ IN VOID *Context
+)
+{
+ EFI_STATUS Status;
+ UINT8 DataSize;
+ UINT8 CmdDataBuffer[IPMI_MAX_SSIF_CMD_DATA_SIZE];
+ IPMI_SYSTEM_INTERFACE Interface;
+
+ Interface = This->Interface;
+
+ if (Interface.Ssif.InterfaceState != IpmiInterfaceInitialized) {
+ return EFI_NOT_READY;
+ }
+
+ if (((CommandData == NULL) && (CommandDataSize!= 0)) || (This == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((ResponseDataSize == NULL) || ((ResponseData == NULL) && *ResponseDataSize)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (IpmiIsIpmiTransportlocked (&Interface.Ssif.SsifTransportLocked)) {
+ return EFI_ACCESS_DENIED;
+ } else {
+ IpmiTransportAcquireLock (&Interface.Ssif.SsifTransportLocked);
+ }
+
+ // Check the SSIF interface multi-part reads/writes supported.
+ // Block length include Command data, NetFn, and Command parameter.
+ if (((Interface.Ssif.RwSupport == SsifSinglePartRw) &&
+ ((CommandDataSize + 2) > IPMI_SMBUS_BLOCK_LENGTH)) ||
+ ((Interface.Ssif.RwSupport == SsifMultiPartRw) &&
+ ((CommandDataSize + 2) > (2*IPMI_SMBUS_BLOCK_LENGTH))) ||
+ ((Interface.Ssif.RwSupport == SsifMultiPartRwWithMiddle) &&
+ ((CommandDataSize + 2) > IPMI_MAX_SSIF_CMD_DATA_SIZE))) {
+
+ IpmiTransportReleaseLock (&Interface.Ssif.SsifTransportLocked);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Interface.Ssif.SsifSoftErrorCount >= MAX_BMC_CMD_FAIL_COUNT) {
+ IpmiTransportReleaseLock (&Interface.Ssif.SsifTransportLocked);
+ return EFI_NOT_READY;
+ }
+
+ CmdDataBuffer[0] = (UINT8) ((NetFunction << 2) | (Lun & 0x03));
+ CmdDataBuffer[1] = Command;
+
+ if (CommandDataSize > 0) {
+ if (CommandData == NULL) {
+ IpmiTransportReleaseLock (&Interface.Ssif.SsifTransportLocked);
+ return EFI_INVALID_PARAMETER;
+ }
+ if (CommandDataSize <= (IPMI_MAX_SSIF_CMD_DATA_SIZE - 2) ) {
+ CopyMem (
+ &CmdDataBuffer[2],
+ CommandData,
+ CommandDataSize );
+ } else {
+ IpmiTransportReleaseLock (&Interface.Ssif.SsifTransportLocked);
+ return EFI_BAD_BUFFER_SIZE;
+ }
+ }
+
+ Status = SendDataToSsifBmcPort (
+ &Interface,
+ Context,
+ CmdDataBuffer,
+ (UINT8)(CommandDataSize + 2));
+
+ if (Status != EFI_SUCCESS) {
+ Interface.Ssif.SsifSoftErrorCount++;
+ IpmiTransportReleaseLock (&Interface.Ssif.SsifTransportLocked);
+ return Status;
+ }
+
+ // Hook to check smbus alert pin.
+ if (Interface.Ssif.SmbAlertSupport) {
+ if (!CheckAlertPinHook()) {
+ IpmiTransportReleaseLock (&Interface.Ssif.SsifTransportLocked);
+ return EFI_DEVICE_ERROR;
+ }
+ } else {
+ MicroSecondDelay(FixedPcdGet32 (PcdSsifRequestRetriesDelay));
+ }
+ DataSize = IPMI_SMBUS_BLOCK_LENGTH;
+
+ Status = ReceiveBmcDataFromSsifPort (
+ &Interface,
+ Context,
+ CmdDataBuffer,
+ &DataSize);
+ if (Status != EFI_SUCCESS) {
+ Interface.Ssif.SsifSoftErrorCount++;
+ IpmiTransportReleaseLock (&Interface.Ssif.SsifTransportLocked);
+ return Status;
+ }
+
+ if (IPMI_ERROR_COMPLETION_CODE(CmdDataBuffer[2])) {
+ IpmiUpdateSoftErrorCount (
+ CmdDataBuffer[2],
+ &Interface,
+ This->InterfaceType );
+ // Write completion code into return buffer if ipmi command returns an error.
+ if (*ResponseDataSize) {
+ if (ResponseData) {
+ *ResponseData = CmdDataBuffer[2];
+ }
+ *ResponseDataSize = 1;
+ }
+ IpmiTransportReleaseLock (&Interface.Ssif.SsifTransportLocked);
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (DataSize < 3) {
+ IpmiTransportReleaseLock (&Interface.Ssif.SsifTransportLocked);
+ return EFI_DEVICE_ERROR;
+ }
+
+ if ((DataSize - 2) > *((UINT8 *)ResponseDataSize)) {
+ *ResponseDataSize = (UINT8) (DataSize - 3);
+ IpmiTransportReleaseLock (&Interface.Ssif.SsifTransportLocked);
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ // Copying the response data into ResponseData buffer.
+ CopyMem (
+ ResponseData,
+ &CmdDataBuffer[2],
+ (DataSize - 2) );
+ *ResponseDataSize = (UINT8) (DataSize - 2);
+
+ IpmiTransportReleaseLock (&Interface.Ssif.SsifTransportLocked);
+ return EFI_SUCCESS;
+}
+
+/**
+ Execute the Get System Interface Capability command and update the RwSupport
+ and PecSupport of Ipmi Instance.
+
+ @param IpmiInstance Ipmi Instance Data structure pointer.
+
+ @return EFI_STATUS Return Status
+
+**/
+VOID
+GetSystemInterfaceCapability (
+ IN OUT IPMI_TRANSPORT2 *IpmiTransport2
+ )
+{
+ EFI_STATUS Status;
+ IPMI_GET_SYSTEM_INTERFACE_CAPABILITY_REQ GetSystemInterfaceCapabilityCmd;
+ IPMI_GET_SYSTEM_INTERFACE_CAPABILITY_RES GetSsifInterfaceCapability;
+ UINT32 DataSize = sizeof (GetSsifInterfaceCapability);
+
+ GetSystemInterfaceCapabilityCmd.SystemInterfaceType = 0x0; // SSIF
+ GetSystemInterfaceCapabilityCmd.Reserved = 0x0;
+
+ Status = IpmiTransport2->IpmiSubmitCommand2 (
+ IpmiTransport2,
+ IPMI_NETFN_APP,
+ BMC_LUN,
+ IPMI_APP_GET_SYSTEM_INTERFACE_CAPABILITIES,
+ (UINT8*) &GetSystemInterfaceCapabilityCmd,
+ sizeof (GetSystemInterfaceCapabilityCmd),
+ (UINT8*) &GetSsifInterfaceCapability,
+ &DataSize);
+ if (!EFI_ERROR (Status)) {
+ IpmiTransport2->Interface.Ssif.RwSupport = GetSsifInterfaceCapability.TransactionSupport;
+ IpmiTransport2->Interface.Ssif.PecSupport = GetSsifInterfaceCapability.PecSupport;
+ }
+}
+
+/**
+ Execute the Get Global Enable command to get receive message queue interrupt.
+
+ @return VOID
+
+**/
+VOID
+GetGlobalEnables (
+ IN OUT IPMI_TRANSPORT2 *IpmiTransport2
+)
+{
+ EFI_STATUS Status;
+ IPMI_BMC_GLOBAL_ENABLES_RES BmcGlobalEnables;
+ UINT32 ResponseDataSize = sizeof (BmcGlobalEnables);
+
+ //
+ // Get Global Enable Information.
+ //
+ Status = IpmiTransport2->IpmiSubmitCommand2(
+ IpmiTransport2,
+ IPMI_NETFN_APP,
+ BMC_LUN,
+ IPMI_APP_GET_BMC_GLOBAL_ENABLES,
+ NULL,
+ 0,
+ (UINT8 *) (&BmcGlobalEnables),
+ &ResponseDataSize );
+ if (!EFI_ERROR(Status)) {
+ //
+ // Set Smb alert pin based on ReceiveMsgQueueInterrupt bit
+ //
+ IpmiTransport2->Interface.Ssif.SmbAlertSupport = BmcGlobalEnables.ReceiveMsgQueueInterrupt;
+ }
+}
+
+/**
+ Initialize SSIF interface specific data.
+
+ @param[in, out] Interface System interface pointer.
+
+ @retval EFI_SUCCESS Interface is successfully initialized.
+ @retval Others Return status while initializing interface.
+
+**/
+EFI_STATUS
+InitSsifInterfaceData (
+ IN OUT IPMI_TRANSPORT2 *IpmiTransport2
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ if (IpmiTransport2->Interface.Ssif.InterfaceState == IpmiInterfaceInitialized) {
+ return Status;
+ }
+
+ IpmiTransport2->Interface.Ssif.SsifRetryCounter = FixedPcdGet16 (PcdSsifCommandtRetryCounter);
+ IpmiTransport2->Interface.Ssif.PecSupport = FALSE;
+ IpmiTransport2->Interface.Ssif.RwSupport = 0x0; // SSIF multi-part reads/writes support.
+ IpmiTransport2->Interface.Ssif.SmbAlertSupport = FALSE; // SMB alert pin support.
+
+ Status = IpmiGetSmbusApiPtr (IpmiTransport2);
+ if (EFI_ERROR(Status)) {
+ IpmiTransport2->Interface.Ssif.InterfaceState = IpmiInterfaceInitError;
+ return Status;
+ }
+
+ IpmiTransportReleaseLock (&IpmiTransport2->Interface.Ssif.SsifTransportLocked);
+ return Status;
+}
--
2.38.1.windows.1
-The information contained in this message may be confidential and proprietary to American Megatrends (AMI). This communication is intended to be read only by the individual or entity to whom it is addressed or by their designee. If the reader of this message is not the intended recipient, you are on notice that any distribution of this message, in any form, is strictly prohibited. Please promptly notify the sender by reply e-mail or by telephone at 770-246-8600, and then delete or destroy all copies of the transmission.
prev parent reply other threads:[~2023-06-13 1:45 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-06-12 12:53 [edk2-devel][edk2-platforms][PATCH V3-3] IpmiFeaturePkg:Provided multiple IPMI interface support in Library Arun K
2023-06-13 1:44 ` Isaac Oram [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=SA1PR11MB5801ED0D4F220E73ED6303BAD055A@SA1PR11MB5801.namprd11.prod.outlook.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox