public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [edk2-devel][edk2-platforms][PATCH V1] IpmiFeaturePkg:Provided multliple IPMI interface support
@ 2023-02-28 16:07 arunk
  2023-04-10  1:59 ` [edk2-devel] [edk2-platforms][PATCH " Chang, Abner
  0 siblings, 1 reply; 2+ messages in thread
From: arunk @ 2023-02-28 16:07 UTC (permalink / raw)
  To: devel@edk2.groups.io, Arun K
  Cc: Sainadh Nagolu, Srinivasan Mani, isaac.w.oram@intel.com,
	nathaniel.l.desimone@intel.com, Liming Gao, Vasudevan S,
	Sundaresan S

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>
Cc: Vasudevan S <vasudevans@ami.com>
Cc: Srinivasan Mani <srinivasanm@ami.com>
Cc: Sundaresan S <sundaresans@ami.com>

Signed-off-by: Arun K <arunk@ami.com>
---
 .../GenericIpmi/Common/IpmiBmc.h              |  10 +
 .../GenericIpmi/Common/IpmiBmcCommon.h        |   2 +
 .../GenericIpmi/Common/IpmiHooks.c            | 222 +++++++
 .../GenericIpmi/Common/IpmiHooks.h            |  92 ++-
 .../GenericIpmi/Dxe/GenericIpmi.inf           |  12 +-
 .../IpmiFeaturePkg/GenericIpmi/Dxe/IpmiInit.c | 183 ++++++
 .../GenericIpmi/Pei/PeiGenericIpmi.c          | 273 +++++++--
 .../GenericIpmi/Pei/PeiGenericIpmi.h          |   3 +
 .../GenericIpmi/Pei/PeiGenericIpmi.inf        |  16 +-
 .../GenericIpmi/Pei/PeiIpmiBmc.c              |   3 +-
 .../GenericIpmi/Pei/PeiIpmiBmc.h              |   9 +
 .../GenericIpmi/Pei/PeiIpmiBmcDef.h           |  31 +-
 .../GenericIpmi/Pei/PeiIpmiHooks.c            | 316 ++++++++++
 .../GenericIpmi/Pei/PeiIpmiHooks.h            | 211 +++++++
 .../GenericIpmi/Smm/SmmGenericIpmi.c          | 178 +++++-
 .../GenericIpmi/Smm/SmmGenericIpmi.inf        |  13 +-
 .../IpmiFeaturePkg/Include/IpmiFeature.dsc    |  12 +
 .../Include/IpmiNetFnAppDefinitions.h         | 239 ++++++++
 .../Include/IpmiTransport2Definitions.h       | 139 +++++
 .../Include/Library/BmcCommonInterfaceLib.h   | 186 ++++++
 .../Include/Library/BtInterfaceLib.h          |  83 +++
 .../Include/Library/SsifInterfaceLib.h        | 165 +++++
 .../Include/Ppi/IpmiTransport2Ppi.h           |  22 +
 .../Include/Protocol/IpmiTransport2Protocol.h |  29 +
 .../IpmiFeaturePkg/IpmiFeaturePkg.dec         |  42 ++
 .../BmcCommonInterfaceLib.c                   | 227 +++++++
 .../BmcCommonInterfaceLib.inf                 |  26 +
 .../BtInterfaceLib/BtInterfaceLib.c           | 570 ++++++++++++++++++
 .../BtInterfaceLib/BtInterfaceLib.inf         |  39 ++
 .../SsifInterfaceLib/DxeSsifInterfaceLib.c    | 131 ++++
 .../SsifInterfaceLib/DxeSsifInterfaceLib.inf  |  39 ++
 .../SsifInterfaceLib/PeiSsifInterfaceLib.c    | 122 ++++
 .../SsifInterfaceLib/PeiSsifInterfaceLib.inf  |  40 ++
 .../SsifInterfaceLib/SmmSsifInterfaceLib.c    | 148 +++++
 .../SsifInterfaceLib/SmmSsifInterfaceLib.inf  |  40 ++
 .../SsifInterfaceLib/SsifInterfaceLibCommon.c | 545 +++++++++++++++++
 36 files changed, 4334 insertions(+), 84 deletions(-)
 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/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/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/Common/IpmiBmc.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Common/IpmiBmc.h
index d306a085e5..19fb2a26a3 100644
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Common/IpmiBmc.h
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Common/IpmiBmc.h
@@ -3,6 +3,7 @@


   @copyright

   Copyright 1999 - 2021 Intel Corporation. <BR>

+  Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>

   SPDX-License-Identifier: BSD-2-Clause-Patent

 **/



@@ -21,6 +22,7 @@
 #include <Library/ReportStatusCodeLib.h>

 #include <Library/IpmiBaseLib.h>

 #include <Protocol/IpmiTransportProtocol.h>

+#include <Protocol/IpmiTransport2Protocol.h>



 #include "IpmiBmcCommon.h"

 #include "KcsBmc.h"

@@ -41,4 +43,12 @@
   SM_IPMI_BMC_SIGNATURE \

   )



+#define INSTANCE_FROM_IPMI_TRANSPORT2_THIS(a) \

+  CR ( \

+  a, \

+  IPMI_BMC_INSTANCE_DATA, \

+  IpmiTransport2, \

+  SM_IPMI_BMC_SIGNATURE \

+  )

+

 #endif // _IPMI_BMC_H_

diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Common/IpmiBmcCommon.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Common/IpmiBmcCommon.h
index 1e5dfd81f1..930bee21f1 100644
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Common/IpmiBmcCommon.h
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Common/IpmiBmcCommon.h
@@ -3,6 +3,7 @@


   @copyright

   Copyright 1999 - 2021 Intel Corporation. <BR>

+  Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>

   SPDX-License-Identifier: BSD-2-Clause-Patent

 **/



@@ -56,6 +57,7 @@ typedef struct {
   UINT8               SoftErrorCount;

   UINT16              IpmiIoBase;

   IPMI_TRANSPORT      IpmiTransport;

+  IPMI_TRANSPORT2     IpmiTransport2;

   EFI_HANDLE          IpmiSmmHandle;

 } IPMI_BMC_INSTANCE_DATA;



diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Common/IpmiHooks.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Common/IpmiHooks.c
index b2788e5a4c..64c3215d90 100644
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Common/IpmiHooks.c
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Common/IpmiHooks.c
@@ -3,6 +3,7 @@


   @copyright

   Copyright 2014 - 2021 Intel Corporation. <BR>

+  Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>

   SPDX-License-Identifier: BSD-2-Clause-Patent

 **/



@@ -48,6 +49,11 @@ Returns:


 --*/

 {

+

+  if (This == NULL) {

+      return EFI_INVALID_PARAMETER;

+  }

+

   //

   // This Will be unchanged ( BMC/KCS style )

   //

@@ -64,6 +70,217 @@ Returns:
            );

 } // IpmiSendCommand()



+EFI_STATUS

+EFIAPI

+IpmiSendCommand2 (

+  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

+

+--*/

+{

+

+  IPMI_BMC_INSTANCE_DATA  *IpmiInstance;

+

+  if (This == NULL) {

+      return EFI_INVALID_PARAMETER;

+  }

+

+  IpmiInstance = INSTANCE_FROM_IPMI_TRANSPORT2_THIS(This);

+

+#if KcsInterfaceSupport

+  if ((IpmiInstance->IpmiTransport2.InterfaceType == SysInterfaceKcs) &&

+      (IpmiInstance->IpmiTransport2.Interface.KcsInterfaceState == IpmiInterfaceInitialized)) {

+

+      return IpmiSendCommand (

+               &IpmiInstance->IpmiTransport,

+               NetFunction,

+               Lun,

+               Command,

+               CommandData,

+               CommandDataSize,

+               ResponseData,

+               ResponseDataSize

+               );

+  }

+#endif

+

+#if BtInterfaceSupport

+  if ((IpmiInstance->IpmiTransport2.InterfaceType == SysInterfaceBt) &&

+      (IpmiInstance->IpmiTransport2.Interface.Bt.InterfaceState == IpmiInterfaceInitialized)) {

+

+      return IpmiBtSendCommandToBmc (

+               &IpmiInstance->IpmiTransport2,

+               NetFunction,

+               Lun,

+               Command,

+               CommandData,

+               (UINT8) CommandDataSize,

+               ResponseData,

+               (UINT8*) ResponseDataSize,

+               NULL

+               );

+  }

+#endif

+

+#if SsifInterfaceSupport

+  if ((IpmiInstance->IpmiTransport2.InterfaceType == SysInterfaceSsif) &&

+      (IpmiInstance->IpmiTransport2.Interface.Ssif.InterfaceState == IpmiInterfaceInitialized)) {

+

+      return IpmiSsifSendCommandToBmc (

+               &IpmiInstance->IpmiTransport2,

+               NetFunction,

+               Lun,

+               Command,

+               CommandData,

+               (UINT8) CommandDataSize,

+               ResponseData,

+               (UINT8*) ResponseDataSize,

+               NULL

+               );

+  }

+#endif

+

+  return EFI_UNSUPPORTED;

+} // IpmiSendCommand2()

+

+EFI_STATUS

+EFIAPI

+IpmiSendCommand2Ex (

+  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

+

+--*/

+

+  IPMI_BMC_INSTANCE_DATA  *IpmiInstance;

+

+  if (This == NULL) {

+      return EFI_INVALID_PARAMETER;

+  }

+

+  IpmiInstance = INSTANCE_FROM_IPMI_TRANSPORT2_THIS(This);

+

+#if KcsInterfaceSupport

+  if ((InterfaceType == SysInterfaceKcs) &&

+      (IpmiInstance->IpmiTransport2.Interface.KcsInterfaceState == IpmiInterfaceInitialized)) {

+

+      return IpmiSendCommand (

+                &IpmiInstance->IpmiTransport,

+                NetFunction,

+                Lun,

+                Command,

+                CommandData,

+                CommandDataSize,

+                ResponseData,

+                ResponseDataSize

+                );

+     }

+#endif

+

+#if BtInterfaceSupport

+  if ((InterfaceType == SysInterfaceBt) &&

+      (IpmiInstance->IpmiTransport2.Interface.Bt.InterfaceState == IpmiInterfaceInitialized)) {

+

+      return IpmiBtSendCommandToBmc (

+                &IpmiInstance->IpmiTransport2,

+                NetFunction,

+                Lun,

+                Command,

+                CommandData,

+                (UINT8) CommandDataSize,

+                ResponseData,

+                (UINT8*) ResponseDataSize,

+                NULL

+                );

+  }

+#endif

+

+#if SsifInterfaceSupport

+  if ((InterfaceType == SysInterfaceSsif) &&

+      (IpmiInstance->IpmiTransport2.Interface.Ssif.InterfaceState == IpmiInterfaceInitialized)) {

+

+      return IpmiSsifSendCommandToBmc (

+                &IpmiInstance->IpmiTransport2,

+                NetFunction,

+                Lun,

+                Command,

+                CommandData,

+                (UINT8) CommandDataSize,

+                ResponseData,

+                (UINT8*) ResponseDataSize,

+                NULL

+                );

+  }

+#endif

+

+  return EFI_UNSUPPORTED;

+}

+

 EFI_STATUS

 EFIAPI

 IpmiGetBmcStatus (

@@ -89,6 +306,11 @@ Returns:


 --*/

 {

+

+  if ((This == NULL) || (BmcStatus == NULL) || (ComAddress == NULL)) {

+      return EFI_INVALID_PARAMETER;

+  }

+

   return IpmiBmcStatus (

            This,

            BmcStatus,

diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Common/IpmiHooks.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Common/IpmiHooks.h
index 823cc08c61..29b793bbf0 100644
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Common/IpmiHooks.h
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Common/IpmiHooks.h
@@ -3,13 +3,20 @@


   @copyright

   Copyright 2014 - 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 "IpmiBmc.h"

+#include <Protocol/IpmiTransportProtocol.h>

+#include <Protocol/IpmiTransport2Protocol.h>

+#include <Library/BtInterfaceLib.h>

+#include <Library/SsifInterfaceLib.h>

+#include <Library/DebugLib.h>

+#include<IpmiBmcCommon.h>

+#include<IpmiBmc.h>



 //

 // Internal(hook) function list

@@ -54,6 +61,89 @@ Returns:
 --*/

 ;



+EFI_STATUS

+EFIAPI

+IpmiSendCommand2 (

+  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

+EFIAPI

+IpmiSendCommand2Ex (

+  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

+

+--*/

+;

+

 EFI_STATUS

 EFIAPI

 IpmiGetBmcStatus (

diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Dxe/GenericIpmi.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Dxe/GenericIpmi.inf
index 8d80aeb6b5..56d1e0c872 100644
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Dxe/GenericIpmi.inf
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Dxe/GenericIpmi.inf
@@ -3,6 +3,7 @@
 #

 # @copyright

 # Copyright 2010 - 2021 Intel Corporation. <BR>

+# Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>

 # SPDX-License-Identifier: BSD-2-Clause-Patent

 ##



@@ -49,16 +50,23 @@
   IoLib

   ReportStatusCodeLib

   TimerLib

+  BmcCommonInterfaceLib

+  BtInterfaceLib

+  SsifInterfaceLib



 [Protocols]

   gIpmiTransportProtocolGuid               # PROTOCOL ALWAYS_PRODUCED

   gEfiVideoPrintProtocolGuid

-

-[Guids]

+  gIpmiTransport2ProtocolGuid



 [Pcd]

   gIpmiFeaturePkgTokenSpaceGuid.PcdIpmiIoBaseAddress

   gIpmiFeaturePkgTokenSpaceGuid.PcdIpmiBmcReadyDelayTimer

+  gIpmiFeaturePkgTokenSpaceGuid.PcdDefaultSystemInterface

+  gIpmiFeaturePkgTokenSpaceGuid.PcdBtInterfaceSupport

+  gIpmiFeaturePkgTokenSpaceGuid.PcdSsifInterfaceSupport

+  gIpmiFeaturePkgTokenSpaceGuid.PcdKcsInterfaceSupport

+  gIpmiFeaturePkgTokenSpaceGuid.PcdBtControlPort



 [Depex]

   gEfiRuntimeArchProtocolGuid AND

diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Dxe/IpmiInit.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Dxe/IpmiInit.c
index d788b48867..8e44f9db9c 100644
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Dxe/IpmiInit.c
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Dxe/IpmiInit.c
@@ -3,6 +3,7 @@


   @copyright

   Copyright 1999 - 2021 Intel Corporation. <BR>

+  Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>

   SPDX-License-Identifier: BSD-2-Clause-Patent

 **/



@@ -13,6 +14,7 @@
 #include "IpmiBmc.h"

 #include "IpmiPhysicalLayer.h"

 #include <Library/TimerLib.h>

+#include <Library/BmcCommonInterfaceLib.h>

 #ifdef FAST_VIDEO_SUPPORT

   #include <Protocol/VideoPrint.h>

 #endif

@@ -342,6 +344,119 @@ Returns:
   return Status;

 } // GetDeviceId()



+/**

+    Initialize the API and parameters for IPMI Transport2 Instance

+

+    @param[in] IpmiInstance         Pointer to IPMI Instance

+

+    @return VOID    Nothing.

+

+**/

+VOID

+InitIpmiTransport2 (

+  IN  IPMI_BMC_INSTANCE_DATA *IpmiInstance

+  )

+{

+

+  IpmiInstance->IpmiTransport2.InterfaceType            = FixedPcdGet8 (PcdDefaultSystemInterface);

+  IpmiInstance->IpmiTransport2.IpmiTransport2BmcStatus  = BmcStatusOk;

+  IpmiInstance->IpmiTransport2.IpmiSubmitCommand2       = IpmiSendCommand2;

+  IpmiInstance->IpmiTransport2.IpmiSubmitCommand2Ex     = IpmiSendCommand2Ex;

+

+#if BtInterfaceSupport

+  InitBtInterfaceData(&IpmiInstance->IpmiTransport2);

+#endif

+

+#if SsifInterfaceSupport

+  InitSsifInterfaceData(&IpmiInstance->IpmiTransport2);

+#endif

+}

+

+/**

+    Notify call back function.

+

+    @param[in] Event    Event which caused this handler.

+    @param[in] Context  Context passed during Event Handler registration.

+

+    @return VOID    Nothing.

+

+**/

+VOID

+EFIAPI

+DxeNotifyCallback (

+  IN EFI_EVENT  Event,

+  IN VOID       *Context

+  )

+{

+  EFI_STATUS             Status;

+  IPMI_INTERFACE_STATE   InterfaceState;

+  EFI_HANDLE             Handle;

+

+  InterfaceState = IpmiInterfaceNotReady;

+

+#if SsifInterfaceSupport

+  InitSsifInterfaceData(&mIpmiInstance->IpmiTransport2);

+

+  if (mIpmiInstance->IpmiTransport2.Interface.Ssif.InterfaceState == IpmiInterfaceInitialized) {

+      InterfaceState = IpmiInterfaceInitialized;

+  }

+#endif

+

+  // Default Interface data should be initialized to install Ipmi Transport2 Protocol.

+  if (InterfaceState != IpmiInterfaceInitialized) {

+      return;

+  }

+

+  Handle = NULL;

+  Status = gBS->InstallProtocolInterface (

+                  &Handle,

+                  &gIpmiTransport2ProtocolGuid,

+                  EFI_NATIVE_INTERFACE,

+                  &mIpmiInstance->IpmiTransport2

+                  );

+  ASSERT_EFI_ERROR (Status);

+}

+

+/**

+    Registers protocol notify call back.

+

+    @param[in] ProtocolGuid     Pointer to Protocol Guid to register

+                                call back.

+

+    @retval EFI_INVALID_PARAMETER   If the ProtocolGuid is 0 or NULL.

+    @retval Others                  Status of call back registration.

+

+**/

+EFI_STATUS

+DxeRegisterProtocolCallback (

+  IN EFI_GUID   *ProtocolGuid

+  )

+{

+  EFI_STATUS  Status;

+  EFI_EVENT   NotifyEvent;

+  VOID        *Registration;

+

+  if ((ProtocolGuid == NULL) ||

+      ((ProtocolGuid != NULL) && IsZeroBuffer (ProtocolGuid, sizeof (EFI_GUID)))) {

+      return EFI_INVALID_PARAMETER;

+  }

+

+  Status = gBS->CreateEvent (

+                  EVT_NOTIFY_SIGNAL,

+                  TPL_NOTIFY,

+                  DxeNotifyCallback,

+                  NULL,

+                  &NotifyEvent);

+

+  if (!EFI_ERROR (Status)) {

+      Status = gBS->RegisterProtocolNotify (

+                      ProtocolGuid,

+                      NotifyEvent,

+                      &Registration);

+  }

+

+  return Status;

+}



 /**

   This function initializes KCS interface to BMC.

@@ -367,7 +482,10 @@ InitializeIpmiKcsPhysicalLayer (
   UINT8                  ErrorCount;

   EFI_HANDLE             Handle;

   UINT8                  Index;

+  IPMI_INTERFACE_STATE   InterfaceState = IpmiInterfaceNotReady;

+#if KcsInterfaceSupport

   EFI_STATUS_CODE_VALUE  StatusCodeValue[MAX_SOFT_COUNT];

+#endif



   ErrorCount = 0;

   mImageHandle = ImageHandle;

@@ -396,6 +514,8 @@ InitializeIpmiKcsPhysicalLayer (
     mIpmiInstance->Signature                        = SM_IPMI_BMC_SIGNATURE;

     mIpmiInstance->SlaveAddress                     = BMC_SLAVE_ADDRESS;

     mIpmiInstance->BmcStatus                        = BMC_NOTREADY;

+

+#if KcsInterfaceSupport

     mIpmiInstance->IpmiTransport.IpmiSubmitCommand  = IpmiSendCommand;

     mIpmiInstance->IpmiTransport.GetBmcStatus       = IpmiGetBmcStatus;



@@ -445,7 +565,70 @@ InitializeIpmiKcsPhysicalLayer (
                       );

       ASSERT_EFI_ERROR (Status);

     }

+#endif

+

+    // Initialise the IPMI transport2

+    InitIpmiTransport2(mIpmiInstance);

+

+    // Check interface data initialized successfully else register notify protocol.

+    for (Index = SysInterfaceKcs; Index < SysInterfaceMax; Index++) {

+

+        switch (Index) {

+#if KcsInterfaceSupport

+            case SysInterfaceKcs:

+                if ((mIpmiInstance->BmcStatus != BMC_HARDFAIL) && (mIpmiInstance->BmcStatus != BMC_UPDATE_IN_PROGRESS)) {

+                    BMC_INTERFACE_STATUS  BmcStatus;

+                    mIpmiInstance->IpmiTransport2.Interface.KcsInterfaceState = IpmiInterfaceInitialized;

+                    Status = CheckSelfTestByInterfaceType(

+                                        &mIpmiInstance->IpmiTransport2,

+                                        &BmcStatus,

+                                        SysInterfaceKcs);

+                    if (!EFI_ERROR (Status) && (BmcStatus != BmcStatusHardFail)) {

+                        InterfaceState = IpmiInterfaceInitialized;

+                    } else {

+                        mIpmiInstance->IpmiTransport2.Interface.KcsInterfaceState = IpmiInterfaceInitError;

+                    }

+                }

+                break;

+#endif



+#if BtInterfaceSupport

+            case SysInterfaceBt:

+                if (mIpmiInstance->IpmiTransport2.Interface.Bt.InterfaceState == IpmiInterfaceInitialized){

+                    InterfaceState = IpmiInterfaceInitialized;

+                }

+                break;

+#endif

+

+#if SsifInterfaceSupport

+            case SysInterfaceSsif:

+                if (mIpmiInstance->IpmiTransport2.Interface.Ssif.InterfaceState == IpmiInterfaceInitialized) {

+                    InterfaceState = IpmiInterfaceInitialized;

+                } else if (mIpmiInstance->IpmiTransport2.Interface.Ssif.InterfaceState == IpmiInterfaceInitError) {

+                    // Register protocol notify for SMBUS Protocol.

+                    Status = DxeRegisterProtocolCallback (

+                                &mIpmiInstance->IpmiTransport2.Interface.Ssif.SsifInterfaceApiGuid);

+                }

+                break;

+#endif

+            default:

+                break;

+        }

+    }

+

+    // Any one of the Interface data should be initialized to install IPMI Transport2 Protocol.

+    if (InterfaceState != IpmiInterfaceInitialized) {

+        return EFI_SUCCESS;

+    }

+

+    Handle = NULL;

+    Status = gBS->InstallProtocolInterface (

+                    &Handle,

+                    &gIpmiTransport2ProtocolGuid,

+                    EFI_NATIVE_INTERFACE,

+                    &mIpmiInstance->IpmiTransport2

+                    );

+    ASSERT_EFI_ERROR (Status);

     return EFI_SUCCESS;

   }

 } // InitializeIpmiKcsPhysicalLayer()

diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiGenericIpmi.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiGenericIpmi.c
index 3efb772b68..dc41ea966e 100644
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiGenericIpmi.c
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiGenericIpmi.c
@@ -3,6 +3,7 @@


   @copyright

   Copyright 2017 - 2021 Intel Corporation. <BR>

+  Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>

   SPDX-License-Identifier: BSD-2-Clause-Patent

 **/



@@ -10,10 +11,132 @@
 #include "PeiGenericIpmi.h"

 #include <Library/ReportStatusCodeLib.h>

 #include <Library/IpmiPlatformHookLib.h>

+#include <Library/BmcCommonInterfaceLib.h>



 ///////////////////////////////////////////////////////////////////////////////

-// Function Implementations

-//

+

+/**

+    Initialize the API and parameters for IPMI Transport2 Instance

+

+    @param[in] IpmiInstance         Pointer to IPMI Instance

+

+    @return VOID

+

+**/

+VOID

+InitIpmiTransport2 (

+  IN  PEI_IPMI_BMC_INSTANCE_DATA *IpmiInstance

+  )

+{

+  IpmiInstance->IpmiTransport2Ppi.InterfaceType           = FixedPcdGet8 (PcdDefaultSystemInterface);

+  IpmiInstance->IpmiTransport2Ppi.IpmiTransport2BmcStatus = BmcStatusOk;

+  IpmiInstance->IpmiTransport2Ppi.IpmiSubmitCommand2      = PeiIpmiSendCommand2;

+  IpmiInstance->IpmiTransport2Ppi.IpmiSubmitCommand2Ex    = PeiIpmiSendCommand2Ex;

+

+#if BtInterfaceSupport

+  if (!EFI_ERROR (PlatformIpmiIoRangeSet(FixedPcdGet16(PcdBtControlPort)))) {

+      InitBtInterfaceData (&IpmiInstance->IpmiTransport2Ppi);

+  }

+#endif

+

+#if SsifInterfaceSupport

+  InitSsifInterfaceData (&IpmiInstance->IpmiTransport2Ppi);

+#endif

+}

+

+/**

+    Notify callback function for interfaces.

+

+    @param[in] PeiServices          Describes the list of possible PEI

+                                    Services.

+    @param[in] NotifyDescriptor     Pointer to notify descriptor.

+    @param[in] Ppi                  Pointer to Ppi.

+

+    @return EFI_STATUS              Status of Notify call back.

+    @retval EFI_NOT_FOUND           Ipmi hob is not found.

+    @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.

+    @retval EFI_SUCCESS             Interface is initialized and installed

+                                    Ipmi Ppi successfully.

+    @retval Others                  Error status while installing Ppi.

+**/

+EFI_STATUS

+EFIAPI

+NotifyCallback (

+  IN EFI_PEI_SERVICES             **PeiServices,

+  IN EFI_PEI_NOTIFY_DESCRIPTOR    *NotifyDescriptor,

+  IN VOID                         *Ppi

+  )

+{

+  EFI_STATUS                    Status;

+  PEI_IPMI_BMC_INSTANCE_DATA    *IpmiInstance;

+  PEI_IPMI_DATA_HOB             *IpmiInstancePtrHob;

+  EFI_HOB_GUID_TYPE             *GuidHob;

+  IPMI_INTERFACE_STATE          InterfaceState;

+

+  InterfaceState = IpmiInterfaceNotReady;

+

+  GuidHob    = GetFirstGuidHob (&gPeiIpmiHobGuid);

+  ASSERT (GuidHob != NULL);

+  if (GuidHob == NULL) {

+      return EFI_NOT_FOUND;

+  }

+

+  IpmiInstancePtrHob = (PEI_IPMI_DATA_HOB *) GET_GUID_HOB_DATA(GuidHob);

+  IpmiInstance       = (PEI_IPMI_BMC_INSTANCE_DATA*) IpmiInstancePtrHob->IpmiInstance;

+

+#if SsifInterfaceSupport

+  InitSsifInterfaceData(&IpmiInstance->IpmiTransport2Ppi);

+

+  if (IpmiInstance->IpmiTransport2Ppi.Interface.Ssif.InterfaceState == IpmiInterfaceInitialized){

+      InterfaceState = IpmiInterfaceInitialized;

+  }

+#endif

+

+  // Default Interface data should be initialized to install Ipmi Transport2 Protocol.

+  if (InterfaceState != IpmiInterfaceInitialized) {

+      return EFI_UNSUPPORTED;

+  }

+

+  Status = PeiServicesInstallPpi (&IpmiInstance->PeiIpmi2BmcDataDesc);

+  return Status;

+}

+

+/**

+    Registers callback for Ppi.

+

+    @param[in] PeiServices  Describes the list of possible PEI Services.

+    @param[in] PpiGuid      Pointer to Ppi guid to register call back.

+

+    @retval EFI_INVALID_PARAMETER   Invalid parameter.

+    @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.

+    @retval Others                  Status of NotifyPpi().

+**/

+EFI_STATUS

+RegisterPpiCallback (

+  IN CONST EFI_PEI_SERVICES     **PeiServices,

+  IN       EFI_GUID             *PpiGuid

+  )

+{

+  EFI_STATUS                  Status;

+  EFI_PEI_NOTIFY_DESCRIPTOR   *PpiNotifyDesc;

+

+  if ((PpiGuid == NULL) ||

+      ((PpiGuid != NULL) && IsZeroBuffer(PpiGuid, sizeof (EFI_GUID)))) {

+      return EFI_INVALID_PARAMETER;

+  }

+

+  PpiNotifyDesc = (EFI_PEI_NOTIFY_DESCRIPTOR*) AllocateZeroPool (sizeof (EFI_PEI_NOTIFY_DESCRIPTOR));

+  if (PpiNotifyDesc == NULL) {

+      return EFI_OUT_OF_RESOURCES;

+  }

+

+  PpiNotifyDesc->Flags  = EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;

+  PpiNotifyDesc->Guid   = PpiGuid;

+  PpiNotifyDesc->Notify = NotifyCallback;

+

+  Status = (*PeiServices)->NotifyPpi (PeiServices, PpiNotifyDesc);

+  return Status;

+}



 /*****************************************************************************

  @brief

@@ -31,8 +154,12 @@ PeiInitializeIpmiKcsPhysicalLayer (
 {

   EFI_STATUS                       Status;

   PEI_IPMI_BMC_INSTANCE_DATA       *mIpmiInstance;

+  PEI_IPMI_DATA_HOB                *IpmiInstancePtrHob;

+  IPMI_INTERFACE_STATE             InterfaceState;

+  UINT8                            Index;



-  mIpmiInstance = NULL;

+  mIpmiInstance  = NULL;

+  InterfaceState = IpmiInterfaceNotReady;



   //

   // Send Pre-Boot signal to BMC

@@ -60,6 +187,18 @@ PeiInitializeIpmiKcsPhysicalLayer (
     return EFI_OUT_OF_RESOURCES;

   }



+

+  // Create Guided hob to pass IPMI Instance data pointer to notify functions.

+  IpmiInstancePtrHob = BuildGuidHob (&gPeiIpmiHobGuid, sizeof(PEI_IPMI_DATA_HOB));

+  if (IpmiInstancePtrHob == NULL) {

+      DEBUG ((DEBUG_ERROR, "Failed to create Hob guid for IPMI Instance!!!\n"));

+      FreePool (mIpmiInstance);

+      return EFI_OUT_OF_RESOURCES;

+  }

+

+  IpmiInstancePtrHob->IpmiInstance         = (UINTN)mIpmiInstance;

+  IpmiInstancePtrHob->PreMemIpmiDataHobPtr = IpmiInstancePtrHob;

+

   //

   // Calibrate TSC Counter.  Stall for 10ms, then multiply the resulting number of

   // ticks in that period by 100 to get the number of ticks in a 1 second timeout

@@ -83,6 +222,7 @@ PeiInitializeIpmiKcsPhysicalLayer (
   mIpmiInstance->PeiIpmiBmcDataDesc.Guid          = &gPeiIpmiTransportPpiGuid;

   mIpmiInstance->PeiIpmiBmcDataDesc.Ppi           = &mIpmiInstance->IpmiTransportPpi;



+#if KcsInterfaceSupport

   //

   // Get the Device ID and check if the system is in Force Update mode.

   //

@@ -94,19 +234,74 @@ PeiInitializeIpmiKcsPhysicalLayer (
   //

   // Do not continue initialization if the BMC is in Force Update Mode.

   //

-  if (mIpmiInstance->BmcStatus == BMC_UPDATE_IN_PROGRESS || mIpmiInstance->BmcStatus == BMC_HARDFAIL) {

-    return EFI_UNSUPPORTED;

+  if (mIpmiInstance->BmcStatus != BMC_UPDATE_IN_PROGRESS && mIpmiInstance->BmcStatus != BMC_HARDFAIL) {

+      Status = PeiServicesInstallPpi (&mIpmiInstance->PeiIpmiBmcDataDesc);

+      if (EFI_ERROR (Status)) {

+        return Status;

+      }

+  }

+#endif

+

+  InitIpmiTransport2(mIpmiInstance);

+

+  // Check interface data initialized successfully else register notify protocol.

+  for (Index = SysInterfaceKcs; Index < SysInterfaceMax; Index++) {

+

+      switch (Index) {

+

+#if KcsInterfaceSupport

+          case SysInterfaceKcs:

+              if ((mIpmiInstance->BmcStatus != BMC_HARDFAIL) && (mIpmiInstance->BmcStatus != BMC_UPDATE_IN_PROGRESS)) {

+                  BMC_INTERFACE_STATUS   BmcStatus;

+                  mIpmiInstance->IpmiTransport2Ppi.Interface.KcsInterfaceState = IpmiInterfaceInitialized;

+                  Status = CheckSelfTestByInterfaceType(

+                                          &mIpmiInstance->IpmiTransport2Ppi,

+                                          &BmcStatus,

+                                          SysInterfaceKcs);

+                  if (!EFI_ERROR (Status) && (BmcStatus != BmcStatusHardFail)) {

+                      InterfaceState = IpmiInterfaceInitialized;

+                  } else {

+                      mIpmiInstance->IpmiTransport2Ppi.Interface.KcsInterfaceState = IpmiInterfaceInitError;

+                  }

+              }

+              break;

+#endif

+

+#if BtInterfaceSupport

+          case SysInterfaceBt:

+              if (mIpmiInstance->IpmiTransport2Ppi.Interface.Bt.InterfaceState == IpmiInterfaceInitialized){

+                  InterfaceState = IpmiInterfaceInitialized;

+              }

+              break;

+#endif

+

+#if SsifInterfaceSupport

+          case SysInterfaceSsif:

+              if (mIpmiInstance->IpmiTransport2Ppi.Interface.Ssif.InterfaceState == IpmiInterfaceInitialized){

+                  InterfaceState = IpmiInterfaceInitialized;

+              } else if (mIpmiInstance->IpmiTransport2Ppi.Interface.Ssif.InterfaceState == IpmiInterfaceInitError) {

+                  // Register protocol notify for SMBUS Protocol.

+                  Status = RegisterPpiCallback (PeiServices, &mIpmiInstance->IpmiTransport2Ppi.Interface.Ssif.SsifInterfaceApiGuid);

+              }

+              break;

+#endif

+          default:

+              break;

+      }

   }



-  //

-  // Just produce PPI

-  //

-  Status = PeiServicesInstallPpi (&mIpmiInstance->PeiIpmiBmcDataDesc);

-  if (EFI_ERROR (Status)) {

-    return Status;

+  // Any one of the Interface data should be initialized to install Ipmi Transport2 Protocol.

+  if (InterfaceState != IpmiInterfaceInitialized) {

+      DEBUG ((DEBUG_INFO, "Interface not ready yet. \n"));

+      return EFI_SUCCESS;

   }



-  return EFI_SUCCESS;

+  mIpmiInstance->PeiIpmi2BmcDataDesc.Flags  = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;

+  mIpmiInstance->PeiIpmi2BmcDataDesc.Guid   = &gPeiIpmiTransport2PpiGuid;

+  mIpmiInstance->PeiIpmi2BmcDataDesc.Ppi    = &mIpmiInstance->IpmiTransport2Ppi;

+

+  Status = PeiServicesInstallPpi (&mIpmiInstance->PeiIpmi2BmcDataDesc);

+  return Status;

 }



 /*****************************************************************************

@@ -176,60 +371,6 @@ PeimIpmiInterfaceInit (
 } // PeimIpmiInterfaceInit()





-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

-

---*/

-{

-  //

-  // This Will be unchanged ( BMC/KCS style )

-  //

-  return PeiIpmiSendCommandToBmc (

-           This,

-           NetFunction,

-           Lun,

-           Command,

-           CommandData,

-           (UINT8) CommandDataSize,

-           ResponseData,

-           (UINT8 *) ResponseDataSize,

-           NULL

-           );

-} // IpmiSendCommand()



 EFI_STATUS

 PeiGetIpmiBmcStatus (

diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiGenericIpmi.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiGenericIpmi.h
index d31af85325..59b26b6c86 100644
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiGenericIpmi.h
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiGenericIpmi.h
@@ -3,6 +3,7 @@


   @copyright

   Copyright 2017 - 2021 Intel Corporation. <BR>

+  Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>

   SPDX-License-Identifier: BSD-2-Clause-Patent

 **/



@@ -23,7 +24,9 @@
 #include <Library/PeiServicesTablePointerLib.h>

 #include <Library/TimerLib.h>

 #include <Library/PciLib.h>

+#include <Library/HobLib.h>



+#include "PeiIpmiHooks.h"

 #include "PeiIpmiBmcDef.h"

 #include "PeiIpmiBmc.h"



diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiGenericIpmi.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiGenericIpmi.inf
index a646161ce1..c42c828c2f 100644
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiGenericIpmi.inf
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiGenericIpmi.inf
@@ -3,6 +3,7 @@
 #

 # @copyright

 # Copyright 2017 - 2021 Intel Corporation. <BR>

+# Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>

 # SPDX-License-Identifier: BSD-2-Clause-Patent

 ##



@@ -30,6 +31,8 @@
   PeiIpmiBmcDef.h

   PeiGenericIpmi.c

   PeiGenericIpmi.h

+  PeiIpmiHooks.c

+  PeiIpmiHooks.h



 [Packages]

   MdePkg/MdePkg.dec

@@ -44,17 +47,28 @@
   ReportStatusCodeLib

   TimerLib

   IpmiPlatformHookLib

+  HobLib

+  BmcCommonInterfaceLib

+  BtInterfaceLib

+  SsifInterfaceLib



 [Guids]

+  gPeiIpmiHobGuid



 [Ppis]

   gPeiIpmiTransportPpiGuid       #ALWAYS PRODUCE

+  gPeiIpmiTransport2PpiGuid



 [Pcd]

   gIpmiFeaturePkgTokenSpaceGuid.PcdIpmiIoBaseAddress

   gIpmiFeaturePkgTokenSpaceGuid.PcdIpmiBmcReadyDelayTimer

   gIpmiFeaturePkgTokenSpaceGuid.PcdSioMailboxBaseAddress

   gIpmiFeaturePkgTokenSpaceGuid.PcdSignalPreBootToBmc

-

+  gIpmiFeaturePkgTokenSpaceGuid.PcdDefaultSystemInterface

+  gIpmiFeaturePkgTokenSpaceGuid.PcdBtInterfaceSupport

+  gIpmiFeaturePkgTokenSpaceGuid.PcdSsifInterfaceSupport

+  gIpmiFeaturePkgTokenSpaceGuid.PcdKcsInterfaceSupport

+  gIpmiFeaturePkgTokenSpaceGuid.PcdBtControlPort

+

 [Depex]

   TRUE

diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiBmc.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiBmc.c
index 32665b3e22..1bd7657c5a 100644
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiBmc.c
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiBmc.c
@@ -3,6 +3,7 @@


   @copyright

   Copyright 2016 - 2021 Intel Corporation. <BR>

+  Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>

   SPDX-License-Identifier: BSD-2-Clause-Patent

 **/



@@ -234,7 +235,7 @@ Returns:




 EFI_STATUS

-PeiIpmiBmcStatus (

+IpmiBmcStatus (

   IN  PEI_IPMI_TRANSPORT_PPI          *This,

   OUT BMC_STATUS                  *BmcStatus,

   OUT SM_COM_ADDRESS              *ComAddress,

diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiBmc.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiBmc.h
index 40b9429e84..51ba65966a 100644
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiBmc.h
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiBmc.h
@@ -3,6 +3,7 @@


   @copyright

   Copyright 2016 - 2021 Intel Corporation. <BR>

+  Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>

   SPDX-License-Identifier: BSD-2-Clause-Patent

 **/



@@ -35,4 +36,12 @@
   SM_IPMI_BMC_SIGNATURE \

   )



+#define INSTANCE_FROM_PEI_IPMI_TRANSPORT2_THIS(a) \

+  CR ( \

+  a, \

+  PEI_IPMI_BMC_INSTANCE_DATA, \

+  IpmiTransport2Ppi, \

+  SM_IPMI_BMC_SIGNATURE \

+  )

+

 #endif // _PEI_IPMI_BMC_H_

diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiBmcDef.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiBmcDef.h
index 3fbe70ce62..2799f2bba6 100644
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiBmcDef.h
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiBmcDef.h
@@ -3,6 +3,7 @@


   @copyright

   Copyright 2016 - 2021 Intel Corporation. <BR>

+  Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>

   SPDX-License-Identifier: BSD-2-Clause-Patent

 **/



@@ -10,6 +11,8 @@
 #define _PEI_IPMI_COMMON_BMC_H_



 #include <Ppi/IpmiTransportPpi.h>

+#include <Ppi/IpmiTransport2Ppi.h>

+#include "ServerManagement.h"



 #define MAX_TEMP_DATA     160

 #define BMC_SLAVE_ADDRESS 0x20

@@ -46,16 +49,18 @@
 // Pei Ipmi instance data

 //

 typedef struct {

-  UINTN                  Signature;

-  UINT64                 KcsTimeoutPeriod;

-  UINT8                  SlaveAddress;

-  UINT8                  TempData[MAX_TEMP_DATA];

-  BMC_STATUS             BmcStatus;

-  UINT64                 ErrorStatus;

-  UINT8                  SoftErrorCount;

-  UINT16                 IpmiIoBase;

-  PEI_IPMI_TRANSPORT_PPI IpmiTransportPpi;

-  EFI_PEI_PPI_DESCRIPTOR PeiIpmiBmcDataDesc;

+  UINTN                     Signature;

+  UINT64                    KcsTimeoutPeriod;

+  UINT8                     SlaveAddress;

+  UINT8                     TempData[MAX_TEMP_DATA];

+  BMC_STATUS                BmcStatus;

+  UINT64                    ErrorStatus;

+  UINT8                     SoftErrorCount;

+  UINT16                    IpmiIoBase;

+  PEI_IPMI_TRANSPORT_PPI    IpmiTransportPpi;

+  IPMI_TRANSPORT2           IpmiTransport2Ppi;

+  EFI_PEI_PPI_DESCRIPTOR    PeiIpmiBmcDataDesc;

+  EFI_PEI_PPI_DESCRIPTOR    PeiIpmi2BmcDataDesc;

 } PEI_IPMI_BMC_INSTANCE_DATA;



 //

@@ -152,5 +157,11 @@ Returns:
 --*/

 ;



+typedef struct _PEI_IPMI_DATA_HOB PEI_IPMI_DATA_HOB;

+

+struct _PEI_IPMI_DATA_HOB {

+    UINTN                     IpmiInstance;            /// IpmiInstance pointer.

+    PEI_IPMI_DATA_HOB         *PreMemIpmiDataHobPtr;   ///< HOB Data pointer before Memory discovered

+};



 #endif //_PEI_IPMI_COMMON_BMC_H_

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..9cc3671aa6
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiHooks.c
@@ -0,0 +1,316 @@
+/** @file
+  IPMI common hook functions
+
+  @copyright
+  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
+
+  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
+
+  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..cacb4ec76e
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiHooks.h
@@ -0,0 +1,211 @@
+/** @file
+  IPMI common hook functions head file
+
+  @copyright
+  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 <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
+  );
+
+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,
+  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/GenericIpmi/Smm/SmmGenericIpmi.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Smm/SmmGenericIpmi.c
index fda215baaa..35faf93e30 100644
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Smm/SmmGenericIpmi.c
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Smm/SmmGenericIpmi.c
@@ -3,6 +3,7 @@


   @copyright

   Copyright 1999 - 2021 Intel Corporation. <BR>

+  Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>

   SPDX-License-Identifier: BSD-2-Clause-Patent

 **/



@@ -24,6 +25,7 @@
 #include "IpmiBmcCommon.h"

 #include "IpmiBmc.h"

 #include <Library/TimerLib.h>

+#include <Library/BmcCommonInterfaceLib.h>



 IPMI_BMC_INSTANCE_DATA             *mIpmiInstance;

 EFI_HANDLE                         mImageHandle;

@@ -114,6 +116,112 @@ Returns:
   return Status;

 }



+/**

+    Initialize the API and parameters for IPMI Transport2 Instance

+

+    @param[in] IpmiInstance         Pointer to IPMI Instance

+

+    @return VOID    Nothing.

+

+**/

+VOID

+InitIpmiTransport2 (

+  IN  IPMI_BMC_INSTANCE_DATA    *IpmiInstance

+  )

+{

+

+  IpmiInstance->IpmiTransport2.InterfaceType           = FixedPcdGet8 (PcdDefaultSystemInterface);

+  IpmiInstance->IpmiTransport2.IpmiTransport2BmcStatus = BmcStatusOk;

+  IpmiInstance->IpmiTransport2.IpmiSubmitCommand2      = IpmiSendCommand2;

+  IpmiInstance->IpmiTransport2.IpmiSubmitCommand2Ex    = IpmiSendCommand2Ex;

+

+#if BtInterfaceSupport

+  InitBtInterfaceData (&IpmiInstance->IpmiTransport2);

+#endif

+

+#if SsifInterfaceSupport

+  InitSsifInterfaceData (&IpmiInstance->IpmiTransport2);

+#endif

+}

+

+/**

+    Notify call back to initialize the interfaces and install Smm Ipmi

+    protocol.

+

+    @param[in] Protocol     Pointer to the protocol guid.

+    @param[in] Interface    Pointer to the protocol instance.

+    @param[in] Handle       Handle on which the protocol is installed.

+

+    @return EFI_STATUS  Status of Notify call back.

+

+**/

+EFI_STATUS

+EFIAPI

+SmmNotifyCallback (

+  IN CONST  EFI_GUID    *Protocol,

+  IN        VOID        *Interface,

+  IN        EFI_HANDLE  Handle

+  )

+{

+

+  EFI_STATUS             Status;

+  IPMI_INTERFACE_STATE   InterfaceState;

+

+  InterfaceState = IpmiInterfaceNotReady;

+

+#if SsifInterfaceSupport

+  InitSsifInterfaceData(&mIpmiInstance->IpmiTransport2);

+

+  if (mIpmiInstance->IpmiTransport2.Interface.Ssif.InterfaceState == IpmiInterfaceInitialized){

+      InterfaceState = IpmiInterfaceInitialized;

+  }

+#endif

+

+  if (InterfaceState != IpmiInterfaceInitialized) {

+      return EFI_SUCCESS;

+  }

+

+  // Default Interface data should be initialized to install Ipmi Transport2 Protocol.

+  if (InterfaceState == IpmiInterfaceInitialized) {

+      Handle = NULL;

+      Status = gSmst->SmmInstallProtocolInterface (

+                          &Handle,

+                          &gSmmIpmiTransport2ProtocolGuid,

+                          EFI_NATIVE_INTERFACE,

+                          &mIpmiInstance->IpmiTransport2

+                          );

+  }

+  return EFI_SUCCESS;

+}

+

+/**

+    Registers Protocol call back

+

+    @param ProtocolGuid       Pointer to Protocol GUID to register call back

+

+    @retval EFI_INVALID_PARAMETER   If the ProtocolGuid is 0 or NULL.

+    @retval Others                  Status of Notify registration.

+**/

+EFI_STATUS

+SmmRegisterProtocolCallback (

+  IN  EFI_GUID  *ProtocolGuid

+)

+{

+    EFI_STATUS  Status;

+    VOID        *Registration;

+

+    if ((ProtocolGuid == NULL) ||

+        ((ProtocolGuid != NULL) && IsZeroBuffer (ProtocolGuid, sizeof (EFI_GUID)))) {

+        return EFI_INVALID_PARAMETER;

+    }

+

+    Status = gSmst->SmmRegisterProtocolNotify (

+                        ProtocolGuid,

+                        SmmNotifyCallback,

+                        &Registration );

+    return Status;

+}

+

 EFI_STATUS

 SmmInitializeIpmiKcsPhysicalLayer (

   IN EFI_HANDLE             ImageHandle,

@@ -141,10 +249,13 @@ Returns:
   UINT8                            ErrorCount;

   EFI_HANDLE                       Handle;

   EFI_STATUS_CODE_VALUE            StatusCodeValue[MAX_SOFT_COUNT];

+  IPMI_INTERFACE_STATE             InterfaceState;

+  UINT8                            Index;



   DEBUG ((DEBUG_INFO,"SmmInitializeIpmiKcsPhysicalLayer entry \n"));

-  ErrorCount = 0;

-  mImageHandle = ImageHandle;

+  ErrorCount     = 0;

+  mImageHandle   = ImageHandle;

+  InterfaceState = IpmiInterfaceNotReady;



   mIpmiInstance = AllocateZeroPool (sizeof (IPMI_BMC_INSTANCE_DATA));

   ASSERT (mIpmiInstance != NULL);

@@ -169,6 +280,7 @@ Returns:
     mIpmiInstance->IpmiTransport.IpmiSubmitCommand  = IpmiSendCommand;

     mIpmiInstance->IpmiTransport.GetBmcStatus       = IpmiGetBmcStatus;



+#if KcsInterfaceSupport

     DEBUG ((DEBUG_INFO,"IPMI: Waiting for Getting BMC DID in SMM \n"));

     //

     // Get the Device ID and check if the system is in Force Update mode.

@@ -190,6 +302,68 @@ Returns:
                       &mIpmiInstance->IpmiTransport

                       );

     ASSERT_EFI_ERROR (Status);

+#endif

+

+    InitIpmiTransport2(mIpmiInstance);

+

+    // Check interface data initialized successfully else register notify protocol.

+    for (Index = SysInterfaceKcs; Index < SysInterfaceMax; Index++) {

+

+        switch (Index) {

+#if KcsInterfaceSupport

+            case SysInterfaceKcs:

+                if ((mIpmiInstance->BmcStatus != BMC_HARDFAIL) && (mIpmiInstance->BmcStatus != BMC_UPDATE_IN_PROGRESS)) {

+                    BMC_INTERFACE_STATUS  BmcStatus;

+                    mIpmiInstance->IpmiTransport2.Interface.KcsInterfaceState = IpmiInterfaceInitialized;

+                    Status = CheckSelfTestByInterfaceType(

+                                               &mIpmiInstance->IpmiTransport2,

+                                               &BmcStatus,

+                                               SysInterfaceKcs);

+                    if (!EFI_ERROR (Status) && (BmcStatus != BmcStatusHardFail)) {

+                        InterfaceState = IpmiInterfaceInitialized;

+                    } else {

+                        mIpmiInstance->IpmiTransport2.Interface.KcsInterfaceState = IpmiInterfaceInitError;

+                    }

+                }

+                break;

+#endif

+

+#if BtInterfaceSupport

+            case SysInterfaceBt:

+                if (mIpmiInstance->IpmiTransport2.Interface.Bt.InterfaceState == IpmiInterfaceInitialized){

+                    InterfaceState = IpmiInterfaceInitialized;

+                }

+                break;

+#endif

+

+#if SsifInterfaceSupport

+            case SysInterfaceSsif:

+                if (mIpmiInstance->IpmiTransport2.Interface.Ssif.InterfaceState == IpmiInterfaceInitialized){

+                    InterfaceState = IpmiInterfaceInitialized;

+                } else if (mIpmiInstance->IpmiTransport2.Interface.Ssif.InterfaceState == IpmiInterfaceInitError) {

+                    // Register protocol notify for SMBUS Protocol.

+                    Status = SmmRegisterProtocolCallback (&mIpmiInstance->IpmiTransport2.Interface.Ssif.SsifInterfaceApiGuid);

+                }

+                break;

+#endif

+            default:

+                break;

+        }

+    }

+

+    // Default Interface data should be initialized to install Ipmi Transport2 Protocol.

+    if (InterfaceState == IpmiInterfaceInitialized) {

+        Handle = NULL;

+        Status = gSmst->SmmInstallProtocolInterface (

+                          &Handle,

+                          &gSmmIpmiTransport2ProtocolGuid,

+                          EFI_NATIVE_INTERFACE,

+                          &mIpmiInstance->IpmiTransport2

+                          );

+        if (EFI_ERROR(Status)) {

+            DEBUG ((DEBUG_ERROR,"IPMI Transport2 protocol install Status = %r \n",Status));

+        }

+    }



     DEBUG ((DEBUG_INFO,"SmmInitializeIpmiKcsPhysicalLayer exit \n"));



diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Smm/SmmGenericIpmi.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Smm/SmmGenericIpmi.inf
index f430195d1e..0e3a387c65 100644
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Smm/SmmGenericIpmi.inf
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Smm/SmmGenericIpmi.inf
@@ -3,6 +3,7 @@
 #

 # @copyright

 # Copyright 2010 - 2021 Intel Corporation. <BR>

+# Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>

 # SPDX-License-Identifier: BSD-2-Clause-Patent

 ##



@@ -39,15 +40,25 @@
   IoLib

   ReportStatusCodeLib

   TimerLib

+  BmcCommonInterfaceLib

+  BtInterfaceLib

+  SsifInterfaceLib



 [Protocols]

   gSmmIpmiTransportProtocolGuid                     # PROTOCOL ALWAYS_PRODUCED

+  gSmmIpmiTransport2ProtocolGuid                    # PROTOCOL ALWAYS_PRODUCED



 [Guids]



 [Pcd]

   gIpmiFeaturePkgTokenSpaceGuid.PcdIpmiSmmIoBaseAddress

   gIpmiFeaturePkgTokenSpaceGuid.PcdIpmiBmcReadyDelayTimer

+  gIpmiFeaturePkgTokenSpaceGuid.PcdDefaultSystemInterface

+  gIpmiFeaturePkgTokenSpaceGuid.PcdBtControlPort

+  gIpmiFeaturePkgTokenSpaceGuid.PcdBtInterfaceSupport

+  gIpmiFeaturePkgTokenSpaceGuid.PcdSsifInterfaceSupport

+  gIpmiFeaturePkgTokenSpaceGuid.PcdKcsInterfaceSupport



 [Depex]

- gIpmiTransportProtocolGuid

+ gIpmiTransportProtocolGuid AND

+ gSmmIpmiTransport2ProtocolGuid

diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiFeature.dsc b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiFeature.dsc
index 237a4fc006..98d9b602e8 100644
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiFeature.dsc
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiFeature.dsc
@@ -7,6 +7,7 @@
 # for the build infrastructure.

 #

 # Copyright (c) 2019 - 2021, Intel Corporation. All rights reserved.<BR>

+# Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>

 #

 # SPDX-License-Identifier: BSD-2-Clause-Patent

 #

@@ -41,10 +42,21 @@


 [LibraryClasses.common.PEI_CORE,LibraryClasses.common.PEIM]

   IpmiBaseLib|IpmiFeaturePkg/Library/PeiIpmiBaseLib/PeiIpmiBaseLib.inf

+  SsifInterfaceLib|IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInterfaceLib/PeiSsifInterfaceLib.inf



 [LibraryClasses.common.DXE_DRIVER,LibraryClasses.common.UEFI_DRIVER]

   IpmiBaseLib|IpmiFeaturePkg/Library/IpmiBaseLib/IpmiBaseLib.inf



+[LibraryClasses.common]

+  BmcCommonInterfaceLib|IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/BmcCommonInterfaceLib.inf

+  BtInterfaceLib|IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/BtInterfaceLib/BtInterfaceLib.inf

+

+[LibraryClasses.common.DXE_RUNTIME_DRIVER, LibraryClasses.common.DXE_DRIVER]

+  SsifInterfaceLib|IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInterfaceLib/DxeSsifInterfaceLib.inf

+

+[LibraryClasses.common.DXE_SMM_DRIVER]

+  SsifInterfaceLib|IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInterfaceLib/SmmSsifInterfaceLib.inf

+

 ################################################################################

 #

 # Component section - list of all components that need built for this feature.

diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiNetFnAppDefinitions.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiNetFnAppDefinitions.h
new file mode 100644
index 0000000000..4d8d5e7160
--- /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 (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..c1258a4172
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiTransport2Definitions.h
@@ -0,0 +1,139 @@
+/** @file IpmiTransport2Definitions.h
+    Bmc Common interface library functions.
+
+  @copyright
+  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
+    System Interface.
+*/
+typedef struct {
+    UINT8                     KcsInterfaceState;
+    BT_SYSTEM_INTERFACE       Bt;      ///< Bt interface.
+    SSIF_SYSTEM_INTERFACE     Ssif;    ///< Ssif interface.
+} IPMI_SYSTEM_INTERFACE;
+
+/** @inrernal
+    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.
+    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..e44b2920c0
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Library/BmcCommonInterfaceLib.h
@@ -0,0 +1,186 @@
+
+/** @file BmcCommonInterfaceLib.h
+    Bmc Common interface library functions.
+
+  @copyright
+  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
+
+
+/**
+    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
+  );
+#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..d1a8669223
--- /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 (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 (
+  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 (
+   IN OUT IPMI_TRANSPORT2   *IpmiTransport2
+ );
+
+#endif
+
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..510ebe3072
--- /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 (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..fceef0b009
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Ppi/IpmiTransport2Ppi.h
@@ -0,0 +1,22 @@
+/** @file
+  IPMI Ttransport2 PPI Header File.
+
+  @copyright
+  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..ee3ba9810e
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/IpmiTransport2Protocol.h
@@ -0,0 +1,29 @@
+
+/** @file IpmiTransport2Protocol.h
+    IpmiTransport2 Protocol Header File.
+
+  @copyright
+  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/IpmiFeaturePkg.dec b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFeaturePkg.dec
index 8c1b902446..3f2dd34093 100644
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFeaturePkg.dec
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFeaturePkg.dec
@@ -9,6 +9,7 @@
 #

 # Copyright (c) 2019-2021, Intel Corporation. All rights reserved.<BR>

 # Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.<BR>

+# Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>

 #

 # SPDX-License-Identifier: BSD-2-Clause-Patent

 #

@@ -42,17 +43,27 @@
   ## @libraryclass  Provides an API for the base IPMI library

   #

   IpmiBaseLib|Include/Library/IpmiBaseLib.h

+

+  ##  @libraryclass  Provides generic functions among all interfaces.

+  BmcCommonInterfaceLib|Include/Library/BmcCommonInterfaceLib.h

+  BtInterfaceLib|Include/Library/BtInterfaceLib.h

+

+  SsifInterfaceLib|Include/Library/SsifInterfaceLib.h



 [Guids]

   gIpmiFeaturePkgTokenSpaceGuid  =  {0xc05283f6, 0xd6a8, 0x48f3, {0x9b, 0x59, 0xfb, 0xca, 0x71, 0x32, 0x0f, 0x12}}

+  gPeiIpmiHobGuid                = {0xcb4d3e13, 0x1e34, 0x4373, {0x8a, 0x81, 0xe9, 0x0, 0x10, 0xf1, 0xdb, 0xa4}}



 [Ppis]

   gPeiIpmiTransportPpiGuid = {0x7bf5fecc, 0xc5b5, 0x4b25, {0x81, 0x1b, 0xb4, 0xb5, 0xb, 0x28, 0x79, 0xf7}}

+  gPeiIpmiTransport2PpiGuid = {0x8122CEBD, 0xF4FD, 0x4EA8, { 0x97, 0x6C, 0xF0, 0x30, 0xAD, 0xDC, 0x4C, 0xB4 }}



 [Protocols]

   gIpmiTransportProtocolGuid  = {0x6bb945e8, 0x3743, 0x433e, {0xb9, 0x0e, 0x29, 0xb3, 0x0d, 0x5d, 0xc6, 0x30}}

   gSmmIpmiTransportProtocolGuid  = {0x8bb070f1, 0xa8f3, 0x471d, {0x86, 0x16, 0x77, 0x4b, 0xa3, 0xf4, 0x30, 0xa0}}

   gEfiVideoPrintProtocolGuid     = {0x3dbf3e06, 0x9d0c, 0x40d3, {0xb2, 0x17, 0x45, 0x5f, 0x33, 0x9e, 0x29, 0x09}}

+  gIpmiTransport2ProtocolGuid = { 0x4A1D0E66, 0x5271, 0x4E22, { 0x83, 0xFE, 0x90, 0x92, 0x1B, 0x74, 0x82, 0x13 }}

+  gSmmIpmiTransport2ProtocolGuid = { 0x1DBD1503, 0x0A60, 0x4230, { 0xAA, 0xA3, 0x80, 0x16, 0xD8, 0xC3, 0xDE, 0x2F }}



 [PcdsFeatureFlag]

   gIpmiFeaturePkgTokenSpaceGuid.PcdIpmiFeatureEnable|FALSE|BOOLEAN|0xA0000001

@@ -61,6 +72,37 @@
   gIpmiFeaturePkgTokenSpaceGuid.PcdMaxSOLChannels|3|UINT8|0xF0000001

   #When True, BIOS will send a Pre-Boot signal to BMC

   gIpmiFeaturePkgTokenSpaceGuid.PcdSignalPreBootToBmc|FALSE|BOOLEAN|0xF0000002

+  #  typedef enum {

+  #      SysInterfaceUnknown, // Unknown interface type.

+  #      SysInterfaceKcs,     // Kcs interface = 1.

+  #      SysInterfaceSmic,    // Smic interface = 2.

+  #      SysInterfaceBt,      // Bt interface = 3.

+  #      SysInterfaceSsif,    // Ssif interface = 4.

+  #      SysInterfaceMax   // Maximum interface type.

+  #  } SYSTEM_INTERFACE_TYPE;

+  gIpmiFeaturePkgTokenSpaceGuid.PcdDefaultSystemInterface|1|UINT8|0xF0000003

+

+  #BT Base address, retry counter and delay parameters

+  gIpmiFeaturePkgTokenSpaceGuid.PcdBtCommandRetryCounter|0x0004E400|UINT32|0xF0000004

+  gIpmiFeaturePkgTokenSpaceGuid.PcdBtControlPort|0xE4|UINT16|0xF0000005

+  gIpmiFeaturePkgTokenSpaceGuid.PcdBtBufferPort|0xE5|UINT16|0xF0000006

+  gIpmiFeaturePkgTokenSpaceGuid.PcdBtDelayPerRetry|15|UINT32|0xF0000007

+  gIpmiFeaturePkgTokenSpaceGuid.PcdBtInterruptMaskPort|0xE6|UINT16|0xF0000008

+  gIpmiFeaturePkgTokenSpaceGuid.PcdBtBufferSize|0x40|UINT8|0xF0000009

+

+  #SSIF slave address, retry counter and delay parameters

+  gIpmiFeaturePkgTokenSpaceGuid.PcdSsifSlaveAddress|0x10|UINT16|0xF000000A

+  gIpmiFeaturePkgTokenSpaceGuid.PcdSsifRequestRetriesDelay|0xCB20|UINT32|0xF000000B

+  gIpmiFeaturePkgTokenSpaceGuid.PcdSsifCommandtRetryCounter|0x5|UINT16|0xF000000C

+

+   #Interface access type for BMC communication. 0-MMIO, 1-IO

+  gIpmiFeaturePkgTokenSpaceGuid.PcdIpmiDefaultAccessType|1|UINT8|0xF000000D

+  gIpmiFeaturePkgTokenSpaceGuid.PcdMmioBaseAddress|0x0|UINT32|0xF000000E

+  gIpmiFeaturePkgTokenSpaceGuid.PcdBaseAddressRange|0x0|UINT32|0xF000000F

+

+  gIpmiFeaturePkgTokenSpaceGuid.PcdKcsInterfaceSupport|1|UINT8|0xF0000010

+  gIpmiFeaturePkgTokenSpaceGuid.PcdBtInterfaceSupport|1|UINT8|0xF0000011

+  gIpmiFeaturePkgTokenSpaceGuid.PcdSsifInterfaceSupport|1|UINT8|0xF0000012



 [PcdsDynamic, PcdsDynamicEx]

   gIpmiFeaturePkgTokenSpaceGuid.PcdFRB2EnabledFlag|TRUE|BOOLEAN|0xD0000001

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..333d4a8643
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/BmcCommonInterfaceLib.c
@@ -0,0 +1,227 @@
+/** @file BmcCommonInterfaceLib.c
+    BmcCommonInterfaceLib generic functions for all interfaces.
+
+  @copyright
+  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..f346a3afae
--- /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 (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..3651727c41
--- /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 (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..dbc87f3e1e
--- /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 (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/SsifInterfaceLib/DxeSsifInterfaceLib.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInterfaceLib/DxeSsifInterfaceLib.c
new file mode 100644
index 0000000000..99e25074f9
--- /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 (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..e61c916541
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInterfaceLib/DxeSsifInterfaceLib.inf
@@ -0,0 +1,39 @@
+## @file DxeSsifInterfaceLib.inf
+#
+#  INF description file for SsifInterfaceLib Library for DXE and UEFI drivers.
+#
+# @copyright
+# 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..02d50e9add
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInterfaceLib/PeiSsifInterfaceLib.c
@@ -0,0 +1,122 @@
+/** @file PeiSsifInterfaceLib.c
+  SSIF Transport Pei phase Implementation library functions.
+
+  @copyright
+  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..d7c410fc4f
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInterfaceLib/PeiSsifInterfaceLib.inf
@@ -0,0 +1,40 @@
+## @file PeiSsifInterfaceLib.inf
+#
+#  INF description file for SsifInterfaceLib Library for PEIMs.
+#
+# @copyright
+# 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..74c9f0206a
--- /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 (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.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..ee67b659be
--- /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 (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..da1d0c85b0
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInterfaceLib/SsifInterfaceLibCommon.c
@@ -0,0 +1,545 @@
+/** @file SsifInterfaceLibCommon.c
+  SSIF Transport Implementation common functions and variables.
+
+  @copyright
+  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.

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

* Re: [edk2-devel] [edk2-platforms][PATCH V1] IpmiFeaturePkg:Provided multliple IPMI interface support
  2023-02-28 16:07 [edk2-devel][edk2-platforms][PATCH V1] IpmiFeaturePkg:Provided multliple IPMI interface support arunk
@ 2023-04-10  1:59 ` Chang, Abner
  0 siblings, 0 replies; 2+ messages in thread
