[edk2-devel][edk2-platforms][PATCH V5-2] IpmiFeaturePkg:Provided multiple IPMI interface support in DXE and SMM

Arun K via groups.io posted 1 patch 9 months, 1 week ago
Failed in applying to current master (apply log)
.../GenericIpmi/Common/IpmiBmc.h              |  13 +-
.../GenericIpmi/Common/IpmiBmcCommon.h        |  82 +--
.../GenericIpmi/Common/IpmiHooks.c            | 298 ++++++++++-
.../GenericIpmi/Common/IpmiHooks.h            | 119 ++++-
.../GenericIpmi/Dxe/GenericIpmi.inf           |  14 +-
.../IpmiFeaturePkg/GenericIpmi/Dxe/IpmiInit.c | 505 +++++++++++++-----
.../GenericIpmi/Smm/SmmGenericIpmi.c          | 351 +++++++++---
.../GenericIpmi/Smm/SmmGenericIpmi.inf        |  12 +
8 files changed, 1117 insertions(+), 277 deletions(-)
[edk2-devel][edk2-platforms][PATCH V5-2] IpmiFeaturePkg:Provided multiple IPMI interface support in DXE and SMM
Posted by Arun K via groups.io 9 months, 1 week ago
Created IpmiTransport2 PPI/Protocol to support multiple
IPMI BMC Interface support such as KCS/BT/SSIF/IPMB with 2 API's
IpmiSubmitCommand2 & IpmiSubmitCommand2Ex.
IpmiSubmitCommand2 - This API use the default interface
(PcdDefaultSystemInterface) to send IPMI command.
IpmiSubmitCommand2Ex - This API use the specific interface type
to send IPMI command which is passed as an argument.

Cc: Isaac Oram <isaac.w.oram@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>

Signed-off-by: Arun K <arunk@ami.com>
---
 .../GenericIpmi/Common/IpmiBmc.h              |  13 +-
 .../GenericIpmi/Common/IpmiBmcCommon.h        |  82 +--
 .../GenericIpmi/Common/IpmiHooks.c            | 298 ++++++++++-
 .../GenericIpmi/Common/IpmiHooks.h            | 119 ++++-
 .../GenericIpmi/Dxe/GenericIpmi.inf           |  14 +-
 .../IpmiFeaturePkg/GenericIpmi/Dxe/IpmiInit.c | 505 +++++++++++++-----
 .../GenericIpmi/Smm/SmmGenericIpmi.c          | 351 +++++++++---
 .../GenericIpmi/Smm/SmmGenericIpmi.inf        |  12 +
 8 files changed, 1117 insertions(+), 277 deletions(-)

diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Common/IpmiBmc.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Common/IpmiBmc.h
index d306a085e5..76ee988623 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,17 +22,17 @@
 #include <Library/ReportStatusCodeLib.h>

 #include <Library/IpmiBaseLib.h>

 #include <Protocol/IpmiTransportProtocol.h>

+#include <Protocol/IpmiTransport2Protocol.h>



 #include "IpmiBmcCommon.h"

 #include "KcsBmc.h"



-

 #define BMC_KCS_TIMEOUT  5   // [s] Single KSC request timeout



 //

 // IPMI Instance signature

 //

-#define SM_IPMI_BMC_SIGNATURE SIGNATURE_32 ('i', 'p', 'm', 'i')

