[edk2-devel][edk2-platforms][PATCH V5-1] IpmiFeaturePkg:Provided multiple IPMI interface support in PEI

Arun K via groups.io posted 1 patch 9 months ago
Failed in applying to current master (apply log)
.../GenericIpmi/Pei/PeiGenericIpmi.c          | 550 +++++++++++++-----
.../GenericIpmi/Pei/PeiGenericIpmi.h          |  75 ++-
.../GenericIpmi/Pei/PeiGenericIpmi.inf        |  17 +
.../GenericIpmi/Pei/PeiIpmiBmc.c              | 117 ++--
.../GenericIpmi/Pei/PeiIpmiBmc.h              |  11 +-
.../GenericIpmi/Pei/PeiIpmiBmcDef.h           |  86 +--
.../GenericIpmi/Pei/PeiIpmiHooks.c            | 346 +++++++++++
.../GenericIpmi/Pei/PeiIpmiHooks.h            | 218 +++++++
8 files changed, 1159 insertions(+), 261 deletions(-)
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiHooks.c
create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiHooks.h
[edk2-devel][edk2-platforms][PATCH V5-1] IpmiFeaturePkg:Provided multiple IPMI interface support in PEI
Posted by Arun K via groups.io 9 months 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/Pei/PeiGenericIpmi.c          | 550 +++++++++++++-----
 .../GenericIpmi/Pei/PeiGenericIpmi.h          |  75 ++-
 .../GenericIpmi/Pei/PeiGenericIpmi.inf        |  17 +
 .../GenericIpmi/Pei/PeiIpmiBmc.c              | 117 ++--
 .../GenericIpmi/Pei/PeiIpmiBmc.h              |  11 +-
 .../GenericIpmi/Pei/PeiIpmiBmcDef.h           |  86 +--
 .../GenericIpmi/Pei/PeiIpmiHooks.c            | 346 +++++++++++
 .../GenericIpmi/Pei/PeiIpmiHooks.h            | 218 +++++++
 8 files changed, 1159 insertions(+), 261 deletions(-)
 create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiHooks.c
 create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiHooks.h

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


   @copyright

   Copyright 2017 - 2021 Intel Corporation. <BR>

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

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

 **/



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

 #include <Library/ReportStatusCodeLib.h>

 #include <Library/IpmiPlatformHookLib.h>

+#include <Library/BmcCommonInterfaceLib.h>



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

-// Function Implementations

-//

+

+static EFI_PEI_NOTIFY_DESCRIPTOR  mNotifyList = {

+  EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,

+  &gEfiPeiMemoryDiscoveredPpiGuid,

+  UpdateIpmiInstancePtr

+};

+

+/**

+    Initialize the API and parameters for IPMI Transport2 Instance

+

+    @param[in] IpmiInstance         Pointer to IPMI Instance

+

+    @return VOID

+

+**/

+VOID

+InitIpmiTransport2 (

+  IN  PEI_IPMI_BMC_INSTANCE_DATA  *IpmiInstance

+  )

+{

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

+  IpmiInstance->IpmiTransport2Ppi.IpmiTransport2BmcStatus = BmcStatusOk;

+  IpmiInstance->IpmiTransport2Ppi.IpmiSubmitCommand2      = PeiIpmiSendCommand2;

+  IpmiInstance->IpmiTransport2Ppi.IpmiSubmitCommand2Ex    = PeiIpmiSendCommand2Ex;

+

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

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

+      InitBtInterfaceData (&IpmiInstance->IpmiTransport2Ppi);

+    }

+  }

+

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

+    InitSsifInterfaceData (&IpmiInstance->IpmiTransport2Ppi);

+  }

+

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

+    InitIpmbInterfaceData (&IpmiInstance->IpmiTransport2Ppi);

+  }

+}

+

+/*++

+

+Routine Description:

+  Notify callback function for interfaces.

+

+Arguments:

+  PeiServices      - Describes the list of possible PEI Services.

+  NotifyDescriptor - Pointer to notify descriptor.

+  Ppi              - Pointer to Ppi.

+

+Returns:

+  Status

+

+--*/

+EFI_STATUS

+EFIAPI

+NotifyCallback (

+  IN EFI_PEI_SERVICES           **PeiServices,

+  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,

+  IN VOID                       *Ppi

+  )

+{

+  EFI_STATUS                  Status;

+  PEI_IPMI_BMC_INSTANCE_DATA  *IpmiInstance;

+  PEI_IPMI_DATA_HOB           *IpmiInstancePtrHob;

+  EFI_HOB_GUID_TYPE           *GuidHob;

+  IPMI_INTERFACE_STATE        InterfaceState;

+

+  InterfaceState = IpmiInterfaceNotReady;

+

+  GuidHob = GetFirstGuidHob (&gPeiIpmiHobGuid);

+  ASSERT (GuidHob != NULL);

+  if (GuidHob == NULL) {

+    return EFI_NOT_FOUND;

+  }

+

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

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

+

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

+    InitSsifInterfaceData (&IpmiInstance->IpmiTransport2Ppi);

+

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

+      InterfaceState = IpmiInterfaceInitialized;

+    }

+  }

+

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

+    InitIpmbInterfaceData (&IpmiInstance->IpmiTransport2Ppi);

+

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

+      InterfaceState = IpmiInterfaceInitialized;

+    }

+  }

+

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

+  if (InterfaceState != IpmiInterfaceInitialized) {

+    return EFI_UNSUPPORTED;

+  }

+

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

+  return Status;

+}

+

+/*++

+

+Routine Description:

+  Registers callback for Ppi.

+

+Arguments:

+  PeiServices      - Describes the list of possible PEI Services.

+  PpiGuid          - Pointer to Ppi guid to register call back.

+

+Returns:

+  Status

+

+--*/

+EFI_STATUS

+RegisterPpiCallback (

+  IN CONST EFI_PEI_SERVICES  **PeiServices,

+  IN       EFI_GUID          *PpiGuid

+  )

+{

+  EFI_STATUS                 Status;

+  EFI_PEI_NOTIFY_DESCRIPTOR  *PpiNotifyDesc;

+

+  if ((PpiGuid == NULL) ||

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

+  {

+    return EFI_INVALID_PARAMETER;

+  }

+

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

+  if (PpiNotifyDesc == NULL) {

+    return EFI_OUT_OF_RESOURCES;

+  }

+

+  PpiNotifyDesc->Flags  = EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;

+  PpiNotifyDesc->Guid   = PpiGuid;

+  PpiNotifyDesc->Notify = NotifyCallback;

+

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

+  return Status;

+}

+

+/*++

+

+Routine Description:

+  After memory is discovered, update the IPMI Instance pointer in Hob.

+

+Arguments:

+  PeiServices      - Describes the list of possible PEI Services.

+  NotifyDescriptor - PPointer to notify descriptor..

+  Ppi              - Pointer to Ppi.

+

+Returns:

+  Status

+

+--*/

+EFI_STATUS

+EFIAPI

+UpdateIpmiInstancePtr (

+  IN EFI_PEI_SERVICES           **PeiServices,

+  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,

+  IN VOID                       *Ppi

+  )

+{

+  PEI_IPMI_BMC_INSTANCE_DATA  *IpmiInstance;

+  PEI_IPMI_DATA_HOB           *IpmiInstancePtrHob;

+  EFI_HOB_GUID_TYPE           *GuidHob;

+

+  GuidHob = GetFirstGuidHob (&gPeiIpmiHobGuid);

+

+  ASSERT (GuidHob != NULL);

+  if (GuidHob == NULL) {

+    return EFI_NOT_FOUND;

+  }

+

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

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

+

+  if (!IpmiInstance) {

+    return EFI_ABORTED;

+  }

+

+  DEBUG ((DEBUG_INFO, "IpmiInstance Signature in CAR Memory: %x\n", IpmiInstance->Signature));

+

+  if ((UINTN)IpmiInstancePtrHob >= (UINTN)IpmiInstancePtrHob->PreMemIpmiDataHobPtr) {

+    IpmiInstance = (PEI_IPMI_BMC_INSTANCE_DATA *)((UINT8 *)IpmiInstance + \

+                                                  (UINTN)((UINTN)IpmiInstancePtrHob - (UINTN)IpmiInstancePtrHob->PreMemIpmiDataHobPtr));

+  } else {

+    IpmiInstance = (PEI_IPMI_BMC_INSTANCE_DATA *)((UINT8 *)IpmiInstance - \

+                                                  (UINTN)((UINTN)IpmiInstancePtrHob->PreMemIpmiDataHobPtr - (UINTN)IpmiInstancePtrHob));

+  }

+

+  IpmiInstancePtrHob->IpmiInstance = (UINTN)IpmiInstance;

+  DEBUG ((DEBUG_INFO, "IpmiInstance Signature after Permanent Memory discovered: %x\n", IpmiInstance->Signature));

+  return EFI_SUCCESS;

+}



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

  @brief

@@ -26,13 +225,17 @@
 EFI_STATUS

 EFIAPI

 PeiInitializeIpmiKcsPhysicalLayer (

-  IN CONST EFI_PEI_SERVICES             **PeiServices

+  IN CONST EFI_PEI_SERVICES  **PeiServices

   )

 {

-  EFI_STATUS                       Status;

-  PEI_IPMI_BMC_INSTANCE_DATA       *mIpmiInstance;

+  EFI_STATUS                  Status;

+  PEI_IPMI_BMC_INSTANCE_DATA  *mIpmiInstance;

+  PEI_IPMI_DATA_HOB           *IpmiInstancePtrHob;

+  IPMI_INTERFACE_STATE        InterfaceState;

+  UINT8                       Index;



-  mIpmiInstance = NULL;

+  mIpmiInstance  = NULL;

+  InterfaceState = IpmiInterfaceNotReady;



   //

   // Send Pre-Boot signal to BMC

@@ -50,63 +253,166 @@ PeiInitializeIpmiKcsPhysicalLayer (
   //

   Status = PlatformIpmiIoRangeSet (PcdGet16 (PcdIpmiIoBaseAddress));

   DEBUG ((DEBUG_INFO, "IPMI Peim:PlatformIpmiIoRangeSet - %r!\n", Status));

-  if (EFI_ERROR(Status)) {

+  if (EFI_ERROR (Status)) {

     return Status;

   }



   mIpmiInstance = AllocateZeroPool (sizeof (PEI_IPMI_BMC_INSTANCE_DATA));

   if (mIpmiInstance == NULL) {

-    DEBUG ((EFI_D_ERROR,"IPMI Peim:EFI_OUT_OF_RESOURCES of memory allocation\n"));

+    DEBUG ((EFI_D_ERROR, "IPMI Peim:EFI_OUT_OF_RESOURCES of memory allocation\n"));

     return EFI_OUT_OF_RESOURCES;

   }



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

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

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

+    if (IpmiInstancePtrHob == NULL) {

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

+      FreePool (mIpmiInstance);

+      return EFI_OUT_OF_RESOURCES;

+    }

+

+    IpmiInstancePtrHob->IpmiInstance         = (UINTN)mIpmiInstance;

+    IpmiInstancePtrHob->PreMemIpmiDataHobPtr = IpmiInstancePtrHob;

+

+    // Check for Memory initialization

+    Status = (*PeiServices)->LocatePpi (

+                                        PeiServices,

+                                        &gEfiPeiMemoryDiscoveredPpiGuid,

+                                        0,

+                                        NULL,

+                                        NULL

+                                        );

+

+    if (EFI_ERROR (Status)) {

+      /* Register Memory discovered PPI call back to update HOB with new

+      IpmiInstance pointer.*/

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

+      if (EFI_ERROR (Status)) {

+        FreePool (mIpmiInstance);

+        return Status;

+      }

+    }

+  }

+

   //

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

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

   //

-  DEBUG ((DEBUG_INFO,"IPMI Peim:IPMI STACK Initialization\n"));

+  DEBUG ((DEBUG_INFO, "IPMI Peim:IPMI STACK Initialization\n"));

   mIpmiInstance->KcsTimeoutPeriod = (BMC_KCS_TIMEOUT_PEI *1000*1000) / KCS_DELAY_UNIT_PEI;

-  DEBUG ((EFI_D_INFO,"IPMI Peim:KcsTimeoutPeriod = 0x%x\n", mIpmiInstance->KcsTimeoutPeriod));

+  DEBUG ((EFI_D_INFO, "IPMI Peim:KcsTimeoutPeriod = 0x%x\n", mIpmiInstance->KcsTimeoutPeriod));



   //

   // Initialize IPMI IO Base.

   //

-  mIpmiInstance->IpmiIoBase                         = PcdGet16 (PcdIpmiIoBaseAddress);

-  DEBUG ((EFI_D_INFO,"IPMI Peim:IpmiIoBase=0x%x\n",mIpmiInstance->IpmiIoBase));

+  mIpmiInstance->IpmiIoBase = PcdGet16 (PcdIpmiIoBaseAddress);

+  DEBUG ((EFI_D_INFO, "IPMI Peim:IpmiIoBase=0x%x\n", mIpmiInstance->IpmiIoBase));

   mIpmiInstance->Signature                          = SM_IPMI_BMC_SIGNATURE;

   mIpmiInstance->SlaveAddress                       = BMC_SLAVE_ADDRESS;

   mIpmiInstance->BmcStatus                          = BMC_NOTREADY;

   mIpmiInstance->IpmiTransportPpi.IpmiSubmitCommand = PeiIpmiSendCommand;

   mIpmiInstance->IpmiTransportPpi.GetBmcStatus      = PeiGetIpmiBmcStatus;



-  mIpmiInstance->PeiIpmiBmcDataDesc.Flags         = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;

-  mIpmiInstance->PeiIpmiBmcDataDesc.Guid          = &gPeiIpmiTransportPpiGuid;

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

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

+  mIpmiInstance->PeiIpmiBmcDataDesc.Guid  = &gPeiIpmiTransportPpiGuid;

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



-  //

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

-  //

-  Status = GetDeviceId (mIpmiInstance);

-  if (EFI_ERROR (Status)) {

-    DEBUG ((EFI_D_ERROR,"IPMI Peim:Get BMC Device Id Failed. Status=%r\n",Status));

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

+    //

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

+    //

+    Status = GetDeviceId (mIpmiInstance);

+    if (EFI_ERROR (Status)) {

+      DEBUG ((EFI_D_ERROR, "IPMI Peim:Get BMC Device Id Failed. Status=%r\n", Status));

+    }

+

+    //

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

+    //

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

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

+      if (EFI_ERROR (Status)) {

+        return Status;

+      }

+    }

   }



-  //

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

-  //

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

-    return EFI_UNSUPPORTED;

+  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->IpmiTransport2Ppi.Interface.KcsInterfaceState = IpmiInterfaceInitialized;

+            Status                                                       = CheckSelfTestByInterfaceType (

+                                                                                                         &mIpmiInstance->IpmiTransport2Ppi,

+                                                                                                         &BmcStatus,

+                                                                                                         SysInterfaceKcs

+                                                                                                         );

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

+              InterfaceState = IpmiInterfaceInitialized;

+            } else {

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

+            }

+          }

+

+          break;

+    }

+

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

+        case SysInterfaceBt:

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

+            InterfaceState = IpmiInterfaceInitialized;

+          }

+

+          break;

+    }

+

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

+        case SysInterfaceSsif:

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

+            InterfaceState = IpmiInterfaceInitialized;

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

+            // Register protocol notify for SMBUS Protocol.

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

+          }

+

+          break;

+    }

+

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

+        case SysInterfaceIpmb:

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

+            InterfaceState = IpmiInterfaceInitialized;

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

+            // Register protocol notify for SMBUS Protocol.

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

