From: "Konstantin Aladyshev" <aladyshev22@gmail.com>
To: devel@edk2.groups.io
Cc: abner.chang@amd.com, isaac.w.oram@intel.com,
AbdulLateef.Attar@amd.com, nicklew@nvidia.com,
Konstantin Aladyshev <aladyshev22@gmail.com>
Subject: [edk2-devel] [PATCH edk2-platforms v2 03/15] ManageabilityPkg: Support both MCTP and IPMI in KCS tranport library
Date: Fri, 20 Oct 2023 15:52:50 +0300 [thread overview]
Message-ID: <20231020125302.1459-4-aladyshev22@gmail.com> (raw)
In-Reply-To: <20231020125302.1459-1-aladyshev22@gmail.com>
The Manageability KCS transport library needs to support requests both
from MCTP and IPMI transports. Currently the code only handles IPMI
case correctly.
In the MCTP case the communication should be based on the MCTP-over-KCS
specification (DSP0254). This specification defines a special KCS
binding header and trailer structures that need to be present in every
MCTP message.
The header structure contains a length field, therefore response packet
size is not needed to be known beforehand.
The trailer structure contains a PEC checksum that can be used to check
itegrity of the response message.
Modify Manageability KCS transport library code to check which message
is processed (IPMI or MCTP) and handle each case correctly based on its
own specification.
Tested:
- The IPMI KCS communication is tested by Abner Chang,
- The MCTP KCS communication is tested by Konstantin Aladyshev on the
AMD EthanolX CRB.
Signed-off-by: Konstantin Aladyshev <aladyshev22@gmail.com>
Signed-off-by: Abner Chang <abner.chang@amd.com>
---
.../Common/KcsCommon.c | 284 +++++++++++++++---
.../MctpProtocol/Common/MctpProtocolCommon.c | 14 +-
2 files changed, 260 insertions(+), 38 deletions(-)
diff --git a/Features/ManageabilityPkg/Library/ManageabilityTransportKcsLib/Common/KcsCommon.c b/Features/ManageabilityPkg/Library/ManageabilityTransportKcsLib/Common/KcsCommon.c
index d5b54c04be..4f7e7d450f 100644
--- a/Features/ManageabilityPkg/Library/ManageabilityTransportKcsLib/Common/KcsCommon.c
+++ b/Features/ManageabilityPkg/Library/ManageabilityTransportKcsLib/Common/KcsCommon.c
@@ -8,16 +8,19 @@
**/
#include <Uefi.h>
#include <IndustryStandard/IpmiKcs.h>
+#include <IndustryStandard/Mctp.h>
#include <Library/BaseMemoryLib.h>
#include <Library/IoLib.h>
#include <Library/DebugLib.h>
#include <Library/ManageabilityTransportHelperLib.h>
+#include <Library/ManageabilityTransportMctpLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/TimerLib.h>
#include "ManageabilityTransportKcs.h"
extern MANAGEABILITY_TRANSPORT_KCS_HARDWARE_INFO mKcsHardwareInfo;
+extern MANAGEABILITY_TRANSPORT_KCS *mSingleSessionToken;
/**
This function waits for parameter Flag to set.
@@ -379,6 +382,218 @@ KcsTransportRead (
return EFI_SUCCESS;
}
+/**
+ This funciton checks the KCS response data according to
+ manageability protocol.
+
+ @param[in] ResponseData Pointer to response data.
+ @param[in] ResponseDataSize Size of response data.
+ @param[out] AdditionalStatus Pointer to receive the additional status.
+
+ @retval EFI_SUCCESS KCS response header is checked without error
+ @retval EFI_DEVICE_ERROR KCS response header has problem.
+**/
+EFI_STATUS
+KcsCheckResponseData (
+ IN UINT8 *ResponseData,
+ IN UINT32 ResponseDataSize,
+ OUT MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS *AdditionalStatus
+ )
+{
+ EFI_STATUS Status;
+ MANAGEABILITY_MCTP_KCS_TRAILER MctpKcsPec;
+ UINT32 PecSize;
+ UINT8 CalculatedPec;
+ CHAR16 *CompletionCodeStr;
+
+ Status = EFI_SUCCESS;
+ *AdditionalStatus = MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS_NO_ERRORS;
+ if (CompareGuid (&gManageabilityProtocolMctpGuid, mSingleSessionToken->Token.ManageabilityProtocolSpecification)) {
+ //
+ // For MCTP over KCS, check PEC
+ //
+ PecSize = sizeof (MANAGEABILITY_MCTP_KCS_TRAILER) + 1; // +1 to read last dummy byte that finishes KCS transfer
+ Status = KcsTransportRead (&MctpKcsPec.Pec, &PecSize);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Error! Failed to read PEC with Status(%r)\n",
+ __func__,
+ Status
+ ));
+ *AdditionalStatus = MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS_ERROR;
+ return Status;
+ }
+
+ if (PecSize != sizeof (MctpKcsPec)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Error! Received PEC size is %d instead of %d\n",
+ __func__,
+ PecSize,
+ sizeof (MctpKcsPec)
+ ));
+ *AdditionalStatus = MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS_ERROR;
+ return EFI_DEVICE_ERROR;
+ }
+
+ HelperManageabilityDebugPrint ((VOID *)&MctpKcsPec.Pec, PecSize - 1, "MCTP over KCS Response PEC:\n");
+ CalculatedPec = HelperManageabilityGenerateCrc8 (MCTP_KCS_PACKET_ERROR_CODE_POLY, 0, ResponseData, ResponseDataSize);
+ if (CalculatedPec != MctpKcsPec.Pec) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Error! Received PEC is 0x%02x instead of 0x%02x\n",
+ __func__,
+ MctpKcsPec.Pec,
+ CalculatedPec
+ ));
+ Status = EFI_DEVICE_ERROR;
+ }
+ } else if (CompareGuid (&gManageabilityProtocolIpmiGuid, mSingleSessionToken->Token.ManageabilityProtocolSpecification)) {
+ //
+ // For IPMI over KCS
+ // Check and print Completion Code
+ //
+ Status = IpmiHelperCheckCompletionCode (*ResponseData, &CompletionCodeStr, AdditionalStatus);
+ if (!EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_MANAGEABILITY_INFO, "Cc: %02x %s.\n", *((UINT8 *)ResponseData), CompletionCodeStr));
+ } else if (Status == EFI_NOT_FOUND) {
+ DEBUG ((DEBUG_ERROR, "Cc: %02x not defined in IpmiCompletionCodeMapping or invalid.\n", *((UINT8 *)ResponseData)));
+ }
+ }
+
+ return Status;
+}
+
+/**
+ This funciton reads the KCS response header according to
+ manageability protocol. Caller has to free the memory
+ allocated for response header.
+
+ @param[in] ResponseHeader Pointer to receive the response header.
+ @param[out] AdditionalStatus Pointer to receive the additional status.
+
+ @retval EFI_SUCCESS KCS response header is checked and returned
+ to caller.
+ @retval EFI_INVALID_PARAMETER One of the given parameter is incorrect.
+ @retval EFI_OUT_OF_RESOURCE Memory allocation is failed for ResponseHeader.
+ @retval EFI_DEVICE_ERROR Incorrect response header.
+**/
+EFI_STATUS
+KcsReadResponseHeader (
+ IN UINT8 **ResponseHeader,
+ OUT MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS *AdditionalStatus
+ )
+{
+ EFI_STATUS Status;
+ UINT32 RspHeaderSize;
+ UINT32 ExpectedHeaderSize;
+ UINT8 *RspHeader;
+
+ if ((ResponseHeader == NULL) || (AdditionalStatus == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *ResponseHeader = NULL;
+ if (CompareGuid (&gManageabilityProtocolMctpGuid, mSingleSessionToken->Token.ManageabilityProtocolSpecification)) {
+
+ // For MCTP over KCS
+ ExpectedHeaderSize = sizeof (MANAGEABILITY_MCTP_KCS_HEADER);
+ DEBUG ((
+ DEBUG_MANAGEABILITY_INFO,
+ "%a: Reading MCTP over KCS response header.\n",
+ __func__
+ ));
+ } else if (CompareGuid (&gManageabilityProtocolIpmiGuid, mSingleSessionToken->Token.ManageabilityProtocolSpecification)) {
+ // For IPMI over KCS
+
+ ExpectedHeaderSize = sizeof (IPMI_KCS_RESPONSE_HEADER);
+ DEBUG ((
+ DEBUG_MANAGEABILITY_INFO,
+ "%a: Reading IPMI over KCS response header.\n",
+ __func__
+ ));
+ } else {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Error! Unsupportted manageability protocol over KCS: %g.\n",
+ __func__,
+ mSingleSessionToken->Token.ManageabilityProtocolSpecification
+ ));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ RspHeader = (UINT8 *)AllocateZeroPool (ExpectedHeaderSize);
+ if (RspHeader == NULL) {
+ DEBUG ((DEBUG_ERROR, "Memory allocation failed for KCS response header!\n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ RspHeaderSize = ExpectedHeaderSize;
+ Status = KcsTransportRead (RspHeader, &RspHeaderSize);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Error! Failed to read KCS response header Status(%r)\n",
+ __func__,
+ Status
+ ));
+ FreePool (RspHeader);
+ *AdditionalStatus = MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS_ERROR;
+ return Status;
+ }
+
+ if (RspHeaderSize != 0) {
+ HelperManageabilityDebugPrint ((VOID *)RspHeader, RspHeaderSize, "KCS Response Header:\n");
+ }
+
+ if (ExpectedHeaderSize != RspHeaderSize) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "The size (%d bytes) of returned resposne header is not the same as expection (%d bytes)!\n",
+ RspHeaderSize,
+ ExpectedHeaderSize
+ ));
+ FreePool (RspHeader);
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (CompareGuid (&gManageabilityProtocolMctpGuid, mSingleSessionToken->Token.ManageabilityProtocolSpecification)) {
+ //
+ // MCTP over KCS
+ //
+ if (((MANAGEABILITY_MCTP_KCS_HEADER *)RspHeader)->NetFunc != MCTP_KCS_NETFN_LUN) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Error! MANAGEABILITY_MCTP_KCS_HEADER.NetFunc is equal 0x%02x instead of 0x%02x\n",
+ __func__,
+ ((MANAGEABILITY_MCTP_KCS_HEADER *)RspHeader)->NetFunc,
+ MCTP_KCS_NETFN_LUN
+ ));
+ FreePool (RspHeader);
+ *AdditionalStatus = MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS_ERROR;
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (((MANAGEABILITY_MCTP_KCS_HEADER *)RspHeader)->DefiningBody != DEFINING_BODY_DMTF_PRE_OS_WORKING_GROUP) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Error! MANAGEABILITY_MCTP_KCS_HEADER.DefiningBody is equal 0x%02x instead of 0x%02x\n",
+ __func__,
+ ((MANAGEABILITY_MCTP_KCS_HEADER *)RspHeader)->DefiningBody,
+ DEFINING_BODY_DMTF_PRE_OS_WORKING_GROUP
+ ));
+ FreePool (RspHeader);
+ *AdditionalStatus = MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS_ERROR;
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ *ResponseHeader = RspHeader;
+ *AdditionalStatus = MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS_NO_ERRORS;
+ return EFI_SUCCESS;
+}
+
/**
This service communicates with BMC using KCS protocol.
@@ -423,11 +638,9 @@ KcsTransportSendCommand (
OUT MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS *AdditionalStatus
)
{
- EFI_STATUS Status;
- UINT32 RspHeaderSize;
- IPMI_KCS_RESPONSE_HEADER RspHeader;
- UINT32 ExpectedResponseDataSize;
- CHAR16 *CompletionCodeStr;
+ EFI_STATUS Status;
+ UINT8 *RspHeader;
+ UINT32 ExpectedResponseDataSize;
if ((RequestData != NULL) && (RequestDataSize == 0)) {
DEBUG ((DEBUG_ERROR, "%a: Mismatched values of RequestData and RequestDataSize\n", __func__));
@@ -467,56 +680,59 @@ KcsTransportSendCommand (
RequestDataSize
);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "KCS Write Failed with Status(%r)", Status));
+ DEBUG ((DEBUG_ERROR, "KCS Write Failed with Status(%r)\n", Status));
return Status;
}
+ }
+ if ((ResponseData != NULL) && (ResponseDataSize != NULL) && (*ResponseDataSize != 0)) {
//
// Read the response header
- RspHeaderSize = sizeof (IPMI_KCS_RESPONSE_HEADER);
- Status = KcsTransportRead ((UINT8 *)&RspHeader, &RspHeaderSize);
+ //
+ Status = KcsReadResponseHeader (&RspHeader, AdditionalStatus);
if (EFI_ERROR (Status)) {
- DEBUG ((
- DEBUG_ERROR,
- "KCS read response header failed Status(%r), " \
- "RspNetFunctionLun = 0x%x, " \
- "Comamnd = 0x%x \n",
- Status,
- RspHeader.NetFunc,
- RspHeader.Command
- ));
return (Status);
}
//
- // Print out the response payloads.
- HelperManageabilityDebugPrint ((VOID *)&RspHeader, RspHeaderSize, "KCS Response Header:\n");
- }
+ // Override ResposeDataSize if the manageability protocol is MCTP.
+ //
+ if (CompareGuid (&gManageabilityProtocolMctpGuid, mSingleSessionToken->Token.ManageabilityProtocolSpecification)) {
+ if (*ResponseDataSize < ((MANAGEABILITY_MCTP_KCS_HEADER *)RspHeader)->ByteCount) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Error! MANAGEABILITY_MCTP_KCS_HEADER.ByteCount (0x%02x) is bigger than provided buffer (0x%02x)\n",
+ __func__,
+ ((MANAGEABILITY_MCTP_KCS_HEADER *)RspHeader)->ByteCount,
+ *ResponseDataSize
+ ));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *ResponseDataSize = ((MANAGEABILITY_MCTP_KCS_HEADER *)RspHeader)->ByteCount;
+ }
+ FreePool (RspHeader);
- if ((ResponseData != NULL) && (ResponseDataSize != NULL) && (*ResponseDataSize != 0)) {
ExpectedResponseDataSize = *ResponseDataSize;
- Status = KcsTransportRead ((UINT8 *)ResponseData, ResponseDataSize);
+ Status = KcsTransportRead (ResponseData, ResponseDataSize);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "KCS response read Failed with Status(%r)", Status));
+ DEBUG ((DEBUG_ERROR, "KCS response read Failed with Status(%r)\n", Status));
}
- //
// Print out the response payloads.
if (*ResponseDataSize != 0) {
if (ExpectedResponseDataSize != *ResponseDataSize) {
- DEBUG ((DEBUG_ERROR, "Expected KCS response size : %d is not matched to returned size : %d.\n", ExpectedResponseDataSize, *ResponseDataSize));
- Status = EFI_DEVICE_ERROR;
+ DEBUG ((
+ DEBUG_ERROR,
+ "Expected KCS response size : %d is not matched to returned size : %d.\n",
+ ExpectedResponseDataSize,
+ *ResponseDataSize
+ ));
+ return EFI_DEVICE_ERROR;
}
HelperManageabilityDebugPrint ((VOID *)ResponseData, (UINT32)*ResponseDataSize, "KCS Response Data:\n");
-
- // Print Completion Code
- Status = IpmiHelperCheckCompletionCode (*((UINT8 *)ResponseData), &CompletionCodeStr, AdditionalStatus);
- if (!EFI_ERROR (Status)) {
- DEBUG ((DEBUG_MANAGEABILITY_INFO, "Cc: %02x %s.\n", *((UINT8 *)ResponseData), CompletionCodeStr));
- } else if (Status == EFI_NOT_FOUND) {
- DEBUG ((DEBUG_MANAGEABILITY_INFO, "Cc: %02x not defined in IpmiCompletionCodeMapping or invalid.\n", *((UINT8 *)ResponseData)));
- }
+ Status = KcsCheckResponseData (ResponseData, *ResponseDataSize, AdditionalStatus);
} else {
DEBUG ((DEBUG_ERROR, "No response, can't determine Completion Code.\n"));
}
diff --git a/Features/ManageabilityPkg/Universal/MctpProtocol/Common/MctpProtocolCommon.c b/Features/ManageabilityPkg/Universal/MctpProtocol/Common/MctpProtocolCommon.c
index 7576007f77..e560c638d5 100644
--- a/Features/ManageabilityPkg/Universal/MctpProtocol/Common/MctpProtocolCommon.c
+++ b/Features/ManageabilityPkg/Universal/MctpProtocol/Common/MctpProtocolCommon.c
@@ -267,6 +267,9 @@ CommonMctpSubmitMessage (
MANAGEABILITY_TRANSPORT_TRAILER MctpTransportTrailer;
MANAGEABILITY_TRANSMISSION_MULTI_PACKAGES *MultiPackages;
MANAGEABILITY_TRANSMISSION_PACKAGE_ATTR *ThisPackage;
+ UINT8 *ResponseBuffer;
+ MCTP_TRANSPORT_HEADER *MctpTransportResponseHeader;
+ MCTP_MESSAGE_HEADER *MctpMessageResponseHeader;
if (TransportToken == NULL) {
DEBUG ((DEBUG_ERROR, "%a: No transport toke for MCTP\n", __func__));
@@ -435,11 +438,12 @@ CommonMctpSubmitMessage (
ThisPackage++;
}
+ ResponseBuffer = (UINT8 *)AllocatePool (*ResponseDataSize + sizeof (MCTP_TRANSPORT_HEADER) + sizeof (MCTP_MESSAGE_HEADER));
// Receive packet.
TransferToken.TransmitPackage.TransmitPayload = NULL;
TransferToken.TransmitPackage.TransmitSizeInByte = 0;
- TransferToken.ReceivePackage.ReceiveBuffer = ResponseData;
- TransferToken.ReceivePackage.ReceiveSizeInByte = *ResponseDataSize;
+ TransferToken.ReceivePackage.ReceiveBuffer = ResponseBuffer;
+ TransferToken.ReceivePackage.ReceiveSizeInByte = *ResponseDataSize + sizeof (MCTP_TRANSPORT_HEADER) + sizeof (MCTP_MESSAGE_HEADER);
TransferToken.TransmitHeader = NULL;
TransferToken.TransmitHeaderSize = 0;
TransferToken.TransmitTrailer = NULL;
@@ -461,8 +465,10 @@ CommonMctpSubmitMessage (
// Return transfer status.
//
*AdditionalTransferError = TransferToken.TransportAdditionalStatus;
- *ResponseDataSize = TransferToken.ReceivePackage.ReceiveSizeInByte;
- Status = TransferToken.TransferStatus;
+ *ResponseDataSize = TransferToken.ReceivePackage.ReceiveSizeInByte - sizeof (MCTP_TRANSPORT_HEADER) - sizeof (MCTP_MESSAGE_HEADER);
+ CopyMem (ResponseData, ResponseBuffer + sizeof (MCTP_TRANSPORT_HEADER) + sizeof (MCTP_MESSAGE_HEADER), *ResponseDataSize);
+ FreePool (ResponseBuffer);
+ Status = TransferToken.TransferStatus;
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a: Failed to send MCTP command over %s: %r\n", __func__, mTransportName, Status));
return Status;
--
2.34.1
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#109853): https://edk2.groups.io/g/devel/message/109853
Mute This Topic: https://groups.io/mt/102080230/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-
next prev parent reply other threads:[~2023-10-20 12:53 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-10-20 12:52 [edk2-devel] [PATCH edk2-platforms v2 00/15] MTCP-over-KCS support Konstantin Aladyshev
2023-10-20 12:52 ` [edk2-devel] [PATCH edk2-platforms v2 01/15] ManageabilityPkg: Add definition for the MCTP KCS TRAILER structure Konstantin Aladyshev
2023-10-20 12:52 ` [edk2-devel] [PATCH edk2-platforms v2 02/15] ManageabilityPkg: Check MCTP EIDs for reserved values Konstantin Aladyshev
2023-10-20 12:52 ` Konstantin Aladyshev [this message]
2023-10-20 12:52 ` [edk2-devel] [PATCH edk2-platforms v2 04/15] ManageabilityPkg: Check header fields in the MCTP response Konstantin Aladyshev
2023-10-20 12:52 ` [edk2-devel] [PATCH edk2-platforms v2 05/15] ManageabilityPkg: Correct typo in MCTP destination EID field Konstantin Aladyshev
2023-10-20 12:52 ` [edk2-devel] [PATCH edk2-platforms v2 06/15] ManageabilityPkg: Update the algorithm of using MCTP endpoint ID PCD Konstantin Aladyshev
2023-10-20 12:52 ` [edk2-devel] [PATCH edk2-platforms v2 07/15] ManageabilityPkg: Correct value for the MCTP TAG_OWNER response bit Konstantin Aladyshev
2023-10-20 12:52 ` [edk2-devel] [PATCH edk2-platforms v2 08/15] ManageabilityPkg: Don't check MCTP header fields if transfer has failed Konstantin Aladyshev
2023-10-20 12:52 ` [edk2-devel] [PATCH edk2-platforms v2 09/15] ManageabilityPkg: Use correct constants for PLDM header checks Konstantin Aladyshev
2023-10-20 12:52 ` [edk2-devel] [PATCH edk2-platforms v2 10/15] ManageabilityPkg: Return error on multiple-packet MCTP responses Konstantin Aladyshev
2023-10-20 12:52 ` [edk2-devel] [PATCH edk2-platforms v2 11/15] ManageabilityPkg: Add PLDM terminus PCDs Konstantin Aladyshev
2023-10-20 12:52 ` [edk2-devel] [PATCH edk2-platforms v2 12/15] PldmProtocolDxe: Correct TID argument usage Konstantin Aladyshev
2023-10-20 12:53 ` [edk2-devel] [PATCH edk2-platforms v2 13/15] ManageabilityPkg/PldmProtocol: Remove PLDM command table Konstantin Aladyshev
2023-10-20 12:53 ` [edk2-devel] [PATCH edk2-platforms v2 14/15] ManageabilityPkg: Return error on PLDM header check fails Konstantin Aladyshev
2023-10-20 12:53 ` [edk2-devel] [PATCH edk2-platforms v2 15/15] PldmSmbiosTransferDxe: Implement Set PLDM terminus ID API Konstantin Aladyshev
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=20231020125302.1459-4-aladyshev22@gmail.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