+#define SM_IPMI_BMC_SIGNATURE        SIGNATURE_32 ('i', 'p', 'm', 'i')

 #define IPMI_SEND_COMMAND_MAX_RETRY  3   // Number of retries

 #define INSTANCE_FROM_SM_IPMI_BMC_THIS(a) \

   CR ( \

@@ -41,4 +42,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 06eab62aae..faf6cc6685 100644
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Common/IpmiBmcCommon.h
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Common/IpmiBmcCommon.h
@@ -3,16 +3,17 @@


   @copyright

   Copyright 1999 - 2021 Intel Corporation. <BR>

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

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

 **/



 #ifndef _IPMI_COMMON_BMC_H_

 #define _IPMI_COMMON_BMC_H_



-#define MAX_TEMP_DATA     255 // 160 Modified to increase number of bytes transfered per command

-#define BMC_SLAVE_ADDRESS 0x20

-#define MAX_SOFT_COUNT    10

-#define COMP_CODE_NORMAL  0x00

+#define MAX_TEMP_DATA      255// 160 Modified to increase number of bytes transfered per command

+#define BMC_SLAVE_ADDRESS  0x20

+#define MAX_SOFT_COUNT     10

+#define COMP_CODE_NORMAL   0x00



 //

 // IPMI command completion codes to check for in the UpdateErrorStatus routine.

@@ -33,8 +34,8 @@
 // D4h C Insufficient privilege, in KCS channel this indicates KCS Policy Control Mode is Deny All.

 // In authenticated channels this indicates invalid authentication/privilege.

 //

-#define COMP_INSUFFICIENT_PRIVILEGE       0xD4

-#define COMP_CODE_UNSPECIFIED             0xFF

+#define COMP_INSUFFICIENT_PRIVILEGE  0xD4

+#define COMP_CODE_UNSPECIFIED        0xFF



 #define COMPLETION_CODES \

   { \

@@ -47,15 +48,16 @@
 // Dxe Ipmi instance data

 //

 typedef struct {

-  UINTN               Signature;

-  UINT64              KcsTimeoutPeriod;

-  UINT8               SlaveAddress;

-  BMC_STATUS          BmcStatus;

-  UINT64              ErrorStatus;

-  UINT8               SoftErrorCount;

-  UINT16              IpmiIoBase;

-  IPMI_TRANSPORT      IpmiTransport;

-  EFI_HANDLE          IpmiSmmHandle;

+  UINTN              Signature;

+  UINT64             KcsTimeoutPeriod;

+  UINT8              SlaveAddress;

+  BMC_STATUS         BmcStatus;

+  UINT64             ErrorStatus;

+  UINT8              SoftErrorCount;

+  UINT16             IpmiIoBase;

+  IPMI_TRANSPORT     IpmiTransport;

+  IPMI_TRANSPORT2    IpmiTransport2;

+  EFI_HANDLE         IpmiSmmHandle;

 } IPMI_BMC_INSTANCE_DATA;



 //

@@ -64,38 +66,39 @@ typedef struct {
 #define IPMI_COMMAND_HEADER_SIZE  2



 typedef struct {

-  UINT8 Lun : 2;

-  UINT8 NetFunction : 6;

-  UINT8 Command;

-  UINT8 CommandData[MAX_TEMP_DATA - IPMI_COMMAND_HEADER_SIZE];

+  UINT8    Lun         : 2;

+  UINT8    NetFunction : 6;

+  UINT8    Command;

+  UINT8    CommandData[MAX_TEMP_DATA - IPMI_COMMAND_HEADER_SIZE];

 } IPMI_COMMAND;



 //

 // Structure of IPMI Command response buffer

 //

-#define IPMI_RESPONSE_HEADER_SIZE 3

+#define IPMI_RESPONSE_HEADER_SIZE  3



 typedef struct {

-  UINT8 Lun : 2;

-  UINT8 NetFunction : 6;

-  UINT8 Command;

-  UINT8 CompletionCode;

-  UINT8 ResponseData[MAX_TEMP_DATA - IPMI_RESPONSE_HEADER_SIZE];

+  UINT8    Lun         : 2;

+  UINT8    NetFunction : 6;

+  UINT8    Command;

+  UINT8    CompletionCode;

+  UINT8    ResponseData[MAX_TEMP_DATA - IPMI_RESPONSE_HEADER_SIZE];

 } IPMI_RESPONSE;



 EFI_STATUS

 EFIAPI

 IpmiSendCommandToBmc (

-  IN      IPMI_TRANSPORT                *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

+  IN      IPMI_TRANSPORT  *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:

@@ -124,15 +127,15 @@ Returns:
 --*/

 ;



-

 EFI_STATUS

 EFIAPI

 IpmiBmcStatus (

-  IN  IPMI_TRANSPORT              *This,

-  OUT BMC_STATUS                  *BmcStatus,

-  OUT SM_COM_ADDRESS              *ComAddress,

-  IN  VOID                        *Context

+  IN  IPMI_TRANSPORT  *This,

+  OUT BMC_STATUS      *BmcStatus,

+  OUT SM_COM_ADDRESS  *ComAddress,

+  IN  VOID            *Context

   )

+

 /*++



 Routine Description:

@@ -157,6 +160,7 @@ VOID
 GetDeviceSpecificTestResults (

   IN      IPMI_BMC_INSTANCE_DATA  *IpmiInstance

   )

+

 /*++



 Routine Description:

diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Common/IpmiHooks.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Common/IpmiHooks.c
index b2788e5a4c..57577b1b35 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

 **/



@@ -11,15 +12,16 @@
 EFI_STATUS

 EFIAPI

 IpmiSendCommand (

-  IN      IPMI_TRANSPORT               *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      IPMI_TRANSPORT  *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:

@@ -48,29 +50,269 @@ Returns:


 --*/

 {

+  if (This == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

   //

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

   //

   return IpmiSendCommandToBmc (

-           This,

-           NetFunction,

-           Lun,

-           Command,

-           CommandData,

-           (UINT8) CommandDataSize,

-           ResponseData,

-           (UINT8*) ResponseDataSize,

-           NULL

-           );

+                               This,

+                               NetFunction,

+                               Lun,

+                               Command,

+                               CommandData,

+                               (UINT8)CommandDataSize,

+                               ResponseData,

+                               (UINT8 *)ResponseDataSize,

+                               NULL

+                               );

 } // 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 ((FixedPcdGet8 (PcdKcsInterfaceSupport) == 1) &&

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

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

+  {

+    return IpmiSendCommand (

+                            &IpmiInstance->IpmiTransport,

+                            NetFunction,

+                            Lun,

+                            Command,

+                            CommandData,

+                            CommandDataSize,

+                            ResponseData,

+                            ResponseDataSize

+                            );

+  }

+

+  if ((FixedPcdGet8 (PcdBtInterfaceSupport) == 1) &&

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

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

+  {

+    return IpmiBtSendCommandToBmc (

+                                   &IpmiInstance->IpmiTransport2,

+                                   NetFunction,

+                                   Lun,

+                                   Command,

+                                   CommandData,

+                                   (UINT8)CommandDataSize,

+                                   ResponseData,

+                                   (UINT8 *)ResponseDataSize,

+                                   NULL

+                                   );

+  }

+

+  if ((FixedPcdGet8 (PcdSsifInterfaceSupport) == 1) &&

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

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

+  {

+    return IpmiSsifSendCommandToBmc (

+                                     &IpmiInstance->IpmiTransport2,

+                                     NetFunction,

+                                     Lun,

+                                     Command,

+                                     CommandData,

+                                     (UINT8)CommandDataSize,

+                                     ResponseData,

+                                     (UINT8 *)ResponseDataSize,

+                                     NULL

+                                     );

+  }

+

+  if ((FixedPcdGet8 (PcdIpmbInterfaceSupport) == 1) &&

+      ((IpmiInstance->IpmiTransport2.InterfaceType == SysInterfaceIpmb) &&

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

+  {

+    return IpmiIpmbSendCommandToBmc (

+                                     &IpmiInstance->IpmiTransport2,

+                                     NetFunction,

+                                     Lun,

+                                     Command,

+                                     CommandData,

+                                     (UINT8)CommandDataSize,

+                                     ResponseData,

+                                     (UINT8 *)ResponseDataSize,

+                                     NULL

+                                     );

+  }

+

+  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 ((FixedPcdGet8 (PcdKcsInterfaceSupport) == 1) &&

+      ((InterfaceType == SysInterfaceKcs) && (IpmiInstance->IpmiTransport2.Interface.KcsInterfaceState == IpmiInterfaceInitialized)))

+  {

+    return IpmiSendCommand (

+                            &IpmiInstance->IpmiTransport,

+                            NetFunction,

+                            Lun,

+                            Command,

+                            CommandData,

+                            CommandDataSize,

+                            ResponseData,

+                            ResponseDataSize

+                            );

+  }

+

+  if ((FixedPcdGet8 (PcdBtInterfaceSupport) == 1) &&

+      ((InterfaceType == SysInterfaceBt) && (IpmiInstance->IpmiTransport2.Interface.Bt.InterfaceState == IpmiInterfaceInitialized)))

+  {

+    return IpmiBtSendCommandToBmc (

+                                   &IpmiInstance->IpmiTransport2,

+                                   NetFunction,

+                                   Lun,

+                                   Command,

+                                   CommandData,

+                                   (UINT8)CommandDataSize,

+                                   ResponseData,

+                                   (UINT8 *)ResponseDataSize,

+                                   NULL

+                                   );

+  }

+

+  if ((FixedPcdGet8 (PcdSsifInterfaceSupport) == 1) &&

+      ((InterfaceType == SysInterfaceSsif) && (IpmiInstance->IpmiTransport2.Interface.Ssif.InterfaceState == IpmiInterfaceInitialized)))

+  {

+    return IpmiSsifSendCommandToBmc (

+                                     &IpmiInstance->IpmiTransport2,

+                                     NetFunction,

+                                     Lun,

+                                     Command,

+                                     CommandData,

+                                     (UINT8)CommandDataSize,

+                                     ResponseData,

+                                     (UINT8 *)ResponseDataSize,

+                                     NULL

+                                     );

+  }

+

+  if ((FixedPcdGet8 (PcdIpmbInterfaceSupport) == 1) &&

+      ((InterfaceType == SysInterfaceIpmb) && (IpmiInstance->IpmiTransport2.Interface.Ipmb.InterfaceState == IpmiInterfaceInitialized)))

+  {

+    return IpmiIpmbSendCommandToBmc (

+                                     &IpmiInstance->IpmiTransport2,

+                                     NetFunction,

+                                     Lun,

+                                     Command,

+                                     CommandData,

+                                     (UINT8)CommandDataSize,

+                                     ResponseData,

+                                     (UINT8 *)ResponseDataSize,

+                                     NULL

+                                     );

+  }

+

+  return EFI_UNSUPPORTED;

+}

+

 EFI_STATUS

 EFIAPI

 IpmiGetBmcStatus (

-  IN IPMI_TRANSPORT                *This,

-  OUT BMC_STATUS                   *BmcStatus,

-  OUT SM_COM_ADDRESS               *ComAddress

+  IN IPMI_TRANSPORT   *This,

+  OUT BMC_STATUS      *BmcStatus,

+  OUT SM_COM_ADDRESS  *ComAddress

   )

+

 /*++



 Routine Description:

@@ -89,10 +331,14 @@ Returns:


 --*/

 {

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

+    return EFI_INVALID_PARAMETER;

+  }

+

   return IpmiBmcStatus (

-           This,

-           BmcStatus,

-           ComAddress,

-           NULL

-           );

+                        This,

+                        BmcStatus,

+                        ComAddress,

+                        NULL

+                        );

 }

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


   @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/IpmbInterfaceLib.h>

+#include <Library/DebugLib.h>

+#include <IpmiBmcCommon.h>

+#include <IpmiBmc.h>



 //

 // Internal(hook) function list

@@ -17,15 +25,16 @@
 EFI_STATUS

 EFIAPI

 IpmiSendCommand (

-  IN      IPMI_TRANSPORT               *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      IPMI_TRANSPORT  *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:

@@ -54,13 +63,99 @@ 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 (

-  IN IPMI_TRANSPORT                                    *This,

-  OUT BMC_STATUS                                       *BmcStatus,

-  OUT SM_COM_ADDRESS                                   *ComAddress

+  IN IPMI_TRANSPORT   *This,

+  OUT BMC_STATUS      *BmcStatus,

+  OUT SM_COM_ADDRESS  *ComAddress

   )

+

 /*++



 Routine Description:

diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Dxe/GenericIpmi.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Dxe/GenericIpmi.inf
index 8d80aeb6b5..1564ceb08a 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,25 @@
   IoLib

   ReportStatusCodeLib

   TimerLib

+  BmcCommonInterfaceLib

+  BtInterfaceLib

+  SsifInterfaceLib

+  IpmbInterfaceLib



 [Protocols]

   gIpmiTransportProtocolGuid               # PROTOCOL ALWAYS_PRODUCED

   gEfiVideoPrintProtocolGuid

-

-[Guids]

+  gIpmiTransport2ProtocolGuid



 [Pcd]

   gIpmiFeaturePkgTokenSpaceGuid.PcdIpmiIoBaseAddress

   gIpmiFeaturePkgTokenSpaceGuid.PcdIpmiBmcReadyDelayTimer

+  gIpmiFeaturePkgTokenSpaceGuid.PcdDefaultSystemInterface

+  gIpmiFeaturePkgTokenSpaceGuid.PcdBtInterfaceSupport

+  gIpmiFeaturePkgTokenSpaceGuid.PcdSsifInterfaceSupport

+  gIpmiFeaturePkgTokenSpaceGuid.PcdIpmbInterfaceSupport

+  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 c333ca2e06..d836e36b4e 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,25 +14,26 @@
 #include "IpmiBmc.h"

 #include "IpmiPhysicalLayer.h"

 #include <Library/TimerLib.h>

+#include <Library/BmcCommonInterfaceLib.h>

 #ifdef FAST_VIDEO_SUPPORT

   #include <Protocol/VideoPrint.h>

 #endif

 #include <Library/UefiRuntimeServicesTableLib.h>



-

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

  * Local variables

  */

-IPMI_BMC_INSTANCE_DATA       *mIpmiInstance = NULL;

-EFI_HANDLE                    mImageHandle;

+IPMI_BMC_INSTANCE_DATA  *mIpmiInstance = NULL;

+EFI_HANDLE              mImageHandle;



 //

 // Specific test interface

 //

 VOID

 GetDeviceSpecificTestResults (

-  IN      IPMI_BMC_INSTANCE_DATA *IpmiInstance

+  IN      IPMI_BMC_INSTANCE_DATA  *IpmiInstance

   )

+

 /*++



 Routine Description:

@@ -54,10 +56,11 @@ Returns:


 EFI_STATUS

 GetSelfTest (

-  IN      IPMI_BMC_INSTANCE_DATA     *IpmiInstance,

-  IN      EFI_STATUS_CODE_VALUE       StatusCodeValue[],

-  IN OUT  UINT8                       *ErrorCount

+  IN      IPMI_BMC_INSTANCE_DATA  *IpmiInstance,

+  IN      EFI_STATUS_CODE_VALUE   StatusCodeValue[],

+  IN OUT  UINT8                   *ErrorCount

   )

+

 /*++



 Routine Description:

@@ -86,13 +89,13 @@ Returns:
   BOOLEAN     bResultFlag = FALSE;

   UINT8       TempData[MAX_TEMP_DATA];



-  IPMI_SELF_TEST_RESULT_RESPONSE *SelfTestResult;

+  IPMI_SELF_TEST_RESULT_RESPONSE  *SelfTestResult;



   //

   // Get the SELF TEST Results.

   //

   //

-  //Note: If BMC PcdIpmiBmcReadyDelayTimer < BMC_KCS_TIMEOUT, it need set Retries as 1. Otherwise it will make SELT failure, caused by below condition (EFI_ERROR(Status) || Retries == 0)

+  // Note: If BMC PcdIpmiBmcReadyDelayTimer < BMC_KCS_TIMEOUT, it need set Retries as 1. Otherwise it will make SELT failure, caused by below condition (EFI_ERROR(Status) || Retries == 0)

   //

   if (PcdGet8 (PcdIpmiBmcReadyDelayTimer) < BMC_KCS_TIMEOUT) {

     Retries = 1;

@@ -102,20 +105,20 @@ Returns:


   DataSize = sizeof (TempData);



-  SelfTestResult = (IPMI_SELF_TEST_RESULT_RESPONSE *) &TempData[0];

+  SelfTestResult         = (IPMI_SELF_TEST_RESULT_RESPONSE *)&TempData[0];

   SelfTestResult->Result = 0;



   do {

     Status = IpmiSendCommand (

-               &IpmiInstance->IpmiTransport,

-               IPMI_NETFN_APP,

-               0,

-               IPMI_APP_GET_SELFTEST_RESULTS,

-               NULL,

-               0,

-               TempData,

-               &DataSize

-               );

+                              &IpmiInstance->IpmiTransport,

+                              IPMI_NETFN_APP,

+                              0,

+                              IPMI_APP_GET_SELFTEST_RESULTS,

+                              NULL,

+                              0,

+                              TempData,

+                              &DataSize

+                              );

     if (Status == EFI_SUCCESS) {

       switch (SelfTestResult->Result) {

         case IPMI_APP_SELFTEST_NO_ERROR:

@@ -127,7 +130,7 @@ Returns:


         default:

           break;

-      } //switch

+      } // switch



       if (bResultFlag) {

         break;

@@ -140,7 +143,7 @@ Returns:
   //

   // If Status indicates a Device error, then the BMC is not responding, so send an error.

   //

-  if (EFI_ERROR (Status) || Retries == 0) {

+  if (EFI_ERROR (Status) || (Retries == 0)) {

     DEBUG ((EFI_D_ERROR, "\n[IPMI]  BMC self-test does not respond (status: %r)!\n\n", Status));

     if (*ErrorCount < MAX_SOFT_COUNT) {

       StatusCodeValue[*ErrorCount] = EFI_COMPUTING_UNIT_FIRMWARE_PROCESSOR | EFI_CU_FP_EC_COMM_ERROR;

@@ -155,12 +158,14 @@ Returns:
     // Copy the Self test results to Error Status.  Data will be copied as long as it

     // does not exceed the size of the ErrorStatus variable.

     //

-    for (Index = 0, TempPtr = (UINT8 *) &IpmiInstance->ErrorStatus;

+    for (Index = 0, TempPtr = (UINT8 *)&IpmiInstance->ErrorStatus;

          (Index < DataSize) && (Index < sizeof (IpmiInstance->ErrorStatus));

          Index++, TempPtr++

-         ) {

+         )

+    {

       *TempPtr = TempData[Index];

     }

+

     //

     // Check the IPMI defined self test results.

     // Additional Cases are device specific test results.

@@ -182,6 +187,7 @@ Returns:
         } else {

           IpmiInstance->BmcStatus = BMC_SOFTFAIL;

         }

+

         //

         // Check if SDR repository is empty and report it if it is.

         //

@@ -191,6 +197,7 @@ Returns:
             (*ErrorCount)++;

           }

         }

+

         break;



       case IPMI_APP_SELFTEST_FATAL_HW_ERROR:

@@ -221,13 +228,13 @@ Returns:
   return EFI_SUCCESS;

 } // GetSelfTest()



-

 EFI_STATUS

 GetDeviceId (

-  IN      IPMI_BMC_INSTANCE_DATA       *IpmiInstance,

-  IN      EFI_STATUS_CODE_VALUE        StatusCodeValue[ ],

-  IN OUT  UINT8                        *ErrorCount

+  IN      IPMI_BMC_INSTANCE_DATA  *IpmiInstance,

+  IN      EFI_STATUS_CODE_VALUE   StatusCodeValue[],

+  IN OUT  UINT8                   *ErrorCount

   )

+

 /*++



 Routine Description:

@@ -244,25 +251,25 @@ Returns:


 --*/

 {

-  EFI_STATUS                      Status;

-  UINT32                          DataSize;

-  SM_CTRL_INFO                    *pBmcInfo;

-  IPMI_MSG_GET_BMC_EXEC_RSP       *pBmcExecContext;

-  UINT32                          Retries;

-  UINT8                           TempData[MAX_TEMP_DATA];

-

-#ifdef FAST_VIDEO_SUPPORT

-  EFI_VIDEOPRINT_PROTOCOL         *VideoPrintProtocol;

-  EFI_STATUS                      VideoPrintStatus;

-#endif

-

-#ifdef FAST_VIDEO_SUPPORT

+  EFI_STATUS                 Status;

+  UINT32                     DataSize;

+  SM_CTRL_INFO               *pBmcInfo;

+  IPMI_MSG_GET_BMC_EXEC_RSP  *pBmcExecContext;

+  UINT32                     Retries;

+  UINT8                      TempData[MAX_TEMP_DATA];

+

+ #ifdef FAST_VIDEO_SUPPORT

+  EFI_VIDEOPRINT_PROTOCOL  *VideoPrintProtocol;

+  EFI_STATUS               VideoPrintStatus;

+ #endif

+

+ #ifdef FAST_VIDEO_SUPPORT

   VideoPrintStatus = gBS->LocateProtocol (

-                            &gEfiVideoPrintProtocolGuid,

-                            NULL,

-                            &VideoPrintProtocol

-                            );

-#endif

+                                          &gEfiVideoPrintProtocolGuid,

+                                          NULL,

+                                          &VideoPrintProtocol

+                                          );

+ #endif



   //

   // Set up a loop to retry for up to PcdIpmiBmcReadyDelayTimer seconds. Calculate retries not timeout

@@ -274,28 +281,38 @@ Returns:
   // Get the device ID information for the BMC.

   //

   DataSize = sizeof (TempData);

-  while (EFI_ERROR (Status = IpmiSendCommand (

-                               &IpmiInstance->IpmiTransport,

-                               IPMI_NETFN_APP, 0,

-                               IPMI_APP_GET_DEVICE_ID,

-                               NULL, 0,

-                               TempData, &DataSize))

-         ) {

-    DEBUG ((DEBUG_ERROR, "[IPMI] BMC does not respond by Get BMC DID (status: %r), %d retries left, ResponseData: 0x%lx\n",

-            Status, Retries, TempData));

+  while (EFI_ERROR (

+                    Status = IpmiSendCommand (

+                                              &IpmiInstance->IpmiTransport,

+                                              IPMI_NETFN_APP,

+                                              0,

+                                              IPMI_APP_GET_DEVICE_ID,

+                                              NULL,

+                                              0,

+                                              TempData,

+                                              &DataSize

+                                              )

+                    )

+         )

+  {

+    DEBUG (

+           (DEBUG_ERROR, "[IPMI] BMC does not respond by Get BMC DID (status: %r), %d retries left, ResponseData: 0x%lx\n",

+            Status, Retries, TempData)

+           );



     if (Retries-- == 0) {

       IpmiInstance->BmcStatus = BMC_HARDFAIL;

       return Status;

     }

+

     //

-    //Handle the case that BMC FW still not enable KCS channel after AC cycle. just stall 1 second

+    // Handle the case that BMC FW still not enable KCS channel after AC cycle. just stall 1 second

     //

     MicroSecondDelay (1*1000*1000);

   }



-  pBmcInfo = (SM_CTRL_INFO*)&TempData[0];

-  DEBUG ((EFI_D_ERROR, "[IPMI] BMC Device ID: 0x%02X, firmware version: %d.%02X UpdateMode:%x\n", pBmcInfo->DeviceId, pBmcInfo->MajorFirmwareRev, pBmcInfo->MinorFirmwareRev,pBmcInfo->UpdateMode));

+  pBmcInfo = (SM_CTRL_INFO *)&TempData[0];

+  DEBUG ((EFI_D_ERROR, "[IPMI] BMC Device ID: 0x%02X, firmware version: %d.%02X UpdateMode:%x\n", pBmcInfo->DeviceId, pBmcInfo->MajorFirmwareRev, pBmcInfo->MinorFirmwareRev, pBmcInfo->UpdateMode));

   //

   // In OpenBMC, UpdateMode: the bit 7 of byte 4 in get device id command is used for the BMC status:

   // 0 means BMC is ready, 1 means BMC is not ready.

@@ -306,18 +323,22 @@ Returns:
     return EFI_SUCCESS;

   } else {

     DataSize = sizeof (TempData);

-    Status = IpmiSendCommand (

-               &IpmiInstance->IpmiTransport,

-               IPMI_NETFN_FIRMWARE, 0,

-               IPMI_GET_BMC_EXECUTION_CONTEXT,

-               NULL, 0,

-               TempData, &DataSize

-               );

-

-    pBmcExecContext = (IPMI_MSG_GET_BMC_EXEC_RSP*)&TempData[0];

+    Status   = IpmiSendCommand (

+                                &IpmiInstance->IpmiTransport,

+                                IPMI_NETFN_FIRMWARE,

+                                0,

+                                IPMI_GET_BMC_EXECUTION_CONTEXT,

+                                NULL,

+                                0,

+                                TempData,

+                                &DataSize

+                                );

+

+    pBmcExecContext = (IPMI_MSG_GET_BMC_EXEC_RSP *)&TempData[0];

     DEBUG ((DEBUG_INFO, "[IPMI] Operational status of BMC: 0x%x\n", pBmcExecContext->CurrentExecutionContext));

     if ((pBmcExecContext->CurrentExecutionContext == IPMI_BMC_IN_FORCED_UPDATE_MODE) &&

-        !EFI_ERROR (Status)) {

+        !EFI_ERROR (Status))

+    {

       DEBUG ((DEBUG_ERROR, "[IPMI] BMC in Forced Update mode, skip waiting for BMC_READY.\n"));

       IpmiInstance->BmcStatus = BMC_UPDATE_IN_PROGRESS;

     } else {

@@ -325,32 +346,174 @@ Returns:
       // Updatemode = 1 mean BMC is not ready, continue waiting.

       //

       while (Retries-- != 0) {

-        MicroSecondDelay(1*1000*1000); //delay 1 seconds

-        DEBUG ((EFI_D_ERROR, "[IPMI] UpdateMode Retries: %d \n",Retries));

+        MicroSecondDelay (1*1000*1000); // delay 1 seconds

+        DEBUG ((EFI_D_ERROR, "[IPMI] UpdateMode Retries: %d \n", Retries));

         DataSize = sizeof (TempData);

-        Status = IpmiSendCommand (

-                   &IpmiInstance->IpmiTransport,

-                   IPMI_NETFN_APP, 0,

-                   IPMI_APP_GET_DEVICE_ID,

-                   NULL, 0,

-                   TempData, &DataSize

-                   );

+        Status   = IpmiSendCommand (

+                                    &IpmiInstance->IpmiTransport,

+                                    IPMI_NETFN_APP,

+                                    0,

+                                    IPMI_APP_GET_DEVICE_ID,

+                                    NULL,

+                                    0,

+                                    TempData,

+                                    &DataSize

+                                    );



         if (!EFI_ERROR (Status)) {

-          pBmcInfo = (SM_CTRL_INFO*)&TempData[0];

-          DEBUG ((DEBUG_ERROR, "[IPMI] UpdateMode Retries: %d   pBmcInfo->UpdateMode:%x, Status: %r, Response Data: 0x%lx\n",Retries, pBmcInfo->UpdateMode, Status, TempData));

+          pBmcInfo = (SM_CTRL_INFO *)&TempData[0];

+          DEBUG ((DEBUG_ERROR, "[IPMI] UpdateMode Retries: %d   pBmcInfo->UpdateMode:%x, Status: %r, Response Data: 0x%lx\n", Retries, pBmcInfo->UpdateMode, Status, TempData));

           if (pBmcInfo->UpdateMode == BMC_READY) {

             mIpmiInstance->BmcStatus = BMC_OK;

             return EFI_SUCCESS;

           }

         }

       }

+

       mIpmiInstance->BmcStatus = BMC_HARDFAIL;

     }

   }

+

   return Status;

 } // GetDeviceId()



+/*++

+

+Routine Description:

+  Initialize the API and parameters for IPMI Transport2 Instance

+

+Arguments:

+  IpmiInstance - Pointer to IPMI Instance.

+

+Returns:

+  VOID

+

+--*/

+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 (FixedPcdGet8 (PcdBtInterfaceSupport) == 1) {

+    InitBtInterfaceData (&IpmiInstance->IpmiTransport2);

+  }

+

+  if (FixedPcdGet8 (PcdSsifInterfaceSupport) == 1) {

+    InitSsifInterfaceData (&IpmiInstance->IpmiTransport2);

+  }

+

+  if (FixedPcdGet8 (PcdIpmbInterfaceSupport) == 1) {

+    InitIpmbInterfaceData (&IpmiInstance->IpmiTransport2);

+  }

+}

+

+/*++

+

+Routine Description:

+  Notify call back function.

+

+Arguments:

+  Event      - Event which caused this handler.

+  Context    - Context passed during Event Handler registration.

+

+Returns:

+  VOID

+

+--*/

+VOID

+EFIAPI

+DxeNotifyCallback (

+  IN EFI_EVENT  Event,

+  IN VOID       *Context

+  )

+{

+  EFI_STATUS            Status;

+  IPMI_INTERFACE_STATE  InterfaceState;

+  EFI_HANDLE            Handle;

+

+  InterfaceState = IpmiInterfaceNotReady;

+

+  if (FixedPcdGet8 (PcdSsifInterfaceSupport) == 1) {

+    InitSsifInterfaceData (&mIpmiInstance->IpmiTransport2);

+

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

+      InterfaceState = IpmiInterfaceInitialized;

+    }

+  }

+

+  if (FixedPcdGet8 (PcdIpmbInterfaceSupport) == 1) {

+    InitIpmbInterfaceData (&mIpmiInstance->IpmiTransport2);

+

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

+      InterfaceState = IpmiInterfaceInitialized;

+    }

+  }

+

+  // 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);

+}

+

+/*++

+

+Routine Description:

+  Registers protocol notify call back.

+

+Arguments:

+  ProtocolGuid      - Pointer to Protocol Guid to register call back.

+

+Returns:

+  Status

+

+--*/

+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.

@@ -368,18 +531,20 @@ Returns:
  **/

 EFI_STATUS

 InitializeIpmiKcsPhysicalLayer (

-  IN EFI_HANDLE             ImageHandle,

-  IN EFI_SYSTEM_TABLE       *SystemTable

+  IN EFI_HANDLE        ImageHandle,

+  IN EFI_SYSTEM_TABLE  *SystemTable

   )

 {

   EFI_STATUS             Status;

   UINT8                  ErrorCount;

   EFI_HANDLE             Handle;

   UINT8                  Index;

+  IPMI_INTERFACE_STATE   InterfaceState = IpmiInterfaceNotReady;

   EFI_STATUS_CODE_VALUE  StatusCodeValue[MAX_SOFT_COUNT];



-  ErrorCount = 0;

+  ErrorCount   = 0;

   mImageHandle = ImageHandle;

+  ZeroMem (StatusCodeValue, MAX_SOFT_COUNT);



   mIpmiInstance = AllocateZeroPool (sizeof (*mIpmiInstance));

   if (mIpmiInstance == NULL) {

@@ -396,66 +561,150 @@ InitializeIpmiKcsPhysicalLayer (
     // Initialize the KCS transaction timeout.

     //

     mIpmiInstance->KcsTimeoutPeriod = (BMC_KCS_TIMEOUT * 1000*1000) / KCS_DELAY_UNIT;

-    DEBUG ((EFI_D_ERROR, "[IPMI] mIpmiInstance->KcsTimeoutPeriod: 0x%lx\n",mIpmiInstance->KcsTimeoutPeriod));

+    DEBUG ((EFI_D_ERROR, "[IPMI] mIpmiInstance->KcsTimeoutPeriod: 0x%lx\n", mIpmiInstance->KcsTimeoutPeriod));



     //

     // Initialize IPMI IO Base.

     //

-    mIpmiInstance->IpmiIoBase                       = PcdGet16 (PcdIpmiIoBaseAddress);

-    mIpmiInstance->Signature                        = SM_IPMI_BMC_SIGNATURE;

-    mIpmiInstance->SlaveAddress                     = BMC_SLAVE_ADDRESS;

-    mIpmiInstance->BmcStatus                        = BMC_NOTREADY;

-    mIpmiInstance->IpmiTransport.IpmiSubmitCommand  = IpmiSendCommand;

-    mIpmiInstance->IpmiTransport.GetBmcStatus       = IpmiGetBmcStatus;

+    mIpmiInstance->IpmiIoBase   = PcdGet16 (PcdIpmiIoBaseAddress);

+    mIpmiInstance->Signature    = SM_IPMI_BMC_SIGNATURE;

+    mIpmiInstance->SlaveAddress = BMC_SLAVE_ADDRESS;

+    mIpmiInstance->BmcStatus    = BMC_NOTREADY;

+

+    if (FixedPcdGet8 (PcdKcsInterfaceSupport) == 1) {

+      mIpmiInstance->IpmiTransport.IpmiSubmitCommand = IpmiSendCommand;

+      mIpmiInstance->IpmiTransport.GetBmcStatus      = IpmiGetBmcStatus;



-    //

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

-    //

-    Status = GetDeviceId (

-               mIpmiInstance,

-               StatusCodeValue,

-               &ErrorCount

-               );

-    //

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

-    //

-    if ((mIpmiInstance->BmcStatus != BMC_UPDATE_IN_PROGRESS) &&

-        (mIpmiInstance->BmcStatus != BMC_HARDFAIL)) {

       //

-      // Get the SELF TEST Results.

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

       //

-      Status = GetSelfTest (

-                 mIpmiInstance,

-                 StatusCodeValue,

-                 &ErrorCount

-                 );

+      Status = GetDeviceId (

+                            mIpmiInstance,

+                            StatusCodeValue,

+                            &ErrorCount

+                            );

+      //

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

+      //

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

+          (mIpmiInstance->BmcStatus != BMC_HARDFAIL))

+      {

+        //

+        // Get the SELF TEST Results.

+        //

+        Status = GetSelfTest (

+                              mIpmiInstance,

+                              StatusCodeValue,

+                              &ErrorCount

+                              );

+      }

+

+      //

+      // iterate through the errors reporting them to the error manager.

+      //

+      for (Index = 0; Index < ErrorCount; Index++) {

+        ReportStatusCode (

+                          EFI_ERROR_CODE | EFI_ERROR_MAJOR,

+                          StatusCodeValue[Index]

+                          );

+      }

+

+      //

+      // Now install the Protocol if the BMC is not in a HardFail State and not in Force Update mode

+      //

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

+        Handle = NULL;

+        Status = gBS->InstallProtocolInterface (

+                                                &Handle,

+                                                &gIpmiTransportProtocolGuid,

+                                                EFI_NATIVE_INTERFACE,

+                                                &mIpmiInstance->IpmiTransport

+                                                );

+        ASSERT_EFI_ERROR (Status);

+      }

     }



-    //

-    // iterate through the errors reporting them to the error manager.

-    //

-    for (Index = 0; Index < ErrorCount; Index++) {

-      ReportStatusCode (

-        EFI_ERROR_CODE | EFI_ERROR_MAJOR,

-        StatusCodeValue[Index]

-        );

+    // Initialise the IPMI transport2

+    InitIpmiTransport2 (mIpmiInstance);

+

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

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

+      switch (Index) {

+      if (FixedPcdGet8 (PcdKcsInterfaceSupport) == 1) {

+          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;

+      }

+

+      if (FixedPcdGet8 (PcdBtInterfaceSupport) == 1) {

+          case SysInterfaceBt:

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

+              InterfaceState = IpmiInterfaceInitialized;

+            }

+

+            break;

+      }

+

+      if (FixedPcdGet8 (PcdSsifInterfaceSupport) == 1) {

+          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;

+      }

+

+      if (FixedPcdGet8 (PcdIpmbInterfaceSupport) == 1) {

+          case SysInterfaceIpmb:

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

+              InterfaceState = IpmiInterfaceInitialized;

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

+              // Register Protocol notify for I2C Protocol.

+              Status = DxeRegisterProtocolCallback (

+                                                    &mIpmiInstance->IpmiTransport2.Interface.Ipmb.IpmbInterfaceApiGuid

+                                                    );

+            }

+

+            break;

+      }

+

+        default:

+          break;

+      }

     }



-    //

-    // Now install the Protocol if the BMC is not in a HardFail State and not in Force Update mode

-    //

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

-      Handle = NULL;

-      Status = gBS->InstallProtocolInterface (

-                      &Handle,

-                      &gIpmiTransportProtocolGuid,

-                      EFI_NATIVE_INTERFACE,

-                      &mIpmiInstance->IpmiTransport

-                      );

-      ASSERT_EFI_ERROR (Status);

+    // 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/Smm/SmmGenericIpmi.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Smm/SmmGenericIpmi.c
index 1af2d18f79..350bc74003 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,17 +25,18 @@
 #include "IpmiBmcCommon.h"

 #include "IpmiBmc.h"

 #include <Library/TimerLib.h>

+#include <Library/BmcCommonInterfaceLib.h>



-IPMI_BMC_INSTANCE_DATA             *mIpmiInstance;

-EFI_HANDLE                         mImageHandle;

-

+IPMI_BMC_INSTANCE_DATA  *mIpmiInstance;

+EFI_HANDLE              mImageHandle;



 EFI_STATUS

 GetDeviceId (

-  IN      IPMI_BMC_INSTANCE_DATA       *IpmiInstance,

-  IN      EFI_STATUS_CODE_VALUE        StatusCodeValue[ ],

-  IN OUT  UINT8                        *ErrorCount

+  IN      IPMI_BMC_INSTANCE_DATA  *IpmiInstance,

+  IN      EFI_STATUS_CODE_VALUE   StatusCodeValue[],

+  IN OUT  UINT8                   *ErrorCount

   )

+

 /*++



 Routine Description:

@@ -51,12 +53,12 @@ Returns:


 --*/

 {

-  EFI_STATUS               Status;

-  UINT32                   DataSize;

-  SM_CTRL_INFO             *ControllerInfo;

-  UINT8                    TimeOut;

-  UINT8                    Retries;

-  UINT8                    TempData[MAX_TEMP_DATA];

+  EFI_STATUS    Status;

+  UINT32        DataSize;

+  SM_CTRL_INFO  *ControllerInfo;

+  UINT8         TimeOut;

+  UINT8         Retries;

+  UINT8         TempData[MAX_TEMP_DATA];



   TimeOut = 0;

   Retries = PcdGet8 (PcdIpmiBmcReadyDelayTimer);

@@ -66,16 +68,16 @@ Returns:
     // Get the device ID information for the BMC.

     //

     DataSize = MAX_TEMP_DATA;

-    Status = IpmiSendCommand (

-               &IpmiInstance->IpmiTransport,

-               IPMI_NETFN_APP,

-               0,

-               IPMI_APP_GET_DEVICE_ID,

-               NULL,

-               0,

-               TempData,

-               &DataSize

-               );

+    Status   = IpmiSendCommand (

+                                &IpmiInstance->IpmiTransport,

+                                IPMI_NETFN_APP,

+                                0,

+                                IPMI_APP_GET_DEVICE_ID,

+                                NULL,

+                                0,

+                                TempData,

+                                &DataSize

+                                );

     if (Status == EFI_SUCCESS) {

       DEBUG ((EFI_D_INFO, "IPMI: SendCommand success!\n"));

       break;

@@ -84,10 +86,10 @@ Returns:
       // Display message and retry.

       //

       DEBUG (

-        (EFI_D_ERROR | EFI_D_INFO,

-         "IPMI: Waiting for BMC (KCS 0x%x)...\n",

-         IpmiInstance->IpmiIoBase)

-        );

+             (EFI_D_ERROR | EFI_D_INFO,

+              "IPMI: Waiting for BMC (KCS 0x%x)...\n",

+              IpmiInstance->IpmiIoBase)

+             );

       MicroSecondDelay (500 * 1000);

       TimeOut++;

     }

@@ -97,7 +99,7 @@ Returns:
   // If there is no error then proceed to check the data returned by the BMC

   //

   if (!EFI_ERROR (Status)) {

-    ControllerInfo = (SM_CTRL_INFO *) TempData;

+    ControllerInfo = (SM_CTRL_INFO *)TempData;

     //

     // If the controller is in Update Mode and the maximum number of errors has not been exceeded, then

     // save the error code to the StatusCode array and increment the counter.  Set the BMC Status to indicate

@@ -115,11 +117,143 @@ Returns:
   return Status;

 }



+/*++

+

+Routine Description:

+  Initialize the API and parameters for IPMI Transport2 Instance

+

+Arguments:

+  IpmiInstance    - Pointer to IPMI Instance.

+

+Returns:

+  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 (FixedPcdGet8 (PcdBtInterfaceSupport) == 1) {

+    InitBtInterfaceData (&IpmiInstance->IpmiTransport2);

+  }

+

+  if (FixedPcdGet8 (PcdSsifInterfaceSupport) == 1) {

+    InitSsifInterfaceData (&IpmiInstance->IpmiTransport2);

+  }

+

+  if (FixedPcdGet8 (PcdIpmbInterfaceSupport) == 1) {

+    InitIpmbInterfaceData (&IpmiInstance->IpmiTransport2);

+  }

+}

+

+/*++

+

+Routine Description:

+  Notify call back to initialize the interfaces and install SMM IPMI

+  protocol.

+

+Arguments:

+  Protocol    - Pointer to the protocol guid.

+  Interface   - Pointer to the protocol instance.

+  Handle      - Handle on which the protocol is installed.

+

+Returns:

+  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 (FixedPcdGet8 (PcdSsifInterfaceSupport) == 1) {

+    InitSsifInterfaceData (&mIpmiInstance->IpmiTransport2);

+

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

+      InterfaceState = IpmiInterfaceInitialized;

+    }

+  }

+

+  if (FixedPcdGet8 (PcdIpmbInterfaceSupport) == 1) {

+    InitIpmbInterfaceData (&mIpmiInstance->IpmiTransport2);

+  }

+

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

+    InterfaceState = IpmiInterfaceInitialized;

+  }

+

+  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;

+}

+

+/*++

+

+Routine Description:

+  Registers Protocol call back.

+

+Arguments:

+  ProtocolGuid    - Pointer to Protocol GUID to register call back.

+

+Returns:

+  Status.

+

+--*/

+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,

-  IN EFI_SYSTEM_TABLE       *SystemTable

+  IN EFI_HANDLE        ImageHandle,

+  IN EFI_SYSTEM_TABLE  *SystemTable

   )

+

 /*++



 Routine Description:

@@ -138,14 +272,17 @@ Returns:


 --*/

 {

-  EFI_STATUS                       Status;

-  UINT8                            ErrorCount;

-  EFI_HANDLE                       Handle;

-  EFI_STATUS_CODE_VALUE            StatusCodeValue[MAX_SOFT_COUNT];

+  EFI_STATUS             Status;

+  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;

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

+  ErrorCount     = 0;

+  mImageHandle   = ImageHandle;

+  InterfaceState = IpmiInterfaceNotReady;



   mIpmiInstance = AllocateZeroPool (sizeof (IPMI_BMC_INSTANCE_DATA));

   ASSERT (mIpmiInstance != NULL);

@@ -154,7 +291,6 @@ Returns:
     ASSERT_EFI_ERROR (EFI_OUT_OF_RESOURCES);

     return EFI_OUT_OF_RESOURCES;

   } else {

-

     //

     // Initialize the KCS transaction timeout. Assume delay unit is 1000 us.

     //

@@ -163,36 +299,115 @@ Returns:
     //

     // Initialize IPMI IO Base, we still use SMS IO base to get device ID and Seltest result since SMM IF may have different cmds supported

     //

-    mIpmiInstance->IpmiIoBase                       = PcdGet16 (PcdIpmiSmmIoBaseAddress);

-    mIpmiInstance->Signature                        = SM_IPMI_BMC_SIGNATURE;

-    mIpmiInstance->SlaveAddress                     = BMC_SLAVE_ADDRESS;

-    mIpmiInstance->BmcStatus                        = BMC_NOTREADY;

-    mIpmiInstance->IpmiTransport.IpmiSubmitCommand  = IpmiSendCommand;

-    mIpmiInstance->IpmiTransport.GetBmcStatus       = IpmiGetBmcStatus;

-

-    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.

-    //

-    // Just obey the Spec..

-    // If we want to improve performance, we're going to comment it.

-    //

-    Status = GetDeviceId (

-               mIpmiInstance,

-               StatusCodeValue,

-               &ErrorCount

-               );

-    ASSERT_EFI_ERROR (Status);

-    Handle = NULL;

-    Status = gSmst->SmmInstallProtocolInterface (

-                      &Handle,

-                      &gSmmIpmiTransportProtocolGuid,

-                      EFI_NATIVE_INTERFACE,

-                      &mIpmiInstance->IpmiTransport

-                      );

-    ASSERT_EFI_ERROR (Status);

+    mIpmiInstance->IpmiIoBase                      = PcdGet16 (PcdIpmiSmmIoBaseAddress);

+    mIpmiInstance->Signature                       = SM_IPMI_BMC_SIGNATURE;

+    mIpmiInstance->SlaveAddress                    = BMC_SLAVE_ADDRESS;

+    mIpmiInstance->BmcStatus                       = BMC_NOTREADY;

+    mIpmiInstance->IpmiTransport.IpmiSubmitCommand = IpmiSendCommand;

+    mIpmiInstance->IpmiTransport.GetBmcStatus      = IpmiGetBmcStatus;

+

+    if (FixedPcdGet8 (PcdKcsInterfaceSupport) == 1) {

+      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.

+      //

+      // Just obey the Spec..

+      // If we want to improve performance, we're going to comment it.

+      //

+      Status = GetDeviceId (

+                            mIpmiInstance,

+                            StatusCodeValue,

+                            &ErrorCount

+                            );

+      ASSERT_EFI_ERROR (Status);

+      Handle = NULL;

+      Status = gSmst->SmmInstallProtocolInterface (

+                                                   &Handle,

+                                                   &gSmmIpmiTransportProtocolGuid,

+                                                   EFI_NATIVE_INTERFACE,

+                                                   &mIpmiInstance->IpmiTransport

+                                                   );

+      ASSERT_EFI_ERROR (Status);

+    }

+

+    InitIpmiTransport2 (mIpmiInstance);

+

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

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

+      switch (Index) {

+      if (FixedPcdGet8 (PcdKcsInterfaceSupport) == 1) {

+          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;

+      }

+

+      if (FixedPcdGet8 (PcdBtInterfaceSupport) == 1) {

+          case SysInterfaceBt:

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

+              InterfaceState = IpmiInterfaceInitialized;

+            }

+

+            break;

+      }

+

+      if (FixedPcdGet8 (PcdSsifInterfaceSupport) == 1) {

+          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;

+      }

+

+      if (FixedPcdGet8 (PcdIpmbInterfaceSupport) == 1) {

+          case SysInterfaceIpmb:

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

+              InterfaceState = IpmiInterfaceInitialized;

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

+              // Register protocol notify for SMBUS Protocol.

+              Status = SmmRegisterProtocolCallback (&mIpmiInstance->IpmiTransport2.Interface.Ipmb.IpmbInterfaceApiGuid);

+            }

+

+            break;

+      }

+

+        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"));

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



     return EFI_SUCCESS;

   }

@@ -200,8 +415,8 @@ Returns:


 EFI_STATUS

 InitializeSmmGenericIpmi (

-  IN EFI_HANDLE             ImageHandle,

-  IN EFI_SYSTEM_TABLE       *SystemTable

+  IN EFI_HANDLE        ImageHandle,

+  IN EFI_SYSTEM_TABLE  *SystemTable

   )

 {

   SmmInitializeIpmiKcsPhysicalLayer (ImageHandle, SystemTable);

diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Smm/SmmGenericIpmi.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Smm/SmmGenericIpmi.inf
index f430195d1e..12dc17ae84 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,26 @@
   IoLib

   ReportStatusCodeLib

   TimerLib

+  BmcCommonInterfaceLib

+  BtInterfaceLib

+  SsifInterfaceLib

+  IpmbInterfaceLib



 [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

+  gIpmiFeaturePkgTokenSpaceGuid.PcdIpmbInterfaceSupport



 [Depex]

  gIpmiTransportProtocolGuid

--
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.


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#107248): https://edk2.groups.io/g/devel/message/107248
Mute This Topic: https://groups.io/mt/100352689/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
Re: [edk2-devel][edk2-platforms][PATCH V5-2] IpmiFeaturePkg:Provided multiple IPMI interface support in DXE and SMM
Posted by Isaac Oram 9 months ago
Reviewed-by: Isaac Oram <isaac.w.oram@intel.com>

-----Original Message-----
From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Arun K via groups.io
Sent: Tuesday, July 25, 2023 8:37 AM
To: devel@edk2.groups.io; Arun K <arunk@ami.com>
Cc: Oram, Isaac W <isaac.w.oram@intel.com>; Desimone, Nathaniel L <nathaniel.l.desimone@intel.com>; Ramkumar Krishnamoorthi <ramkumark@ami.com>; Gao, Liming <gaoliming@byosoft.com.cn>
Subject: [edk2-devel][edk2-platforms][PATCH V5-2] IpmiFeaturePkg:Provided multiple IPMI interface support in DXE and SMM

Created IpmiTransport2 PPI/Protocol to support multiple
IPMI BMC Interface support such as KCS/BT/SSIF/IPMB with 2 API's
IpmiSubmitCommand2 & IpmiSubmitCommand2Ex.
IpmiSubmitCommand2 - This API use the default interface
(PcdDefaultSystemInterface) to send IPMI command.
IpmiSubmitCommand2Ex - This API use the specific interface type
to send IPMI command which is passed as an argument.

Cc: Isaac Oram <isaac.w.oram@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>

Signed-off-by: Arun K <arunk@ami.com>
---
 .../GenericIpmi/Common/IpmiBmc.h              |  13 +-
 .../GenericIpmi/Common/IpmiBmcCommon.h        |  82 +--
 .../GenericIpmi/Common/IpmiHooks.c            | 298 ++++++++++-
 .../GenericIpmi/Common/IpmiHooks.h            | 119 ++++-
 .../GenericIpmi/Dxe/GenericIpmi.inf           |  14 +-
 .../IpmiFeaturePkg/GenericIpmi/Dxe/IpmiInit.c | 505 +++++++++++++-----
 .../GenericIpmi/Smm/SmmGenericIpmi.c          | 351 +++++++++---
 .../GenericIpmi/Smm/SmmGenericIpmi.inf        |  12 +
 8 files changed, 1117 insertions(+), 277 deletions(-)

diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Common/IpmiBmc.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Common/IpmiBmc.h
index d306a085e5..76ee988623 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,17 +22,17 @@
 #include <Library/ReportStatusCodeLib.h>

 #include <Library/IpmiBaseLib.h>

 #include <Protocol/IpmiTransportProtocol.h>

+#include <Protocol/IpmiTransport2Protocol.h>



 #include "IpmiBmcCommon.h"

 #include "KcsBmc.h"



-

 #define BMC_KCS_TIMEOUT  5   // [s] Single KSC request timeout



 //

 // IPMI Instance signature

 //

-#define SM_IPMI_BMC_SIGNATURE SIGNATURE_32 ('i', 'p', 'm', 'i')

+#define SM_IPMI_BMC_SIGNATURE        SIGNATURE_32 ('i', 'p', 'm', 'i')

 #define IPMI_SEND_COMMAND_MAX_RETRY  3   // Number of retries

 #define INSTANCE_FROM_SM_IPMI_BMC_THIS(a) \

   CR ( \

@@ -41,4 +42,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 06eab62aae..faf6cc6685 100644
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Common/IpmiBmcCommon.h
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Common/IpmiBmcCommon.h
@@ -3,16 +3,17 @@


   @copyright

   Copyright 1999 - 2021 Intel Corporation. <BR>

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

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

 **/



 #ifndef _IPMI_COMMON_BMC_H_

 #define _IPMI_COMMON_BMC_H_



-#define MAX_TEMP_DATA     255 // 160 Modified to increase number of bytes transfered per command

-#define BMC_SLAVE_ADDRESS 0x20

-#define MAX_SOFT_COUNT    10

-#define COMP_CODE_NORMAL  0x00

+#define MAX_TEMP_DATA      255// 160 Modified to increase number of bytes transfered per command

+#define BMC_SLAVE_ADDRESS  0x20

+#define MAX_SOFT_COUNT     10

+#define COMP_CODE_NORMAL   0x00



 //

 // IPMI command completion codes to check for in the UpdateErrorStatus routine.

@@ -33,8 +34,8 @@
 // D4h C Insufficient privilege, in KCS channel this indicates KCS Policy Control Mode is Deny All.

 // In authenticated channels this indicates invalid authentication/privilege.

 //

-#define COMP_INSUFFICIENT_PRIVILEGE       0xD4

-#define COMP_CODE_UNSPECIFIED             0xFF

+#define COMP_INSUFFICIENT_PRIVILEGE  0xD4

+#define COMP_CODE_UNSPECIFIED        0xFF



 #define COMPLETION_CODES \

   { \

@@ -47,15 +48,16 @@
 // Dxe Ipmi instance data

 //

 typedef struct {

-  UINTN               Signature;

-  UINT64              KcsTimeoutPeriod;

-  UINT8               SlaveAddress;

-  BMC_STATUS          BmcStatus;

-  UINT64              ErrorStatus;

-  UINT8               SoftErrorCount;

-  UINT16              IpmiIoBase;

-  IPMI_TRANSPORT      IpmiTransport;

-  EFI_HANDLE          IpmiSmmHandle;

+  UINTN              Signature;

+  UINT64             KcsTimeoutPeriod;

+  UINT8              SlaveAddress;

+  BMC_STATUS         BmcStatus;

+  UINT64             ErrorStatus;

+  UINT8              SoftErrorCount;

+  UINT16             IpmiIoBase;

+  IPMI_TRANSPORT     IpmiTransport;

+  IPMI_TRANSPORT2    IpmiTransport2;

+  EFI_HANDLE         IpmiSmmHandle;

 } IPMI_BMC_INSTANCE_DATA;



 //

@@ -64,38 +66,39 @@ typedef struct {
 #define IPMI_COMMAND_HEADER_SIZE  2



 typedef struct {

-  UINT8 Lun : 2;

-  UINT8 NetFunction : 6;

-  UINT8 Command;

-  UINT8 CommandData[MAX_TEMP_DATA - IPMI_COMMAND_HEADER_SIZE];

+  UINT8    Lun         : 2;

+  UINT8    NetFunction : 6;

+  UINT8    Command;

+  UINT8    CommandData[MAX_TEMP_DATA - IPMI_COMMAND_HEADER_SIZE];

 } IPMI_COMMAND;



 //

 // Structure of IPMI Command response buffer

 //

-#define IPMI_RESPONSE_HEADER_SIZE 3

+#define IPMI_RESPONSE_HEADER_SIZE  3



 typedef struct {

-  UINT8 Lun : 2;

-  UINT8 NetFunction : 6;

-  UINT8 Command;

-  UINT8 CompletionCode;

-  UINT8 ResponseData[MAX_TEMP_DATA - IPMI_RESPONSE_HEADER_SIZE];

+  UINT8    Lun         : 2;

+  UINT8    NetFunction : 6;

+  UINT8    Command;

+  UINT8    CompletionCode;

+  UINT8    ResponseData[MAX_TEMP_DATA - IPMI_RESPONSE_HEADER_SIZE];

 } IPMI_RESPONSE;



 EFI_STATUS

 EFIAPI

 IpmiSendCommandToBmc (

-  IN      IPMI_TRANSPORT                *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

+  IN      IPMI_TRANSPORT  *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:

@@ -124,15 +127,15 @@ Returns:
 --*/

 ;



-

 EFI_STATUS

 EFIAPI

 IpmiBmcStatus (

-  IN  IPMI_TRANSPORT              *This,

-  OUT BMC_STATUS                  *BmcStatus,

-  OUT SM_COM_ADDRESS              *ComAddress,

-  IN  VOID                        *Context

+  IN  IPMI_TRANSPORT  *This,

+  OUT BMC_STATUS      *BmcStatus,

+  OUT SM_COM_ADDRESS  *ComAddress,

+  IN  VOID            *Context

   )

+

 /*++



 Routine Description:

@@ -157,6 +160,7 @@ VOID
 GetDeviceSpecificTestResults (

   IN      IPMI_BMC_INSTANCE_DATA  *IpmiInstance

   )

+

 /*++



 Routine Description:

diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Common/IpmiHooks.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Common/IpmiHooks.c
index b2788e5a4c..57577b1b35 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

 **/



@@ -11,15 +12,16 @@
 EFI_STATUS

 EFIAPI

 IpmiSendCommand (

-  IN      IPMI_TRANSPORT               *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      IPMI_TRANSPORT  *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:

@@ -48,29 +50,269 @@ Returns:


 --*/

 {

+  if (This == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

   //

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

   //

   return IpmiSendCommandToBmc (

-           This,

-           NetFunction,

-           Lun,

-           Command,

-           CommandData,

-           (UINT8) CommandDataSize,

-           ResponseData,

-           (UINT8*) ResponseDataSize,

-           NULL

-           );

+                               This,

+                               NetFunction,

+                               Lun,

+                               Command,

+                               CommandData,

+                               (UINT8)CommandDataSize,

+                               ResponseData,

+                               (UINT8 *)ResponseDataSize,

+                               NULL

+                               );

 } // 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 ((FixedPcdGet8 (PcdKcsInterfaceSupport) == 1) &&

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

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

+  {

+    return IpmiSendCommand (

+                            &IpmiInstance->IpmiTransport,

+                            NetFunction,

+                            Lun,

+                            Command,

+                            CommandData,

+                            CommandDataSize,

+                            ResponseData,

+                            ResponseDataSize

+                            );

+  }

+

+  if ((FixedPcdGet8 (PcdBtInterfaceSupport) == 1) &&

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

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

+  {

+    return IpmiBtSendCommandToBmc (

+                                   &IpmiInstance->IpmiTransport2,

+                                   NetFunction,

+                                   Lun,

+                                   Command,

+                                   CommandData,

+                                   (UINT8)CommandDataSize,

+                                   ResponseData,

+                                   (UINT8 *)ResponseDataSize,

+                                   NULL

+                                   );

+  }

+

+  if ((FixedPcdGet8 (PcdSsifInterfaceSupport) == 1) &&

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

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

+  {

+    return IpmiSsifSendCommandToBmc (

+                                     &IpmiInstance->IpmiTransport2,

+                                     NetFunction,

+                                     Lun,

+                                     Command,

+                                     CommandData,

+                                     (UINT8)CommandDataSize,

+                                     ResponseData,

+                                     (UINT8 *)ResponseDataSize,

+                                     NULL

+                                     );

+  }

+

+  if ((FixedPcdGet8 (PcdIpmbInterfaceSupport) == 1) &&

+      ((IpmiInstance->IpmiTransport2.InterfaceType == SysInterfaceIpmb) &&

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

+  {

+    return IpmiIpmbSendCommandToBmc (

+                                     &IpmiInstance->IpmiTransport2,

+                                     NetFunction,

+                                     Lun,

+                                     Command,

+                                     CommandData,

+                                     (UINT8)CommandDataSize,

+                                     ResponseData,

+                                     (UINT8 *)ResponseDataSize,

+                                     NULL

+                                     );

+  }

+

+  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 ((FixedPcdGet8 (PcdKcsInterfaceSupport) == 1) &&

+      ((InterfaceType == SysInterfaceKcs) && (IpmiInstance->IpmiTransport2.Interface.KcsInterfaceState == IpmiInterfaceInitialized)))

+  {

+    return IpmiSendCommand (

+                            &IpmiInstance->IpmiTransport,

+                            NetFunction,

+                            Lun,

+                            Command,

+                            CommandData,

+                            CommandDataSize,

+                            ResponseData,

+                            ResponseDataSize

+                            );

+  }

+

+  if ((FixedPcdGet8 (PcdBtInterfaceSupport) == 1) &&

+      ((InterfaceType == SysInterfaceBt) && (IpmiInstance->IpmiTransport2.Interface.Bt.InterfaceState == IpmiInterfaceInitialized)))

+  {

+    return IpmiBtSendCommandToBmc (

+                                   &IpmiInstance->IpmiTransport2,

+                                   NetFunction,

+                                   Lun,

+                                   Command,

+                                   CommandData,

+                                   (UINT8)CommandDataSize,

+                                   ResponseData,

+                                   (UINT8 *)ResponseDataSize,

+                                   NULL

+                                   );

+  }

+

+  if ((FixedPcdGet8 (PcdSsifInterfaceSupport) == 1) &&

+      ((InterfaceType == SysInterfaceSsif) && (IpmiInstance->IpmiTransport2.Interface.Ssif.InterfaceState == IpmiInterfaceInitialized)))

+  {

+    return IpmiSsifSendCommandToBmc (

+                                     &IpmiInstance->IpmiTransport2,

+                                     NetFunction,

+                                     Lun,

+                                     Command,

+                                     CommandData,

+                                     (UINT8)CommandDataSize,

+                                     ResponseData,

+                                     (UINT8 *)ResponseDataSize,

+                                     NULL

+                                     );

+  }

+

+  if ((FixedPcdGet8 (PcdIpmbInterfaceSupport) == 1) &&

+      ((InterfaceType == SysInterfaceIpmb) && (IpmiInstance->IpmiTransport2.Interface.Ipmb.InterfaceState == IpmiInterfaceInitialized)))

+  {

+    return IpmiIpmbSendCommandToBmc (

+                                     &IpmiInstance->IpmiTransport2,

+                                     NetFunction,

+                                     Lun,

+                                     Command,

+                                     CommandData,

+                                     (UINT8)CommandDataSize,

+                                     ResponseData,

+                                     (UINT8 *)ResponseDataSize,

+                                     NULL

+                                     );

+  }

+

+  return EFI_UNSUPPORTED;

+}

+

 EFI_STATUS

 EFIAPI

 IpmiGetBmcStatus (

-  IN IPMI_TRANSPORT                *This,

-  OUT BMC_STATUS                   *BmcStatus,

-  OUT SM_COM_ADDRESS               *ComAddress

+  IN IPMI_TRANSPORT   *This,

+  OUT BMC_STATUS      *BmcStatus,

+  OUT SM_COM_ADDRESS  *ComAddress

   )

+

 /*++



 Routine Description:

@@ -89,10 +331,14 @@ Returns:


 --*/

 {

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

+    return EFI_INVALID_PARAMETER;

+  }

+

   return IpmiBmcStatus (

-           This,

-           BmcStatus,

-           ComAddress,

-           NULL

-           );

+                        This,

+                        BmcStatus,

+                        ComAddress,

+                        NULL

+                        );

 }

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


   @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/IpmbInterfaceLib.h>

+#include <Library/DebugLib.h>

+#include <IpmiBmcCommon.h>

+#include <IpmiBmc.h>



 //

 // Internal(hook) function list

@@ -17,15 +25,16 @@
 EFI_STATUS

 EFIAPI

 IpmiSendCommand (

-  IN      IPMI_TRANSPORT               *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      IPMI_TRANSPORT  *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:

@@ -54,13 +63,99 @@ 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 (

-  IN IPMI_TRANSPORT                                    *This,

-  OUT BMC_STATUS                                       *BmcStatus,

-  OUT SM_COM_ADDRESS                                   *ComAddress

+  IN IPMI_TRANSPORT   *This,

+  OUT BMC_STATUS      *BmcStatus,

+  OUT SM_COM_ADDRESS  *ComAddress

   )

+

 /*++



 Routine Description:

diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Dxe/GenericIpmi.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Dxe/GenericIpmi.inf
index 8d80aeb6b5..1564ceb08a 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,25 @@
   IoLib

   ReportStatusCodeLib

   TimerLib

+  BmcCommonInterfaceLib

+  BtInterfaceLib

+  SsifInterfaceLib

+  IpmbInterfaceLib



 [Protocols]

   gIpmiTransportProtocolGuid               # PROTOCOL ALWAYS_PRODUCED

   gEfiVideoPrintProtocolGuid

-

-[Guids]

+  gIpmiTransport2ProtocolGuid



 [Pcd]

   gIpmiFeaturePkgTokenSpaceGuid.PcdIpmiIoBaseAddress

   gIpmiFeaturePkgTokenSpaceGuid.PcdIpmiBmcReadyDelayTimer

+  gIpmiFeaturePkgTokenSpaceGuid.PcdDefaultSystemInterface

+  gIpmiFeaturePkgTokenSpaceGuid.PcdBtInterfaceSupport

+  gIpmiFeaturePkgTokenSpaceGuid.PcdSsifInterfaceSupport

+  gIpmiFeaturePkgTokenSpaceGuid.PcdIpmbInterfaceSupport

+  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 c333ca2e06..d836e36b4e 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,25 +14,26 @@
 #include "IpmiBmc.h"

 #include "IpmiPhysicalLayer.h"

 #include <Library/TimerLib.h>

+#include <Library/BmcCommonInterfaceLib.h>

 #ifdef FAST_VIDEO_SUPPORT

   #include <Protocol/VideoPrint.h>

 #endif

 #include <Library/UefiRuntimeServicesTableLib.h>



-

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

  * Local variables

  */

-IPMI_BMC_INSTANCE_DATA       *mIpmiInstance = NULL;

-EFI_HANDLE                    mImageHandle;

+IPMI_BMC_INSTANCE_DATA  *mIpmiInstance = NULL;

+EFI_HANDLE              mImageHandle;



 //

 // Specific test interface

 //

 VOID

 GetDeviceSpecificTestResults (

-  IN      IPMI_BMC_INSTANCE_DATA *IpmiInstance

+  IN      IPMI_BMC_INSTANCE_DATA  *IpmiInstance

   )

+

 /*++



 Routine Description:

@@ -54,10 +56,11 @@ Returns:


 EFI_STATUS

 GetSelfTest (

-  IN      IPMI_BMC_INSTANCE_DATA     *IpmiInstance,

-  IN      EFI_STATUS_CODE_VALUE       StatusCodeValue[],

-  IN OUT  UINT8                       *ErrorCount

+  IN      IPMI_BMC_INSTANCE_DATA  *IpmiInstance,

+  IN      EFI_STATUS_CODE_VALUE   StatusCodeValue[],

+  IN OUT  UINT8                   *ErrorCount

   )

+

 /*++



 Routine Description:

@@ -86,13 +89,13 @@ Returns:
   BOOLEAN     bResultFlag = FALSE;

   UINT8       TempData[MAX_TEMP_DATA];



-  IPMI_SELF_TEST_RESULT_RESPONSE *SelfTestResult;

+  IPMI_SELF_TEST_RESULT_RESPONSE  *SelfTestResult;



   //

   // Get the SELF TEST Results.

   //

   //

-  //Note: If BMC PcdIpmiBmcReadyDelayTimer < BMC_KCS_TIMEOUT, it need set Retries as 1. Otherwise it will make SELT failure, caused by below condition (EFI_ERROR(Status) || Retries == 0)

+  // Note: If BMC PcdIpmiBmcReadyDelayTimer < BMC_KCS_TIMEOUT, it need set Retries as 1. Otherwise it will make SELT failure, caused by below condition (EFI_ERROR(Status) || Retries == 0)

   //

   if (PcdGet8 (PcdIpmiBmcReadyDelayTimer) < BMC_KCS_TIMEOUT) {

     Retries = 1;

@@ -102,20 +105,20 @@ Returns:


   DataSize = sizeof (TempData);



-  SelfTestResult = (IPMI_SELF_TEST_RESULT_RESPONSE *) &TempData[0];

+  SelfTestResult         = (IPMI_SELF_TEST_RESULT_RESPONSE *)&TempData[0];

   SelfTestResult->Result = 0;



   do {

     Status = IpmiSendCommand (

-               &IpmiInstance->IpmiTransport,

-               IPMI_NETFN_APP,

-               0,

-               IPMI_APP_GET_SELFTEST_RESULTS,

-               NULL,

-               0,

-               TempData,

-               &DataSize

-               );

+                              &IpmiInstance->IpmiTransport,

+                              IPMI_NETFN_APP,

+                              0,

+                              IPMI_APP_GET_SELFTEST_RESULTS,

+                              NULL,

+                              0,

+                              TempData,

+                              &DataSize

+                              );

     if (Status == EFI_SUCCESS) {

       switch (SelfTestResult->Result) {

         case IPMI_APP_SELFTEST_NO_ERROR:

@@ -127,7 +130,7 @@ Returns:


         default:

           break;

-      } //switch

+      } // switch



       if (bResultFlag) {

         break;

@@ -140,7 +143,7 @@ Returns:
   //

   // If Status indicates a Device error, then the BMC is not responding, so send an error.

   //

-  if (EFI_ERROR (Status) || Retries == 0) {

+  if (EFI_ERROR (Status) || (Retries == 0)) {

     DEBUG ((EFI_D_ERROR, "\n[IPMI]  BMC self-test does not respond (status: %r)!\n\n", Status));

     if (*ErrorCount < MAX_SOFT_COUNT) {

       StatusCodeValue[*ErrorCount] = EFI_COMPUTING_UNIT_FIRMWARE_PROCESSOR | EFI_CU_FP_EC_COMM_ERROR;

@@ -155,12 +158,14 @@ Returns:
     // Copy the Self test results to Error Status.  Data will be copied as long as it

     // does not exceed the size of the ErrorStatus variable.

     //

-    for (Index = 0, TempPtr = (UINT8 *) &IpmiInstance->ErrorStatus;

+    for (Index = 0, TempPtr = (UINT8 *)&IpmiInstance->ErrorStatus;

          (Index < DataSize) && (Index < sizeof (IpmiInstance->ErrorStatus));

          Index++, TempPtr++

-         ) {

+         )

+    {

       *TempPtr = TempData[Index];

     }

+

     //

     // Check the IPMI defined self test results.

     // Additional Cases are device specific test results.

@@ -182,6 +187,7 @@ Returns:
         } else {

           IpmiInstance->BmcStatus = BMC_SOFTFAIL;

         }

+

         //

         // Check if SDR repository is empty and report it if it is.

         //

@@ -191,6 +197,7 @@ Returns:
             (*ErrorCount)++;

           }

         }

+

         break;



       case IPMI_APP_SELFTEST_FATAL_HW_ERROR:

@@ -221,13 +228,13 @@ Returns:
   return EFI_SUCCESS;

 } // GetSelfTest()



-

 EFI_STATUS

 GetDeviceId (

-  IN      IPMI_BMC_INSTANCE_DATA       *IpmiInstance,

-  IN      EFI_STATUS_CODE_VALUE        StatusCodeValue[ ],

-  IN OUT  UINT8                        *ErrorCount

+  IN      IPMI_BMC_INSTANCE_DATA  *IpmiInstance,

+  IN      EFI_STATUS_CODE_VALUE   StatusCodeValue[],

+  IN OUT  UINT8                   *ErrorCount

   )

+

 /*++



 Routine Description:

@@ -244,25 +251,25 @@ Returns:


 --*/

 {

-  EFI_STATUS                      Status;

-  UINT32                          DataSize;

-  SM_CTRL_INFO                    *pBmcInfo;

-  IPMI_MSG_GET_BMC_EXEC_RSP       *pBmcExecContext;

-  UINT32                          Retries;

-  UINT8                           TempData[MAX_TEMP_DATA];

-

-#ifdef FAST_VIDEO_SUPPORT

-  EFI_VIDEOPRINT_PROTOCOL         *VideoPrintProtocol;

-  EFI_STATUS                      VideoPrintStatus;

-#endif

-

-#ifdef FAST_VIDEO_SUPPORT

+  EFI_STATUS                 Status;

+  UINT32                     DataSize;

+  SM_CTRL_INFO               *pBmcInfo;

+  IPMI_MSG_GET_BMC_EXEC_RSP  *pBmcExecContext;

+  UINT32                     Retries;

+  UINT8                      TempData[MAX_TEMP_DATA];

+

+ #ifdef FAST_VIDEO_SUPPORT

+  EFI_VIDEOPRINT_PROTOCOL  *VideoPrintProtocol;

+  EFI_STATUS               VideoPrintStatus;

+ #endif

+

+ #ifdef FAST_VIDEO_SUPPORT

   VideoPrintStatus = gBS->LocateProtocol (

-                            &gEfiVideoPrintProtocolGuid,

-                            NULL,

-                            &VideoPrintProtocol

-                            );

-#endif

+                                          &gEfiVideoPrintProtocolGuid,

+                                          NULL,

+                                          &VideoPrintProtocol

+                                          );

+ #endif



   //

   // Set up a loop to retry for up to PcdIpmiBmcReadyDelayTimer seconds. Calculate retries not timeout

@@ -274,28 +281,38 @@ Returns:
   // Get the device ID information for the BMC.

   //

   DataSize = sizeof (TempData);

-  while (EFI_ERROR (Status = IpmiSendCommand (

-                               &IpmiInstance->IpmiTransport,

-                               IPMI_NETFN_APP, 0,

-                               IPMI_APP_GET_DEVICE_ID,

-                               NULL, 0,

-                               TempData, &DataSize))

-         ) {

-    DEBUG ((DEBUG_ERROR, "[IPMI] BMC does not respond by Get BMC DID (status: %r), %d retries left, ResponseData: 0x%lx\n",

-            Status, Retries, TempData));

+  while (EFI_ERROR (

+                    Status = IpmiSendCommand (

+                                              &IpmiInstance->IpmiTransport,

+                                              IPMI_NETFN_APP,

+                                              0,

+                                              IPMI_APP_GET_DEVICE_ID,

+                                              NULL,

+                                              0,

+                                              TempData,

+                                              &DataSize

+                                              )

+                    )

+         )

+  {

+    DEBUG (

+           (DEBUG_ERROR, "[IPMI] BMC does not respond by Get BMC DID (status: %r), %d retries left, ResponseData: 0x%lx\n",

+            Status, Retries, TempData)

+           );



     if (Retries-- == 0) {

       IpmiInstance->BmcStatus = BMC_HARDFAIL;

       return Status;

     }

+

     //

-    //Handle the case that BMC FW still not enable KCS channel after AC cycle. just stall 1 second

+    // Handle the case that BMC FW still not enable KCS channel after AC cycle. just stall 1 second

     //

     MicroSecondDelay (1*1000*1000);

   }



-  pBmcInfo = (SM_CTRL_INFO*)&TempData[0];

-  DEBUG ((EFI_D_ERROR, "[IPMI] BMC Device ID: 0x%02X, firmware version: %d.%02X UpdateMode:%x\n", pBmcInfo->DeviceId, pBmcInfo->MajorFirmwareRev, pBmcInfo->MinorFirmwareRev,pBmcInfo->UpdateMode));

+  pBmcInfo = (SM_CTRL_INFO *)&TempData[0];

+  DEBUG ((EFI_D_ERROR, "[IPMI] BMC Device ID: 0x%02X, firmware version: %d.%02X UpdateMode:%x\n", pBmcInfo->DeviceId, pBmcInfo->MajorFirmwareRev, pBmcInfo->MinorFirmwareRev, pBmcInfo->UpdateMode));

   //

   // In OpenBMC, UpdateMode: the bit 7 of byte 4 in get device id command is used for the BMC status:

   // 0 means BMC is ready, 1 means BMC is not ready.

@@ -306,18 +323,22 @@ Returns:
     return EFI_SUCCESS;

   } else {

     DataSize = sizeof (TempData);

-    Status = IpmiSendCommand (

-               &IpmiInstance->IpmiTransport,

-               IPMI_NETFN_FIRMWARE, 0,

-               IPMI_GET_BMC_EXECUTION_CONTEXT,

-               NULL, 0,

-               TempData, &DataSize

-               );

-

-    pBmcExecContext = (IPMI_MSG_GET_BMC_EXEC_RSP*)&TempData[0];

+    Status   = IpmiSendCommand (

+                                &IpmiInstance->IpmiTransport,

+                                IPMI_NETFN_FIRMWARE,

+                                0,

+                                IPMI_GET_BMC_EXECUTION_CONTEXT,

+                                NULL,

+                                0,

+                                TempData,

+                                &DataSize

+                                );

+

+    pBmcExecContext = (IPMI_MSG_GET_BMC_EXEC_RSP *)&TempData[0];

     DEBUG ((DEBUG_INFO, "[IPMI] Operational status of BMC: 0x%x\n", pBmcExecContext->CurrentExecutionContext));

     if ((pBmcExecContext->CurrentExecutionContext == IPMI_BMC_IN_FORCED_UPDATE_MODE) &&

-        !EFI_ERROR (Status)) {

+        !EFI_ERROR (Status))

+    {

       DEBUG ((DEBUG_ERROR, "[IPMI] BMC in Forced Update mode, skip waiting for BMC_READY.\n"));

       IpmiInstance->BmcStatus = BMC_UPDATE_IN_PROGRESS;

     } else {

@@ -325,32 +346,174 @@ Returns:
       // Updatemode = 1 mean BMC is not ready, continue waiting.

       //

       while (Retries-- != 0) {

-        MicroSecondDelay(1*1000*1000); //delay 1 seconds

-        DEBUG ((EFI_D_ERROR, "[IPMI] UpdateMode Retries: %d \n",Retries));

+        MicroSecondDelay (1*1000*1000); // delay 1 seconds

+        DEBUG ((EFI_D_ERROR, "[IPMI] UpdateMode Retries: %d \n", Retries));

         DataSize = sizeof (TempData);

-        Status = IpmiSendCommand (

-                   &IpmiInstance->IpmiTransport,

-                   IPMI_NETFN_APP, 0,

-                   IPMI_APP_GET_DEVICE_ID,

-                   NULL, 0,

-                   TempData, &DataSize

-                   );

+        Status   = IpmiSendCommand (

+                                    &IpmiInstance->IpmiTransport,

+                                    IPMI_NETFN_APP,

+                                    0,

+                                    IPMI_APP_GET_DEVICE_ID,

+                                    NULL,

+                                    0,

+                                    TempData,

+                                    &DataSize

+                                    );



         if (!EFI_ERROR (Status)) {

-          pBmcInfo = (SM_CTRL_INFO*)&TempData[0];

-          DEBUG ((DEBUG_ERROR, "[IPMI] UpdateMode Retries: %d   pBmcInfo->UpdateMode:%x, Status: %r, Response Data: 0x%lx\n",Retries, pBmcInfo->UpdateMode, Status, TempData));

+          pBmcInfo = (SM_CTRL_INFO *)&TempData[0];

+          DEBUG ((DEBUG_ERROR, "[IPMI] UpdateMode Retries: %d   pBmcInfo->UpdateMode:%x, Status: %r, Response Data: 0x%lx\n", Retries, pBmcInfo->UpdateMode, Status, TempData));

           if (pBmcInfo->UpdateMode == BMC_READY) {

             mIpmiInstance->BmcStatus = BMC_OK;

             return EFI_SUCCESS;

           }

         }

       }

+

       mIpmiInstance->BmcStatus = BMC_HARDFAIL;

     }

   }

+

   return Status;

 } // GetDeviceId()



+/*++

+

+Routine Description:

+  Initialize the API and parameters for IPMI Transport2 Instance

+

+Arguments:

+  IpmiInstance - Pointer to IPMI Instance.

+

+Returns:

+  VOID

+

+--*/

+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 (FixedPcdGet8 (PcdBtInterfaceSupport) == 1) {

+    InitBtInterfaceData (&IpmiInstance->IpmiTransport2);

+  }

+

+  if (FixedPcdGet8 (PcdSsifInterfaceSupport) == 1) {

+    InitSsifInterfaceData (&IpmiInstance->IpmiTransport2);

+  }

+

+  if (FixedPcdGet8 (PcdIpmbInterfaceSupport) == 1) {

+    InitIpmbInterfaceData (&IpmiInstance->IpmiTransport2);

+  }

+}

+

+/*++

+

+Routine Description:

+  Notify call back function.

+

+Arguments:

+  Event      - Event which caused this handler.

+  Context    - Context passed during Event Handler registration.

+

+Returns:

+  VOID

+

+--*/

+VOID

+EFIAPI

+DxeNotifyCallback (

+  IN EFI_EVENT  Event,

+  IN VOID       *Context

+  )

+{

+  EFI_STATUS            Status;

+  IPMI_INTERFACE_STATE  InterfaceState;

+  EFI_HANDLE            Handle;

+

+  InterfaceState = IpmiInterfaceNotReady;

+

+  if (FixedPcdGet8 (PcdSsifInterfaceSupport) == 1) {

+    InitSsifInterfaceData (&mIpmiInstance->IpmiTransport2);

+

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

+      InterfaceState = IpmiInterfaceInitialized;

+    }

+  }

+

+  if (FixedPcdGet8 (PcdIpmbInterfaceSupport) == 1) {

+    InitIpmbInterfaceData (&mIpmiInstance->IpmiTransport2);

+

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

+      InterfaceState = IpmiInterfaceInitialized;

+    }

+  }

+

+  // 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);

+}

+

+/*++

+

+Routine Description:

+  Registers protocol notify call back.

+

+Arguments:

+  ProtocolGuid      - Pointer to Protocol Guid to register call back.

+

+Returns:

+  Status

+

+--*/

+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.

@@ -368,18 +531,20 @@ Returns:
  **/

 EFI_STATUS

 InitializeIpmiKcsPhysicalLayer (

-  IN EFI_HANDLE             ImageHandle,

-  IN EFI_SYSTEM_TABLE       *SystemTable

+  IN EFI_HANDLE        ImageHandle,

+  IN EFI_SYSTEM_TABLE  *SystemTable

   )

 {

   EFI_STATUS             Status;

   UINT8                  ErrorCount;

   EFI_HANDLE             Handle;

   UINT8                  Index;

+  IPMI_INTERFACE_STATE   InterfaceState = IpmiInterfaceNotReady;

   EFI_STATUS_CODE_VALUE  StatusCodeValue[MAX_SOFT_COUNT];



-  ErrorCount = 0;

+  ErrorCount   = 0;

   mImageHandle = ImageHandle;

+  ZeroMem (StatusCodeValue, MAX_SOFT_COUNT);



   mIpmiInstance = AllocateZeroPool (sizeof (*mIpmiInstance));

   if (mIpmiInstance == NULL) {

@@ -396,66 +561,150 @@ InitializeIpmiKcsPhysicalLayer (
     // Initialize the KCS transaction timeout.

     //

     mIpmiInstance->KcsTimeoutPeriod = (BMC_KCS_TIMEOUT * 1000*1000) / KCS_DELAY_UNIT;

-    DEBUG ((EFI_D_ERROR, "[IPMI] mIpmiInstance->KcsTimeoutPeriod: 0x%lx\n",mIpmiInstance->KcsTimeoutPeriod));

+    DEBUG ((EFI_D_ERROR, "[IPMI] mIpmiInstance->KcsTimeoutPeriod: 0x%lx\n", mIpmiInstance->KcsTimeoutPeriod));



     //

     // Initialize IPMI IO Base.

     //

-    mIpmiInstance->IpmiIoBase                       = PcdGet16 (PcdIpmiIoBaseAddress);

-    mIpmiInstance->Signature                        = SM_IPMI_BMC_SIGNATURE;

-    mIpmiInstance->SlaveAddress                     = BMC_SLAVE_ADDRESS;

-    mIpmiInstance->BmcStatus                        = BMC_NOTREADY;

-    mIpmiInstance->IpmiTransport.IpmiSubmitCommand  = IpmiSendCommand;

-    mIpmiInstance->IpmiTransport.GetBmcStatus       = IpmiGetBmcStatus;

+    mIpmiInstance->IpmiIoBase   = PcdGet16 (PcdIpmiIoBaseAddress);

+    mIpmiInstance->Signature    = SM_IPMI_BMC_SIGNATURE;

+    mIpmiInstance->SlaveAddress = BMC_SLAVE_ADDRESS;

+    mIpmiInstance->BmcStatus    = BMC_NOTREADY;

+

+    if (FixedPcdGet8 (PcdKcsInterfaceSupport) == 1) {

+      mIpmiInstance->IpmiTransport.IpmiSubmitCommand = IpmiSendCommand;

+      mIpmiInstance->IpmiTransport.GetBmcStatus      = IpmiGetBmcStatus;



-    //

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

-    //

-    Status = GetDeviceId (

-               mIpmiInstance,

-               StatusCodeValue,

-               &ErrorCount

-               );

-    //

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

-    //

-    if ((mIpmiInstance->BmcStatus != BMC_UPDATE_IN_PROGRESS) &&

-        (mIpmiInstance->BmcStatus != BMC_HARDFAIL)) {

       //

-      // Get the SELF TEST Results.

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

       //

-      Status = GetSelfTest (

-                 mIpmiInstance,

-                 StatusCodeValue,

-                 &ErrorCount

-                 );

+      Status = GetDeviceId (

+                            mIpmiInstance,

+                            StatusCodeValue,

+                            &ErrorCount

+                            );

+      //

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

+      //

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

+          (mIpmiInstance->BmcStatus != BMC_HARDFAIL))

+      {

+        //

+        // Get the SELF TEST Results.

+        //

+        Status = GetSelfTest (

+                              mIpmiInstance,

+                              StatusCodeValue,

+                              &ErrorCount

+                              );

+      }

+

+      //

+      // iterate through the errors reporting them to the error manager.

+      //

+      for (Index = 0; Index < ErrorCount; Index++) {

+        ReportStatusCode (

+                          EFI_ERROR_CODE | EFI_ERROR_MAJOR,

+                          StatusCodeValue[Index]

+                          );

+      }

+

+      //

+      // Now install the Protocol if the BMC is not in a HardFail State and not in Force Update mode

+      //

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

+        Handle = NULL;

+        Status = gBS->InstallProtocolInterface (

+                                                &Handle,

+                                                &gIpmiTransportProtocolGuid,

+                                                EFI_NATIVE_INTERFACE,

+                                                &mIpmiInstance->IpmiTransport

+                                                );

+        ASSERT_EFI_ERROR (Status);

+      }

     }



-    //

-    // iterate through the errors reporting them to the error manager.

-    //

-    for (Index = 0; Index < ErrorCount; Index++) {

-      ReportStatusCode (

-        EFI_ERROR_CODE | EFI_ERROR_MAJOR,

-        StatusCodeValue[Index]

-        );

+    // Initialise the IPMI transport2

+    InitIpmiTransport2 (mIpmiInstance);

+

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

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

+      switch (Index) {

+      if (FixedPcdGet8 (PcdKcsInterfaceSupport) == 1) {

+          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;

+      }

+

+      if (FixedPcdGet8 (PcdBtInterfaceSupport) == 1) {

+          case SysInterfaceBt:

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

+              InterfaceState = IpmiInterfaceInitialized;

+            }

+

+            break;

+      }

+

+      if (FixedPcdGet8 (PcdSsifInterfaceSupport) == 1) {

+          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;

+      }

+

+      if (FixedPcdGet8 (PcdIpmbInterfaceSupport) == 1) {

+          case SysInterfaceIpmb:

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

+              InterfaceState = IpmiInterfaceInitialized;

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

+              // Register Protocol notify for I2C Protocol.

+              Status = DxeRegisterProtocolCallback (

+                                                    &mIpmiInstance->IpmiTransport2.Interface.Ipmb.IpmbInterfaceApiGuid

+                                                    );

+            }

+

+            break;

+      }

+

+        default:

+          break;

+      }

     }



-    //

-    // Now install the Protocol if the BMC is not in a HardFail State and not in Force Update mode

-    //

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

-      Handle = NULL;

-      Status = gBS->InstallProtocolInterface (

-                      &Handle,

-                      &gIpmiTransportProtocolGuid,

-                      EFI_NATIVE_INTERFACE,

-                      &mIpmiInstance->IpmiTransport

-                      );

-      ASSERT_EFI_ERROR (Status);

+    // 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/Smm/SmmGenericIpmi.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Smm/SmmGenericIpmi.c
index 1af2d18f79..350bc74003 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,17 +25,18 @@
 #include "IpmiBmcCommon.h"

 #include "IpmiBmc.h"

 #include <Library/TimerLib.h>

+#include <Library/BmcCommonInterfaceLib.h>



-IPMI_BMC_INSTANCE_DATA             *mIpmiInstance;

-EFI_HANDLE                         mImageHandle;

-

+IPMI_BMC_INSTANCE_DATA  *mIpmiInstance;

+EFI_HANDLE              mImageHandle;



 EFI_STATUS

 GetDeviceId (

-  IN      IPMI_BMC_INSTANCE_DATA       *IpmiInstance,

-  IN      EFI_STATUS_CODE_VALUE        StatusCodeValue[ ],

-  IN OUT  UINT8                        *ErrorCount

+  IN      IPMI_BMC_INSTANCE_DATA  *IpmiInstance,

+  IN      EFI_STATUS_CODE_VALUE   StatusCodeValue[],

+  IN OUT  UINT8                   *ErrorCount

   )

+

 /*++



 Routine Description:

@@ -51,12 +53,12 @@ Returns:


 --*/

 {

-  EFI_STATUS               Status;

-  UINT32                   DataSize;

-  SM_CTRL_INFO             *ControllerInfo;

-  UINT8                    TimeOut;

-  UINT8                    Retries;

-  UINT8                    TempData[MAX_TEMP_DATA];

+  EFI_STATUS    Status;

+  UINT32        DataSize;

+  SM_CTRL_INFO  *ControllerInfo;

+  UINT8         TimeOut;

+  UINT8         Retries;

+  UINT8         TempData[MAX_TEMP_DATA];



   TimeOut = 0;

   Retries = PcdGet8 (PcdIpmiBmcReadyDelayTimer);

@@ -66,16 +68,16 @@ Returns:
     // Get the device ID information for the BMC.

     //

     DataSize = MAX_TEMP_DATA;

-    Status = IpmiSendCommand (

-               &IpmiInstance->IpmiTransport,

-               IPMI_NETFN_APP,

-               0,

-               IPMI_APP_GET_DEVICE_ID,

-               NULL,

-               0,

-               TempData,

-               &DataSize

-               );

+    Status   = IpmiSendCommand (

+                                &IpmiInstance->IpmiTransport,

+                                IPMI_NETFN_APP,

+                                0,

+                                IPMI_APP_GET_DEVICE_ID,

+                                NULL,

+                                0,

+                                TempData,

+                                &DataSize

+                                );

     if (Status == EFI_SUCCESS) {

       DEBUG ((EFI_D_INFO, "IPMI: SendCommand success!\n"));

       break;

@@ -84,10 +86,10 @@ Returns:
       // Display message and retry.

       //

       DEBUG (

-        (EFI_D_ERROR | EFI_D_INFO,

-         "IPMI: Waiting for BMC (KCS 0x%x)...\n",

-         IpmiInstance->IpmiIoBase)

-        );

+             (EFI_D_ERROR | EFI_D_INFO,

+              "IPMI: Waiting for BMC (KCS 0x%x)...\n",

+              IpmiInstance->IpmiIoBase)

+             );

       MicroSecondDelay (500 * 1000);

       TimeOut++;

     }

@@ -97,7 +99,7 @@ Returns:
   // If there is no error then proceed to check the data returned by the BMC

   //

   if (!EFI_ERROR (Status)) {

-    ControllerInfo = (SM_CTRL_INFO *) TempData;

+    ControllerInfo = (SM_CTRL_INFO *)TempData;

     //

     // If the controller is in Update Mode and the maximum number of errors has not been exceeded, then

     // save the error code to the StatusCode array and increment the counter.  Set the BMC Status to indicate

@@ -115,11 +117,143 @@ Returns:
   return Status;

 }



+/*++

+

+Routine Description:

+  Initialize the API and parameters for IPMI Transport2 Instance

+

+Arguments:

+  IpmiInstance    - Pointer to IPMI Instance.

+

+Returns:

+  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 (FixedPcdGet8 (PcdBtInterfaceSupport) == 1) {

+    InitBtInterfaceData (&IpmiInstance->IpmiTransport2);

+  }

+

+  if (FixedPcdGet8 (PcdSsifInterfaceSupport) == 1) {

+    InitSsifInterfaceData (&IpmiInstance->IpmiTransport2);

+  }

+

+  if (FixedPcdGet8 (PcdIpmbInterfaceSupport) == 1) {

+    InitIpmbInterfaceData (&IpmiInstance->IpmiTransport2);

+  }

+}

+

+/*++

+

+Routine Description:

+  Notify call back to initialize the interfaces and install SMM IPMI

+  protocol.

+

+Arguments:

+  Protocol    - Pointer to the protocol guid.

+  Interface   - Pointer to the protocol instance.

+  Handle      - Handle on which the protocol is installed.

+

+Returns:

+  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 (FixedPcdGet8 (PcdSsifInterfaceSupport) == 1) {

+    InitSsifInterfaceData (&mIpmiInstance->IpmiTransport2);

+

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

+      InterfaceState = IpmiInterfaceInitialized;

+    }

+  }

+

+  if (FixedPcdGet8 (PcdIpmbInterfaceSupport) == 1) {

+    InitIpmbInterfaceData (&mIpmiInstance->IpmiTransport2);

+  }

+

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

+    InterfaceState = IpmiInterfaceInitialized;

+  }

+

+  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;

+}

+

+/*++

+

+Routine Description:

+  Registers Protocol call back.

+

+Arguments:

+  ProtocolGuid    - Pointer to Protocol GUID to register call back.

+

+Returns:

+  Status.

+

+--*/

+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,

-  IN EFI_SYSTEM_TABLE       *SystemTable

+  IN EFI_HANDLE        ImageHandle,

+  IN EFI_SYSTEM_TABLE  *SystemTable

   )

+

 /*++



 Routine Description:

@@ -138,14 +272,17 @@ Returns:


 --*/

 {

-  EFI_STATUS                       Status;

-  UINT8                            ErrorCount;

-  EFI_HANDLE                       Handle;

-  EFI_STATUS_CODE_VALUE            StatusCodeValue[MAX_SOFT_COUNT];

+  EFI_STATUS             Status;

+  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;

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

+  ErrorCount     = 0;

+  mImageHandle   = ImageHandle;

+  InterfaceState = IpmiInterfaceNotReady;



   mIpmiInstance = AllocateZeroPool (sizeof (IPMI_BMC_INSTANCE_DATA));

   ASSERT (mIpmiInstance != NULL);

@@ -154,7 +291,6 @@ Returns:
     ASSERT_EFI_ERROR (EFI_OUT_OF_RESOURCES);

     return EFI_OUT_OF_RESOURCES;

   } else {

-

     //

     // Initialize the KCS transaction timeout. Assume delay unit is 1000 us.

     //

@@ -163,36 +299,115 @@ Returns:
     //

     // Initialize IPMI IO Base, we still use SMS IO base to get device ID and Seltest result since SMM IF may have different cmds supported

     //

-    mIpmiInstance->IpmiIoBase                       = PcdGet16 (PcdIpmiSmmIoBaseAddress);

-    mIpmiInstance->Signature                        = SM_IPMI_BMC_SIGNATURE;

-    mIpmiInstance->SlaveAddress                     = BMC_SLAVE_ADDRESS;

-    mIpmiInstance->BmcStatus                        = BMC_NOTREADY;

-    mIpmiInstance->IpmiTransport.IpmiSubmitCommand  = IpmiSendCommand;

-    mIpmiInstance->IpmiTransport.GetBmcStatus       = IpmiGetBmcStatus;

-

-    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.

-    //

-    // Just obey the Spec..

-    // If we want to improve performance, we're going to comment it.

-    //

-    Status = GetDeviceId (

-               mIpmiInstance,

-               StatusCodeValue,

-               &ErrorCount

-               );

-    ASSERT_EFI_ERROR (Status);

-    Handle = NULL;

-    Status = gSmst->SmmInstallProtocolInterface (

-                      &Handle,

-                      &gSmmIpmiTransportProtocolGuid,

-                      EFI_NATIVE_INTERFACE,

-                      &mIpmiInstance->IpmiTransport

-                      );

-    ASSERT_EFI_ERROR (Status);

+    mIpmiInstance->IpmiIoBase                      = PcdGet16 (PcdIpmiSmmIoBaseAddress);

+    mIpmiInstance->Signature                       = SM_IPMI_BMC_SIGNATURE;

+    mIpmiInstance->SlaveAddress                    = BMC_SLAVE_ADDRESS;

+    mIpmiInstance->BmcStatus                       = BMC_NOTREADY;

+    mIpmiInstance->IpmiTransport.IpmiSubmitCommand = IpmiSendCommand;

+    mIpmiInstance->IpmiTransport.GetBmcStatus      = IpmiGetBmcStatus;

+

+    if (FixedPcdGet8 (PcdKcsInterfaceSupport) == 1) {

+      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.

+      //

+      // Just obey the Spec..

+      // If we want to improve performance, we're going to comment it.

+      //

+      Status = GetDeviceId (

+                            mIpmiInstance,

+                            StatusCodeValue,

+                            &ErrorCount

+                            );

+      ASSERT_EFI_ERROR (Status);

+      Handle = NULL;

+      Status = gSmst->SmmInstallProtocolInterface (

+                                                   &Handle,

+                                                   &gSmmIpmiTransportProtocolGuid,

+                                                   EFI_NATIVE_INTERFACE,

+                                                   &mIpmiInstance->IpmiTransport

+                                                   );

+      ASSERT_EFI_ERROR (Status);

+    }

+

+    InitIpmiTransport2 (mIpmiInstance);

+

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

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

+      switch (Index) {

+      if (FixedPcdGet8 (PcdKcsInterfaceSupport) == 1) {

+          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;

+      }

+

+      if (FixedPcdGet8 (PcdBtInterfaceSupport) == 1) {

+          case SysInterfaceBt:

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

+              InterfaceState = IpmiInterfaceInitialized;

+            }

+

+            break;

+      }

+

+      if (FixedPcdGet8 (PcdSsifInterfaceSupport) == 1) {

+          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;

+      }

+

+      if (FixedPcdGet8 (PcdIpmbInterfaceSupport) == 1) {

+          case SysInterfaceIpmb:

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

+              InterfaceState = IpmiInterfaceInitialized;

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

+              // Register protocol notify for SMBUS Protocol.

+              Status = SmmRegisterProtocolCallback (&mIpmiInstance->IpmiTransport2.Interface.Ipmb.IpmbInterfaceApiGuid);

+            }

+

+            break;

+      }

+

+        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"));

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



     return EFI_SUCCESS;

   }

@@ -200,8 +415,8 @@ Returns:


 EFI_STATUS

 InitializeSmmGenericIpmi (

-  IN EFI_HANDLE             ImageHandle,

-  IN EFI_SYSTEM_TABLE       *SystemTable

+  IN EFI_HANDLE        ImageHandle,

+  IN EFI_SYSTEM_TABLE  *SystemTable

   )

 {

   SmmInitializeIpmiKcsPhysicalLayer (ImageHandle, SystemTable);

diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Smm/SmmGenericIpmi.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Smm/SmmGenericIpmi.inf
index f430195d1e..12dc17ae84 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,26 @@
   IoLib

   ReportStatusCodeLib

   TimerLib

+  BmcCommonInterfaceLib

+  BtInterfaceLib

+  SsifInterfaceLib

+  IpmbInterfaceLib



 [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

+  gIpmiFeaturePkgTokenSpaceGuid.PcdIpmbInterfaceSupport



 [Depex]

  gIpmiTransportProtocolGuid

--
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.







-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#107464): https://edk2.groups.io/g/devel/message/107464
Mute This Topic: https://groups.io/mt/100352689/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
Re: [edk2-devel] [edk2-platforms][PATCH V5-2] IpmiFeaturePkg:Provided multiple IPMI interface support in DXE and SMM
Posted by Isaac Oram 9 months ago
Pushed as 3037c13015016f7c398da37eabe33fb0961dc490

Note I fixed PatchCheck.py issues and committed in an order that doesn't break git bisect.


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#107473): https://edk2.groups.io/g/devel/message/107473
Mute This Topic: https://groups.io/mt/100352689/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-