+          }

+

+          break;

+    }

+

+      default:

+        break;

+    }

   }



-  //

-  // Just produce PPI

-  //

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

-  if (EFI_ERROR (Status)) {

-    return Status;

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

+  if (InterfaceState != IpmiInterfaceInitialized) {

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

+    return EFI_SUCCESS;

   }



-  return EFI_SUCCESS;

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

+  mIpmiInstance->PeiIpmi2BmcDataDesc.Guid  = &gPeiIpmiTransport2PpiGuid;

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

+

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

+  return Status;

 }



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

@@ -119,29 +425,29 @@ PeiInitializeIpmiKcsPhysicalLayer (
 **/

 EFI_STATUS

 SendPreBootSignaltoBmc (

-  IN CONST EFI_PEI_SERVICES             **PeiServices

+  IN CONST EFI_PEI_SERVICES  **PeiServices

   )

 {

-  EFI_STATUS                        Status;

-  EFI_PEI_CPU_IO_PPI                *CpuIoPpi;

-  UINT32                            ProvisionPort = 0;

-  UINT8                             PreBoot = 0;

+  EFI_STATUS          Status;

+  EFI_PEI_CPU_IO_PPI  *CpuIoPpi;

+  UINT32              ProvisionPort = 0;

+  UINT8               PreBoot       = 0;



   //

   // Locate CpuIo service

   //

-  CpuIoPpi = (**PeiServices).CpuIo;

+  CpuIoPpi      = (**PeiServices).CpuIo;

   ProvisionPort = PcdGet32 (PcdSioMailboxBaseAddress) + MBXDAT_B;

-  PreBoot = 0x01;// PRE-BOOT

+  PreBoot       = 0x01;// PRE-BOOT



   Status = CpuIoPpi->Io.Write (

-                          PeiServices,

-                          CpuIoPpi,

-                          EfiPeiCpuIoWidthUint8,

-                          ProvisionPort,

-                          1,

-                          &PreBoot

-                          );

+                               PeiServices,

+                               CpuIoPpi,

+                               EfiPeiCpuIoWidthUint8,

+                               ProvisionPort,

+                               1,

+                               &PreBoot

+                               );

   if (EFI_ERROR (Status)) {

     DEBUG ((EFI_D_ERROR, "SendPreBootSignaltoBmc () Write PRE-BOOT Status=%r\n", Status));

     return Status;

@@ -175,68 +481,13 @@ PeimIpmiInterfaceInit (
   return Status;

 } // PeimIpmiInterfaceInit()



-

-EFI_STATUS

-PeiIpmiSendCommand (

-  IN      PEI_IPMI_TRANSPORT_PPI       *This,

-  IN      UINT8                        NetFunction,

-  IN      UINT8                        Lun,

-  IN      UINT8                        Command,

-  IN      UINT8                        *CommandData,

-  IN      UINT32                       CommandDataSize,

-  IN OUT  UINT8                        *ResponseData,

-  IN OUT  UINT32                       *ResponseDataSize

-  )

-/*++

-

-Routine Description:

-

-  Send Ipmi Command in the right mode: HECI or KCS,  to the

-  appropiate device, ME or BMC.

-

-Arguments:

-

-  This              - Pointer to IPMI protocol instance

-  NetFunction       - Net Function of command to send

-  Lun               - LUN of command to send

-  Command           - IPMI command to send

-  CommandData       - Pointer to command data buffer, if needed

-  CommandDataSize   - Size of command data buffer

-  ResponseData      - Pointer to response data buffer

-  ResponseDataSize  - Pointer to response data buffer size

-

-Returns:

-

-  EFI_INVALID_PARAMETER - One of the input values is bad

-  EFI_DEVICE_ERROR      - IPMI command failed

-  EFI_BUFFER_TOO_SMALL  - Response buffer is too small

-  EFI_UNSUPPORTED       - Command is not supported by BMC

-  EFI_SUCCESS           - Command completed successfully

-

---*/

-{

-  //

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

-  //

-  return PeiIpmiSendCommandToBmc (

-           This,

-           NetFunction,

-           Lun,

-           Command,

-           CommandData,

-           (UINT8) CommandDataSize,

-           ResponseData,

-           (UINT8 *) ResponseDataSize,

-           NULL

-           );

-} // IpmiSendCommand()

-

 EFI_STATUS

 PeiGetIpmiBmcStatus (

-  IN      PEI_IPMI_TRANSPORT_PPI       *This,

-  OUT BMC_STATUS                       *BmcStatus,

-  OUT SM_COM_ADDRESS                   *ComAddress

+  IN      PEI_IPMI_TRANSPORT_PPI  *This,

+  OUT BMC_STATUS                  *BmcStatus,

+  OUT SM_COM_ADDRESS              *ComAddress

   )

+

 /*++



 Routine Description:

@@ -256,18 +507,18 @@ Returns:
 --*/

 {

   return PeiIpmiBmcStatus (

-           This,

-           BmcStatus,

-           ComAddress,

-           NULL

-           );

+                           This,

+                           BmcStatus,

+                           ComAddress,

+                           NULL

+                           );

 }



-

 EFI_STATUS

 GetDeviceId (

-  IN      PEI_IPMI_BMC_INSTANCE_DATA   *mIpmiInstance

+  IN      PEI_IPMI_BMC_INSTANCE_DATA  *mIpmiInstance

   )

+

 /*++



 Routine Description:

@@ -284,11 +535,11 @@ Returns:


 --*/

 {

-  EFI_STATUS          Status;

-  UINT32              DataSize;

-  SM_CTRL_INFO        *pBmcInfo;

-  UINTN               Retries;

-  UINT8               TempData[MAX_TEMP_DATA];

+  EFI_STATUS    Status;

+  UINT32        DataSize;

+  SM_CTRL_INFO  *pBmcInfo;

+  UINTN         Retries;

+  UINT8         TempData[MAX_TEMP_DATA];



   //

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

@@ -300,32 +551,41 @@ Returns:
   // Get the device ID information for the BMC.

   //

   DataSize = sizeof (TempData);

-  while (EFI_ERROR (Status = PeiIpmiSendCommand (

-                               &mIpmiInstance->IpmiTransportPpi,

-                               IPMI_NETFN_APP,

-                               0,

-                               IPMI_APP_GET_DEVICE_ID,

-                               NULL,

-                               0,

-                               TempData,

-                               &DataSize

-                               ))) {

-    DEBUG ((EFI_D_ERROR, "[IPMI] BMC does not respond (status: %r), %d retries left\n",

-            Status, Retries));

+  while (EFI_ERROR (

+                    Status = PeiIpmiSendCommand (

+                                                 &mIpmiInstance->IpmiTransportPpi,

+                                                 IPMI_NETFN_APP,

+                                                 0,

+                                                 IPMI_APP_GET_DEVICE_ID,

+                                                 NULL,

+                                                 0,

+                                                 TempData,

+                                                 &DataSize

+                                                 )

+                    ))

+  {

+    DEBUG (

+           (EFI_D_ERROR, "[IPMI] BMC does not respond (status: %r), %d retries left\n",

+            Status, Retries)

+           );



     if (Retries-- == 0) {

       ReportStatusCode (EFI_ERROR_CODE | EFI_ERROR_MAJOR, EFI_COMPUTING_UNIT_FIRMWARE_PROCESSOR | EFI_CU_FP_EC_COMM_ERROR);

       mIpmiInstance->BmcStatus = BMC_HARDFAIL;

       return Status;

     }

+

     //

     // 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 ((DEBUG_INFO, "[IPMI PEI] 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 (

+         (DEBUG_INFO, "[IPMI PEI] 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.

@@ -339,20 +599,20 @@ Returns:
     // Updatemode = 1 mean BMC is not ready, continue waiting.

     //

     while (Retries-- != 0) {

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

-      DEBUG ((DEBUG_INFO, "[IPMI PEI] UpdateMode Retries:%x \n",Retries));

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

+      DEBUG ((DEBUG_INFO, "[IPMI PEI] UpdateMode Retries:%x \n", Retries));

       Status = PeiIpmiSendCommand (

-                 &mIpmiInstance->IpmiTransportPpi,

-                 IPMI_NETFN_APP,

-                 0,

-                 IPMI_APP_GET_DEVICE_ID,

-                 NULL,

-                 0,

-                 TempData,

-                 &DataSize

-                 );

+                                   &mIpmiInstance->IpmiTransportPpi,

+                                   IPMI_NETFN_APP,

+                                   0,

+                                   IPMI_APP_GET_DEVICE_ID,

+                                   NULL,

+                                   0,

+                                   TempData,

+                                   &DataSize

+                                   );

       if (!EFI_ERROR (Status)) {

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

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

         DEBUG ((DEBUG_INFO, "[IPMI PEI] UpdateMode Retries:%x   pBmcInfo->UpdateMode:%x\n", Retries, pBmcInfo->UpdateMode));

         if (pBmcInfo->UpdateMode == BMC_READY) {

           mIpmiInstance->BmcStatus = BMC_OK;

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


   @copyright

   Copyright 2017 - 2021 Intel Corporation. <BR>

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

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

 **/



@@ -23,49 +24,53 @@
 #include <Library/PeiServicesTablePointerLib.h>

 #include <Library/TimerLib.h>

 #include <Library/PciLib.h>

+#include <Library/HobLib.h>



+#include "PeiIpmiHooks.h"

 #include "PeiIpmiBmcDef.h"

 #include "PeiIpmiBmc.h"



 //

 // Prototypes

 //

-#define MBXDAT_B                          0x0B

-#define BMC_KCS_TIMEOUT_PEI               5     // [s] Single KSC request timeout

-#define KCS_DELAY_UNIT_PEI                1000  // [s] Each KSC IO delay

-#define IPMI_DEFAULT_IO_BASE              0xCA2

+#define MBXDAT_B              0x0B

+#define BMC_KCS_TIMEOUT_PEI   5                 // [s] Single KSC request timeout

+#define KCS_DELAY_UNIT_PEI    1000              // [s] Each KSC IO delay

+#define IPMI_DEFAULT_IO_BASE  0xCA2



 //

 // Internal(hook) function list

 //

 EFI_STATUS

 SendPreBootSignaltoBmc (

-  IN CONST EFI_PEI_SERVICES             **PeiServices

+  IN CONST EFI_PEI_SERVICES  **PeiServices

   )

-  /*++

+

+/*++



 Routine Description:

-  Send Pre-Boot signal to BMC

+Send Pre-Boot signal to BMC



 Arguments:

-  PeiServices           - General purpose services available to every PEIM.

+PeiServices           - General purpose services available to every PEIM.



 Returns:

-  EFI_SUCCESS           - Success

+EFI_SUCCESS           - Success

 --*/

 ;



 EFI_STATUS

 PeiIpmiSendCommand (

-  IN      PEI_IPMI_TRANSPORT_PPI       *This,

-  IN      UINT8                        NetFunction,

-  IN      UINT8                        Lun,

-  IN      UINT8                        Command,

-  IN      UINT8                        *CommandData,

-  IN      UINT32                       CommandDataSize,

-  IN OUT  UINT8                        *ResponseData,

-  IN OUT  UINT32                       *ResponseDataSize

+  IN      PEI_IPMI_TRANSPORT_PPI  *This,

+  IN      UINT8                   NetFunction,

+  IN      UINT8                   Lun,

+  IN      UINT8                   Command,

+  IN      UINT8                   *CommandData,

+  IN      UINT32                  CommandDataSize,

+  IN OUT  UINT8                   *ResponseData,

+  IN OUT  UINT32                  *ResponseDataSize

   )

+

 /*++



 Routine Description:

@@ -92,10 +97,11 @@ Returns:


 EFI_STATUS

 PeiGetIpmiBmcStatus (

-  IN  PEI_IPMI_TRANSPORT_PPI                           *This,

-  OUT BMC_STATUS                                       *BmcStatus,

-  OUT SM_COM_ADDRESS                                   *ComAddress

+  IN  PEI_IPMI_TRANSPORT_PPI  *This,

+  OUT BMC_STATUS              *BmcStatus,

+  OUT SM_COM_ADDRESS          *ComAddress

   )

+

 /*++



 Routine Description:

@@ -116,8 +122,9 @@ Returns:
 //

 EFI_STATUS

 GetDeviceId (

-  IN      PEI_IPMI_BMC_INSTANCE_DATA   *mIpmiInstance

+  IN      PEI_IPMI_BMC_INSTANCE_DATA  *mIpmiInstance

   )

+

 /*++



 Routine Description:

@@ -134,5 +141,29 @@ Returns:


 --*/

 ;

-#endif //_PEI_IPMI_INIT_H_



+EFI_STATUS

+EFIAPI

+UpdateIpmiInstancePtr (

+  IN EFI_PEI_SERVICES           **PeiServices,

+  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,

+  IN VOID                       *Ppi

+  )

+

+/*++

+

+Routine Description:

+  After memory is discovered, update the IPMI Instance pointer in Hob.

+

+Arguments:

+  PeiServices      - Describes the list of possible PEI Services.

+  NotifyDescriptor - PPointer to notify descriptor..

+  Ppi              - Pointer to Ppi.

+

+Returns:

+  Status

+

+--*/

+;

+

+#endif //_PEI_IPMI_INIT_H_

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

 # @copyright

 # Copyright 2017 - 2021 Intel Corporation. <BR>

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

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

 ##



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

   PeiGenericIpmi.c

   PeiGenericIpmi.h

+  PeiIpmiHooks.c

+  PeiIpmiHooks.h



 [Packages]

   MdePkg/MdePkg.dec

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

   TimerLib

   IpmiPlatformHookLib

+  HobLib

+  BmcCommonInterfaceLib

+  BtInterfaceLib

+  SsifInterfaceLib

+  IpmbInterfaceLib



 [Guids]

+  gPeiIpmiHobGuid



 [Ppis]

   gPeiIpmiTransportPpiGuid       #ALWAYS PRODUCE

+  gPeiIpmiTransport2PpiGuid

+  gEfiPeiMemoryDiscoveredPpiGuid #CONSUMES



 [Pcd]

   gIpmiFeaturePkgTokenSpaceGuid.PcdIpmiIoBaseAddress

   gIpmiFeaturePkgTokenSpaceGuid.PcdIpmiBmcReadyDelayTimer

   gIpmiFeaturePkgTokenSpaceGuid.PcdSioMailboxBaseAddress

   gIpmiFeaturePkgTokenSpaceGuid.PcdSignalPreBootToBmc

+  gIpmiFeaturePkgTokenSpaceGuid.PcdDefaultSystemInterface

+  gIpmiFeaturePkgTokenSpaceGuid.PcdBtInterfaceSupport

+  gIpmiFeaturePkgTokenSpaceGuid.PcdSsifInterfaceSupport

+  gIpmiFeaturePkgTokenSpaceGuid.PcdKcsInterfaceSupport

+  gIpmiFeaturePkgTokenSpaceGuid.PcdIpmbInterfaceSupport

+  gIpmiFeaturePkgTokenSpaceGuid.PcdBtControlPort



 [Depex]

   TRUE

diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiBmc.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiBmc.c
index dbe25421ae..01901764a9 100644
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiBmc.c
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiBmc.c
@@ -3,6 +3,7 @@


   @copyright

   Copyright 2016 - 2021 Intel Corporation. <BR>

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

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

 **/



@@ -10,9 +11,10 @@


 EFI_STATUS

 UpdateErrorStatus (

-  IN UINT8                      BmcError,

-  PEI_IPMI_BMC_INSTANCE_DATA    *IpmiInstance

+  IN UINT8                    BmcError,

+  PEI_IPMI_BMC_INSTANCE_DATA  *IpmiInstance

   )

+

 /*++



 Routine Description:

@@ -55,16 +57,17 @@ Returns:


 EFI_STATUS

 PeiIpmiSendCommandToBmc (

-  IN      PEI_IPMI_TRANSPORT_PPI        *This,

-  IN      UINT8                         NetFunction,

-  IN      UINT8                         Lun,

-  IN      UINT8                         Command,

-  IN      UINT8                         *CommandData,

-  IN      UINT8                         CommandDataSize,

-  IN OUT  UINT8                         *ResponseData,

-  IN OUT  UINT8                         *ResponseDataSize,

-  IN      VOID                          *Context

+  IN      PEI_IPMI_TRANSPORT_PPI  *This,

+  IN      UINT8                   NetFunction,

+  IN      UINT8                   Lun,

+  IN      UINT8                   Command,

+  IN      UINT8                   *CommandData,

+  IN      UINT8                   CommandDataSize,

+  IN OUT  UINT8                   *ResponseData,

+  IN OUT  UINT8                   *ResponseDataSize,

+  IN      VOID                    *Context

   )

+

 /*++



 Routine Description:

@@ -108,15 +111,15 @@ Returns:
   // response data.  Since the command format is different from the response

   // format, the buffer is cast to both structure definitions.

   //

-  IpmiCommand   = (IPMI_COMMAND*)  TempData;

-  IpmiResponse  = (IPMI_RESPONSE*) TempData;

+  IpmiCommand  = (IPMI_COMMAND *)TempData;

+  IpmiResponse = (IPMI_RESPONSE *)TempData;



   //

   // Send IPMI command to BMC

   //

-  IpmiCommand->Lun          = Lun;

-  IpmiCommand->NetFunction  = NetFunction;

-  IpmiCommand->Command      = Command;

+  IpmiCommand->Lun         = Lun;

+  IpmiCommand->NetFunction = NetFunction;

+  IpmiCommand->Command     = Command;



   //

   // Ensure that the buffer is valid before attempting to copy the command data

@@ -128,19 +131,19 @@ Returns:
     }



     CopyMem (

-      IpmiCommand->CommandData,

-      CommandData,

-      CommandDataSize

-      );

+             IpmiCommand->CommandData,

+             CommandData,

+             CommandDataSize

+             );

   }



   Status = SendDataToBmcPort (

-             IpmiInstance->KcsTimeoutPeriod,

-             IpmiInstance->IpmiIoBase,

-             Context,

-             (UINT8 *) IpmiCommand,

-             (CommandDataSize + IPMI_COMMAND_HEADER_SIZE)

-             );

+                              IpmiInstance->KcsTimeoutPeriod,

+                              IpmiInstance->IpmiIoBase,

+                              Context,

+                              (UINT8 *)IpmiCommand,

+                              (CommandDataSize + IPMI_COMMAND_HEADER_SIZE)

+                              );



   if (Status != EFI_SUCCESS) {

     IpmiInstance->BmcStatus = BMC_SOFTFAIL;

@@ -153,13 +156,13 @@ Returns:
   // Get Response to IPMI Command from BMC.

   //

   DataSize = MAX_TEMP_DATA;

-  Status = ReceiveBmcDataFromPort (

-             IpmiInstance->KcsTimeoutPeriod,

-             IpmiInstance->IpmiIoBase,

-             Context,

-             (UINT8 *) IpmiResponse,

-             &DataSize

-             );

+  Status   = ReceiveBmcDataFromPort (

+                                     IpmiInstance->KcsTimeoutPeriod,

+                                     IpmiInstance->IpmiIoBase,

+                                     Context,

+                                     (UINT8 *)IpmiResponse,

+                                     &DataSize

+                                     );



   if (Status != EFI_SUCCESS) {

     IpmiInstance->BmcStatus = BMC_SOFTFAIL;

@@ -169,15 +172,16 @@ Returns:
   }



   if ((IpmiResponse->CompletionCode != COMP_CODE_NORMAL) &&

-      (IpmiInstance->BmcStatus == BMC_UPDATE_IN_PROGRESS)) {

+      (IpmiInstance->BmcStatus == BMC_UPDATE_IN_PROGRESS))

+  {

     //

     // If the completion code is not normal and the BMC is in Force Update

     // mode, then update the error status and return EFI_UNSUPPORTED.

     //

     UpdateErrorStatus (

-      IpmiResponse->CompletionCode,

-      IpmiInstance

-      );

+                       IpmiResponse->CompletionCode,

+                       IpmiInstance

+                       );

     return EFI_UNSUPPORTED;

   } else if (IpmiResponse->CompletionCode != COMP_CODE_NORMAL) {

     //

@@ -185,9 +189,9 @@ Returns:
     // is not normal, then update the error status and return device error.

     //

     UpdateErrorStatus (

-      IpmiResponse->CompletionCode,

-      IpmiInstance

-      );

+                       IpmiResponse->CompletionCode,

+                       IpmiInstance

+                       );

     return EFI_DEVICE_ERROR;

   }



@@ -215,32 +219,33 @@ Returns:
   //

   *ResponseDataSize = DataSize - IPMI_RESPONSE_HEADER_SIZE;

   CopyMem (

-    ResponseData,

-    IpmiResponse->ResponseData,

-    *ResponseDataSize

-    );

+           ResponseData,

+           IpmiResponse->ResponseData,

+           *ResponseDataSize

+           );



   //

   // Add completion code in response data to meet the requirement of IPMI spec 2.0

   //

   *ResponseDataSize += 1; // Add one byte for Completion Code

   for (Index = 1; Index < *ResponseDataSize; Index++) {

-    ResponseData [*ResponseDataSize - Index] = ResponseData [*ResponseDataSize - (Index + 1)];

+    ResponseData[*ResponseDataSize - Index] = ResponseData[*ResponseDataSize - (Index + 1)];

   }

-  ResponseData [0] = IpmiResponse->CompletionCode;

+

+  ResponseData[0] = IpmiResponse->CompletionCode;



   IpmiInstance->BmcStatus = BMC_OK;

   return EFI_SUCCESS;

 }



-

 EFI_STATUS

-PeiIpmiBmcStatus (

-  IN  PEI_IPMI_TRANSPORT_PPI          *This,

-  OUT BMC_STATUS                  *BmcStatus,

-  OUT SM_COM_ADDRESS              *ComAddress,

-  IN  VOID                            *Context

+IpmiBmcStatus (

+  IN  PEI_IPMI_TRANSPORT_PPI  *This,

+  OUT BMC_STATUS              *BmcStatus,

+  OUT SM_COM_ADDRESS          *ComAddress,

+  IN  VOID                    *Context

   )

+

 /*++



 Routine Description:

@@ -268,10 +273,10 @@ Returns:
     IpmiInstance->BmcStatus = BMC_HARDFAIL;

   }



-  *BmcStatus = IpmiInstance->BmcStatus;

-  ComAddress->ChannelType = SmBmc;

-  ComAddress->Address.BmcAddress.LunAddress = 0x0;

-  ComAddress->Address.BmcAddress.SlaveAddress = IpmiInstance->SlaveAddress;

+  *BmcStatus                                    = IpmiInstance->BmcStatus;

+  ComAddress->ChannelType                       = SmBmc;

+  ComAddress->Address.BmcAddress.LunAddress     = 0x0;

+  ComAddress->Address.BmcAddress.SlaveAddress   = IpmiInstance->SlaveAddress;

   ComAddress->Address.BmcAddress.ChannelAddress = 0x0;



   return EFI_SUCCESS;

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


   @copyright

   Copyright 2016 - 2021 Intel Corporation. <BR>

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

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

 **/



@@ -25,7 +26,7 @@
 //

 // 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 INSTANCE_FROM_PEI_SM_IPMI_BMC_THIS(a) \

   CR ( \

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

   )



+#define INSTANCE_FROM_PEI_IPMI_TRANSPORT2_THIS(a) \

+  CR ( \

+  a, \

+  PEI_IPMI_BMC_INSTANCE_DATA, \

+  IpmiTransport2Ppi, \

+  SM_IPMI_BMC_SIGNATURE \

+  )

+

 #endif // _PEI_IPMI_BMC_H_

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


   @copyright

   Copyright 2016 - 2021 Intel Corporation. <BR>

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

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

 **/



@@ -10,11 +11,13 @@
 #define _PEI_IPMI_COMMON_BMC_H_



 #include <Ppi/IpmiTransportPpi.h>

+#include <Ppi/IpmiTransport2Ppi.h>

+#include "ServerManagement.h"



-#define MAX_TEMP_DATA     160

-#define BMC_SLAVE_ADDRESS 0x20

-#define MAX_SOFT_COUNT    10

-#define COMP_CODE_NORMAL  0x00

+#define MAX_TEMP_DATA      160

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

@@ -46,15 +49,17 @@
 // Pei Ipmi instance data

 //

 typedef struct {

-  UINTN                  Signature;

-  UINT64                 KcsTimeoutPeriod;

-  UINT8                  SlaveAddress;

-  BMC_STATUS             BmcStatus;

-  UINT64                 ErrorStatus;

-  UINT8                  SoftErrorCount;

-  UINT16                 IpmiIoBase;

-  PEI_IPMI_TRANSPORT_PPI IpmiTransportPpi;

-  EFI_PEI_PPI_DESCRIPTOR PeiIpmiBmcDataDesc;

+  UINTN                     Signature;

+  UINT64                    KcsTimeoutPeriod;

+  UINT8                     SlaveAddress;

+  BMC_STATUS                BmcStatus;

+  UINT64                    ErrorStatus;

+  UINT8                     SoftErrorCount;

+  UINT16                    IpmiIoBase;

+  PEI_IPMI_TRANSPORT_PPI    IpmiTransportPpi;

+  IPMI_TRANSPORT2           IpmiTransport2Ppi;

+  EFI_PEI_PPI_DESCRIPTOR    PeiIpmiBmcDataDesc;

+  EFI_PEI_PPI_DESCRIPTOR    PeiIpmi2BmcDataDesc;

 } PEI_IPMI_BMC_INSTANCE_DATA;



 //

@@ -63,38 +68,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;

 #pragma pack()



 EFI_STATUS

 PeiIpmiSendCommandToBmc (

-  IN      PEI_IPMI_TRANSPORT_PPI        *This,

-  IN      UINT8                         NetFunction,

-  IN      UINT8                         Lun,

-  IN      UINT8                         Command,

-  IN      UINT8                         *CommandData,

-  IN      UINT8                         CommandDataSize,

-  IN OUT  UINT8                         *ResponseData,

-  IN OUT  UINT8                         *ResponseDataSize,

-  IN      VOID                          *Context

+  IN      PEI_IPMI_TRANSPORT_PPI  *This,

+  IN      UINT8                   NetFunction,

+  IN      UINT8                   Lun,

+  IN      UINT8                   Command,

+  IN      UINT8                   *CommandData,

+  IN      UINT8                   CommandDataSize,

+  IN OUT  UINT8                   *ResponseData,

+  IN OUT  UINT8                   *ResponseDataSize,

+  IN      VOID                    *Context

   )

+

 /*++



 Routine Description:

@@ -123,14 +129,14 @@ Returns:
 --*/

 ;



-

 EFI_STATUS

 PeiIpmiBmcStatus (

-  IN      PEI_IPMI_TRANSPORT_PPI       *This,

-  OUT BMC_STATUS                       *BmcStatus,

-  OUT SM_COM_ADDRESS                   *ComAddress,

-  IN  VOID                             *Context

+  IN      PEI_IPMI_TRANSPORT_PPI  *This,

+  OUT BMC_STATUS                  *BmcStatus,

+  OUT SM_COM_ADDRESS              *ComAddress,

+  IN  VOID                        *Context

   )

+

 /*++



 Routine Description:

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

 ;



+typedef struct _PEI_IPMI_DATA_HOB PEI_IPMI_DATA_HOB;

+

+struct _PEI_IPMI_DATA_HOB {

+  UINTN                IpmiInstance;                   /// IpmiInstance pointer.

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

+};



 #endif //_PEI_IPMI_COMMON_BMC_H_

diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiHooks.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiHooks.c
new file mode 100644
index 0000000000..f5a933d35c
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiHooks.c
@@ -0,0 +1,346 @@
+/** @file
+  IPMI common hook functions
+
+  @copyright
+  Copyright 1999 - 2021 Intel Corporation. <BR>
+  Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <ServerManagement.h>
+#include <PeiIpmiHooks.h>
+
+EFI_STATUS
+PeiIpmiSendCommand (
+  IN      PEI_IPMI_TRANSPORT_PPI  *This,
+  IN      UINT8                   NetFunction,
+  IN      UINT8                   Lun,
+  IN      UINT8                   Command,
+  IN      UINT8                   *CommandData,
+  IN      UINT32                  CommandDataSize,
+  IN OUT  UINT8                   *ResponseData,
+  IN OUT  UINT32                  *ResponseDataSize
+  )
+
+/*++
+
+Routine Description:
+
+  Send Ipmi Command in the right mode: HECI or KCS,  to the
+  appropiate device, ME or BMC.
+
+Arguments:
+
+  This              - Pointer to IPMI protocol instance
+  NetFunction       - Net Function of command to send
+  Lun               - LUN of command to send
+  Command           - IPMI command to send
+  CommandData       - Pointer to command data buffer, if needed
+  CommandDataSize   - Size of command data buffer
+  ResponseData      - Pointer to response data buffer
+  ResponseDataSize  - Pointer to response data buffer size
+
+Returns:
+
+  EFI_INVALID_PARAMETER - One of the input values is bad
+  EFI_DEVICE_ERROR      - IPMI command failed
+  EFI_BUFFER_TOO_SMALL  - Response buffer is too small
+  EFI_UNSUPPORTED       - Command is not supported by BMC
+  EFI_SUCCESS           - Command completed successfully
+
+--*/
+{
+  if (This == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // This Will be unchanged ( BMC/KCS style )
+  //
+  return PeiIpmiSendCommandToBmc (
+                                  This,
+                                  NetFunction,
+                                  Lun,
+                                  Command,
+                                  CommandData,
+                                  (UINT8)CommandDataSize,
+                                  ResponseData,
+                                  (UINT8 *)ResponseDataSize,
+                                  NULL
+                                  );
+} // IpmiSendCommand()
+
+EFI_STATUS
+PeiIpmiSendCommand2 (
+  IN      IPMI_TRANSPORT2  *This,
+  IN      UINT8            NetFunction,
+  IN      UINT8            Lun,
+  IN      UINT8            Command,
+  IN      UINT8            *CommandData,
+  IN      UINT32           CommandDataSize,
+  IN OUT  UINT8            *ResponseData,
+  IN OUT  UINT32           *ResponseDataSize
+  )
+
+/*++
+
+Routine Description:
+
+  This API use the default interface (PcdDefaultSystemInterface) to send IPMI command
+  in the right mode to the appropiate device, ME or BMC.
+
+Arguments:
+
+  This              - Pointer to IPMI protocol instance
+  NetFunction       - Net Function of command to send
+  Lun               - LUN of command to send
+  Command           - IPMI command to send
+  CommandData       - Pointer to command data buffer, if needed
+  CommandDataSize   - Size of command data buffer
+  ResponseData      - Pointer to response data buffer
+  ResponseDataSize  - Pointer to response data buffer size
+
+Returns:
+
+  EFI_INVALID_PARAMETER - One of the input values is bad
+  EFI_DEVICE_ERROR      - IPMI command failed
+  EFI_BUFFER_TOO_SMALL  - Response buffer is too small
+  EFI_UNSUPPORTED       - Command is not supported by BMC
+  EFI_SUCCESS           - Command completed successfully
+
+--*/
+{
+  PEI_IPMI_BMC_INSTANCE_DATA  *PeiIpmiInstance;
+
+  if (This == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  PeiIpmiInstance = INSTANCE_FROM_PEI_IPMI_TRANSPORT2_THIS (This);
+
+  if ((FixedPcdGet8 (PcdKcsInterfaceSupport) == 1) &&
+      ((PeiIpmiInstance->IpmiTransport2Ppi.InterfaceType == SysInterfaceKcs) &&
+       (PeiIpmiInstance->IpmiTransport2Ppi.Interface.KcsInterfaceState == IpmiInterfaceInitialized)))
+  {
+    return PeiIpmiSendCommand (
+                               &PeiIpmiInstance->IpmiTransportPpi,
+                               NetFunction,
+                               Lun,
+                               Command,
+                               CommandData,
+                               CommandDataSize,
+                               ResponseData,
+                               ResponseDataSize
+                               );
+  }
+
+  if ((FixedPcdGet8 (PcdBtInterfaceSupport) == 1) &&
+      ((PeiIpmiInstance->IpmiTransport2Ppi.InterfaceType == SysInterfaceBt) &&
+       (PeiIpmiInstance->IpmiTransport2Ppi.Interface.Bt.InterfaceState == IpmiInterfaceInitialized)))
+  {
+    return IpmiBtSendCommandToBmc (
+                                   &PeiIpmiInstance->IpmiTransport2Ppi,
+                                   NetFunction,
+                                   Lun,
+                                   Command,
+                                   CommandData,
+                                   (UINT8)CommandDataSize,
+                                   ResponseData,
+                                   (UINT8 *)ResponseDataSize,
+                                   NULL
+                                   );
+  }
+
+  if ((FixedPcdGet8 (PcdSsifInterfaceSupport) == 1) &&
+      ((PeiIpmiInstance->IpmiTransport2Ppi.InterfaceType == SysInterfaceSsif) &&
+       (PeiIpmiInstance->IpmiTransport2Ppi.Interface.Ssif.InterfaceState == IpmiInterfaceInitialized)))
+  {
+    return IpmiSsifSendCommandToBmc (
+                                     &PeiIpmiInstance->IpmiTransport2Ppi,
+                                     NetFunction,
+                                     Lun,
+                                     Command,
+                                     CommandData,
+                                     (UINT8)CommandDataSize,
+                                     ResponseData,
+                                     (UINT8 *)ResponseDataSize,
+                                     NULL
+                                     );
+  }
+
+  if ((FixedPcdGet8 (PcdIpmbInterfaceSupport) == 1) &&
+      ((PeiIpmiInstance->IpmiTransport2Ppi.InterfaceType == SysInterfaceIpmb) &&
+       (PeiIpmiInstance->IpmiTransport2Ppi.Interface.Ipmb.InterfaceState == IpmiInterfaceInitialized)))
+  {
+    return IpmiIpmbSendCommandToBmc (
+                                     &PeiIpmiInstance->IpmiTransport2Ppi,
+                                     NetFunction,
+                                     Lun,
+                                     Command,
+                                     CommandData,
+                                     (UINT8)CommandDataSize,
+                                     ResponseData,
+                                     (UINT8 *)ResponseDataSize,
+                                     NULL
+                                     );
+  }
+
+  return EFI_UNSUPPORTED;
+} // IpmiSendCommand()
+
+EFI_STATUS
+PeiIpmiSendCommand2Ex (
+  IN      IPMI_TRANSPORT2        *This,
+  IN      UINT8                  NetFunction,
+  IN      UINT8                  Lun,
+  IN      UINT8                  Command,
+  IN      UINT8                  *CommandData,
+  IN      UINT32                 CommandDataSize,
+  IN OUT  UINT8                  *ResponseData,
+  IN OUT  UINT32                 *ResponseDataSize,
+  IN      SYSTEM_INTERFACE_TYPE  InterfaceType
+  )
+{
+  /*++
+  Routine Description:
+
+    This API use the specific interface type to send IPMI command
+    in the right mode to the appropiate device, ME or BMC.
+
+  Arguments:
+
+    This              - Pointer to IPMI protocol instance
+    NetFunction       - Net Function of command to send
+    Lun               - LUN of command to send
+    Command           - IPMI command to send
+    CommandData       - Pointer to command data buffer, if needed
+    CommandDataSize   - Size of command data buffer
+    ResponseData      - Pointer to response data buffer
+    ResponseDataSize  - Pointer to response data buffer size
+    InterfaceType     - BMC Interface type.
+
+  Returns:
+
+    EFI_INVALID_PARAMETER - One of the input values is bad
+    EFI_DEVICE_ERROR      - IPMI command failed
+    EFI_BUFFER_TOO_SMALL  - Response buffer is too small
+    EFI_UNSUPPORTED       - Command is not supported by BMC
+    EFI_SUCCESS           - Command completed successfully
+
+  --*/
+
+  PEI_IPMI_BMC_INSTANCE_DATA  *PeiIpmiInstance;
+
+  if (This == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  PeiIpmiInstance = INSTANCE_FROM_PEI_IPMI_TRANSPORT2_THIS (This);
+
+  if ((FixedPcdGet8 (PcdKcsInterfaceSupport) == 1) &&
+      ((InterfaceType == SysInterfaceKcs) &&
+       (PeiIpmiInstance->IpmiTransport2Ppi.Interface.KcsInterfaceState == IpmiInterfaceInitialized)))
+  {
+    return PeiIpmiSendCommand (
+                               &PeiIpmiInstance->IpmiTransportPpi,
+                               NetFunction,
+                               Lun,
+                               Command,
+                               CommandData,
+                               CommandDataSize,
+                               ResponseData,
+                               ResponseDataSize
+                               );
+  }
+
+  if ((FixedPcdGet8 (PcdBtInterfaceSupport) == 1) &&
+      ((InterfaceType == SysInterfaceBt) &&
+       (PeiIpmiInstance->IpmiTransport2Ppi.Interface.Bt.InterfaceState == IpmiInterfaceInitialized)))
+  {
+    return IpmiBtSendCommandToBmc (
+                                   &PeiIpmiInstance->IpmiTransport2Ppi,
+                                   NetFunction,
+                                   Lun,
+                                   Command,
+                                   CommandData,
+                                   (UINT8)CommandDataSize,
+                                   ResponseData,
+                                   (UINT8 *)ResponseDataSize,
+                                   NULL
+                                   );
+  }
+
+  if ((FixedPcdGet8 (PcdSsifInterfaceSupport) == 1) &&
+      ((InterfaceType == SysInterfaceSsif) &&
+       (PeiIpmiInstance->IpmiTransport2Ppi.Interface.Ssif.InterfaceState == IpmiInterfaceInitialized)))
+  {
+    return IpmiSsifSendCommandToBmc (
+                                     &PeiIpmiInstance->IpmiTransport2Ppi,
+                                     NetFunction,
+                                     Lun,
+                                     Command,
+                                     CommandData,
+                                     (UINT8)CommandDataSize,
+                                     ResponseData,
+                                     (UINT8 *)ResponseDataSize,
+                                     NULL
+                                     );
+  }
+
+  if ((FixedPcdGet8 (PcdIpmbInterfaceSupport) == 1) &&
+      ((InterfaceType == SysInterfaceIpmb) &&
+       (PeiIpmiInstance->IpmiTransport2Ppi.Interface.Ipmb.InterfaceState == IpmiInterfaceInitialized)))
+  {
+    return IpmiIpmbSendCommandToBmc (
+                                     &PeiIpmiInstance->IpmiTransport2Ppi,
+                                     NetFunction,
+                                     Lun,
+                                     Command,
+                                     CommandData,
+                                     (UINT8)CommandDataSize,
+                                     ResponseData,
+                                     (UINT8 *)ResponseDataSize,
+                                     NULL
+                                     );
+  }
+
+  return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+PeiIpmiBmcStatus (
+  IN  PEI_IPMI_TRANSPORT_PPI  *This,
+  OUT BMC_STATUS              *BmcStatus,
+  OUT SM_COM_ADDRESS          *ComAddress,
+  IN  VOID                    *Context
+  )
+
+/*++
+
+Routine Description:
+
+  Updates the BMC status and returns the Com Address
+
+Arguments:
+
+  This        - Pointer to IPMI protocol instance
+  BmcStatus   - BMC status
+  ComAddress  - Com Address
+
+Returns:
+
+  EFI_SUCCESS - Success
+
+--*/
+{
+  if ((This == NULL) || (BmcStatus == NULL) || (ComAddress == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return IpmiBmcStatus (
+                        This,
+                        BmcStatus,
+                        ComAddress,
+                        NULL
+                        );
+}
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiHooks.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiHooks.h
new file mode 100644
index 0000000000..25be1fd94a
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiHooks.h
@@ -0,0 +1,218 @@
+/** @file
+  IPMI common hook functions head file
+
+  @copyright
+  Copyright 2016 - 2021 Intel Corporation. <BR>
+  Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _IPMI_HOOKS_H
+#define _IPMI_HOOKS_H
+
+#include <Ppi/IpmiTransportPpi.h>
+#include <Ppi/IpmiTransport2Ppi.h>
+#include <Library/BtInterfaceLib.h>
+#include <Library/SsifInterfaceLib.h>
+#include <Library/IpmbInterfaceLib.h>
+#include <PeiIpmiBmcDef.h>
+#include <PeiIpmiBmc.h>
+
+//
+// Internal(hook) function list
+//
+
+EFI_STATUS
+PeiIpmiSendCommand (
+  IN      PEI_IPMI_TRANSPORT_PPI  *This,
+  IN      UINT8                   NetFunction,
+  IN      UINT8                   Lun,
+  IN      UINT8                   Command,
+  IN      UINT8                   *CommandData,
+  IN      UINT32                  CommandDataSize,
+  IN OUT  UINT8                   *ResponseData,
+  IN OUT  UINT32                  *ResponseDataSize
+  )
+
+/*++
+
+Routine Description:
+
+  Send Ipmi Command in the right mode: HECI or KCS,  to the
+  appropiate device, ME or BMC.
+
+Arguments:
+
+  This              - Pointer to IPMI protocol instance
+  NetFunction       - Net Function of command to send
+  Lun               - LUN of command to send
+  Command           - IPMI command to send
+  CommandData       - Pointer to command data buffer, if needed
+  CommandDataSize   - Size of command data buffer
+  ResponseData      - Pointer to response data buffer
+  ResponseDataSize  - Pointer to response data buffer size
+
+Returns:
+
+  EFI_INVALID_PARAMETER - One of the input values is bad
+  EFI_DEVICE_ERROR      - IPMI command failed
+  EFI_BUFFER_TOO_SMALL  - Response buffer is too small
+  EFI_UNSUPPORTED       - Command is not supported by BMC
+  EFI_SUCCESS           - Command completed successfully
+
+--*/
+;
+
+EFI_STATUS
+PeiIpmiSendCommand2 (
+  IN      IPMI_TRANSPORT2  *This,
+  IN      UINT8            NetFunction,
+  IN      UINT8            Lun,
+  IN      UINT8            Command,
+  IN      UINT8            *CommandData,
+  IN      UINT32           CommandDataSize,
+  IN OUT  UINT8            *ResponseData,
+  IN OUT  UINT32           *ResponseDataSize
+  )
+
+/*++
+
+Routine Description:
+
+  This API use the default interface (PcdDefaultSystemInterface) to send IPMI command
+  in the right mode to the appropiate device, ME or BMC.
+
+Arguments:
+
+  This              - Pointer to IPMI protocol instance
+  NetFunction       - Net Function of command to send
+  Lun               - LUN of command to send
+  Command           - IPMI command to send
+  CommandData       - Pointer to command data buffer, if needed
+  CommandDataSize   - Size of command data buffer
+  ResponseData      - Pointer to response data buffer
+  ResponseDataSize  - Pointer to response data buffer size
+
+Returns:
+
+  EFI_INVALID_PARAMETER - One of the input values is bad
+  EFI_DEVICE_ERROR      - IPMI command failed
+  EFI_BUFFER_TOO_SMALL  - Response buffer is too small
+  EFI_UNSUPPORTED       - Command is not supported by BMC
+  EFI_SUCCESS           - Command completed successfully
+
+--*/
+;
+
+EFI_STATUS
+PeiIpmiSendCommand2Ex (
+  IN      IPMI_TRANSPORT2        *This,
+  IN      UINT8                  NetFunction,
+  IN      UINT8                  Lun,
+  IN      UINT8                  Command,
+  IN      UINT8                  *CommandData,
+  IN      UINT32                 CommandDataSize,
+  IN OUT  UINT8                  *ResponseData,
+  IN OUT  UINT32                 *ResponseDataSize,
+  IN      SYSTEM_INTERFACE_TYPE  InterfaceType
+  );
+
+EFI_STATUS
+PeiIpmiSendCommandToBMC (
+  IN      PEI_IPMI_TRANSPORT_PPI  *This,
+  IN      UINT8                   NetFunction,
+  IN      UINT8                   Lun,
+  IN      UINT8                   Command,
+  IN      UINT8                   *CommandData,
+  IN      UINT8                   CommandDataSize,
+  IN OUT  UINT8                   *ResponseData,
+  IN OUT  UINT8                   *ResponseDataSize,
+  IN      VOID                    *Context
+  )
+
+/*++
+Routine Description:
+
+  This API use the specific interface type to send IPMI command
+  in the right mode to the appropiate device, ME or BMC.
+
+Arguments:
+
+  This              - Pointer to IPMI protocol instance
+  NetFunction       - Net Function of command to send
+  Lun               - LUN of command to send
+  Command           - IPMI command to send
+  CommandData       - Pointer to command data buffer, if needed
+  CommandDataSize   - Size of command data buffer
+  ResponseData      - Pointer to response data buffer
+  ResponseDataSize  - Pointer to response data buffer size
+  InterfaceType     - BMC Interface type.
+
+Returns:
+
+  EFI_INVALID_PARAMETER - One of the input values is bad
+  EFI_DEVICE_ERROR      - IPMI command failed
+  EFI_BUFFER_TOO_SMALL  - Response buffer is too small
+  EFI_UNSUPPORTED       - Command is not supported by BMC
+  EFI_SUCCESS           - Command completed successfully
+
+--*/
+;
+
+EFI_STATUS
+PeiIpmiBmcStatus (
+  IN  PEI_IPMI_TRANSPORT_PPI  *This,
+  OUT BMC_STATUS              *BmcStatus,
+  OUT SM_COM_ADDRESS          *ComAddress,
+  IN  VOID                    *Context
+  )
+
+/*++
+
+Routine Description:
+
+  Updates the BMC status and returns the Com Address
+
+Arguments:
+
+  This        - Pointer to IPMI protocol instance
+  BmcStatus   - BMC status
+  ComAddress  - Com Address
+  Context     - Context
+
+Returns:
+
+  EFI_SUCCESS - Success
+
+--*/
+;
+
+EFI_STATUS
+IpmiBmcStatus (
+  IN  PEI_IPMI_TRANSPORT_PPI  *This,
+  OUT BMC_STATUS              *BmcStatus,
+  OUT SM_COM_ADDRESS          *ComAddress,
+  IN  VOID                    *Context
+  )
+
+/*++
+
+Routine Description:
+
+  Updates the BMC status and returns the Com Address
+
+Arguments:
+
+  This        - Pointer to IPMI protocol instance
+  BmcStatus   - BMC status
+  ComAddress  - Com Address
+  Context     - Context
+
+Returns:
+
+  EFI_SUCCESS - Success
+
+--*/
+;
+
+#endif
--
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 (#107247): https://edk2.groups.io/g/devel/message/107247
Mute This Topic: https://groups.io/mt/100352666/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-1] IpmiFeaturePkg:Provided multiple IPMI interface support in PEI
Posted by Isaac Oram 8 months, 4 weeks ago
Reviewed-by: Isaac Oram <isaac.w.oram@intel.com>

-----Original Message-----
From: Arun K <arunk@ami.com> 
Sent: Tuesday, July 25, 2023 8:36 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-1] IpmiFeaturePkg:Provided multiple IPMI interface support in PEI

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/Pei/PeiGenericIpmi.c          | 550 +++++++++++++-----
 .../GenericIpmi/Pei/PeiGenericIpmi.h          |  75 ++-
 .../GenericIpmi/Pei/PeiGenericIpmi.inf        |  17 +
 .../GenericIpmi/Pei/PeiIpmiBmc.c              | 117 ++--
 .../GenericIpmi/Pei/PeiIpmiBmc.h              |  11 +-
 .../GenericIpmi/Pei/PeiIpmiBmcDef.h           |  86 +--
 .../GenericIpmi/Pei/PeiIpmiHooks.c            | 346 +++++++++++
 .../GenericIpmi/Pei/PeiIpmiHooks.h            | 218 +++++++
 8 files changed, 1159 insertions(+), 261 deletions(-)
 create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiHooks.c
 create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiHooks.h

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


   @copyright

   Copyright 2017 - 2021 Intel Corporation. <BR>

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

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

 **/



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

 #include <Library/ReportStatusCodeLib.h>

 #include <Library/IpmiPlatformHookLib.h>

+#include <Library/BmcCommonInterfaceLib.h>



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

-// Function Implementations

-//

+

+static EFI_PEI_NOTIFY_DESCRIPTOR  mNotifyList = {

+  EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,

+  &gEfiPeiMemoryDiscoveredPpiGuid,

+  UpdateIpmiInstancePtr

+};

+

+/**

+    Initialize the API and parameters for IPMI Transport2 Instance

+

+    @param[in] IpmiInstance         Pointer to IPMI Instance

+

+    @return VOID

+

+**/

+VOID

+InitIpmiTransport2 (

+  IN  PEI_IPMI_BMC_INSTANCE_DATA  *IpmiInstance

+  )

+{

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

+  IpmiInstance->IpmiTransport2Ppi.IpmiTransport2BmcStatus = BmcStatusOk;

+  IpmiInstance->IpmiTransport2Ppi.IpmiSubmitCommand2      = PeiIpmiSendCommand2;

+  IpmiInstance->IpmiTransport2Ppi.IpmiSubmitCommand2Ex    = PeiIpmiSendCommand2Ex;

+

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

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

+      InitBtInterfaceData (&IpmiInstance->IpmiTransport2Ppi);

+    }

+  }

+

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

+    InitSsifInterfaceData (&IpmiInstance->IpmiTransport2Ppi);

+  }

+

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

+    InitIpmbInterfaceData (&IpmiInstance->IpmiTransport2Ppi);

+  }

+}

+

+/*++

+

+Routine Description:

+  Notify callback function for interfaces.

+

+Arguments:

+  PeiServices      - Describes the list of possible PEI Services.

+  NotifyDescriptor - Pointer to notify descriptor.

+  Ppi              - Pointer to Ppi.

+

+Returns:

+  Status

+

+--*/

+EFI_STATUS

+EFIAPI

+NotifyCallback (

+  IN EFI_PEI_SERVICES           **PeiServices,

+  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,

+  IN VOID                       *Ppi

+  )

+{

+  EFI_STATUS                  Status;

+  PEI_IPMI_BMC_INSTANCE_DATA  *IpmiInstance;

+  PEI_IPMI_DATA_HOB           *IpmiInstancePtrHob;

+  EFI_HOB_GUID_TYPE           *GuidHob;

+  IPMI_INTERFACE_STATE        InterfaceState;

+

+  InterfaceState = IpmiInterfaceNotReady;

+

+  GuidHob = GetFirstGuidHob (&gPeiIpmiHobGuid);

+  ASSERT (GuidHob != NULL);

+  if (GuidHob == NULL) {

+    return EFI_NOT_FOUND;

+  }

+

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

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

+

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

+    InitSsifInterfaceData (&IpmiInstance->IpmiTransport2Ppi);

+

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

+      InterfaceState = IpmiInterfaceInitialized;

+    }

+  }

+

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

+    InitIpmbInterfaceData (&IpmiInstance->IpmiTransport2Ppi);

+

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

+      InterfaceState = IpmiInterfaceInitialized;

+    }

+  }

+

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

+  if (InterfaceState != IpmiInterfaceInitialized) {

+    return EFI_UNSUPPORTED;

+  }

+

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

+  return Status;

+}

+

+/*++

+

+Routine Description:

+  Registers callback for Ppi.

+

+Arguments:

+  PeiServices      - Describes the list of possible PEI Services.

+  PpiGuid          - Pointer to Ppi guid to register call back.

+

+Returns:

+  Status

+

+--*/

+EFI_STATUS

+RegisterPpiCallback (

+  IN CONST EFI_PEI_SERVICES  **PeiServices,

+  IN       EFI_GUID          *PpiGuid

+  )

+{

+  EFI_STATUS                 Status;

+  EFI_PEI_NOTIFY_DESCRIPTOR  *PpiNotifyDesc;

+

+  if ((PpiGuid == NULL) ||

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

+  {

+    return EFI_INVALID_PARAMETER;

+  }

+

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

+  if (PpiNotifyDesc == NULL) {

+    return EFI_OUT_OF_RESOURCES;

+  }

+

+  PpiNotifyDesc->Flags  = EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;

+  PpiNotifyDesc->Guid   = PpiGuid;

+  PpiNotifyDesc->Notify = NotifyCallback;

+

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

+  return Status;

+}

+

+/*++

+

+Routine Description:

+  After memory is discovered, update the IPMI Instance pointer in Hob.

+

+Arguments:

+  PeiServices      - Describes the list of possible PEI Services.

+  NotifyDescriptor - PPointer to notify descriptor..

+  Ppi              - Pointer to Ppi.

+

+Returns:

+  Status

+

+--*/

+EFI_STATUS

+EFIAPI

+UpdateIpmiInstancePtr (

+  IN EFI_PEI_SERVICES           **PeiServices,

+  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,

+  IN VOID                       *Ppi

+  )

+{

+  PEI_IPMI_BMC_INSTANCE_DATA  *IpmiInstance;

+  PEI_IPMI_DATA_HOB           *IpmiInstancePtrHob;

+  EFI_HOB_GUID_TYPE           *GuidHob;

+

+  GuidHob = GetFirstGuidHob (&gPeiIpmiHobGuid);

+

+  ASSERT (GuidHob != NULL);

+  if (GuidHob == NULL) {

+    return EFI_NOT_FOUND;

+  }

+

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

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

+

+  if (!IpmiInstance) {

+    return EFI_ABORTED;

+  }

+

+  DEBUG ((DEBUG_INFO, "IpmiInstance Signature in CAR Memory: %x\n", IpmiInstance->Signature));

+

+  if ((UINTN)IpmiInstancePtrHob >= (UINTN)IpmiInstancePtrHob->PreMemIpmiDataHobPtr) {

+    IpmiInstance = (PEI_IPMI_BMC_INSTANCE_DATA *)((UINT8 *)IpmiInstance + \

+                                                  (UINTN)((UINTN)IpmiInstancePtrHob - (UINTN)IpmiInstancePtrHob->PreMemIpmiDataHobPtr));

+  } else {

+    IpmiInstance = (PEI_IPMI_BMC_INSTANCE_DATA *)((UINT8 *)IpmiInstance - \

+                                                  (UINTN)((UINTN)IpmiInstancePtrHob->PreMemIpmiDataHobPtr - (UINTN)IpmiInstancePtrHob));

+  }

+

+  IpmiInstancePtrHob->IpmiInstance = (UINTN)IpmiInstance;

+  DEBUG ((DEBUG_INFO, "IpmiInstance Signature after Permanent Memory discovered: %x\n", IpmiInstance->Signature));

+  return EFI_SUCCESS;

+}



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

  @brief

@@ -26,13 +225,17 @@
 EFI_STATUS

 EFIAPI

 PeiInitializeIpmiKcsPhysicalLayer (

-  IN CONST EFI_PEI_SERVICES             **PeiServices

+  IN CONST EFI_PEI_SERVICES  **PeiServices

   )

 {

-  EFI_STATUS                       Status;

-  PEI_IPMI_BMC_INSTANCE_DATA       *mIpmiInstance;

+  EFI_STATUS                  Status;

+  PEI_IPMI_BMC_INSTANCE_DATA  *mIpmiInstance;

+  PEI_IPMI_DATA_HOB           *IpmiInstancePtrHob;

+  IPMI_INTERFACE_STATE        InterfaceState;

+  UINT8                       Index;



-  mIpmiInstance = NULL;

+  mIpmiInstance  = NULL;

+  InterfaceState = IpmiInterfaceNotReady;



   //

   // Send Pre-Boot signal to BMC

@@ -50,63 +253,166 @@ PeiInitializeIpmiKcsPhysicalLayer (
   //

   Status = PlatformIpmiIoRangeSet (PcdGet16 (PcdIpmiIoBaseAddress));

   DEBUG ((DEBUG_INFO, "IPMI Peim:PlatformIpmiIoRangeSet - %r!\n", Status));

-  if (EFI_ERROR(Status)) {

+  if (EFI_ERROR (Status)) {

     return Status;

   }



   mIpmiInstance = AllocateZeroPool (sizeof (PEI_IPMI_BMC_INSTANCE_DATA));

   if (mIpmiInstance == NULL) {

-    DEBUG ((EFI_D_ERROR,"IPMI Peim:EFI_OUT_OF_RESOURCES of memory allocation\n"));

+    DEBUG ((EFI_D_ERROR, "IPMI Peim:EFI_OUT_OF_RESOURCES of memory allocation\n"));

     return EFI_OUT_OF_RESOURCES;

   }



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

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

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

+    if (IpmiInstancePtrHob == NULL) {

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

+      FreePool (mIpmiInstance);

+      return EFI_OUT_OF_RESOURCES;

+    }

+

+    IpmiInstancePtrHob->IpmiInstance         = (UINTN)mIpmiInstance;

+    IpmiInstancePtrHob->PreMemIpmiDataHobPtr = IpmiInstancePtrHob;

+

+    // Check for Memory initialization

+    Status = (*PeiServices)->LocatePpi (

+                                        PeiServices,

+                                        &gEfiPeiMemoryDiscoveredPpiGuid,

+                                        0,

+                                        NULL,

+                                        NULL

+                                        );

+

+    if (EFI_ERROR (Status)) {

+      /* Register Memory discovered PPI call back to update HOB with new

+      IpmiInstance pointer.*/

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

+      if (EFI_ERROR (Status)) {

+        FreePool (mIpmiInstance);

+        return Status;

+      }

+    }

+  }

+

   //

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

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

   //

-  DEBUG ((DEBUG_INFO,"IPMI Peim:IPMI STACK Initialization\n"));

+  DEBUG ((DEBUG_INFO, "IPMI Peim:IPMI STACK Initialization\n"));

   mIpmiInstance->KcsTimeoutPeriod = (BMC_KCS_TIMEOUT_PEI *1000*1000) / KCS_DELAY_UNIT_PEI;

-  DEBUG ((EFI_D_INFO,"IPMI Peim:KcsTimeoutPeriod = 0x%x\n", mIpmiInstance->KcsTimeoutPeriod));

+  DEBUG ((EFI_D_INFO, "IPMI Peim:KcsTimeoutPeriod = 0x%x\n", mIpmiInstance->KcsTimeoutPeriod));



   //

   // Initialize IPMI IO Base.

   //

-  mIpmiInstance->IpmiIoBase                         = PcdGet16 (PcdIpmiIoBaseAddress);

-  DEBUG ((EFI_D_INFO,"IPMI Peim:IpmiIoBase=0x%x\n",mIpmiInstance->IpmiIoBase));

+  mIpmiInstance->IpmiIoBase = PcdGet16 (PcdIpmiIoBaseAddress);

+  DEBUG ((EFI_D_INFO, "IPMI Peim:IpmiIoBase=0x%x\n", mIpmiInstance->IpmiIoBase));

   mIpmiInstance->Signature                          = SM_IPMI_BMC_SIGNATURE;

   mIpmiInstance->SlaveAddress                       = BMC_SLAVE_ADDRESS;

   mIpmiInstance->BmcStatus                          = BMC_NOTREADY;

   mIpmiInstance->IpmiTransportPpi.IpmiSubmitCommand = PeiIpmiSendCommand;

   mIpmiInstance->IpmiTransportPpi.GetBmcStatus      = PeiGetIpmiBmcStatus;



-  mIpmiInstance->PeiIpmiBmcDataDesc.Flags         = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;

-  mIpmiInstance->PeiIpmiBmcDataDesc.Guid          = &gPeiIpmiTransportPpiGuid;

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

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

+  mIpmiInstance->PeiIpmiBmcDataDesc.Guid  = &gPeiIpmiTransportPpiGuid;

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



-  //

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

-  //

-  Status = GetDeviceId (mIpmiInstance);

-  if (EFI_ERROR (Status)) {

-    DEBUG ((EFI_D_ERROR,"IPMI Peim:Get BMC Device Id Failed. Status=%r\n",Status));

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

+    //

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

+    //

+    Status = GetDeviceId (mIpmiInstance);

+    if (EFI_ERROR (Status)) {

+      DEBUG ((EFI_D_ERROR, "IPMI Peim:Get BMC Device Id Failed. Status=%r\n", Status));

+    }

+

+    //

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

+    //

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

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

+      if (EFI_ERROR (Status)) {

+        return Status;

+      }

+    }

   }



-  //

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

-  //

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

-    return EFI_UNSUPPORTED;

+  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->IpmiTransport2Ppi.Interface.KcsInterfaceState = IpmiInterfaceInitialized;

+            Status                                                       = CheckSelfTestByInterfaceType (

+                                                                                                         &mIpmiInstance->IpmiTransport2Ppi,

+                                                                                                         &BmcStatus,

+                                                                                                         SysInterfaceKcs

+                                                                                                         );

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

+              InterfaceState = IpmiInterfaceInitialized;

+            } else {

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

+            }

+          }

+

+          break;

+    }

+

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

+        case SysInterfaceBt:

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

+            InterfaceState = IpmiInterfaceInitialized;

+          }

+

+          break;

+    }

+

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

+        case SysInterfaceSsif:

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

+            InterfaceState = IpmiInterfaceInitialized;

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

+            // Register protocol notify for SMBUS Protocol.

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

+          }

+

+          break;

+    }