From: Chang, Abner @ 2023-04-10  1:59 UTC (permalink / raw)
  To: Arun K, devel

[-- Attachment #1: Type: text/plain, Size: 725 bytes --]

On Wed, Mar 1, 2023 at 12:37 AM, Arun K wrote:
Hi Arun,
Could you please consider providing those transport interfaces to ManageabilityPkg here: https://github.com/tianocore/edk2-platforms/tree/master/Features/ManageabilityPkg? ( https://github.com/tianocore/edk2-platforms/tree/master/Features/ManageabilityPkg )
As we would like to replace IpmiFeaturePkg with ManageabilityPKg, the intention of ManageabilityPKg is to provide the industry-standard manageability protocols and interfaces edk2 implementation.
We can have more discussions on making your code to compliant with ManageabilityPkg framework. I can probably help with revising one of the transport interfaces you provided to ManageabilityPkg.
Thanks
Abner

[-- Attachment #2: Type: text/html, Size: 1623 bytes --]

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

end of thread, other threads:[~2023-04-10  1:59 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-02-28 16:07 [edk2-devel][edk2-platforms][PATCH V1] IpmiFeaturePkg:Provided multliple IPMI interface support arunk
2023-04-10  1:59 ` [edk2-devel] [edk2-platforms][PATCH " Chang, Abner

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