[edk2-devel] [edk2-platforms][PATCH V2 5/8] ManageabilityPkg/ManageabilityTransportKcsLib

Chang, Abner via groups.io abner.chang=amd.com at groups.io
Tue Mar 21 01:34:58 UTC 2023


[AMD Official Use Only - General]

Hi Nickle,
Thanks for catching those issue. I am fixing it now.

There is few feedbacks below,

> -----Original Message-----
> From: Nickle Wang <nicklew at nvidia.com>
> Sent: Monday, March 20, 2023 9:32 PM
> To: Chang, Abner <Abner.Chang at amd.com>; devel at edk2.groups.io
> Cc: Liming Gao <gaoliming at byosoft.com.cn>; Isaac Oram
> <isaac.w.oram at intel.com>; Nate DeSimone
> <nathaniel.l.desimone at intel.com>; Attar, AbdulLateef (Abdul Lateef)
> <AbdulLateef.Attar at amd.com>; Igor Kulchytskyy <igork at ami.com>
> Subject: RE: [edk2-platforms][PATCH V2 5/8]
> ManageabilityPkg/ManageabilityTransportKcsLib
> 
> Caution: This message originated from an External Source. Use proper
> caution when opening attachments, clicking links, or responding.
> 
> 
> Please see my comments inline below.
> 
> Regards,
> Nickle
> 
> -----Original Message-----
> From: abner.chang at amd.com <abner.chang at amd.com>
> Sent: Wednesday, March 8, 2023 10:17 PM
> To: devel at edk2.groups.io
> Cc: Liming Gao <gaoliming at byosoft.com.cn>; Isaac Oram
> <isaac.w.oram at intel.com>; Nate DeSimone
> <nathaniel.l.desimone at intel.com>; Abdul Lateef Attar
> <abdattar at amd.com>; Nickle Wang <nicklew at nvidia.com>; Igor Kulchytskyy
> <igork at ami.com>
> Subject: [edk2-platforms][PATCH V2 5/8]
> ManageabilityPkg/ManageabilityTransportKcsLib
> 
> External email: Use caution opening links or attachments
> 
> 
> From: Abner Chang <abner.chang at amd.com>
> 
> This is the KCS manageability transport library instance follows the design
> guidance described in Readme file under ManageabilityPkg.
> 
> Signed-off-by: Abner Chang <abner.chang at amd.com>
> Cc: Liming Gao <gaoliming at byosoft.com.cn>
> Cc: Isaac Oram <isaac.w.oram at intel.com>
> Cc: Nate DeSimone <nathaniel.l.desimone at intel.com>
> Cc: Abdul Lateef Attar <abdattar at amd.com>
> Cc: Nickle Wang <nicklew at nvidia.com>
> Cc: Igor Kulchytskyy <igork at ami.com>
> ---
>  .../ManageabilityPkg/ManageabilityPkg.dsc     |   3 +
>  .../Dxe/DxeManageabilityTransportKcs.inf      |  44 ++
>  .../Common/ManageabilityTransportKcs.h        | 106 ++++
>  .../Common/KcsCommon.c                        | 480 ++++++++++++++++++
>  .../Dxe/ManageabilityTransportKcs.c           | 384 ++++++++++++++
>  .../Dxe/ManageabilityTransportKcs.uni         |  13 +
>  6 files changed, 1030 insertions(+)
>  create mode 100644
> Features/ManageabilityPkg/Library/ManageabilityTransportKcsLib/Dxe/Dxe
> ManageabilityTransportKcs.inf
>  create mode 100644
> Features/ManageabilityPkg/Library/ManageabilityTransportKcsLib/Common
> /ManageabilityTransportKcs.h
>  create mode 100644
> Features/ManageabilityPkg/Library/ManageabilityTransportKcsLib/Common
> /KcsCommon.c
>  create mode 100644
> Features/ManageabilityPkg/Library/ManageabilityTransportKcsLib/Dxe/Man
> ageabilityTransportKcs.c
>  create mode 100644
> Features/ManageabilityPkg/Library/ManageabilityTransportKcsLib/Dxe/Man
> ageabilityTransportKcs.uni
> 
> diff --git a/Features/ManageabilityPkg/ManageabilityPkg.dsc
> b/Features/ManageabilityPkg/ManageabilityPkg.dsc
> index 0dd0ab41fc..45e07ac34f 100644
> --- a/Features/ManageabilityPkg/ManageabilityPkg.dsc
> +++ b/Features/ManageabilityPkg/ManageabilityPkg.dsc
> @@ -36,6 +36,9 @@
>  !include MinPlatformPkg/Include/Dsc/CorePeiLib.dsc
>  !include MinPlatformPkg/Include/Dsc/CoreDxeLib.dsc
> 
> +[Components]
> +
> +ManageabilityPkg/Library/ManageabilityTransportKcsLib/Dxe/DxeManagea
> bil
> +ityTransportKcs.inf
> +
>  [LibraryClasses]
> 
> ManageabilityTransportLib|ManageabilityPkg/Library/BaseManageabilityTra
> nsportNullLib/BaseManageabilityTransportNull.inf
> 
> diff --git
> a/Features/ManageabilityPkg/Library/ManageabilityTransportKcsLib/Dxe/Dx
> eManageabilityTransportKcs.inf
> b/Features/ManageabilityPkg/Library/ManageabilityTransportKcsLib/Dxe/Dx
> eManageabilityTransportKcs.inf
> new file mode 100644
> index 0000000000..f0a6afa074
> --- /dev/null
> +++
> b/Features/ManageabilityPkg/Library/ManageabilityTransportKcsLib/Dxe
> +++ /DxeManageabilityTransportKcs.inf
> @@ -0,0 +1,44 @@
> +## @file
> +# KCS instance of Manageability Transport Library # # Copyright (C)
> +2023 Advanced Micro Devices, Inc. All rights reserved.<BR> #
> +SPDX-License-Identifier: BSD-2-Clause-Patent # ##
> +
> +[Defines]
> +  INF_VERSION                    = 0x0001001B
> +  BASE_NAME                      = DxeManageabilityTransportKcs
> +  MODULE_UNI_FILE                = ManageabilityTransportKcs.uni
> +  FILE_GUID                      = FCCC8B34-145A-4927-9F08-553ADC579AF7
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = ManageabilityTransportLib
> +
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64 ARM AARCH64
> +#
> +
> +[Sources]
> +  ManageabilityTransportKcs.c
> +  ../Common/KcsCommon.c
> +  ../Common/ManageabilityTransportKcs.h
> +
> +[Packages]
> +  ManageabilityPkg/ManageabilityPkg.dec
> +  MdePkg/MdePkg.dec
> +
> +[LibraryClasses]
> +  DebugLib
> +  IoLib
> +  TimerLib
> +  MemoryAllocationLib
> +
> +[Guids]
> +  gManageabilityTransportKcsGuid
> +  gManageabilityProtocolMctpGuid
> +  gManageabilityProtocolIpmiGuid
> +
> +[FixedPcd]
> +  gEfiMdePkgTokenSpaceGuid.PcdIpmiKcsBaseAddress   # Used as default
> KCS I/O base adddress
> +
> diff --git
> a/Features/ManageabilityPkg/Library/ManageabilityTransportKcsLib/Commo
> n/ManageabilityTransportKcs.h
> b/Features/ManageabilityPkg/Library/ManageabilityTransportKcsLib/Comm
> on/ManageabilityTransportKcs.h
> new file mode 100644
> index 0000000000..d5a16efc81
> --- /dev/null
> +++
> b/Features/ManageabilityPkg/Library/ManageabilityTransportKcsLib/Com
> +++ mon/ManageabilityTransportKcs.h
> @@ -0,0 +1,106 @@
> +/** @file
> +
> +  Manageability transport KCS internal used definitions.
> +
> +  Copyright (C) 2023 Advanced Micro Devices, Inc. All rights
> +reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent **/
> +
> +#ifndef MANAGEABILITY_TRANSPORT_KCS_LIB_H_
> +#define MANAGEABILITY_TRANSPORT_KCS_LIB_H_
> +
> +#include <Library/ManageabilityTransportLib.h>
> +
> +#define MANAGEABILITY_TRANSPORT_KCS_SIGNATURE  SIGNATURE_32
> ('M', 'T',
> +'K', 'C')
> +
> +#define KCS_BASE_ADDRESS  mKcsHardwareInfo.IoBaseAddress
> +#define KCS_REG_DATA_IN   mKcsHardwareInfo.IoDataInAddress
> +#define KCS_REG_DATA_OUT  mKcsHardwareInfo.IoDataOutAddress
> +#define KCS_REG_COMMAND   mKcsHardwareInfo.IoCommandAddress
> +#define KCS_REG_STATUS    mKcsHardwareInfo.IoStatusAddress
> +
> +///
> +/// Manageability transport KCS internal data structure.
> +///
> +typedef struct {
> +  UINTN                            Signature;
> +  MANAGEABILITY_TRANSPORT_TOKEN    Token;
> +} MANAGEABILITY_TRANSPORT_KCS;
> +
> +#define MANAGEABILITY_TRANSPORT_KCS_FROM_LINK(a)  CR (a,
> +MANAGEABILITY_TRANSPORT_KCS, Token,
> +MANAGEABILITY_TRANSPORT_KCS_SIGNATURE)
> +
> +#define IPMI_KCS_GET_STATE(s)  (s >> 6) #define IPMI_KCS_SET_STATE(s)
> +(s << 6)
> +
> +/// 5 sec, according to IPMI spec
> +#define IPMI_KCS_TIMEOUT_5_SEC  5000*1000
> +#define IPMI_KCS_TIMEOUT_1MS    1000
> +
> +/**
> +  This service communicates with BMC using KCS protocol.
> +
> +  @param[in]      NetFunction           Net function of the command.
> +  @param[in]      Command               IPMI Command.
> +  @param[in]      RequestData           Command Request Data.
> +  @param[in]      RequestDataSize       Size of Command Request Data.
> +  @param[out]     ResponseData          Command Response Data. The
> completion
> +                                        code is the first byte of response
> +                                        data.
> +  @param[in, out] ResponseDataSize      Size of Command Response Data.
> +
> +  @retval         EFI_SUCCESS           The command byte stream was
> +                                        successfully submit to the device and a
> +                                        response was successfully received.
> +  @retval         EFI_NOT_FOUND         The command was not successfully sent
> +                                        to the device or a response was not
> +                                        successfully received from the device.
> +  @retval         EFI_NOT_READY         Ipmi Device is not ready for Ipmi
> +                                        command access.
> +  @retval         EFI_DEVICE_ERROR      Ipmi Device hardware error.
> +  @retval         EFI_TIMEOUT           The command time out.
> +  @retval         EFI_UNSUPPORTED       The command was not successfully
> sent to
> +                                        the device.
> +  @retval         EFI_OUT_OF_RESOURCES  The resource allocation is out of
> +                                        resource or data size error.
> +**/
> +
> +EFI_STATUS
> +EFIAPI
> +KcsTransportSendCommand (
> +  IN  UINT8      NetFunction,
> +  IN  UINT8      Command,
> +  IN  UINT8      *RequestData,
> +  IN  UINT32     RequestDataSize,
> +  OUT UINT8      *ResponseData,
> +  IN OUT UINT32  *ResponseDataSize
> +  );
> +
> +/**
> +  This function reads 8-bit value from register address.
> +
> +  @param[in]      Address               This represents either 16-bit IO address
> +                                        or 32-bit memory mapped address.
> +
> +  @retval         UINT8                 8-bit value.
> +**/
> +UINT8
> +KcsRegisterRead8 (
> +  MANAGEABILITY_TRANSPORT_HARDWARE_IO  Address
> +  );
> +
> +/**
> +  This function writes 8-bit value to register address.
> +
> +  @param[in]      Address               This represents either 16-bit IO address
> +                                        or 32-bit memory mapped address.
> +  @param[in]      Value                 8-bit value write to register address
> +
> +  @retval         UINT8                 8-bit value.
> 
> This is VOID function so there is no return value here.
> 
> +**/
> +VOID
> +KcsRegisterWrite8 (
> +  MANAGEABILITY_TRANSPORT_HARDWARE_IO  Address,
> +  UINT8                                Value
> +  );
> +
> +#endif
> diff --git
> a/Features/ManageabilityPkg/Library/ManageabilityTransportKcsLib/Commo
> n/KcsCommon.c
> b/Features/ManageabilityPkg/Library/ManageabilityTransportKcsLib/Comm
> on/KcsCommon.c
> new file mode 100644
> index 0000000000..ff20f4a18e
> --- /dev/null
> +++
> b/Features/ManageabilityPkg/Library/ManageabilityTransportKcsLib/Com
> +++ mon/KcsCommon.c
> @@ -0,0 +1,480 @@
> +/** @file
> +
> +  KCS instance of Manageability Transport Library
> +
> +  Copyright (C) 2023 Advanced Micro Devices, Inc. All rights
> + reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +#include <Uefi.h>
> +#include <IndustryStandard/IpmiKcs.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/MemoryAllocationLib.h> #include <Library/TimerLib.h>
> +
> +#include "ManageabilityTransportKcs.h"
> +
> +extern MANAGEABILITY_TRANSPORT_KCS_HARDWARE_INFO
> mKcsHardwareInfo;
> +
> +/**
> +  This function waits for parameter Flag to set.
> +  Checks status flag in every 1ms internal till 5 seconds elapses.
> +
> +  @param[in]  Flag        KCS Flag to test.
> +  @retval     EFI_SUCCESS The KCS flag under test is set.
> +  @retval     EFI_TIMEOUT The KCS flag didn't set in 5 second windows.
> +**/
> +EFI_STATUS
> +WaitStatusSet (
> +  IN  UINT8  Flag
> +  )
> +{
> +  UINT64  Timeout = 0;
> +
> +  while (!(KcsRegisterRead8 (KCS_REG_STATUS) & Flag)) {
> +    MicroSecondDelay (IPMI_KCS_TIMEOUT_1MS);
> +    Timeout = Timeout + IPMI_KCS_TIMEOUT_1MS;
> +    if (Timeout >= IPMI_KCS_TIMEOUT_5_SEC) {
> +      return EFI_TIMEOUT;
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  This function waits for parameter Flag to get cleared.
> +  Checks status flag in every 1ms internal till 5 seconds elapses.
> +
> +  @param[in]  Flag        KCS Flag to test.
> +
> +  @retval     EFI_SUCCESS The KCS flag under test is clear.
> +  @retval     EFI_TIMEOUT The KCS flag didn't cleared in 5 second windows.
> +**/
> +EFI_STATUS
> +WaitStatusClear (
> +  IN  UINT8  Flag
> +  )
> +{
> +  UINT64  Timeout = 0;
> +
> +  while (KcsRegisterRead8 (KCS_REG_STATUS) & Flag) {
> +    MicroSecondDelay (IPMI_KCS_TIMEOUT_1MS);
> +    Timeout = Timeout + IPMI_KCS_TIMEOUT_1MS;
> +    if (Timeout >= IPMI_KCS_TIMEOUT_5_SEC) {
> +      return EFI_TIMEOUT;
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  This function validates KCS OBF bit.
> +  Checks whether OBF bit is set or not.
> +
> +  @retval EFI_SUCCESS    OBF bit is set.
> +  @retval EFI_NOT_READY  OBF bit is not set.
> +**/
> +EFI_STATUS
> +ClearOBF (
> +  VOID
> +  )
> +{
> +  if (KcsRegisterRead8 (KCS_REG_STATUS) & IPMI_KCS_OBF) {
> +    KcsRegisterRead8 (KCS_REG_DATA_IN); // read the data to clear the OBF
> +    if (KcsRegisterRead8 (KCS_REG_STATUS) & IPMI_KCS_OBF) {
> +      return EFI_NOT_READY;
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  This function writes/sends data to the KCS port.
> +  Algorithm is based on flow chart provided in IPMI spec 2.0
> +  Figure 9-6, KCS Interface BMC to SMS Write Transfer Flow Chart
> +
> +  @param[in]  NetFunction           Net function of the command.
> +  @param[in]  Command               IPMI Command.
> +  @param[in]  RequestData           Command Request Data.
> +  @param[in]  RequestDataSize       Size of Command Request Data.
> +
> +  @retval     EFI_SUCCESS           The command byte stream was successfully
> +                                    submit to the device and a response was
> +                                    successfully received.
> +  @retval     EFI_NOT_FOUND         The command was not successfully sent to
> the
> +                                    device or a response was not successfully
> +                                    received from the device.
> +  @retval     EFI_NOT_READY         Ipmi Device is not ready for Ipmi command
> +                                    access.
> +  @retval     EFI_DEVICE_ERROR      Ipmi Device hardware error.
> +  @retval     EFI_TIMEOUT           The command time out.
> +  @retval     EFI_UNSUPPORTED       The command was not successfully sent
> to
> +                                    the device.
> +  @retval     EFI_OUT_OF_RESOURCES  The resource allocation is out of
> resource or
> +                                    data size error.
> +**/
> +EFI_STATUS
> +KcsTransportWrite (
> +  IN  UINT8   NetFunction,
> +  IN  UINT8   Command,
> +  IN  UINT8   *RequestData,
> +  IN  UINT32  RequestDataSize
> +  )
> 
> It looks like the RequestData can be NULL. If it is, we can add "OPTIONAL"
> above.
> 
> We can also check to see if RequestDataSize is not  0 when RequestData is
> not NULL.
> 
> +{
> +  EFI_STATUS  Status;
> +  UINT32      Length;
> +  UINT8       *Buffer;
> +  UINT8       *BufferPtr;
> +
> +  Length = sizeof (NetFunction) + sizeof (Command);  if (RequestData !=
> + NULL) {
> +    Length = Length + RequestDataSize;
> +  }
> +
> +  Buffer = AllocateZeroPool (Length);
> +  if (Buffer == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  //
> +  // Buffer[0] = NetFunction
> +  // Buffer[1] = Command
> +  // Buffer [2..RequestDataSize] = RequestData  //  BufferPtr = Buffer;
> + CopyMem (BufferPtr, &NetFunction, sizeof (NetFunction));  BufferPtr +=
> + sizeof (NetFunction);  CopyMem (BufferPtr, &Command, sizeof
> + (Command));  BufferPtr += sizeof (Command);  if (Length > (sizeof
> + (NetFunction) + sizeof (Command))) {
> +    CopyMem (BufferPtr, RequestData, RequestDataSize);  }
> +
> +  BufferPtr = Buffer;
> +
> +  // Step 1. wait for IBF to get clear
> +  Status = WaitStatusClear (IPMI_KCS_IBF);  if (EFI_ERROR (Status)) {
> +    FreePool (Buffer);
> +    return Status;
> +  }
> +
> +  // Step 2. clear OBF
> +  if (EFI_ERROR (ClearOBF ())) {
> +    FreePool (Buffer);
> +    return EFI_NOT_READY;
> +  }
> +
> +  // Step 3. WR_START to CMD, phase=wr_start
> +  KcsRegisterWrite8 (KCS_REG_COMMAND,
> + IPMI_KCS_CONTROL_CODE_WRITE_START);
> +
> +  // Step 4. wait for IBF to get clear
> +  Status = WaitStatusClear (IPMI_KCS_IBF);  if (EFI_ERROR (Status)) {
> +    FreePool (Buffer);
> +    return Status;
> +  }
> +
> +  // Step 5. check state it should be WRITE_STATE, else exit with error
> + if (IPMI_KCS_GET_STATE (KcsRegisterRead8 (KCS_REG_STATUS)) !=
> IPMI_KCS_WRITE_STATE) {
> +    FreePool (Buffer);
> +    return EFI_NOT_READY;
> +  }
> +
> +  // Step 6, Clear OBF
> +  if (EFI_ERROR (ClearOBF ())) {
> +    FreePool (Buffer);
> +    return EFI_NOT_READY;
> +  }
> +
> +  while (Length > 1) {
> +    // Step 7, phase wr_data, write one byte of Data
> +    KcsRegisterWrite8 (KCS_REG_DATA_OUT, *BufferPtr);
> +    Length--;
> +    BufferPtr++;
> +
> +    // Step 8. wait for IBF clear
> +    Status = WaitStatusClear (IPMI_KCS_IBF);
> +    if (EFI_ERROR (Status)) {
> +      FreePool (Buffer);
> +      return Status;
> +    }
> +
> +    // Step 9. check state it should be WRITE_STATE, else exit with error
> +    if (IPMI_KCS_GET_STATE (KcsRegisterRead8 (KCS_REG_STATUS)) !=
> IPMI_KCS_WRITE_STATE) {
> +      FreePool (Buffer);
> +      return EFI_NOT_READY;
> +    }
> +
> +    // Step 10
> +    if (EFI_ERROR (ClearOBF ())) {
> +      FreePool (Buffer);
> +      return EFI_NOT_READY;
> +    }
> +
> +    //
> +    // Step 11, check for DATA completion if more than one byte;
> +    // if still need to be transferred then go to step 7 and repeat
> +    //
> +  }
> +
> +  // Step 12, WR_END  to CMD
> +  KcsRegisterWrite8 (KCS_REG_COMMAND,
> IPMI_KCS_CONTROL_CODE_WRITE_END);
> +
> +  // Step 13. wait for IBF to get clear  Status = WaitStatusClear
> + (IPMI_KCS_IBF);  if (EFI_ERROR (Status)) {
> +    FreePool (Buffer);
> +    return Status;
> +  }
> +
> +  // Step 14. check state it should be WRITE_STATE, else exit with
> + error  if (IPMI_KCS_GET_STATE (KcsRegisterRead8 (KCS_REG_STATUS)) !=
> IPMI_KCS_WRITE_STATE) {
> +    FreePool (Buffer);
> +    return EFI_NOT_READY;
> +  }
> +
> +  // Step 15
> +  if (EFI_ERROR (ClearOBF ())) {
> +    FreePool (Buffer);
> +    return EFI_NOT_READY;
> +  }
> +
> +  // Step 16, write the last byte
> +  KcsRegisterWrite8 (KCS_REG_DATA_OUT, *BufferPtr);
> +  FreePool (Buffer);
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  This function sends/receives data from KCS port.
> +  Algorithm is based on flow chart provided in IPMI spec 2.0
> +  Figure 9-7, KCS Interface BMC to SMS Read Transfer Flow Chart
> +
> +  @param [in]       DataBytes             Buffer to hold the read Data.
> +  @param [in, out]  Length                Number of Bytes read from KCS port.
> +  @retval           EFI_SUCCESS           The command byte stream was
> +                                          successfully submit to the device and
> +                                          a response was successfully received.
> +  @retval           EFI_NOT_FOUND         The command was not successfully
> sent
> +                                          to the device or a response was not
> +                                          successfully received from the
> +                                          device.
> +  @retval           EFI_NOT_READY         Ipmi Device is not ready for Ipmi
> +                                          command access.
> +  @retval           EFI_DEVICE_ERROR      Ipmi Device hardware error.
> +  @retval           EFI_TIMEOUT           The command time out.
> +  @retval           EFI_UNSUPPORTED       The command was not successfully
> set
> +                                          to the device.
> +  @retval           EFI_OUT_OF_RESOURCES  The resource allocation is out of
> +                                          resource or data size error.
> +**/
> +EFI_STATUS
> +KcsTransportRead (
> +  OUT    UINT8   *DataByte,
> +  IN OUT UINT32  *Length
> +  )
> +{
> +  EFI_STATUS  Status;
> +  UINT32      ReadLength;
> 
> It would be good if we check and see if input pointer is NULL or not. If it is,
> return EFI_INVALID_PARAMETER back to caller.
> 
> +
> +  ReadLength = 0;
> +  while (ReadLength < *Length) {
> +    // Step 1. wait for IBF to get clear
> +    Status = WaitStatusClear (IPMI_KCS_IBF);
> +    if (EFI_ERROR (Status)) {
> +      *Length = ReadLength;
> +      return Status;
> +    }
> +
> +    // Step 2. check state it should be READ_STATE, else exit with error
> +    if (IPMI_KCS_GET_STATE (KcsRegisterRead8 (KCS_REG_STATUS)) ==
> IPMI_KCS_READ_STATE) {
> +      // Step 2.1.1 check of OBF to get clear
> +      Status = WaitStatusSet (IPMI_KCS_OBF);
> +      if (EFI_ERROR (Status)) {
> +        *Length = ReadLength;
> +        return Status;
> +      }
> +
> +      // Step 2.1.2 read data from data out
> +      DataByte[ReadLength++] = KcsRegisterRead8 (KCS_REG_DATA_IN);
> +      Status                 = WaitStatusClear (IPMI_KCS_IBF);
> +      if (EFI_ERROR (Status)) {
> +        *Length = ReadLength;
> +        return Status;
> +      }
> +
> +      // Step 2.1.3 Write READ byte to data in register.
> +      KcsRegisterWrite8 (KCS_REG_DATA_OUT,
> IPMI_KCS_CONTROL_CODE_READ);
> +    } else if (IPMI_KCS_GET_STATE (KcsRegisterRead8 (KCS_REG_STATUS))
> == IPMI_KCS_IDLE_STATE) {
> +      // Step 2.2.1
> +      Status = WaitStatusSet (IPMI_KCS_OBF);
> +      if (EFI_ERROR (Status)) {
> +        *Length = ReadLength;
> +        return Status;
> +      }
> +
> +      // Step 2.2.2 read dummy data
> +      KcsRegisterRead8 (KCS_REG_DATA_IN); // Dummy read as per IPMI
> spec
> +      *Length = ReadLength;
> +      return EFI_SUCCESS;
> +    } else {
> +      *Length = ReadLength;
> +      return EFI_DEVICE_ERROR;
> +    }
> +  }
> +
> +  *Length = ReadLength;
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  This service communicates with BMC using KCS protocol.
> +
> +  @param[in]      NetFunction           Net function of the command.
> +  @param[in]      Command               IPMI Command.
> +  @param[in]      RequestData           Command Request Data.
> +  @param[in]      RequestDataSize       Size of Command Request Data.
> +  @param[out]     ResponseData          Command Response Data. The
> completion
> +                                        code is the first byte of response
> +                                        data.
> +  @param[in, out] ResponseDataSize      Size of Command Response Data.
> +
> +  @retval         EFI_SUCCESS           The command byte stream was
> +                                        successfully submit to the device and a
> +                                        response was successfully received.
> +  @retval         EFI_NOT_FOUND         The command was not successfully sent
> +                                        to the device or a response was not
> +                                        successfully received from the device.
> +  @retval         EFI_NOT_READY         Ipmi Device is not ready for Ipmi
> +                                        command access.
> +  @retval         EFI_DEVICE_ERROR      Ipmi Device hardware error.
> +  @retval         EFI_TIMEOUT           The command time out.
> +  @retval         EFI_UNSUPPORTED       The command was not successfully
> sent to
> +                                        the device.
> +  @retval         EFI_OUT_OF_RESOURCES  The resource allocation is out of
> +                                        resource or data size error.
> +**/
> +EFI_STATUS
> +EFIAPI
> +KcsTransportSendCommand (
> +  IN  UINT8      NetFunction,
> +  IN  UINT8      Command,
> +  IN  UINT8      *RequestData,
> +  IN  UINT32     RequestDataSize,
> +  OUT UINT8      *ResponseData,
> +  IN OUT UINT32  *ResponseDataSize
> 
> Form the function header, this is just OUT, right?
ResponseDataSize  is in and out. I will also add more descriptions in function header.



> +  )
> +{
> +  EFI_STATUS                Status;
> +  UINT32                    RspHeaderSize;
> +  IPMI_KCS_RESPONSE_HEADER  RspHeader;
> +
> +  if ((RequestData != NULL) && (RequestDataSize <= 0)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> 
> Do we need similar check to ResponseData and ResponseDataSize?
Yes, I also add OPTIONAL to those parameters in function prototype.
Thanks
Abner
> 
> +
> +  Status = KcsTransportWrite (
> +             (NetFunction << 2),
> +             Command,
> +             RequestData,
> +             RequestDataSize
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "IPMI KCS Write Failed with Status(%r) for NetFunction(0x%x)," \
> +      " Command(0x%x).\n",
> +      Status,
> +      NetFunction,
> +      Command
> +      ));
> +    return Status;
> +  }
> +
> +  //
> +  // Read the response header
> +  RspHeaderSize = sizeof (IPMI_KCS_RESPONSE_HEADER);
> +  Status        = KcsTransportRead ((UINT8 *)&RspHeader, &RspHeaderSize);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "IPMI KCS read response header failed Status(%r), " \
> +      "RspNetFunctionLun = 0x%x, " \
> +      "Comamnd = 0x%x \n",
> +      Status,
> +      RspHeader.NetFunc,
> +      RspHeader.Command
> +      ));
> +    return (Status);
> +  }
> +
> +  Status = KcsTransportRead ((UINT8 *)ResponseData, ResponseDataSize);
> + if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "IPMI KCS response read Failed with Status(%r) for NetFunction(0x%x),"
> \
> +      " Command(0x%x).\n",
> +      Status,
> +      NetFunction,
> +      Command
> +      ));
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  This function reads 8-bit value from register address.
> +
> +  @param[in]      Address               This represents either 16-bit IO address
> +                                        or 32-bit memory mapped address.
> +
> +  @retval         UINT8                 8-bit value.
> +**/
> +UINT8
> +KcsRegisterRead8 (
> +  MANAGEABILITY_TRANSPORT_HARDWARE_IO  Address
> +  )
> +{
> +  UINT8  Value;
> +
> +  if (mKcsHardwareInfo.MemoryMap ==
> MANAGEABILITY_TRANSPORT_KCS_MEMORY_MAP_IO) {
> +    // Read 8-bit value from 32-bit Memory mapped address.
> +    Value = MmioRead8 ((UINTN)Address.IoAddress32);  } else {
> +    // Read 8-bit value from 16-bit I/O address
> +    Value = IoRead8 ((UINTN)Address.IoAddress16);  }
> +
> +  return Value;
> +}
> +
> +/**
> +  This function writes 8-bit value to register address.
> +
> +  @param[in]      Address               This represents either 16-bit IO address
> +                                        or 32-bit memory mapped address.
> +  @param[in]      Value                 8-bit value write to register address
> +
> +  @retval         UINT8                 8-bit value.
> +**/
> +VOID
> +KcsRegisterWrite8 (
> +  MANAGEABILITY_TRANSPORT_HARDWARE_IO  Address,
> +  UINT8                                Value
> +  )
> +{
> +  if (mKcsHardwareInfo.MemoryMap ==
> MANAGEABILITY_TRANSPORT_KCS_MEMORY_MAP_IO) {
> +    // Write 8-bit value to 32-bit Memory mapped address.
> +    MmioWrite8 ((UINTN)Address.IoAddress32, Value);
> +  } else {
> +    // Write 8-bit value to 16-bit I/O address
> +    IoWrite8 ((UINTN)Address.IoAddress16, Value);
> +  }
> +}
> diff --git
> a/Features/ManageabilityPkg/Library/ManageabilityTransportKcsLib/Dxe/M
> anageabilityTransportKcs.c
> b/Features/ManageabilityPkg/Library/ManageabilityTransportKcsLib/Dxe/M
> anageabilityTransportKcs.c
> new file mode 100644
> index 0000000000..7eb39ddc7a
> --- /dev/null
> +++
> b/Features/ManageabilityPkg/Library/ManageabilityTransportKcsLib/Dxe
> +++ /ManageabilityTransportKcs.c
> @@ -0,0 +1,384 @@
> +/** @file
> +
> +  KCS instance of Manageability Transport Library
> +
> +  Copyright (C) 2023 Advanced Micro Devices, Inc. All rights
> + reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +*/
> +
> +#include <Uefi.h>
> +#include <IndustryStandard/IpmiKcs.h>
> +#include <Library/IoLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/MemoryAllocationLib.h> #include
> +<Library/ManageabilityTransportLib.h>
> +#include <Library/ManageabilityTransportIpmiLib.h>
> +#include <Library/ManageabilityTransportHelperLib.h>
> +
> +#include "ManageabilityTransportKcs.h"
> +
> +MANAGEABILITY_TRANSPORT_KCS  *mSingleSessionToken = NULL;
> +
> +EFI_GUID  *SupportedManageabilityProtocol[] = {
> +  &gManageabilityProtocolIpmiGuid,
> +  &gManageabilityProtocolMctpGuid
> +};
> +
> +UINT8  NumberOfSupportedProtocol = (sizeof
> +(SupportedManageabilityProtocol)/sizeof (EFI_GUID *));
> +
> +MANAGEABILITY_TRANSPORT_KCS_HARDWARE_INFO  mKcsHardwareInfo;
> +
> +/**
> +  This function initializes the transport interface.
> +
> +  @param [in]  TransportToken           The transport token acquired through
> +                                        AcquireTransportSession function.
> +  @param [in]  HardwareInfo             The hardware information
> +                                        assigned to KCS transport interface.
> +
> +  @retval      EFI_SUCCESS              Transport interface is initialized
> +                                        successfully.
> +  @retval      EFI_INVALID_PARAMETER    The invalid transport token.
> +  @retval      EFI_NOT_READY            The transport interface works fine but
> +  @retval                               is not ready.
> +  @retval      EFI_DEVICE_ERROR         The transport interface has problems.
> +  @retval      EFI_ALREADY_STARTED      Teh protocol interface has already
> initialized.
> +  @retval      Otherwise                Other errors.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +KcsTransportInit (
> +  IN  MANAGEABILITY_TRANSPORT_TOKEN                 *TransportToken,
> +  IN  MANAGEABILITY_TRANSPORT_HARDWARE_INFORMATION
> HardwareInfo
> +OPTIONAL
> +  )
> +{
> +  CHAR16  *ManageabilityProtocolName;
> +
> +  if (TransportToken == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a: Invalid transport token.\n",
> __FUNCTION__));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (HardwareInfo.Kcs == NULL) {
> +    DEBUG ((DEBUG_INFO, "%a: Hardware information is not provided, use
> dfault settings.\n", __FUNCTION__));
> +    mKcsHardwareInfo.MemoryMap                    =
> MANAGEABILITY_TRANSPORT_KCS_IO_MAP_IO;
> +    mKcsHardwareInfo.IoBaseAddress.IoAddress16    = PcdGet16
> (PcdIpmiKcsBaseAddress);
> +    mKcsHardwareInfo.IoDataInAddress.IoAddress16  =
> mKcsHardwareInfo.IoBaseAddress.IoAddress16 +
> IPMI_KCS_DATA_IN_REGISTER_OFFSET;
> +    mKcsHardwareInfo.IoDataOutAddress.IoAddress16 =
> mKcsHardwareInfo.IoBaseAddress.IoAddress16 +
> IPMI_KCS_DATA_OUT_REGISTER_OFFSET;
> +    mKcsHardwareInfo.IoCommandAddress.IoAddress16 =
> mKcsHardwareInfo.IoBaseAddress.IoAddress16 +
> IPMI_KCS_COMMAND_REGISTER_OFFSET;
> +    mKcsHardwareInfo.IoStatusAddress.IoAddress16  =
> + mKcsHardwareInfo.IoBaseAddress.IoAddress16 +
> IPMI_KCS_STATUS_REGISTER_OFFSET;  } else {
> +    mKcsHardwareInfo.MemoryMap        =
> ((MANAGEABILITY_TRANSPORT_KCS_HARDWARE_INFO
> *)HardwareInfo.Kcs)->MemoryMap;
> +    mKcsHardwareInfo.IoBaseAddress    =
> ((MANAGEABILITY_TRANSPORT_KCS_HARDWARE_INFO
> *)HardwareInfo.Kcs)->IoBaseAddress;
> +    mKcsHardwareInfo.IoDataInAddress  =
> ((MANAGEABILITY_TRANSPORT_KCS_HARDWARE_INFO
> *)HardwareInfo.Kcs)->IoDataInAddress;
> +    mKcsHardwareInfo.IoDataOutAddress =
> ((MANAGEABILITY_TRANSPORT_KCS_HARDWARE_INFO
> *)HardwareInfo.Kcs)->IoDataOutAddress;
> +    mKcsHardwareInfo.IoCommandAddress =
> ((MANAGEABILITY_TRANSPORT_KCS_HARDWARE_INFO
> *)HardwareInfo.Kcs)->IoCommandAddress;
> +    mKcsHardwareInfo.IoStatusAddress  =
> + ((MANAGEABILITY_TRANSPORT_KCS_HARDWARE_INFO
> + *)HardwareInfo.Kcs)->IoStatusAddress;
> +  }
> +
> +  // Get protocol specification name.
> +  ManageabilityProtocolName = HelperManageabilitySpecName
> + (TransportToken->ManageabilityProtocolSpecification);
> +
> +  DEBUG ((DEBUG_INFO, "%a: KCS transport hardware for %s is:\n",
> + __FUNCTION__, ManageabilityProtocolName));  if
> (mKcsHardwareInfo.MemoryMap) {
> +    DEBUG ((DEBUG_INFO, "Memory Map I/O\n", __FUNCTION__));
> +    DEBUG ((DEBUG_INFO, "Base Memory Address : 0x%08x\n",
> mKcsHardwareInfo.IoBaseAddress.IoAddress32));
> +    DEBUG ((DEBUG_INFO, "Data in Address     : 0x%08x\n",
> mKcsHardwareInfo.IoDataInAddress.IoAddress32));
> +    DEBUG ((DEBUG_INFO, "Data out Address    : 0x%08x\n",
> mKcsHardwareInfo.IoDataOutAddress.IoAddress32));
> +    DEBUG ((DEBUG_INFO, "Command Address     : 0x%08x\n",
> mKcsHardwareInfo.IoCommandAddress.IoAddress32));
> +    DEBUG ((DEBUG_INFO, "Status Address      : 0x%08x\n",
> mKcsHardwareInfo.IoStatusAddress.IoAddress32));
> +  } else {
> +    DEBUG ((DEBUG_INFO, "I/O Map I/O\n"));
> +    DEBUG ((DEBUG_INFO, "Base I/O port    : 0x%04x\n",
> mKcsHardwareInfo.IoBaseAddress.IoAddress16));
> +    DEBUG ((DEBUG_INFO, "Data in I/O port : 0x%04x\n",
> mKcsHardwareInfo.IoDataInAddress.IoAddress16));
> +    DEBUG ((DEBUG_INFO, "Data out I/O port: 0x%04x\n",
> mKcsHardwareInfo.IoDataOutAddress.IoAddress16));
> +    DEBUG ((DEBUG_INFO, "Command I/O port : 0x%04x\n",
> mKcsHardwareInfo.IoCommandAddress.IoAddress16));
> +    DEBUG ((DEBUG_INFO, "Status I/O port  : 0x%04x\n",
> + mKcsHardwareInfo.IoStatusAddress.IoAddress16));
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  This function returns the transport interface status.
> +  The generic EFI_STATUS is returned to caller directly, The additional
> +  information of transport interface could be optionally returned in
> +  TransportAdditionalStatus to describes the status that can't be
> +  described obviously through EFI_STATUS.
> +  See the definition of MANAGEABILITY_TRANSPORT_STATUS.
> +
> +  @param [in]   TransportToken             The transport token acquired through
> +                                           AcquireTransportSession function.
> +  @param [out]  TransportAdditionalStatus  The additional status of
> transport
> +                                           interface.
> +                                           NULL means no additional status of this
> +                                           transport interface.
> +
> +  @retval      EFI_SUCCESS              Transport interface status is returned.
> +  @retval      EFI_INVALID_PARAMETER    The invalid transport token.
> +  @retval      EFI_DEVICE_ERROR         The transport interface has problems to
> return
> +  @retval      EFI_UNSUPPORTED          The transport interface doesn't have
> status report.
> +               Otherwise                Other errors.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +KcsTransportStatus (
> +  IN  MANAGEABILITY_TRANSPORT_TOKEN              *TransportToken,
> +  OUT MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS
> +*TransportAdditionalStatus OPTIONAL
> +  )
> +{
> +  UINT8  TransportStatus;
> +
> +  if (TransportToken == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a: Invalid transport token.\n",
> __FUNCTION__));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (TransportAdditionalStatus == NULL) {
> +    return EFI_SUCCESS;
> +  }
> +
> +  TransportStatus            = IPMI_KCS_GET_STATE (KcsRegisterRead8
> (KCS_REG_STATUS));
> +  *TransportAdditionalStatus =
> + MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS_NO_ERRORS;
> 
> TransportAdditionalStatus can be NULL. This may create CPU assertion.
We checked if TransportAdditionalStatus==NULL in few lines above.

Thanks
Abner

> 
> +  if (TransportStatus != IPMI_KCS_IDLE_STATE) {
> +    if (TransportStatus == IPMI_KCS_READ_STATE) {
> +      //
> +      // Transport is in read state.
> +      *TransportAdditionalStatus |=
> MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS_BUSY_IN_READ;
> +      return EFI_NOT_READY;
> +    } else if (TransportStatus == IPMI_KCS_WRITE_STATE) {
> +      //
> +      // Transport is in read state.
> +      *TransportAdditionalStatus |=
> MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS_BUSY_IN_WRITE;
> +      return EFI_NOT_READY;
> +    } else {
> +      return EFI_DEVICE_ERROR;
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  This function resets the transport interface.
> +  The generic EFI_STATUS is returned to caller directly after reseting
> +transport
> +  interface. The additional information of transport interface could be
> +optionally
> +  returned in TransportAdditionalStatus to describes the status that
> +can't be
> +  described obviously through EFI_STATUS.
> +  See the definition of MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS.
> +
> +  @param [in]   TransportToken             The transport token acquired through
> +                                           AcquireTransportSession function.
> +  @param [out]  TransportAdditionalStatus  The additional status of specific
> transport
> +                                           interface after the reset.
> +                                           NULL means no additional status of this
> +                                           transport interface.
> +
> +  @retval      EFI_SUCCESS              Transport interface status is returned.
> +  @retval      EFI_INVALID_PARAMETER    The invalid transport token.
> +  @retval      EFI_TIMEOUT              The reset process is time out.
> +  @retval      EFI_DEVICE_ERROR         The transport interface has problems to
> return
> +                                        status.
> +               Otherwise                Other errors.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +KcsTransportReset (
> +  IN  MANAGEABILITY_TRANSPORT_TOKEN              *TransportToken,
> +  OUT MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS
> +*TransportAdditionalStatus OPTIONAL
> +  )
> +{
> +  return EFI_UNSUPPORTED;
> +}
> +
> +/**
> +  This function transmit the request over target transport interface.
> +  The generic EFI_STATUS is returned to caller directly after reseting
> +transport
> +  interface. The additional information of transport interface could be
> +optionally
> +  returned in TransportAdditionalStatus to describes the status that
> +can't be
> +  described obviously through EFI_STATUS.
> +  See the definition of MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS.
> +
> +  @param [in]  TransportToken           The transport token acquired through
> +                                        AcquireTransportSession function.
> +  @param [in]  TransferToken            The transfer token, see the definition of
> +                                        MANAGEABILITY_TRANSFER_TOKEN.
> +
> +  @retval      The EFI status is returned in
> MANAGEABILITY_TRANSFER_TOKEN.
> +
> +**/
> +VOID
> +EFIAPI
> +KcsTransportTransmitReceive (
> +  IN  MANAGEABILITY_TRANSPORT_TOKEN  *TransportToken,
> +  IN  MANAGEABILITY_TRANSFER_TOKEN   *TransferToken
> +  )
> +{
> +  EFI_STATUS                           Status;
> +  MANAGEABILITY_IPMI_TRANSPORT_HEADER  *TransmitHeader;
> +
> +  if (TransportToken == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a: Invalid transport token.\n",
> __FUNCTION__));
> +    return;
> +  }
> 
> We need same check to TransferToken.
> 
> +
> +  TransmitHeader = (MANAGEABILITY_IPMI_TRANSPORT_HEADER
> + *)TransferToken->TransmitHeader;  if (TransmitHeader == NULL) {
> +    TransferToken->TransferStatus = EFI_INVALID_PARAMETER;
> +    return;
> +  }
> +
> +  Status = KcsTransportSendCommand (
> +             TransmitHeader->NetFn,
> +             TransmitHeader->Command,
> +             TransferToken->TransmitPackage.TransmitPayload,
> +             TransferToken->TransmitPackage.TransmitSizeInByte,
> +             TransferToken->ReceivePackage.ReceiveBuffer,
> +             &TransferToken->ReceivePackage.ReceiveSizeInByte
> +             );
> +
> +  TransferToken->TransferStatus = Status;
> +  KcsTransportStatus (TransportToken,
> +&TransferToken->TransportAdditionalStatus);
> +}
> +
> +/**
> +  This function acquires to create a transport session to transmit
> +manageability
> +  packet. A transport token is returned to caller for the follow up operations.
> +
> +  @param [in]   ManageabilityProtocolSpec  The protocol spec the transport
> interface is acquired.
> +  @param [out]  TransportToken             The pointer to receive the transport
> token created by
> +                                           the target transport interface library.
> +  @retval       EFI_SUCCESS                Token is created successfully.
> +  @retval       EFI_OUT_OF_RESOURCES       Out of resource to create a new
> transport session.
> +  @retval       EFI_UNSUPPORTED            Protocol is not supported on this
> transport interface.
> +  @retval       Otherwise                  Other errors.
> +
> +**/
> +EFI_STATUS
> +AcquireTransportSession (
> +  IN  EFI_GUID                       *ManageabilityProtocolSpec,
> +  OUT MANAGEABILITY_TRANSPORT_TOKEN  **TransportToken
> +  )
> +{
> +  EFI_STATUS                   Status;
> +  MANAGEABILITY_TRANSPORT_KCS  *KcsTransportToken;
> +
> +  if (ManageabilityProtocolSpec == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a: No Manageability protocol specification
> specified.\n", __FUNCTION__));
> +    return EFI_INVALID_PARAMETER;
> +  }
> 
> Please also check TransportToken pointer.
> 
> +
> +  Status = HelperManageabilityCheckSupportedSpec (
> +             &gManageabilityTransportKcsGuid,
> +             SupportedManageabilityProtocol,
> +             NumberOfSupportedProtocol,
> +             ManageabilityProtocolSpec
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a: Protocol is not supported on this transport
> interface.\n", __FUNCTION__));
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  if (mSingleSessionToken != NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a: This manageability transport library only
> supports one session transport token.\n", __FUNCTION__));
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  KcsTransportToken = AllocateZeroPool (sizeof
> + (MANAGEABILITY_TRANSPORT_KCS));  if (KcsTransportToken == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a: Fail to allocate memory for
> MANAGEABILITY_TRANSPORT_KCS\n", __FUNCTION__));
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +  KcsTransportToken->Token.Transport = AllocateZeroPool (sizeof
> + (MANAGEABILITY_TRANSPORT));  if (KcsTransportToken->Token.Transport
> == NULL) {
> +    FreePool (KcsTransportToken);
> +    DEBUG ((DEBUG_ERROR, "%a: Fail to allocate memory for
> MANAGEABILITY_TRANSPORT\n", __FUNCTION__));
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  KcsTransportToken->Signature                                            =
> MANAGEABILITY_TRANSPORT_KCS_SIGNATURE;
> +  KcsTransportToken->Token.ManageabilityProtocolSpecification             =
> ManageabilityProtocolSpec;
> +  KcsTransportToken->Token.Transport->TransportVersion                    =
> MANAGEABILITY_TRANSPORT_TOKEN_VERSION;
> +  KcsTransportToken->Token.Transport-
> >ManageabilityTransportSpecification = &gManageabilityTransportKcsGuid;
> +  KcsTransportToken->Token.Transport->TransportName                       =
> L"KCS";
> +  KcsTransportToken->Token.Transport->Function.Version1_0                 =
> AllocateZeroPool (sizeof (MANAGEABILITY_TRANSPORT_FUNCTION_V1_0));
> +  if (KcsTransportToken->Token.Transport->Function.Version1_0 == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a: Fail to allocate memory for
> MANAGEABILITY_TRANSPORT_FUNCTION_V1_0\n", __FUNCTION__));
> +    FreePool (KcsTransportToken);
> +    FreePool (KcsTransportToken->Token.Transport);
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  KcsTransportToken->Token.Transport->Function.Version1_0-
> >TransportInit            = KcsTransportInit;
> +  KcsTransportToken->Token.Transport->Function.Version1_0-
> >TransportReset           = KcsTransportReset;
> +  KcsTransportToken->Token.Transport->Function.Version1_0-
> >TransportStatus          = KcsTransportStatus;
> +
> + KcsTransportToken->Token.Transport->Function.Version1_0-
> >TransportTran
> + smitReceive = KcsTransportTransmitReceive;
> +
> +  mSingleSessionToken = KcsTransportToken;
> +  *TransportToken     = &KcsTransportToken->Token;
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  This function returns the transport capabilities.
> +
> +  @param [out]  TransportFeature        Pointer to receive transport
> capabilities.
> +                                        See the definitions of
> +                                        MANAGEABILITY_TRANSPORT_CAPABILITY.
> +
> +**/
> +VOID
> +GetTransportCapability (
> +  OUT MANAGEABILITY_TRANSPORT_CAPABILITY  *TransportCapability
> +  )
> +{
> +  if (TransportCapability != NULL) {
> +    *TransportCapability = 0;
> +  }
> +}
> +
> +/**
> +  This function releases the manageability session.
> +
> +  @param [in]  TransportToken         The transport token acquired through
> +                                      AcquireTransportSession.
> +  @retval      EFI_SUCCESS            Token is released successfully.
> +  @retval      EFI_INVALID_PARAMETER  Invalid TransportToken.
> +  @retval      Otherwise              Other errors.
> +
> +**/
> +EFI_STATUS
> +ReleaseTransportSession (
> +  IN MANAGEABILITY_TRANSPORT_TOKEN  *TransportToken
> +  )
> +{
> +  EFI_STATUS                   Status;
> +  MANAGEABILITY_TRANSPORT_KCS  *KcsTransportToken;
> +
> +  if (TransportToken == NULL) {
> +    Status = EFI_INVALID_PARAMETER;
> +  }
> +
> +  KcsTransportToken = MANAGEABILITY_TRANSPORT_KCS_FROM_LINK
> + (TransportToken);  if (mSingleSessionToken != KcsTransportToken) {
> +    Status = EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (KcsTransportToken != NULL) {
> +    FreePool (KcsTransportToken->Token.Transport->Function.Version1_0);
> +    FreePool (KcsTransportToken->Token.Transport);
> +    FreePool (KcsTransportToken);
> +    mSingleSessionToken = NULL;
> +    Status              = EFI_SUCCESS;
> +  }
> +
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a: Fail to release KCS transport token
> + (%r).\n", __FUNCTION__, Status));  }
> +
> +  return Status;
> +}
> diff --git
> a/Features/ManageabilityPkg/Library/ManageabilityTransportKcsLib/Dxe/M
> anageabilityTransportKcs.uni
> b/Features/ManageabilityPkg/Library/ManageabilityTransportKcsLib/Dxe/M
> anageabilityTransportKcs.uni
> new file mode 100644
> index 0000000000..61a3e8b588
> --- /dev/null
> +++
> b/Features/ManageabilityPkg/Library/ManageabilityTransportKcsLib/Dxe
> +++ /ManageabilityTransportKcs.uni
> @@ -0,0 +1,13 @@
> +// /** @file
> +// KCS instance of Manageability Transport Library // // Copyright (C)
> +2023 Advanced Micro Devices, Inc. All rights reserved.<BR> // //
> +SPDX-License-Identifier: BSD-2-Clause-Patent // // **/
> +
> +#string STR_MODULE_ABSTRACT             #language en-US "KCS instance of
> Manageability Transport Library"
> +
> +#string STR_MODULE_DESCRIPTION          #language en-US "KCS
> Manageability Transport library implementation."
> +
> --
> 2.37.1.windows.1


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#101462): https://edk2.groups.io/g/devel/message/101462
Mute This Topic: https://groups.io/mt/97473057/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-




More information about the edk2-devel-archive mailing list