+

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

+        case SysInterfaceIpmb:

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

+            InterfaceState = IpmiInterfaceInitialized;

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

+            // Register protocol notify for SMBUS Protocol.

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

+          }

+

+          break;

+    }

+

+      default:

+        break;

+    }

   }



-  //

-  // Just produce PPI

-  //

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

-  if (EFI_ERROR (Status)) {

-    return Status;

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

+  if (InterfaceState != IpmiInterfaceInitialized) {

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

+    return EFI_SUCCESS;

   }



-  return EFI_SUCCESS;

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

+  mIpmiInstance->PeiIpmi2BmcDataDesc.Guid  = &gPeiIpmiTransport2PpiGuid;

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

+

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

+  return Status;

 }



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

@@ -119,29 +425,29 @@ PeiInitializeIpmiKcsPhysicalLayer (
 **/

 EFI_STATUS

 SendPreBootSignaltoBmc (

-  IN CONST EFI_PEI_SERVICES             **PeiServices

+  IN CONST EFI_PEI_SERVICES  **PeiServices

   )

 {

-  EFI_STATUS                        Status;

-  EFI_PEI_CPU_IO_PPI                *CpuIoPpi;

-  UINT32                            ProvisionPort = 0;

-  UINT8                             PreBoot = 0;

+  EFI_STATUS          Status;

+  EFI_PEI_CPU_IO_PPI  *CpuIoPpi;

+  UINT32              ProvisionPort = 0;

+  UINT8               PreBoot       = 0;



   //

   // Locate CpuIo service

   //

-  CpuIoPpi = (**PeiServices).CpuIo;

+  CpuIoPpi      = (**PeiServices).CpuIo;

   ProvisionPort = PcdGet32 (PcdSioMailboxBaseAddress) + MBXDAT_B;

-  PreBoot = 0x01;// PRE-BOOT

+  PreBoot       = 0x01;// PRE-BOOT



   Status = CpuIoPpi->Io.Write (

-                          PeiServices,

-                          CpuIoPpi,

-                          EfiPeiCpuIoWidthUint8,

-                          ProvisionPort,

-                          1,

-                          &PreBoot

-                          );

+                               PeiServices,

+                               CpuIoPpi,

+                               EfiPeiCpuIoWidthUint8,

+                               ProvisionPort,

+                               1,

+                               &PreBoot

+                               );

   if (EFI_ERROR (Status)) {

     DEBUG ((EFI_D_ERROR, "SendPreBootSignaltoBmc () Write PRE-BOOT Status=%r\n", Status));

     return Status;

@@ -175,68 +481,13 @@ PeimIpmiInterfaceInit (
   return Status;

 } // PeimIpmiInterfaceInit()



-

-EFI_STATUS

-PeiIpmiSendCommand (

-  IN      PEI_IPMI_TRANSPORT_PPI       *This,

-  IN      UINT8                        NetFunction,

-  IN      UINT8                        Lun,

-  IN      UINT8                        Command,

-  IN      UINT8                        *CommandData,

-  IN      UINT32                       CommandDataSize,

-  IN OUT  UINT8                        *ResponseData,

-  IN OUT  UINT32                       *ResponseDataSize

-  )

-/*++

-

-Routine Description:

-

-  Send Ipmi Command in the right mode: HECI or KCS,  to the

-  appropiate device, ME or BMC.

-

-Arguments:

-

-  This              - Pointer to IPMI protocol instance

-  NetFunction       - Net Function of command to send

-  Lun               - LUN of command to send

-  Command           - IPMI command to send

-  CommandData       - Pointer to command data buffer, if needed

-  CommandDataSize   - Size of command data buffer

-  ResponseData      - Pointer to response data buffer

-  ResponseDataSize  - Pointer to response data buffer size

-

-Returns:

-

-  EFI_INVALID_PARAMETER - One of the input values is bad

-  EFI_DEVICE_ERROR      - IPMI command failed

-  EFI_BUFFER_TOO_SMALL  - Response buffer is too small

-  EFI_UNSUPPORTED       - Command is not supported by BMC

-  EFI_SUCCESS           - Command completed successfully

-

---*/

-{

-  //

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

-  //

-  return PeiIpmiSendCommandToBmc (

-           This,

-           NetFunction,

-           Lun,

-           Command,

-           CommandData,

-           (UINT8) CommandDataSize,

-           ResponseData,

-           (UINT8 *) ResponseDataSize,

-           NULL

-           );

-} // IpmiSendCommand()

-

 EFI_STATUS

 PeiGetIpmiBmcStatus (

-  IN      PEI_IPMI_TRANSPORT_PPI       *This,

-  OUT BMC_STATUS                       *BmcStatus,

-  OUT SM_COM_ADDRESS                   *ComAddress

+  IN      PEI_IPMI_TRANSPORT_PPI  *This,

+  OUT BMC_STATUS                  *BmcStatus,

+  OUT SM_COM_ADDRESS              *ComAddress

   )

+

 /*++



 Routine Description:

@@ -256,18 +507,18 @@ Returns:
 --*/

 {

   return PeiIpmiBmcStatus (

-           This,

-           BmcStatus,

-           ComAddress,

-           NULL

-           );

+                           This,

+                           BmcStatus,

+                           ComAddress,

+                           NULL

+                           );

 }



-

 EFI_STATUS

 GetDeviceId (

-  IN      PEI_IPMI_BMC_INSTANCE_DATA   *mIpmiInstance

+  IN      PEI_IPMI_BMC_INSTANCE_DATA  *mIpmiInstance

   )

+

 /*++



 Routine Description:

@@ -284,11 +535,11 @@ Returns:


 --*/

 {

-  EFI_STATUS          Status;

-  UINT32              DataSize;

-  SM_CTRL_INFO        *pBmcInfo;

-  UINTN               Retries;

-  UINT8               TempData[MAX_TEMP_DATA];

+  EFI_STATUS    Status;

+  UINT32        DataSize;

+  SM_CTRL_INFO  *pBmcInfo;

+  UINTN         Retries;

+  UINT8         TempData[MAX_TEMP_DATA];



   //

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

@@ -300,32 +551,41 @@ Returns:
   // Get the device ID information for the BMC.

   //

   DataSize = sizeof (TempData);

-  while (EFI_ERROR (Status = PeiIpmiSendCommand (

-                               &mIpmiInstance->IpmiTransportPpi,

-                               IPMI_NETFN_APP,

-                               0,

-                               IPMI_APP_GET_DEVICE_ID,

-                               NULL,

-                               0,

-                               TempData,

-                               &DataSize

-                               ))) {

-    DEBUG ((EFI_D_ERROR, "[IPMI] BMC does not respond (status: %r), %d retries left\n",

-            Status, Retries));

+  while (EFI_ERROR (

+                    Status = PeiIpmiSendCommand (

+                                                 &mIpmiInstance->IpmiTransportPpi,

+                                                 IPMI_NETFN_APP,

+                                                 0,

+                                                 IPMI_APP_GET_DEVICE_ID,

+                                                 NULL,

+                                                 0,

+                                                 TempData,

+                                                 &DataSize

+                                                 )

+                    ))

+  {

+    DEBUG (

+           (EFI_D_ERROR, "[IPMI] BMC does not respond (status: %r), %d retries left\n",

+            Status, Retries)

+           );



     if (Retries-- == 0) {

       ReportStatusCode (EFI_ERROR_CODE | EFI_ERROR_MAJOR, EFI_COMPUTING_UNIT_FIRMWARE_PROCESSOR | EFI_CU_FP_EC_COMM_ERROR);

       mIpmiInstance->BmcStatus = BMC_HARDFAIL;

       return Status;

     }

+

     //

     // 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 ((DEBUG_INFO, "[IPMI PEI] 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 (

+         (DEBUG_INFO, "[IPMI PEI] 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.

@@ -339,20 +599,20 @@ Returns:
     // Updatemode = 1 mean BMC is not ready, continue waiting.

     //

     while (Retries-- != 0) {

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

-      DEBUG ((DEBUG_INFO, "[IPMI PEI] UpdateMode Retries:%x \n",Retries));

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

+      DEBUG ((DEBUG_INFO, "[IPMI PEI] UpdateMode Retries:%x \n", Retries));

       Status = PeiIpmiSendCommand (

-                 &mIpmiInstance->IpmiTransportPpi,

-                 IPMI_NETFN_APP,

-                 0,

-                 IPMI_APP_GET_DEVICE_ID,

-                 NULL,

-                 0,

-                 TempData,

-                 &DataSize

-                 );

+                                   &mIpmiInstance->IpmiTransportPpi,

+                                   IPMI_NETFN_APP,

+                                   0,

+                                   IPMI_APP_GET_DEVICE_ID,

+                                   NULL,

+                                   0,

+                                   TempData,

+                                   &DataSize

+                                   );

       if (!EFI_ERROR (Status)) {

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

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

         DEBUG ((DEBUG_INFO, "[IPMI PEI] UpdateMode Retries:%x   pBmcInfo->UpdateMode:%x\n", Retries, pBmcInfo->UpdateMode));

         if (pBmcInfo->UpdateMode == BMC_READY) {

           mIpmiInstance->BmcStatus = BMC_OK;

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


   @copyright

   Copyright 2017 - 2021 Intel Corporation. <BR>

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

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

 **/



@@ -23,49 +24,53 @@
 #include <Library/PeiServicesTablePointerLib.h>

 #include <Library/TimerLib.h>

 #include <Library/PciLib.h>

+#include <Library/HobLib.h>



+#include "PeiIpmiHooks.h"

 #include "PeiIpmiBmcDef.h"

 #include "PeiIpmiBmc.h"



 //

 // Prototypes

 //

-#define MBXDAT_B                          0x0B

-#define BMC_KCS_TIMEOUT_PEI               5     // [s] Single KSC request timeout

-#define KCS_DELAY_UNIT_PEI                1000  // [s] Each KSC IO delay

-#define IPMI_DEFAULT_IO_BASE              0xCA2

+#define MBXDAT_B              0x0B

+#define BMC_KCS_TIMEOUT_PEI   5                 // [s] Single KSC request timeout

+#define KCS_DELAY_UNIT_PEI    1000              // [s] Each KSC IO delay

+#define IPMI_DEFAULT_IO_BASE  0xCA2



 //

 // Internal(hook) function list

 //

 EFI_STATUS

 SendPreBootSignaltoBmc (

-  IN CONST EFI_PEI_SERVICES             **PeiServices

+  IN CONST EFI_PEI_SERVICES  **PeiServices

   )

-  /*++

+

+/*++



 Routine Description:

-  Send Pre-Boot signal to BMC

+Send Pre-Boot signal to BMC



 Arguments:

-  PeiServices           - General purpose services available to every PEIM.

+PeiServices           - General purpose services available to every PEIM.



 Returns:

-  EFI_SUCCESS           - Success

+EFI_SUCCESS           - Success

 --*/

 ;



 EFI_STATUS

 PeiIpmiSendCommand (

-  IN      PEI_IPMI_TRANSPORT_PPI       *This,

-  IN      UINT8                        NetFunction,

-  IN      UINT8                        Lun,

-  IN      UINT8                        Command,

-  IN      UINT8                        *CommandData,

-  IN      UINT32                       CommandDataSize,

-  IN OUT  UINT8                        *ResponseData,

-  IN OUT  UINT32                       *ResponseDataSize

+  IN      PEI_IPMI_TRANSPORT_PPI  *This,

+  IN      UINT8                   NetFunction,

+  IN      UINT8                   Lun,

+  IN      UINT8                   Command,

+  IN      UINT8                   *CommandData,

+  IN      UINT32                  CommandDataSize,

+  IN OUT  UINT8                   *ResponseData,

+  IN OUT  UINT32                  *ResponseDataSize

   )

+

 /*++



 Routine Description:

@@ -92,10 +97,11 @@ Returns:


 EFI_STATUS

 PeiGetIpmiBmcStatus (

-  IN  PEI_IPMI_TRANSPORT_PPI                           *This,

-  OUT BMC_STATUS                                       *BmcStatus,

-  OUT SM_COM_ADDRESS                                   *ComAddress

+  IN  PEI_IPMI_TRANSPORT_PPI  *This,

+  OUT BMC_STATUS              *BmcStatus,

+  OUT SM_COM_ADDRESS          *ComAddress

   )

+

 /*++



 Routine Description:

@@ -116,8 +122,9 @@ Returns:
 //

 EFI_STATUS

 GetDeviceId (

-  IN      PEI_IPMI_BMC_INSTANCE_DATA   *mIpmiInstance

+  IN      PEI_IPMI_BMC_INSTANCE_DATA  *mIpmiInstance

   )

+

 /*++



 Routine Description:

@@ -134,5 +141,29 @@ Returns:


 --*/

 ;

-#endif //_PEI_IPMI_INIT_H_



+EFI_STATUS

+EFIAPI

+UpdateIpmiInstancePtr (

+  IN EFI_PEI_SERVICES           **PeiServices,

+  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,

+  IN VOID                       *Ppi

+  )

+

+/*++

+

+Routine Description:

+  After memory is discovered, update the IPMI Instance pointer in Hob.

+

+Arguments:

+  PeiServices      - Describes the list of possible PEI Services.

+  NotifyDescriptor - PPointer to notify descriptor..

+  Ppi              - Pointer to Ppi.

+

+Returns:

+  Status

+

+--*/

+;

+

+#endif //_PEI_IPMI_INIT_H_

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

 # @copyright

 # Copyright 2017 - 2021 Intel Corporation. <BR>

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

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

 ##



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

   PeiGenericIpmi.c

   PeiGenericIpmi.h

+  PeiIpmiHooks.c

+  PeiIpmiHooks.h



 [Packages]

   MdePkg/MdePkg.dec

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

   TimerLib

   IpmiPlatformHookLib

+  HobLib

+  BmcCommonInterfaceLib

+  BtInterfaceLib

+  SsifInterfaceLib

+  IpmbInterfaceLib



 [Guids]

+  gPeiIpmiHobGuid



 [Ppis]

   gPeiIpmiTransportPpiGuid       #ALWAYS PRODUCE

+  gPeiIpmiTransport2PpiGuid

+  gEfiPeiMemoryDiscoveredPpiGuid #CONSUMES



 [Pcd]

   gIpmiFeaturePkgTokenSpaceGuid.PcdIpmiIoBaseAddress

   gIpmiFeaturePkgTokenSpaceGuid.PcdIpmiBmcReadyDelayTimer

   gIpmiFeaturePkgTokenSpaceGuid.PcdSioMailboxBaseAddress

   gIpmiFeaturePkgTokenSpaceGuid.PcdSignalPreBootToBmc

+  gIpmiFeaturePkgTokenSpaceGuid.PcdDefaultSystemInterface

+  gIpmiFeaturePkgTokenSpaceGuid.PcdBtInterfaceSupport

+  gIpmiFeaturePkgTokenSpaceGuid.PcdSsifInterfaceSupport

+  gIpmiFeaturePkgTokenSpaceGuid.PcdKcsInterfaceSupport

+  gIpmiFeaturePkgTokenSpaceGuid.PcdIpmbInterfaceSupport

+  gIpmiFeaturePkgTokenSpaceGuid.PcdBtControlPort



 [Depex]

   TRUE

diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiBmc.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiBmc.c
index dbe25421ae..01901764a9 100644
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiBmc.c
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiBmc.c
@@ -3,6 +3,7 @@


   @copyright

   Copyright 2016 - 2021 Intel Corporation. <BR>

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

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

 **/



@@ -10,9 +11,10 @@


 EFI_STATUS

 UpdateErrorStatus (

-  IN UINT8                      BmcError,

-  PEI_IPMI_BMC_INSTANCE_DATA    *IpmiInstance

+  IN UINT8                    BmcError,

+  PEI_IPMI_BMC_INSTANCE_DATA  *IpmiInstance

   )

+

 /*++



 Routine Description:

@@ -55,16 +57,17 @@ Returns:


 EFI_STATUS

 PeiIpmiSendCommandToBmc (

-  IN      PEI_IPMI_TRANSPORT_PPI        *This,

-  IN      UINT8                         NetFunction,

-  IN      UINT8                         Lun,

-  IN      UINT8                         Command,

-  IN      UINT8                         *CommandData,

-  IN      UINT8                         CommandDataSize,

-  IN OUT  UINT8                         *ResponseData,

-  IN OUT  UINT8                         *ResponseDataSize,

-  IN      VOID                          *Context

+  IN      PEI_IPMI_TRANSPORT_PPI  *This,

+  IN      UINT8                   NetFunction,

+  IN      UINT8                   Lun,

+  IN      UINT8                   Command,

+  IN      UINT8                   *CommandData,

+  IN      UINT8                   CommandDataSize,

+  IN OUT  UINT8                   *ResponseData,

+  IN OUT  UINT8                   *ResponseDataSize,

+  IN      VOID                    *Context

   )

+

 /*++



 Routine Description:

@@ -108,15 +111,15 @@ Returns:
   // response data.  Since the command format is different from the response

   // format, the buffer is cast to both structure definitions.

   //

-  IpmiCommand   = (IPMI_COMMAND*)  TempData;

-  IpmiResponse  = (IPMI_RESPONSE*) TempData;

+  IpmiCommand  = (IPMI_COMMAND *)TempData;

+  IpmiResponse = (IPMI_RESPONSE *)TempData;



   //

   // Send IPMI command to BMC

   //

-  IpmiCommand->Lun          = Lun;

-  IpmiCommand->NetFunction  = NetFunction;

-  IpmiCommand->Command      = Command;

+  IpmiCommand->Lun         = Lun;

+  IpmiCommand->NetFunction = NetFunction;

+  IpmiCommand->Command     = Command;



   //

   // Ensure that the buffer is valid before attempting to copy the command data

@@ -128,19 +131,19 @@ Returns:
     }



     CopyMem (

-      IpmiCommand->CommandData,

-      CommandData,

-      CommandDataSize

-      );

+             IpmiCommand->CommandData,

+             CommandData,

+             CommandDataSize

+             );

   }



   Status = SendDataToBmcPort (

-             IpmiInstance->KcsTimeoutPeriod,

-             IpmiInstance->IpmiIoBase,

-             Context,

-             (UINT8 *) IpmiCommand,

-             (CommandDataSize + IPMI_COMMAND_HEADER_SIZE)

-             );

+                              IpmiInstance->KcsTimeoutPeriod,

+                              IpmiInstance->IpmiIoBase,

+                              Context,

+                              (UINT8 *)IpmiCommand,

+                              (CommandDataSize + IPMI_COMMAND_HEADER_SIZE)

+                              );



   if (Status != EFI_SUCCESS) {

     IpmiInstance->BmcStatus = BMC_SOFTFAIL;

@@ -153,13 +156,13 @@ Returns:
   // Get Response to IPMI Command from BMC.

   //

   DataSize = MAX_TEMP_DATA;

-  Status = ReceiveBmcDataFromPort (

-             IpmiInstance->KcsTimeoutPeriod,

-             IpmiInstance->IpmiIoBase,

-             Context,

-             (UINT8 *) IpmiResponse,

-             &DataSize

-             );

+  Status   = ReceiveBmcDataFromPort (

+                                     IpmiInstance->KcsTimeoutPeriod,

+                                     IpmiInstance->IpmiIoBase,

+                                     Context,

+                                     (UINT8 *)IpmiResponse,

+                                     &DataSize

+                                     );



   if (Status != EFI_SUCCESS) {

     IpmiInstance->BmcStatus = BMC_SOFTFAIL;

@@ -169,15 +172,16 @@ Returns:
   }



   if ((IpmiResponse->CompletionCode != COMP_CODE_NORMAL) &&

-      (IpmiInstance->BmcStatus == BMC_UPDATE_IN_PROGRESS)) {

+      (IpmiInstance->BmcStatus == BMC_UPDATE_IN_PROGRESS))

+  {

     //

     // If the completion code is not normal and the BMC is in Force Update

     // mode, then update the error status and return EFI_UNSUPPORTED.

     //

     UpdateErrorStatus (

-      IpmiResponse->CompletionCode,

-      IpmiInstance

-      );

+                       IpmiResponse->CompletionCode,

+                       IpmiInstance

+                       );

     return EFI_UNSUPPORTED;

   } else if (IpmiResponse->CompletionCode != COMP_CODE_NORMAL) {

     //

@@ -185,9 +189,9 @@ Returns:
     // is not normal, then update the error status and return device error.

     //

     UpdateErrorStatus (

-      IpmiResponse->CompletionCode,

-      IpmiInstance

-      );

+                       IpmiResponse->CompletionCode,

+                       IpmiInstance

+                       );

     return EFI_DEVICE_ERROR;

   }



@@ -215,32 +219,33 @@ Returns:
   //

   *ResponseDataSize = DataSize - IPMI_RESPONSE_HEADER_SIZE;

   CopyMem (

-    ResponseData,

-    IpmiResponse->ResponseData,

-    *ResponseDataSize

-    );

+           ResponseData,

+           IpmiResponse->ResponseData,

+           *ResponseDataSize

+           );



   //

   // Add completion code in response data to meet the requirement of IPMI spec 2.0

   //

   *ResponseDataSize += 1; // Add one byte for Completion Code

   for (Index = 1; Index < *ResponseDataSize; Index++) {

-    ResponseData [*ResponseDataSize - Index] = ResponseData [*ResponseDataSize - (Index + 1)];

+    ResponseData[*ResponseDataSize - Index] = ResponseData[*ResponseDataSize - (Index + 1)];

   }

-  ResponseData [0] = IpmiResponse->CompletionCode;

+

+  ResponseData[0] = IpmiResponse->CompletionCode;



   IpmiInstance->BmcStatus = BMC_OK;

   return EFI_SUCCESS;

 }



-

 EFI_STATUS

-PeiIpmiBmcStatus (

-  IN  PEI_IPMI_TRANSPORT_PPI          *This,

-  OUT BMC_STATUS                  *BmcStatus,

-  OUT SM_COM_ADDRESS              *ComAddress,

-  IN  VOID                            *Context

+IpmiBmcStatus (

+  IN  PEI_IPMI_TRANSPORT_PPI  *This,

+  OUT BMC_STATUS              *BmcStatus,

+  OUT SM_COM_ADDRESS          *ComAddress,

+  IN  VOID                    *Context

   )

+

 /*++



 Routine Description:

@@ -268,10 +273,10 @@ Returns:
     IpmiInstance->BmcStatus = BMC_HARDFAIL;

   }



-  *BmcStatus = IpmiInstance->BmcStatus;

-  ComAddress->ChannelType = SmBmc;

-  ComAddress->Address.BmcAddress.LunAddress = 0x0;

-  ComAddress->Address.BmcAddress.SlaveAddress = IpmiInstance->SlaveAddress;

+  *BmcStatus                                    = IpmiInstance->BmcStatus;

+  ComAddress->ChannelType                       = SmBmc;

+  ComAddress->Address.BmcAddress.LunAddress     = 0x0;

+  ComAddress->Address.BmcAddress.SlaveAddress   = IpmiInstance->SlaveAddress;

   ComAddress->Address.BmcAddress.ChannelAddress = 0x0;



   return EFI_SUCCESS;

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


   @copyright

   Copyright 2016 - 2021 Intel Corporation. <BR>

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

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

 **/



@@ -25,7 +26,7 @@
 //

 // 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 INSTANCE_FROM_PEI_SM_IPMI_BMC_THIS(a) \

   CR ( \

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

   )



+#define INSTANCE_FROM_PEI_IPMI_TRANSPORT2_THIS(a) \

+  CR ( \

+  a, \

+  PEI_IPMI_BMC_INSTANCE_DATA, \

+  IpmiTransport2Ppi, \

+  SM_IPMI_BMC_SIGNATURE \

+  )

+

 #endif // _PEI_IPMI_BMC_H_

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


   @copyright

   Copyright 2016 - 2021 Intel Corporation. <BR>

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

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

 **/



@@ -10,11 +11,13 @@
 #define _PEI_IPMI_COMMON_BMC_H_



 #include <Ppi/IpmiTransportPpi.h>

+#include <Ppi/IpmiTransport2Ppi.h>

+#include "ServerManagement.h"



-#define MAX_TEMP_DATA     160

-#define BMC_SLAVE_ADDRESS 0x20

-#define MAX_SOFT_COUNT    10

-#define COMP_CODE_NORMAL  0x00

+#define MAX_TEMP_DATA      160

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

@@ -46,15 +49,17 @@
 // Pei Ipmi instance data

 //

 typedef struct {

-  UINTN                  Signature;

-  UINT64                 KcsTimeoutPeriod;

-  UINT8                  SlaveAddress;

-  BMC_STATUS             BmcStatus;

-  UINT64                 ErrorStatus;

-  UINT8                  SoftErrorCount;

-  UINT16                 IpmiIoBase;

-  PEI_IPMI_TRANSPORT_PPI IpmiTransportPpi;

-  EFI_PEI_PPI_DESCRIPTOR PeiIpmiBmcDataDesc;

+  UINTN                     Signature;

+  UINT64                    KcsTimeoutPeriod;

+  UINT8                     SlaveAddress;

+  BMC_STATUS                BmcStatus;

+  UINT64                    ErrorStatus;

+  UINT8                     SoftErrorCount;

+  UINT16                    IpmiIoBase;

+  PEI_IPMI_TRANSPORT_PPI    IpmiTransportPpi;

+  IPMI_TRANSPORT2           IpmiTransport2Ppi;

+  EFI_PEI_PPI_DESCRIPTOR    PeiIpmiBmcDataDesc;

+  EFI_PEI_PPI_DESCRIPTOR    PeiIpmi2BmcDataDesc;

 } PEI_IPMI_BMC_INSTANCE_DATA;



 //

@@ -63,38 +68,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;

 #pragma pack()



 EFI_STATUS

 PeiIpmiSendCommandToBmc (

-  IN      PEI_IPMI_TRANSPORT_PPI        *This,

-  IN      UINT8                         NetFunction,

-  IN      UINT8                         Lun,

-  IN      UINT8                         Command,

-  IN      UINT8                         *CommandData,

-  IN      UINT8                         CommandDataSize,

-  IN OUT  UINT8                         *ResponseData,

-  IN OUT  UINT8                         *ResponseDataSize,

-  IN      VOID                          *Context

+  IN      PEI_IPMI_TRANSPORT_PPI  *This,

+  IN      UINT8                   NetFunction,

+  IN      UINT8                   Lun,

+  IN      UINT8                   Command,

+  IN      UINT8                   *CommandData,

+  IN      UINT8                   CommandDataSize,

+  IN OUT  UINT8                   *ResponseData,

+  IN OUT  UINT8                   *ResponseDataSize,

+  IN      VOID                    *Context

   )

+

 /*++



 Routine Description:

@@ -123,14 +129,14 @@ Returns:
 --*/

 ;



-

 EFI_STATUS

 PeiIpmiBmcStatus (

-  IN      PEI_IPMI_TRANSPORT_PPI       *This,

-  OUT BMC_STATUS                       *BmcStatus,

-  OUT SM_COM_ADDRESS                   *ComAddress,

-  IN  VOID                             *Context

+  IN      PEI_IPMI_TRANSPORT_PPI  *This,

+  OUT BMC_STATUS                  *BmcStatus,

+  OUT SM_COM_ADDRESS              *ComAddress,

+  IN  VOID                        *Context

   )

+

 /*++



 Routine Description:

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

 ;



+typedef struct _PEI_IPMI_DATA_HOB PEI_IPMI_DATA_HOB;

+

+struct _PEI_IPMI_DATA_HOB {

+  UINTN                IpmiInstance;                   /// IpmiInstance pointer.

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

+};



 #endif //_PEI_IPMI_COMMON_BMC_H_

diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiHooks.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiHooks.c
new file mode 100644
index 0000000000..f5a933d35c
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiHooks.c
@@ -0,0 +1,346 @@
+/** @file
+  IPMI common hook functions
+
+  @copyright
+  Copyright 1999 - 2021 Intel Corporation. <BR>
+  Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <ServerManagement.h>
+#include <PeiIpmiHooks.h>
+
+EFI_STATUS
+PeiIpmiSendCommand (
+  IN      PEI_IPMI_TRANSPORT_PPI  *This,
+  IN      UINT8                   NetFunction,
+  IN      UINT8                   Lun,
+  IN      UINT8                   Command,
+  IN      UINT8                   *CommandData,
+  IN      UINT32                  CommandDataSize,
+  IN OUT  UINT8                   *ResponseData,
+  IN OUT  UINT32                  *ResponseDataSize
+  )
+
+/*++
+
+Routine Description:
+
+  Send Ipmi Command in the right mode: HECI or KCS,  to the
+  appropiate device, ME or BMC.
+
+Arguments:
+
+  This              - Pointer to IPMI protocol instance
+  NetFunction       - Net Function of command to send
+  Lun               - LUN of command to send
+  Command           - IPMI command to send
+  CommandData       - Pointer to command data buffer, if needed
+  CommandDataSize   - Size of command data buffer
+  ResponseData      - Pointer to response data buffer
+  ResponseDataSize  - Pointer to response data buffer size
+
+Returns:
+
+  EFI_INVALID_PARAMETER - One of the input values is bad
+  EFI_DEVICE_ERROR      - IPMI command failed
+  EFI_BUFFER_TOO_SMALL  - Response buffer is too small
+  EFI_UNSUPPORTED       - Command is not supported by BMC
+  EFI_SUCCESS           - Command completed successfully
+
+--*/
+{
+  if (This == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // This Will be unchanged ( BMC/KCS style )
+  //
+  return PeiIpmiSendCommandToBmc (
+                                  This,
+                                  NetFunction,
+                                  Lun,
+                                  Command,
+                                  CommandData,
+                                  (UINT8)CommandDataSize,
+                                  ResponseData,
+                                  (UINT8 *)ResponseDataSize,
+                                  NULL
+                                  );
+} // IpmiSendCommand()
+
+EFI_STATUS
+PeiIpmiSendCommand2 (
+  IN      IPMI_TRANSPORT2  *This,
+  IN      UINT8            NetFunction,
+  IN      UINT8            Lun,
+  IN      UINT8            Command,
+  IN      UINT8            *CommandData,
+  IN      UINT32           CommandDataSize,
+  IN OUT  UINT8            *ResponseData,
+  IN OUT  UINT32           *ResponseDataSize
+  )
+
+/*++
+
+Routine Description:
+
+  This API use the default interface (PcdDefaultSystemInterface) to send IPMI command
+  in the right mode to the appropiate device, ME or BMC.
+
+Arguments:
+
+  This              - Pointer to IPMI protocol instance
+  NetFunction       - Net Function of command to send
+  Lun               - LUN of command to send
+  Command           - IPMI command to send
+  CommandData       - Pointer to command data buffer, if needed
+  CommandDataSize   - Size of command data buffer
+  ResponseData      - Pointer to response data buffer
+  ResponseDataSize  - Pointer to response data buffer size
+
+Returns:
+
+  EFI_INVALID_PARAMETER - One of the input values is bad
+  EFI_DEVICE_ERROR      - IPMI command failed
+  EFI_BUFFER_TOO_SMALL  - Response buffer is too small
+  EFI_UNSUPPORTED       - Command is not supported by BMC
+  EFI_SUCCESS           - Command completed successfully
+
+--*/
+{
+  PEI_IPMI_BMC_INSTANCE_DATA  *PeiIpmiInstance;
+
+  if (This == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  PeiIpmiInstance = INSTANCE_FROM_PEI_IPMI_TRANSPORT2_THIS (This);
+
+  if ((FixedPcdGet8 (PcdKcsInterfaceSupport) == 1) &&
+      ((PeiIpmiInstance->IpmiTransport2Ppi.InterfaceType == SysInterfaceKcs) &&
+       (PeiIpmiInstance->IpmiTransport2Ppi.Interface.KcsInterfaceState == IpmiInterfaceInitialized)))
+  {
+    return PeiIpmiSendCommand (
+                               &PeiIpmiInstance->IpmiTransportPpi,
+                               NetFunction,
+                               Lun,
+                               Command,
+                               CommandData,
+                               CommandDataSize,
+                               ResponseData,
+                               ResponseDataSize
+                               );
+  }
+
+  if ((FixedPcdGet8 (PcdBtInterfaceSupport) == 1) &&
+      ((PeiIpmiInstance->IpmiTransport2Ppi.InterfaceType == SysInterfaceBt) &&
+       (PeiIpmiInstance->IpmiTransport2Ppi.Interface.Bt.InterfaceState == IpmiInterfaceInitialized)))
+  {
+    return IpmiBtSendCommandToBmc (
+                                   &PeiIpmiInstance->IpmiTransport2Ppi,
+                                   NetFunction,
+                                   Lun,
+                                   Command,
+                                   CommandData,
+                                   (UINT8)CommandDataSize,
+                                   ResponseData,
+                                   (UINT8 *)ResponseDataSize,
+                                   NULL
+                                   );
+  }
+
+  if ((FixedPcdGet8 (PcdSsifInterfaceSupport) == 1) &&
+      ((PeiIpmiInstance->IpmiTransport2Ppi.InterfaceType == SysInterfaceSsif) &&
+       (PeiIpmiInstance->IpmiTransport2Ppi.Interface.Ssif.InterfaceState == IpmiInterfaceInitialized)))
+  {
+    return IpmiSsifSendCommandToBmc (
+                                     &PeiIpmiInstance->IpmiTransport2Ppi,
+                                     NetFunction,
+                                     Lun,
+                                     Command,
+                                     CommandData,
+                                     (UINT8)CommandDataSize,
+                                     ResponseData,
+                                     (UINT8 *)ResponseDataSize,
+                                     NULL
+                                     );
+  }
+
+  if ((FixedPcdGet8 (PcdIpmbInterfaceSupport) == 1) &&
+      ((PeiIpmiInstance->IpmiTransport2Ppi.InterfaceType == SysInterfaceIpmb) &&
+       (PeiIpmiInstance->IpmiTransport2Ppi.Interface.Ipmb.InterfaceState == IpmiInterfaceInitialized)))
+  {
+    return IpmiIpmbSendCommandToBmc (
+                                     &PeiIpmiInstance->IpmiTransport2Ppi,
+                                     NetFunction,
+                                     Lun,
+                                     Command,
+                                     CommandData,
+                                     (UINT8)CommandDataSize,
+                                     ResponseData,
+                                     (UINT8 *)ResponseDataSize,
+                                     NULL
+                                     );
+  }
+
+  return EFI_UNSUPPORTED;
+} // IpmiSendCommand()
+
+EFI_STATUS
+PeiIpmiSendCommand2Ex (
+  IN      IPMI_TRANSPORT2        *This,
+  IN      UINT8                  NetFunction,
+  IN      UINT8                  Lun,
+  IN      UINT8                  Command,
+  IN      UINT8                  *CommandData,
+  IN      UINT32                 CommandDataSize,
+  IN OUT  UINT8                  *ResponseData,
+  IN OUT  UINT32                 *ResponseDataSize,
+  IN      SYSTEM_INTERFACE_TYPE  InterfaceType
+  )
+{
+  /*++
+  Routine Description:
+
+    This API use the specific interface type to send IPMI command
+    in the right mode to the appropiate device, ME or BMC.
+
+  Arguments:
+
+    This              - Pointer to IPMI protocol instance
+    NetFunction       - Net Function of command to send
+    Lun               - LUN of command to send
+    Command           - IPMI command to send
+    CommandData       - Pointer to command data buffer, if needed
+    CommandDataSize   - Size of command data buffer
+    ResponseData      - Pointer to response data buffer
+    ResponseDataSize  - Pointer to response data buffer size
+    InterfaceType     - BMC Interface type.
+
+  Returns:
+
+    EFI_INVALID_PARAMETER - One of the input values is bad
+    EFI_DEVICE_ERROR      - IPMI command failed
+    EFI_BUFFER_TOO_SMALL  - Response buffer is too small
+    EFI_UNSUPPORTED       - Command is not supported by BMC
+    EFI_SUCCESS           - Command completed successfully
+
+  --*/
+
+  PEI_IPMI_BMC_INSTANCE_DATA  *PeiIpmiInstance;
+
+  if (This == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  PeiIpmiInstance = INSTANCE_FROM_PEI_IPMI_TRANSPORT2_THIS (This);
+
+  if ((FixedPcdGet8 (PcdKcsInterfaceSupport) == 1) &&
+      ((InterfaceType == SysInterfaceKcs) &&
+       (PeiIpmiInstance->IpmiTransport2Ppi.Interface.KcsInterfaceState == IpmiInterfaceInitialized)))
+  {
+    return PeiIpmiSendCommand (
+                               &PeiIpmiInstance->IpmiTransportPpi,
+                               NetFunction,
+                               Lun,
+                               Command,
+                               CommandData,
+                               CommandDataSize,
+                               ResponseData,
+                               ResponseDataSize
+                               );
+  }
+
+  if ((FixedPcdGet8 (PcdBtInterfaceSupport) == 1) &&
+      ((InterfaceType == SysInterfaceBt) &&
+       (PeiIpmiInstance->IpmiTransport2Ppi.Interface.Bt.InterfaceState == IpmiInterfaceInitialized)))
+  {
+    return IpmiBtSendCommandToBmc (
+                                   &PeiIpmiInstance->IpmiTransport2Ppi,
+                                   NetFunction,
+                                   Lun,
+                                   Command,
+                                   CommandData,
+                                   (UINT8)CommandDataSize,
+                                   ResponseData,
+                                   (UINT8 *)ResponseDataSize,
+                                   NULL
+                                   );
+  }
+
+  if ((FixedPcdGet8 (PcdSsifInterfaceSupport) == 1) &&
+      ((InterfaceType == SysInterfaceSsif) &&
+       (PeiIpmiInstance->IpmiTransport2Ppi.Interface.Ssif.InterfaceState == IpmiInterfaceInitialized)))
+  {
+    return IpmiSsifSendCommandToBmc (
+                                     &PeiIpmiInstance->IpmiTransport2Ppi,
+                                     NetFunction,
+                                     Lun,
+                                     Command,
+                                     CommandData,
+                                     (UINT8)CommandDataSize,
+                                     ResponseData,
+                                     (UINT8 *)ResponseDataSize,
+                                     NULL
+                                     );
+  }
+
+  if ((FixedPcdGet8 (PcdIpmbInterfaceSupport) == 1) &&
+      ((InterfaceType == SysInterfaceIpmb) &&
+       (PeiIpmiInstance->IpmiTransport2Ppi.Interface.Ipmb.InterfaceState == IpmiInterfaceInitialized)))
+  {
+    return IpmiIpmbSendCommandToBmc (
+                                     &PeiIpmiInstance->IpmiTransport2Ppi,
+                                     NetFunction,
+                                     Lun,
+                                     Command,
+                                     CommandData,
+                                     (UINT8)CommandDataSize,
+                                     ResponseData,
+                                     (UINT8 *)ResponseDataSize,
+                                     NULL
+                                     );
+  }
+
+  return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+PeiIpmiBmcStatus (
+  IN  PEI_IPMI_TRANSPORT_PPI  *This,
+  OUT BMC_STATUS              *BmcStatus,
+  OUT SM_COM_ADDRESS          *ComAddress,
+  IN  VOID                    *Context
+  )
+
+/*++
+
+Routine Description:
+
+  Updates the BMC status and returns the Com Address
+
+Arguments:
+
+  This        - Pointer to IPMI protocol instance
+  BmcStatus   - BMC status
+  ComAddress  - Com Address
+
+Returns:
+
+  EFI_SUCCESS - Success
+
+--*/
+{
+  if ((This == NULL) || (BmcStatus == NULL) || (ComAddress == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return IpmiBmcStatus (
+                        This,
+                        BmcStatus,
+                        ComAddress,
+                        NULL
+                        );
+}
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiHooks.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiHooks.h
new file mode 100644
index 0000000000..25be1fd94a
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericIpmi/Pei/PeiIpmiHooks.h
@@ -0,0 +1,218 @@
+/** @file
+  IPMI common hook functions head file
+
+  @copyright
+  Copyright 2016 - 2021 Intel Corporation. <BR>
+  Copyright (c) 1985 - 2023, American Megatrends International LLC. <BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _IPMI_HOOKS_H
+#define _IPMI_HOOKS_H
+
+#include <Ppi/IpmiTransportPpi.h>
+#include <Ppi/IpmiTransport2Ppi.h>
+#include <Library/BtInterfaceLib.h>
+#include <Library/SsifInterfaceLib.h>
+#include <Library/IpmbInterfaceLib.h>
+#include <PeiIpmiBmcDef.h>
+#include <PeiIpmiBmc.h>
+
+//
+// Internal(hook) function list
+//
+
+EFI_STATUS
+PeiIpmiSendCommand (
+  IN      PEI_IPMI_TRANSPORT_PPI  *This,
+  IN      UINT8                   NetFunction,
+  IN      UINT8                   Lun,
+  IN      UINT8                   Command,
+  IN      UINT8                   *CommandData,
+  IN      UINT32                  CommandDataSize,
+  IN OUT  UINT8                   *ResponseData,
+  IN OUT  UINT32                  *ResponseDataSize
+  )
+
+/*++
+
+Routine Description:
+
+  Send Ipmi Command in the right mode: HECI or KCS,  to the
+  appropiate device, ME or BMC.
+
+Arguments:
+
+  This              - Pointer to IPMI protocol instance
+  NetFunction       - Net Function of command to send
+  Lun               - LUN of command to send
+  Command           - IPMI command to send
+  CommandData       - Pointer to command data buffer, if needed
+  CommandDataSize   - Size of command data buffer
+  ResponseData      - Pointer to response data buffer
+  ResponseDataSize  - Pointer to response data buffer size
+
+Returns:
+
+  EFI_INVALID_PARAMETER - One of the input values is bad
+  EFI_DEVICE_ERROR      - IPMI command failed
+  EFI_BUFFER_TOO_SMALL  - Response buffer is too small
+  EFI_UNSUPPORTED       - Command is not supported by BMC
+  EFI_SUCCESS           - Command completed successfully
+
+--*/
+;
+
+EFI_STATUS
+PeiIpmiSendCommand2 (
+  IN      IPMI_TRANSPORT2  *This,
+  IN      UINT8            NetFunction,
+  IN      UINT8            Lun,
+  IN      UINT8            Command,
+  IN      UINT8            *CommandData,
+  IN      UINT32           CommandDataSize,
+  IN OUT  UINT8            *ResponseData,
+  IN OUT  UINT32           *ResponseDataSize
+  )
+
+/*++
+
+Routine Description:
+
+  This API use the default interface (PcdDefaultSystemInterface) to send IPMI command
+  in the right mode to the appropiate device, ME or BMC.
+
+Arguments:
+
+  This              - Pointer to IPMI protocol instance
+  NetFunction       - Net Function of command to send
+  Lun               - LUN of command to send
+  Command           - IPMI command to send
+  CommandData       - Pointer to command data buffer, if needed
+  CommandDataSize   - Size of command data buffer
+  ResponseData      - Pointer to response data buffer
+  ResponseDataSize  - Pointer to response data buffer size
+
+Returns:
+
+  EFI_INVALID_PARAMETER - One of the input values is bad
+  EFI_DEVICE_ERROR      - IPMI command failed
+  EFI_BUFFER_TOO_SMALL  - Response buffer is too small
+  EFI_UNSUPPORTED       - Command is not supported by BMC
+  EFI_SUCCESS           - Command completed successfully
+
+--*/
+;
+
+EFI_STATUS
+PeiIpmiSendCommand2Ex (
+  IN      IPMI_TRANSPORT2        *This,
+  IN      UINT8                  NetFunction,
+  IN      UINT8                  Lun,
+  IN      UINT8                  Command,
+  IN      UINT8                  *CommandData,
+  IN      UINT32                 CommandDataSize,
+  IN OUT  UINT8                  *ResponseData,
+  IN OUT  UINT32                 *ResponseDataSize,
+  IN      SYSTEM_INTERFACE_TYPE  InterfaceType
+  );
+
+EFI_STATUS
+PeiIpmiSendCommandToBMC (
+  IN      PEI_IPMI_TRANSPORT_PPI  *This,
+  IN      UINT8                   NetFunction,
+  IN      UINT8                   Lun,
+  IN      UINT8                   Command,
+  IN      UINT8                   *CommandData,
+  IN      UINT8                   CommandDataSize,
+  IN OUT  UINT8                   *ResponseData,
+  IN OUT  UINT8                   *ResponseDataSize,
+  IN      VOID                    *Context
+  )
+
+/*++
+Routine Description:
+
+  This API use the specific interface type to send IPMI command
+  in the right mode to the appropiate device, ME or BMC.
+
+Arguments:
+
+  This              - Pointer to IPMI protocol instance
+  NetFunction       - Net Function of command to send
+  Lun               - LUN of command to send
+  Command           - IPMI command to send
+  CommandData       - Pointer to command data buffer, if needed
+  CommandDataSize   - Size of command data buffer
+  ResponseData      - Pointer to response data buffer
+  ResponseDataSize  - Pointer to response data buffer size
+  InterfaceType     - BMC Interface type.
+
+Returns:
+
+  EFI_INVALID_PARAMETER - One of the input values is bad
+  EFI_DEVICE_ERROR      - IPMI command failed
+  EFI_BUFFER_TOO_SMALL  - Response buffer is too small
+  EFI_UNSUPPORTED       - Command is not supported by BMC
+  EFI_SUCCESS           - Command completed successfully
+
+--*/
+;
+
+EFI_STATUS
+PeiIpmiBmcStatus (
+  IN  PEI_IPMI_TRANSPORT_PPI  *This,
+  OUT BMC_STATUS              *BmcStatus,
+  OUT SM_COM_ADDRESS          *ComAddress,
+  IN  VOID                    *Context
+  )
+
+/*++
+
+Routine Description:
+
+  Updates the BMC status and returns the Com Address
+
+Arguments:
+
+  This        - Pointer to IPMI protocol instance
+  BmcStatus   - BMC status
+  ComAddress  - Com Address
+  Context     - Context
+
+Returns:
+
+  EFI_SUCCESS - Success
+
+--*/
+;
+
+EFI_STATUS
+IpmiBmcStatus (
+  IN  PEI_IPMI_TRANSPORT_PPI  *This,
+  OUT BMC_STATUS              *BmcStatus,
+  OUT SM_COM_ADDRESS          *ComAddress,
+  IN  VOID                    *Context
+  )
+
+/*++
+
+Routine Description:
+
+  Updates the BMC status and returns the Com Address
+
+Arguments:
+
+  This        - Pointer to IPMI protocol instance
+  BmcStatus   - BMC status
+  ComAddress  - Com Address
+  Context     - Context
+
+Returns:
+
+  EFI_SUCCESS - Success
+
+--*/
+;
+
+#endif
--
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 (#107465): https://edk2.groups.io/g/devel/message/107465
Mute This Topic: https://groups.io/mt/100352666/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-1] IpmiFeaturePkg:Provided multiple IPMI interface support in PEI
Posted by Isaac Oram 8 months, 4 weeks ago
Pushed as 421e64019d4622b049f510ba8eef7c82fba7b32d

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 (#107472): https://edk2.groups.io/g/devel/message/107472
Mute This Topic: https://groups.io/mt/100352666/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-