public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Nickle Wang" <nicklew@nvidia.com>
To: "abner.chang@amd.com" <abner.chang@amd.com>,
	"devel@edk2.groups.io" <devel@edk2.groups.io>
Cc: Isaac Oram <isaac.w.oram@intel.com>,
	Abdul Lateef Attar <abdattar@amd.com>,
	Igor Kulchytskyy <igork@ami.com>
Subject: Re: [edk2-platforms][PATCH V2 11/14] ManageabilityPkg/PldmProtocol: Add PLDM protocol
Date: Thu, 20 Apr 2023 07:05:47 +0000	[thread overview]
Message-ID: <MW4PR12MB7031AE50B9C45DF629494C45D9639@MW4PR12MB7031.namprd12.prod.outlook.com> (raw)
In-Reply-To: <20230418071543.1951-12-abner.chang@amd.com>

Reviewed-by: Nickle Wang <nicklew@nvidia.com>

Regards,
Nickle

> -----Original Message-----
> From: abner.chang@amd.com <abner.chang@amd.com>
> Sent: Tuesday, April 18, 2023 3:16 PM
> To: devel@edk2.groups.io
> Cc: Isaac Oram <isaac.w.oram@intel.com>; Abdul Lateef Attar
> <abdattar@amd.com>; Nickle Wang <nicklew@nvidia.com>; Igor Kulchytskyy
> <igork@ami.com>
> Subject: [edk2-platforms][PATCH V2 11/14] ManageabilityPkg/PldmProtocol:
> Add PLDM protocol
> 
> External email: Use caution opening links or attachments
> 
> 
> From: Abner Chang <abner.chang@amd.com>
> 
> PldmProtocol that transmits PLDM message over manageability transport
> interface library.
> 
> Signed-off-by: Abner Chang <abner.chang@amd.com>
> Cc: Isaac Oram <isaac.w.oram@intel.com>
> Cc: Abdul Lateef Attar <abdattar@amd.com>
> Cc: Nickle Wang <nicklew@nvidia.com>
> Cc: Igor Kulchytskyy <igork@ami.com>
> ---
>  .../Include/Dsc/Manageability.dsc             |   1 +
>  .../PldmProtocol/Dxe/PldmProtocolDxe.inf      |  50 ++
>  .../PldmProtocol/Common/PldmProtocolCommon.h  | 109
> +++++  .../PldmProtocol/Common/PldmProtocolCommon.c  | 437
> ++++++++++++++++++  .../Universal/PldmProtocol/Dxe/PldmProtocol.c | 181
> ++++++++
>  5 files changed, 778 insertions(+)
>  create mode 100644
> Features/ManageabilityPkg/Universal/PldmProtocol/Dxe/PldmProtocolDxe.inf
>  create mode 100644
> Features/ManageabilityPkg/Universal/PldmProtocol/Common/PldmProtocolCo
> mmon.h
>  create mode 100644
> Features/ManageabilityPkg/Universal/PldmProtocol/Common/PldmProtocolCo
> mmon.c
>  create mode 100644
> Features/ManageabilityPkg/Universal/PldmProtocol/Dxe/PldmProtocol.c
> 
> diff --git a/Features/ManageabilityPkg/Include/Dsc/Manageability.dsc
> b/Features/ManageabilityPkg/Include/Dsc/Manageability.dsc
> index 17f067c6d0..0fab562844 100644
> --- a/Features/ManageabilityPkg/Include/Dsc/Manageability.dsc
> +++ b/Features/ManageabilityPkg/Include/Dsc/Manageability.dsc
> @@ -32,6 +32,7 @@
> 
>  [Components.X64]
>    ManageabilityPkg/Universal/IpmiProtocol/Smm/IpmiProtocolSmm.inf
> +  ManageabilityPkg/Universal/PldmProtocol/Dxe/PldmProtocolDxe.inf
> 
> ManageabilityPkg/Universal/PldmSmbiosTransferDxe/PldmSmbiosTransferDxe.i
> nf
>    ManageabilityPkg/Universal/MctpProtocol/Dxe/MctpProtocolDxe.inf
> 
> diff --git
> a/Features/ManageabilityPkg/Universal/PldmProtocol/Dxe/PldmProtocolDxe.in
> f
> b/Features/ManageabilityPkg/Universal/PldmProtocol/Dxe/PldmProtocolDxe.in
> f
> new file mode 100644
> index 0000000000..006f77b09a
> --- /dev/null
> +++ b/Features/ManageabilityPkg/Universal/PldmProtocol/Dxe/PldmProtocolD
> +++ xe.inf
> @@ -0,0 +1,50 @@
> +## @file
> +# EDKII PLDM Pootocol module INF file.
> +#
> +# Copyright (C) 2023 Advanced Micro Devices, Inc. All rights
> +reserved.<BR> # SPDX-License-Identifier: BSD-2-Clause-Patent ##
> +
> +[Defines]
> +  INF_VERSION                    = 0x0001001d
> +  BASE_NAME                      = PldmProtocolDxe
> +  FILE_GUID                      = DA83FBDC-ECFE-4094-9ED3-EAFD1342333F
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = DxePldmProtocolEntry
> +  UNLOAD_IMAGE                   = PldmProtocolUnloadImage
> +
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64 ARM AARCH64
> +#
> +
> +[Sources]
> +  PldmProtocol.c
> +  ../Common/PldmProtocolCommon.c
> +  ../Common/PldmProtocolCommon.h
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  ManageabilityPkg/ManageabilityPkg.dec
> +
> +[LibraryClasses]
> +  BaseMemoryLib
> +  DebugLib
> +  ManageabilityTransportHelperLib
> +  ManageabilityTransportLib
> +  UefiDriverEntryPoint
> +  UefiBootServicesTableLib
> +
> +[Guids]
> +  gManageabilityTransportMctpGuid
> +
> +[Protocols]
> +  gEdkiiPldmProtocolGuid
> +
> +[FixedPcd]
> +  gManageabilityPkgTokenSpaceGuid.PcdMctpSourceEndpointId
> +  gManageabilityPkgTokenSpaceGuid.PcdMctpDestinationEndpointId
> +
> +[Depex]
> +  TRUE
> diff --git
> a/Features/ManageabilityPkg/Universal/PldmProtocol/Common/PldmProtocolC
> ommon.h
> b/Features/ManageabilityPkg/Universal/PldmProtocol/Common/PldmProtocolC
> ommon.h
> new file mode 100644
> index 0000000000..231d6e802e
> --- /dev/null
> +++
> b/Features/ManageabilityPkg/Universal/PldmProtocol/Common/PldmProtoc
> +++ olCommon.h
> @@ -0,0 +1,109 @@
> +/** @file
> +
> +  EDKII PLDM Protocol common header file.
> +
> +  Copyright (C) 2023 Advanced Micro Devices, Inc. All rights
> +reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent **/
> +
> +#ifndef MANAGEABILITY_EDKII_PLDM_COMMON_H_
> +#define MANAGEABILITY_EDKII_PLDM_COMMON_H_
> +
> +#include <IndustryStandard/Pldm.h>
> +#include <Library/ManageabilityTransportLib.h>
> +
> +typedef struct {
> +  UINT8     PldmType;
> +  UINT8     PldmCommand;
> +  UINT32    ResponseSize;
> +} PLDM_MESSAGE_PACKET_MAPPING;
> +
> +/**
> +  This functions setup the PLDM transport hardware information
> +according
> +  to the specification of transport token acquired from transport library.
> +
> +  @param[in]         TransportToken       The transport interface.
> +  @param[out]        HardwareInformation  Pointer to receive the hardware
> information.
> +
> +  @retval EFI_SUCCESS            Hardware information is returned in
> HardwareInformation.
> +                                 Caller must free the memory allocated for
> HardwareInformation
> +                                 once it doesn't need it.
> +  @retval EFI_UNSUPPORTED        No hardware information for the
> specification specified
> +                                 in the transport token.
> +**/
> +EFI_STATUS
> +SetupPldmTransportHardwareInformation (
> +  IN   MANAGEABILITY_TRANSPORT_TOKEN                 *TransportToken,
> +  OUT  MANAGEABILITY_TRANSPORT_HARDWARE_INFORMATION
> +*HardwareInformation
> +  );
> +
> +/**
> +  This functions setup the final header/body/trailer packets for
> +  the acquired transport interface.
> +
> +  @param[in]         TransportToken     The transport interface.
> +  @param[in]         PldmType           PLDM message type.
> +  @param[in]         PldmCommand        PLDM command of this PLDM type.
> +  @param[out]        PacketHeader       The pointer to receive header of request.
> +  @param[out]        PacketHeaderSize   Packet header size in bytes.
> +  @param[in, out]    PacketBody         The request body.
> +                                        When IN, it is the caller's request body.
> +                                        When OUT and NULL, the request body is not
> +                                        changed.
> +                                        Whee out and non-NULL, the request body is
> +                                        changed to comfort the transport interface.
> +  @param[in, out]    PacketBodySize     The request body size.
> +                                        When IN and non-zero, it is the new data
> +                                        length of request body.
> +                                        When IN and zero, the request body is unchanged.
> +  @param[out]        PacketTrailer      The pointer to receive trailer of request.
> +  @param[out]        PacketTrailerSize  Packet trailer size in bytes.
> +
> +  @retval EFI_SUCCESS            Request packet is returned.
> +  @retval EFI_UNSUPPORTED        Request packet is not returned because
> +                                 the unsupported transport interface.
> +**/
> +EFI_STATUS
> +SetupPldmRequestTransportPacket (
> +  IN   MANAGEABILITY_TRANSPORT_TOKEN    *TransportToken,
> +  IN   UINT8                            PldmType,
> +  IN   UINT8                            PldmCommand,
> +  OUT  MANAGEABILITY_TRANSPORT_HEADER   *PacketHeader,
> +  OUT  UINT16                           *PacketHeaderSize,
> +  IN OUT UINT8                          **PacketBody,
> +  IN OUT UINT32                         *PacketBodySize,
> +  OUT  MANAGEABILITY_TRANSPORT_TRAILER  *PacketTrailer,
> +  OUT  UINT16                           *PacketTrailerSize
> +  );
> +
> +/**
> +  Common code to submit PLDM commands
> +
> +  @param[in]         TransportToken    Transport token.
> +  @param[in]         PldmType          PLDM message type.
> +  @param[in]         PldmCommand       PLDM command of this PLDM type.
> +  @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          PLDM transport interface is not ready for PLDM
> command access.
> +  @retval EFI_DEVICE_ERROR       PLDM 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
> +CommonPldmSubmitCommand (
> +  IN     MANAGEABILITY_TRANSPORT_TOKEN  *TransportToken,
> +  IN     UINT8                          PldmType,
> +  IN     UINT8                          PldmCommand,
> +  IN     UINT8                          *RequestData OPTIONAL,
> +  IN     UINT32                         RequestDataSize,
> +  OUT    UINT8                          *ResponseData OPTIONAL,
> +  IN OUT UINT32                         *ResponseDataSize
> +  );
> +
> +#endif // MANAGEABILITY_EDKII_PLDM_COMMON_H_
> diff --git
> a/Features/ManageabilityPkg/Universal/PldmProtocol/Common/PldmProtocolC
> ommon.c
> b/Features/ManageabilityPkg/Universal/PldmProtocol/Common/PldmProtocolC
> ommon.c
> new file mode 100644
> index 0000000000..bb4d3f61a0
> --- /dev/null
> +++
> b/Features/ManageabilityPkg/Universal/PldmProtocol/Common/PldmProtoc
> +++ olCommon.c
> @@ -0,0 +1,437 @@
> +/** @file
> +
> +  IPMI Manageability Protocol common file.
> +
> +  Copyright (C) 2023 Advanced Micro Devices, Inc. All rights
> + reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +#include <Uefi.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/MemoryAllocationLib.h> #include
> +<Library/ManageabilityTransportLib.h>
> +#include <Library/ManageabilityTransportHelperLib.h>
> +#include <Library/ManageabilityTransportMctpLib.h>
> +#include <IndustryStandard/Mctp.h>
> +#include <IndustryStandard/Pldm.h>
> +#include <IndustryStandard/PldmSmbiosTransfer.h>
> +#include "PldmProtocolCommon.h"
> +
> +extern CHAR16  *mTransportName;
> +extern UINT8   mPldmRequestInstanceId;
> +
> +PLDM_MESSAGE_PACKET_MAPPING  PldmMessagePacketMappingTable[] = {
> +  { PLDM_TYPE_SMBIOS,
> +PLDM_GET_SMBIOS_STRUCTURE_TABLE_METADATA_COMMAND_CODE,
> sizeof
> +(PLDM_GET_SMBIOS_STRUCTURE_TABLE_METADATA_RESPONSE_FORMAT) },
> +  { PLDM_TYPE_SMBIOS,
> PLDM_SET_SMBIOS_STRUCTURE_TABLE_METADATA_COMMAND_CODE, sizeof
> (PLDM_SET_SMBIOS_STRUCTURE_TABLE_METADATA_RESPONSE_FORMAT) },
> +  { PLDM_TYPE_SMBIOS,
> PLDM_SET_SMBIOS_STRUCTURE_TABLE_COMMAND_CODE,          sizeof
> (PLDM_SET_SMBIOS_STRUCTURE_TABLE_REQUEST_FORMAT)           }
> +};
> +
> +/**
> +  This function returns the expected full size of PLDM response message.
> +
> +  @param[in]         PldmType        PLDM message type.
> +  @param[in]         PldmCommand     PLDM command of this PLDM type.
> +
> +  @retval  Zero       No matched entry for this PldmType/PldmCommand.
> +  @retval  None-zero  Size of full packet is returned.
> +**/
> +UINT32
> +GetFullPacketResponseSize (
> +  IN UINT8  PldmType,
> +  IN UINT8  PldmCommand
> +  )
> +{
> +  INT16                        Index;
> +  PLDM_MESSAGE_PACKET_MAPPING  *ThisEntry;
> +
> +  ThisEntry = PldmMessagePacketMappingTable;  for (Index = 0; Index <
> + (sizeof (PldmMessagePacketMappingTable)/ sizeof
> (PLDM_MESSAGE_PACKET_MAPPING)); Index++) {
> +    if ((PldmType == ThisEntry->PldmType) && (PldmCommand == ThisEntry-
> >PldmCommand)) {
> +      return ThisEntry->ResponseSize;
> +    }
> +
> +    ThisEntry++;
> +  }
> +
> +  return 0;
> +}
> +
> +/**
> +  This functions setup the final header/body/trailer packets for
> +  the acquired transport interface.
> +
> +  @param[in]         TransportToken     The transport interface.
> +  @param[in]         PldmType           PLDM message type.
> +  @param[in]         PldmCommand        PLDM command of this PLDM type.
> +  @param[out]        PacketHeader       The pointer to receive header of request.
> +  @param[out]        PacketHeaderSize   Packet header size in bytes.
> +  @param[in, out]    PacketBody         The request body.
> +                                        When IN, it is the caller's request body.
> +                                        When OUT and NULL, the request body is not
> +                                        changed.
> +                                        Whee out and non-NULL, the request body is
> +                                        changed to comfort the transport interface.
> +  @param[in, out]    PacketBodySize     The request body size.
> +                                        When IN and non-zero, it is the new data
> +                                        length of request body.
> +                                        When IN and zero, the request body is unchanged.
> +  @param[out]        PacketTrailer      The pointer to receive trailer of request.
> +  @param[out]        PacketTrailerSize  Packet trailer size in bytes.
> +
> +  @retval EFI_SUCCESS            Request packet is returned.
> +  @retval EFI_UNSUPPORTED        Request packet is not returned because
> +                                 the unsupported transport interface.
> +**/
> +EFI_STATUS
> +SetupPldmRequestTransportPacket (
> +  IN   MANAGEABILITY_TRANSPORT_TOKEN    *TransportToken,
> +  IN   UINT8                            PldmType,
> +  IN   UINT8                            PldmCommand,
> +  OUT  MANAGEABILITY_TRANSPORT_HEADER   *PacketHeader,
> +  OUT  UINT16                           *PacketHeaderSize,
> +  IN OUT UINT8                          **PacketBody,
> +  IN OUT UINT32                         *PacketBodySize,
> +  OUT  MANAGEABILITY_TRANSPORT_TRAILER  *PacketTrailer,
> +  OUT  UINT16                           *PacketTrailerSize
> +  )
> +{
> +  MANAGEABILITY_MCTP_TRANSPORT_HEADER  *MctpHeader;
> +  PLDM_REQUEST_HEADER                  *PldmRequestHeader;
> +
> +  if ((PacketHeader == NULL) || (PacketHeaderSize == NULL) ||
> +      (PacketBody   == NULL) || (PacketBodySize == NULL) ||
> +      (PacketTrailer == NULL) || (PacketTrailerSize == NULL)
> +      )
> +  {
> +    DEBUG ((DEBUG_ERROR, "%a: One or more than one of the required
> parameters is NULL.\n", __FUNCTION__));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (CompareGuid (&gManageabilityTransportMctpGuid, TransportToken-
> >Transport->ManageabilityTransportSpecification)) {
> +    DEBUG ((DEBUG_MANAGEABILITY_INFO, "%a: Setup transport header for
> + PLDM over MCTP.\n", __FUNCTION__));
> +
> +    // This is MCTP transport interface.
> +    MctpHeader = AllocateZeroPool (sizeof
> (MANAGEABILITY_MCTP_TRANSPORT_HEADER));
> +    if (MctpHeader == NULL) {
> +      DEBUG ((DEBUG_ERROR, "%a: Not enough memory for
> MANAGEABILITY_MCTP_TRANSPORT_HEADER.\n", __FUNCTION__));
> +      return EFI_OUT_OF_RESOURCES;
> +    }
> +
> +    MctpHeader->SourceEndpointId             = PcdGet8
> (PcdMctpSourceEndpointId);
> +    MctpHeader->SourceEndpointId             = PcdGet8
> (PcdMctpDestinationEndpointId);
> +    MctpHeader->MessageHeader.IntegrityCheck = FALSE;
> +    MctpHeader->MessageHeader.MessageType    =
> MCTP_MESSAGE_TYPE_PLDM;
> +    *PacketHeader                            = (MANAGEABILITY_TRANSPORT_HEADER
> *)MctpHeader;
> +    *PacketHeaderSize                        = sizeof
> (MANAGEABILITY_TRANSPORT_HEADER);
> +    *PacketTrailer                           = NULL;
> +    *PacketTrailerSize                       = 0;
> +  } else {
> +    DEBUG ((DEBUG_ERROR, "%a: No implementation of building up packet.\n",
> __FUNCTION__));
> +    ASSERT (FALSE);
> +  }
> +
> +  //
> +  // Create header for the final request message.
> +  //
> +  PldmRequestHeader = (PLDM_REQUEST_HEADER *)AllocateZeroPool (sizeof
> + (PLDM_REQUEST_HEADER) + *PacketBodySize);  if (PldmRequestHeader ==
> NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a: Not enough memory for final PLDM request
> message.\n", __FUNCTION__));
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  PldmRequestHeader->RequestBit          =
> PLDM_MESSAGE_HEADER_IS_REQUEST;
> +  PldmRequestHeader->HeaderVersion       =
> PLDM_MESSAGE_HEADER_VERSION;
> +  PldmRequestHeader->PldmType            = PldmType;
> +  PldmRequestHeader->PldmTypeCommandCode = PldmCommand;
> +  PldmRequestHeader->InstanceId          = mPldmRequestInstanceId;
> +  if ((*PacketBody != NULL) && (*PacketBodySize != 0)) {
> +    CopyMem (
> +      (VOID *)((UINT8 *)PldmRequestHeader + sizeof (PLDM_REQUEST_HEADER)),
> +      (VOID *)*PacketBody,
> +      *PacketBodySize
> +      );
> +  }
> +
> +  *PacketBody     = (UINT8 *)PldmRequestHeader;
> +  *PacketBodySize = sizeof (PLDM_REQUEST_HEADER) + *PacketBodySize;
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Common code to submit PLDM commands
> +
> +  @param[in]         TransportToken    Transport token.
> +  @param[in]         PldmType          PLDM message type.
> +  @param[in]         PldmCommand       PLDM command of this PLDM type.
> +  @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
> +CommonPldmSubmitCommand (
> +  IN     MANAGEABILITY_TRANSPORT_TOKEN  *TransportToken,
> +  IN     UINT8                          PldmType,
> +  IN     UINT8                          PldmCommand,
> +  IN     UINT8                          *RequestData OPTIONAL,
> +  IN     UINT32                         RequestDataSize,
> +  OUT    UINT8                          *ResponseData OPTIONAL,
> +  IN OUT UINT32                         *ResponseDataSize
> +  )
> +{
> +  EFI_STATUS                                 Status;
> +  UINT8                                      *ThisRequestData;
> +  UINT32                                     ThisRequestDataSize;
> +  MANAGEABILITY_TRANSFER_TOKEN               TransferToken;
> +  MANAGEABILITY_TRANSPORT_HEADER             PldmTransportHeader;
> +  MANAGEABILITY_TRANSPORT_TRAILER            PldmTransportTrailer;
> +  MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS
> TransportAdditionalStatus;
> +  UINT8                                      *FullPacketResponseData;
> +  UINT32                                     FullPacketResponseDataSize;
> +  PLDM_RESPONSE_HEADER                       *ResponseHeader;
> +  UINT16                                     HeaderSize;
> +  UINT16                                     TrailerSize;
> +
> +  if (TransportToken == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a: No transport token for PLDM\n",
> __FUNCTION__));
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  Status = TransportToken->Transport->Function.Version1_0->TransportStatus (
> +                                                             TransportToken,
> +                                                             &TransportAdditionalStatus
> +                                                             );  if
> + (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a: Transport %s for PLDM has problem - (%r)\n",
> __FUNCTION__, mTransportName, Status));
> +    return Status;
> +  }
> +
> +  ThisRequestData = RequestData;            // Save the original request data
> because the request data maybe modified
> +                                            // in SetupIpmiRequestTransportPacket() according to
> transport interface.
> +  ThisRequestDataSize = RequestDataSize;    // Save the original request data
> size because the request data size maybe modified
> +                                            //  in SetupIpmiRequestTransportPacket() according to
> transport interface.
> +  PldmTransportHeader  = NULL;
> +  PldmTransportTrailer = NULL;
> +  Status               = SetupPldmRequestTransportPacket (
> +                           TransportToken,
> +                           PldmType,
> +                           PldmCommand,
> +                           &PldmTransportHeader,
> +                           &HeaderSize,
> +                           &ThisRequestData,
> +                           &ThisRequestDataSize,
> +                           &PldmTransportTrailer,
> +                           &TrailerSize
> +                           );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a: Fail to build packets - (%r)\n", __FUNCTION__,
> Status));
> +    return Status;
> +  }
> +
> +  ZeroMem (&TransferToken, sizeof (MANAGEABILITY_TRANSFER_TOKEN));
> +  TransferToken.TransmitHeader      = PldmTransportHeader;
> +  TransferToken.TransmitHeaderSize  = HeaderSize;
> +  TransferToken.TransmitTrailer     = PldmTransportTrailer;
> +  TransferToken.TransmitTrailerSize = TrailerSize;
> +
> +  // Transmit packet.
> +  if ((ThisRequestData == NULL) || (ThisRequestDataSize == 0)) {
> +    // Transmit parameter were not changed by
> SetupIpmiRequestTransportPacket().
> +    TransferToken.TransmitPackage.TransmitPayload    = RequestData;
> +    TransferToken.TransmitPackage.TransmitSizeInByte =
> + ThisRequestDataSize;  } else {
> +    // Transmit parameter were changed by SetupIpmiRequestTransportPacket().
> +    TransferToken.TransmitPackage.TransmitPayload    = ThisRequestData;
> +    TransferToken.TransmitPackage.TransmitSizeInByte =
> + ThisRequestDataSize;  }
> +
> +  TransferToken.TransmitPackage.TransmitTimeoutInMillisecond =
> + MANAGEABILITY_TRANSPORT_NO_TIMEOUT;
> +
> +  // Set receive packet.
> +  FullPacketResponseDataSize = GetFullPacketResponseSize (PldmType,
> + PldmCommand);  if (FullPacketResponseDataSize == 0) {
> +    DEBUG ((DEBUG_ERROR, "  No mapping entry in
> PldmMessagePacketMappingTable for PLDM Type:%d Command %d\n",
> PldmType, PldmCommand));
> +    ASSERT (FALSE);
> +  }
> +
> +  FullPacketResponseData = (UINT8 *)AllocateZeroPool
> + (FullPacketResponseDataSize);  if (FullPacketResponseData == NULL) {
> +    DEBUG ((DEBUG_ERROR, "  Not enough memory for
> FullPacketResponseDataSize.\n"));
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto ErrorExit2;
> +  }
> +
> +  // Print out PLDM packet.
> +  DEBUG ((
> +    DEBUG_MANAGEABILITY_INFO,
> +    "%a: Send PLDM type: 0x%x, Command: 0x%x: Request size: 0x%x, Response
> size: 0x%x\n",
> +    __FUNCTION__,
> +    PldmType,
> +    PldmCommand,
> +    TransferToken.TransmitPackage.TransmitSizeInByte,
> +    FullPacketResponseDataSize
> +    ));
> +
> +  HelperManageabilityDebugPrint (
> +    (VOID *)TransferToken.TransmitPackage.TransmitPayload,
> +    TransferToken.TransmitPackage.TransmitSizeInByte,
> +    "PLDM full request payload.\n"
> +    );
> +
> +  TransferToken.ReceivePackage.ReceiveBuffer                =
> FullPacketResponseData;
> +  TransferToken.ReceivePackage.ReceiveSizeInByte            =
> FullPacketResponseDataSize;
> +  TransferToken.ReceivePackage.TransmitTimeoutInMillisecond =
> + MANAGEABILITY_TRANSPORT_NO_TIMEOUT;
> +  TransportToken->Transport->Function.Version1_0-
> >TransportTransmitReceive (
> +                                                    TransportToken,
> +                                                    &TransferToken
> +                                                    );  //  // Check
> + the response size.
> +  if (TransferToken.ReceivePackage.ReceiveSizeInByte < sizeof
> (PLDM_RESPONSE_HEADER)) {
> +    DEBUG ((
> +      DEBUG_MANAGEABILITY_INFO,
> +      "Invalid response header size of PLDM Type %d Command %d, Returned size:
> %d Expected size: %d\n",
> +      PldmType,
> +      PldmCommand,
> +      TransferToken.ReceivePackage.ReceiveSizeInByte,
> +      FullPacketResponseDataSize
> +      ));
> +    if (ResponseDataSize != NULL) {
> +      if (*ResponseDataSize > TransferToken.ReceivePackage.ReceiveSizeInByte)
> {
> +        *ResponseDataSize = TransferToken.ReceivePackage.ReceiveSizeInByte;
> +      }
> +    }
> +
> +    if (ResponseData != NULL) {
> +      CopyMem ((VOID *)ResponseData, (VOID *)FullPacketResponseData,
> *ResponseDataSize);
> +    }
> +
> +    goto ErrorExit;
> +  }
> +
> +  //
> +  // Check the integrity of response. data.
> +  ResponseHeader = (PLDM_RESPONSE_HEADER *)FullPacketResponseData;  if
> + ((ResponseHeader->PldmHeader.DatagramBit != 0) ||
> +      (ResponseHeader->PldmHeader.RequestBit != 0) ||
> +      (ResponseHeader->PldmHeader.InstanceId != mPldmRequestInstanceId) ||
> +      (ResponseHeader->PldmHeader.PldmType != PldmType) ||
> +      (ResponseHeader->PldmHeader.PldmTypeCommandCode !=
> PldmCommand))
> + {
> +    DEBUG ((DEBUG_ERROR, "PLDM integrity check of response data is
> failed.\n"));
> +    DEBUG ((DEBUG_ERROR, "    Request bit  = %d (Expected value: 0)\n"));
> +    DEBUG ((DEBUG_ERROR, "    Datagram     = %d (Expected value: 0)\n"));
> +    DEBUG ((DEBUG_ERROR, "    Instance ID  = %d (Expected value: %d)\n",
> ResponseHeader->PldmHeader.InstanceId, mPldmRequestInstanceId));
> +    DEBUG ((DEBUG_ERROR, "    Pldm Type    = %d (Expected value: %d)\n",
> ResponseHeader->PldmHeader.PldmType, PldmType));
> +    DEBUG ((DEBUG_ERROR, "    Pldm Command = %d (Expected value: %d)\n",
> ResponseHeader->PldmHeader.PldmTypeCommandCode, PldmCommand));
> +    if (ResponseDataSize != NULL) {
> +      if (*ResponseDataSize > TransferToken.ReceivePackage.ReceiveSizeInByte)
> {
> +        *ResponseDataSize = TransferToken.ReceivePackage.ReceiveSizeInByte;
> +      }
> +    }
> +
> +    if (ResponseData != NULL) {
> +      CopyMem ((VOID *)ResponseData, (VOID *)FullPacketResponseData,
> *ResponseDataSize);
> +    }
> +
> +    goto ErrorExit;
> +  }
> +
> +  //
> +  // Check the response size
> +  if (TransferToken.ReceivePackage.ReceiveSizeInByte !=
> FullPacketResponseDataSize) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "The response size is incorrect: Response size %d (Expected %d),
> Completion code %d.\n",
> +      TransferToken.ReceivePackage.ReceiveSizeInByte,
> +      FullPacketResponseDataSize,
> +      ResponseHeader->PldmCompletionCode
> +      ));
> +    if (ResponseDataSize != NULL) {
> +      if (*ResponseDataSize > TransferToken.ReceivePackage.ReceiveSizeInByte)
> {
> +        *ResponseDataSize = TransferToken.ReceivePackage.ReceiveSizeInByte;
> +      }
> +    }
> +
> +    if (ResponseData != NULL) {
> +      CopyMem ((VOID *)ResponseData, (VOID *)FullPacketResponseData,
> *ResponseDataSize);
> +    }
> +
> +    goto ErrorExit;
> +  }
> +
> +  if (*ResponseDataSize != (TransferToken.ReceivePackage.ReceiveSizeInByte -
> sizeof (PLDM_RESPONSE_HEADER))) {
> +    DEBUG ((DEBUG_ERROR, "  The size of response is not matched to
> RequestDataSize assigned by caller.\n"));
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "Caller expects %d, the response size minus PLDM_RESPONSE_HEADER size
> is %d, Completion Code %d.\n",
> +      *ResponseDataSize,
> +      TransferToken.ReceivePackage.ReceiveSizeInByte - sizeof
> (PLDM_RESPONSE_HEADER),
> +      ResponseHeader->PldmCompletionCode
> +      ));
> +    if (ResponseDataSize != NULL) {
> +      if (*ResponseDataSize > TransferToken.ReceivePackage.ReceiveSizeInByte)
> {
> +        *ResponseDataSize = TransferToken.ReceivePackage.ReceiveSizeInByte;
> +      }
> +    }
> +
> +    if (ResponseData != NULL) {
> +      CopyMem ((VOID *)ResponseData, (VOID *)FullPacketResponseData,
> *ResponseDataSize);
> +    }
> +
> +    goto ErrorExit;
> +  }
> +
> +  // Print out PLDM full responses payload.
> +  HelperManageabilityDebugPrint ((VOID *)FullPacketResponseData,
> + FullPacketResponseDataSize, "PLDM full response payload\n");
> +
> +  // Copy response data (without header) to caller's buffer.
> +  if ((ResponseData != NULL) && (*ResponseDataSize != 0)) {
> +    *ResponseDataSize = FullPacketResponseDataSize - sizeof
> (PLDM_RESPONSE_HEADER);
> +    CopyMem (
> +      (VOID *)ResponseData,
> +      (VOID *)(FullPacketResponseData + sizeof (PLDM_RESPONSE_HEADER)),
> +      *ResponseDataSize
> +      );
> +  }
> +
> +  // Return transfer status.
> +  //
> +ErrorExit:
> +  Status = TransferToken.TransferStatus;
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a: Failed to send PLDM command over %s\n",
> +__FUNCTION__, mTransportName));
> +  }
> +
> +ErrorExit2:
> +  if (PldmTransportHeader != NULL) {
> +    FreePool ((VOID *)PldmTransportHeader);
> +  }
> +
> +  if (PldmTransportTrailer != NULL) {
> +    FreePool ((VOID *)PldmTransportTrailer);  }
> +
> +  if (ThisRequestData != NULL) {
> +    FreePool ((VOID *)ThisRequestData);  }
> +
> +  if (FullPacketResponseData != NULL) {
> +    FreePool ((VOID *)FullPacketResponseData);  }
> +
> +  //
> +  // Update PLDM message instance ID.
> +  mPldmRequestInstanceId++;
> +  mPldmRequestInstanceId &= PLDM_MESSAGE_HEADER_INSTANCE_ID_MASK;
> +  return Status;
> +}
> diff --git
> a/Features/ManageabilityPkg/Universal/PldmProtocol/Dxe/PldmProtocol.c
> b/Features/ManageabilityPkg/Universal/PldmProtocol/Dxe/PldmProtocol.c
> new file mode 100644
> index 0000000000..bb34fec16e
> --- /dev/null
> +++ b/Features/ManageabilityPkg/Universal/PldmProtocol/Dxe/PldmProtocol.
> +++ c
> @@ -0,0 +1,181 @@
> +/** @file
> +  This file provides edk2 PLDM SMBIOS Transfer Protocol implementation.
> +
> +  Copyright (C) 2023 Advanced Micro Devices, Inc. All rights
> +reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent **/
> +
> +#include <PiDxe.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h> #include
> +<Library/UefiBootServicesTableLib.h>
> +#include <Library/ManageabilityTransportLib.h>
> +#include <Library/ManageabilityTransportHelperLib.h>
> +#include <IndustryStandard/Pldm.h>
> +#include <Protocol/PldmProtocol.h>
> +
> +#include "PldmProtocolCommon.h"
> +
> +MANAGEABILITY_TRANSPORT_TOKEN  *mTransportToken = NULL;
> +CHAR16                         *mTransportName;
> +UINT8                          mPldmRequestInstanceId;
> +UINT32                         TransportMaximumPayload;
> +
> +/**
> +  This service enables submitting commands via EDKII PLDM protocol.
> +
> +  @param[in]         This              EDKII_PLDM_PROTOCOL instance.
> +  @param[in]         PldmType          PLDM message type.
> +  @param[in]         Command           PLDM Command of PLDM message type.
> +  @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          PLDM transport interface is not ready for PLDM
> command access.
> +  @retval EFI_DEVICE_ERROR       PLDM transport interface 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.
> +  @retval EFI_INVALID_PARAMETER  Both RequestData and ResponseData are
> +NULL **/ EFI_STATUS EFIAPI PldmSubmitCommand (
> +  IN     EDKII_PLDM_PROTOCOL  *This,
> +  IN     UINT8                PldmType,
> +  IN     UINT8                Command,
> +  IN     UINT8                *RequestData,
> +  IN     UINT32               RequestDataSize,
> +  OUT    UINT8                *ResponseData,
> +  IN OUT UINT32               *ResponseDataSize
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  if ((RequestData == NULL) && (ResponseData == NULL)) {
> +    DEBUG ((DEBUG_ERROR, "%a: Both RequestData and ResponseData are
> NULL\n", __FUNCTION__));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Status = CommonPldmSubmitCommand (
> +             mTransportToken,
> +             PldmType,
> +             Command,
> +             RequestData,
> +             RequestDataSize,
> +             ResponseData,
> +             ResponseDataSize
> +             );
> +  return Status;
> +}
> +
> +EDKII_PLDM_PROTOCOL_V1_0  mPldmProtocolV10 = {
> +  PldmSubmitCommand
> +};
> +
> +EDKII_PLDM_PROTOCOL  mPldmProtocol;
> +
> +/**
> +  The entry point of the PLDM SMBIOS Transfer DXE driver.
> +
> +  @param[in] ImageHandle - Handle of this driver image  @param[in]
> + SystemTable - Table containing standard EFI services
> +
> +  @retval EFI_SUCCESS    - PLDM Protocol is installed successfully.
> +  @retval Otherwise      - Other errors.
> +**/
> +EFI_STATUS
> +EFIAPI
> +DxePldmProtocolEntry (
> +  IN EFI_HANDLE        ImageHandle,
> +  IN EFI_SYSTEM_TABLE  *SystemTable
> +  )
> +{
> +  EFI_STATUS                                    Status;
> +  EFI_HANDLE                                    Handle;
> +  MANAGEABILITY_TRANSPORT_CAPABILITY            TransportCapability;
> +  MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS
> TransportAdditionalStatus;
> +  MANAGEABILITY_TRANSPORT_HARDWARE_INFORMATION  HardwareInfo;
> +
> +  Status = HelperAcquireManageabilityTransport (
> +             &gManageabilityProtocolPldmGuid,
> +             &mTransportToken
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a: Failed to acquire transport interface for PLDM
> protocol - %r\n", __FUNCTION__, Status));
> +    return Status;
> +  }
> +
> +  Status = GetTransportCapability (mTransportToken,
> + &TransportCapability);  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a: Failed to GetTransportCapability().\n",
> __FUNCTION__));
> +    return Status;
> +  }
> +
> +  TransportMaximumPayload =
> + MANAGEABILITY_TRANSPORT_PAYLOAD_SIZE_FROM_CAPABILITY
> (TransportCapability);  if (TransportMaximumPayload == (1 <<
> MANAGEABILITY_TRANSPORT_CAPABILITY_MAXIMUM_PAYLOAD_NOT_AVAILA
> BLE)) {
> +    DEBUG ((DEBUG_MANAGEABILITY_INFO, "%a: Transport interface maximum
> + payload is undefined.\n", __FUNCTION__));  } else {
> +    TransportMaximumPayload -= 1;
> +    DEBUG ((DEBUG_MANAGEABILITY_INFO, "%a: Transport interface for PLDM
> + protocol has maximum payload 0x%x.\n", __FUNCTION__,
> + TransportMaximumPayload));  }
> +
> +  mTransportName = HelperManageabilitySpecName
> + (mTransportToken->Transport->ManageabilityTransportSpecification);
> +  DEBUG ((DEBUG_MANAGEABILITY_INFO, "%a: PLDM protocol over %s.\n",
> + __FUNCTION__, mTransportName));
> +
> +  // Initial transport interface with the hardware information assigned.
> +  HardwareInfo.Pointer = NULL;
> +  Status               = HelperInitManageabilityTransport (
> +                           mTransportToken,
> +                           HardwareInfo,
> +                           &TransportAdditionalStatus
> +                           );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  mPldmRequestInstanceId             = 0;
> +  mPldmProtocol.ProtocolVersion      = EDKII_PLDM_PROTOCOL_VERSION;
> +  mPldmProtocol.Functions.Version1_0 = &mPldmProtocolV10;
> +  Handle                             = NULL;
> +  Status                             = gBS->InstallProtocolInterface (
> +                                              &Handle,
> +                                              &gEdkiiPldmProtocolGuid,
> +                                              EFI_NATIVE_INTERFACE,
> +                                              (VOID **)&mPldmProtocol
> +                                              );  if (EFI_ERROR
> + (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a: Failed to install EDKII PLDM protocol -
> + %r\n", __FUNCTION__, Status));  }
> +
> +  return Status;
> +}
> +
> +/**
> +  This is the unload handler of PLDM SMBIOS Transfer DXE driver.
> +
> +  @param[in] ImageHandle           The driver's image handle.
> +
> +  @retval    EFI_SUCCESS           The image is unloaded.
> +  @retval    Others                Failed to unload the image.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +PldmProtocolUnloadImage (
> +  IN EFI_HANDLE  ImageHandle
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = EFI_SUCCESS;
> +  if (mTransportToken != NULL) {
> +    Status = ReleaseTransportSession (mTransportToken);  }
> +
> +  return Status;
> +}
> --
> 2.37.1.windows.1


  reply	other threads:[~2023-04-20  7:05 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-04-18  7:15 [edk2-platforms][PATCH V2 00/14] ManageabilityPkg part II Chang, Abner
2023-04-18  7:15 ` [edk2-platforms][PATCH V2 01/14] ManageabilityPkg: Add more helper functions Chang, Abner
2023-04-19  5:29   ` Attar, AbdulLateef (Abdul Lateef)
2023-04-20 15:18     ` Chang, Abner
2023-04-20  6:42   ` Nickle Wang
2023-04-20 15:45     ` Chang, Abner
2023-04-18  7:15 ` [edk2-platforms][PATCH V2 02/14] ManageabilityPkg: Support Maximum Transfer Unit Chang, Abner
2023-04-20  4:28   ` Attar, AbdulLateef (Abdul Lateef)
2023-04-20  6:08   ` [edk2-devel] " Tinh Nguyen
2023-04-21  0:51     ` Chang, Abner
2023-04-21  6:59       ` Tinh Nguyen
2023-04-21  7:09         ` Chang, Abner
     [not found]         ` <1757E190B31AA266.29498@groups.io>
2023-04-24  1:42           ` Chang, Abner
     [not found]     ` <1757CCE5059D419D.29498@groups.io>
2023-04-21  5:26       ` Chang, Abner
2023-04-20  6:44   ` Nickle Wang
2023-04-18  7:15 ` [edk2-platforms][PATCH V2 03/14] ManageabilityPkg: Add HeaderSize and TrailerSize Chang, Abner
2023-04-20  6:47   ` Nickle Wang
2023-04-18  7:15 ` [edk2-platforms][PATCH V2 04/14] ManageabilityPkg: Add PldmProtocolLib Chang, Abner
2023-04-20  6:50   ` Nickle Wang
2023-04-18  7:15 ` [edk2-platforms][PATCH V2 05/14] ManageabilityPkg: Add PldmSmbiosTransferDxe driver Chang, Abner
2023-04-20  6:52   ` Nickle Wang
2023-04-18  7:15 ` [edk2-platforms][PATCH V2 06/14] ManageabilityPkg/KCS: KCS transport interface Chang, Abner
2023-04-20  6:53   ` Nickle Wang
2023-04-18  7:15 ` [edk2-platforms][PATCH V2 07/14] ManageabilityPkg: Add definitions of MCTP Chang, Abner
2023-04-20  6:54   ` Nickle Wang
2023-04-18  7:15 ` [edk2-platforms][PATCH V2 08/14] ManageabilityPkg: Add MCTP manageability header file Chang, Abner
2023-04-20  6:56   ` Nickle Wang
2023-04-18  7:15 ` [edk2-platforms][PATCH V2 09/14] ManageabilityPkg/MctpProtocol: Add MctpProtocol Chang, Abner
2023-04-20  7:00   ` Nickle Wang
2023-04-18  7:15 ` [edk2-platforms][PATCH V2 10/14] ManageabilityPkg: Add MCTP transport interface Chang, Abner
2023-04-20  7:04   ` Nickle Wang
2023-04-18  7:15 ` [edk2-platforms][PATCH V2 11/14] ManageabilityPkg/PldmProtocol: Add PLDM protocol Chang, Abner
2023-04-20  7:05   ` Nickle Wang [this message]
2023-04-18  7:15 ` [edk2-platforms][PATCH V2 12/14] ManageabilityPkg: Add Manageability PCDs Chang, Abner
2023-04-20  5:26   ` Tinh Nguyen
2023-04-20  7:07   ` Nickle Wang
2023-04-18  7:15 ` [edk2-platforms][PATCH V2 13/14] ManageabilityPkg: Relocate Manageability.dsc Chang, Abner
2023-04-20  5:28   ` Tinh Nguyen
2023-04-20  7:08   ` Nickle Wang
2023-04-18  7:15 ` [edk2-platforms][PATCH V2 14/14] ManageabilityPkg: Add Manageability FDFs Chang, Abner
2023-04-20  5:29   ` Tinh Nguyen
2023-04-20  7:08   ` Nickle Wang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=MW4PR12MB7031AE50B9C45DF629494C45D9639@MW4PR12MB7031.namprd12.prod.outlook.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox