blob: 2c768d460787ac3002d98a4c05f3746e635d5f45 [file]
/** @file
MCTP Manageability Protocol common file.
Copyright (C) 2023-2026 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/ManageabilityTransportHelperLib.h>
#include <Library/ManageabilityTransportMctpLib.h>
#include <Library/ManageabilityTransportLib.h>
#include <IndustryStandard/Mctp.h>
#include "MctpProtocolCommon.h"
extern CHAR16 *mTransportName;
extern UINT32 mTransportMaximumPayload;
MANAGEABILITY_TRANSPORT_HARDWARE_INFORMATION mHardwareInformation;
UINT8 mMctpPacketSequence;
BOOLEAN mStartOfMessage;
BOOLEAN mEndOfMessage;
/**
This functions setup the MCTP 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
SetupMctpTransportHardwareInformation (
IN MANAGEABILITY_TRANSPORT_TOKEN *TransportToken,
OUT MANAGEABILITY_TRANSPORT_HARDWARE_INFORMATION *HardwareInformation
)
{
MANAGEABILITY_TRANSPORT_KCS_HARDWARE_INFO *KcsHardwareInfo;
BOOLEAN MctpKcsMemMapIo;
KcsHardwareInfo = NULL;
if (CompareGuid (&gManageabilityTransportKcsGuid, TransportToken->Transport->ManageabilityTransportSpecification)) {
KcsHardwareInfo = AllocatePool (sizeof (MANAGEABILITY_TRANSPORT_KCS_HARDWARE_INFO));
if (KcsHardwareInfo == NULL) {
DEBUG ((DEBUG_ERROR, "%a: Not enough memory for MANAGEABILITY_TRANSPORT_KCS_HARDWARE_INFO.\n", __func__));
return EFI_OUT_OF_RESOURCES;
}
MctpKcsMemMapIo = PcdGetBool (PcdMctpKcsMemoryMappedIo);
if (MctpKcsMemMapIo) {
KcsHardwareInfo->MemoryMap = MANAGEABILITY_TRANSPORT_KCS_MEMORY_MAP_IO;
KcsHardwareInfo->IoBaseAddress.IoAddress32 = MCTP_KCS_BASE_ADDRESS;
KcsHardwareInfo->IoDataInAddress.IoAddress32 = MCTP_KCS_REG_DATA_IN_MEMMAP;
KcsHardwareInfo->IoDataOutAddress.IoAddress32 = MCTP_KCS_REG_DATA_OUT_MEMMAP;
KcsHardwareInfo->IoCommandAddress.IoAddress32 = MCTP_KCS_REG_COMMAND_MEMMAP;
KcsHardwareInfo->IoStatusAddress.IoAddress32 = MCTP_KCS_REG_STATUS_MEMMAP;
} else {
KcsHardwareInfo->MemoryMap = MANAGEABILITY_TRANSPORT_KCS_IO_MAP_IO;
KcsHardwareInfo->IoBaseAddress.IoAddress16 = (UINT16)MCTP_KCS_BASE_ADDRESS;
KcsHardwareInfo->IoDataInAddress.IoAddress16 = (UINT16)MCTP_KCS_REG_DATA_IN_IO;
KcsHardwareInfo->IoDataOutAddress.IoAddress16 = (UINT16)MCTP_KCS_REG_DATA_OUT_IO;
KcsHardwareInfo->IoCommandAddress.IoAddress16 = (UINT16)MCTP_KCS_REG_COMMAND_IO;
KcsHardwareInfo->IoStatusAddress.IoAddress16 = (UINT16)MCTP_KCS_REG_STATUS_IO;
}
HardwareInformation->Kcs = KcsHardwareInfo;
return EFI_SUCCESS;
} else {
DEBUG ((DEBUG_ERROR, "%a: No implementation of setting hardware information.", __func__));
ASSERT (FALSE);
}
return EFI_UNSUPPORTED;
}
/**
This functions setup the final header/body/trailer packets for
the acquired transport interface.
@param[in] TransportToken The transport interface.
@param[in] MctpType MCTP message type.
@param[in] MctpSourceEndpointId MCTP source endpoint ID.
@param[in] MctpDestinationEndpointId MCTP source endpoint ID.
@param[in] RequestDataIntegrityCheck Indicates whether MCTP message has
integrity check byte.
@param[out] PacketHeader The pointer to receive header of request.
@param[out] PacketHeaderSize Packet header size.
@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.
@retval EFI_SUCCESS Request packet is returned.
@retval EFI_OUT_OF_RESOURCE Not enough resource to create the request
transport packets.
@retval EFI_UNSUPPORTED Request packet is not returned because
the unsupported transport interface.
**/
EFI_STATUS
SetupMctpRequestTransportPacket (
IN MANAGEABILITY_TRANSPORT_TOKEN *TransportToken,
IN UINT8 MctpType,
IN UINT8 MctpSourceEndpointId,
IN UINT8 MctpDestinationEndpointId,
IN BOOLEAN RequestDataIntegrityCheck,
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_KCS_HEADER *MctpKcsHeader;
MCTP_TRANSPORT_HEADER *MctpTransportHeader;
MCTP_MESSAGE_HEADER *MctpMessageHeader;
MANAGEABILITY_MCTP_KCS_TRAILER *MctpKcsTrailer;
UINT8 *ThisPackage;
if ((PacketHeader == NULL) || (PacketHeaderSize == NULL) ||
(PacketBody == NULL) || (PacketBodySize == NULL) ||
(PacketTrailer == NULL) || (PacketTrailerSize == NULL)
)
{
DEBUG ((DEBUG_ERROR, "%a: One or more than one of the input parameter is invalid.\n", __func__));
return EFI_INVALID_PARAMETER;
}
if (CompareGuid (&gManageabilityTransportKcsGuid, TransportToken->Transport->ManageabilityTransportSpecification)) {
MctpKcsHeader = (MANAGEABILITY_MCTP_KCS_HEADER *)AllocateZeroPool (sizeof (MANAGEABILITY_MCTP_KCS_HEADER));
if (MctpKcsHeader == NULL) {
DEBUG ((DEBUG_ERROR, "%a: Not enough resource for MANAGEABILITY_MCTP_KCS_HEADER.\n", __func__));
return EFI_OUT_OF_RESOURCES;
}
MctpKcsTrailer = (MANAGEABILITY_MCTP_KCS_TRAILER *)AllocateZeroPool (sizeof (MANAGEABILITY_MCTP_KCS_TRAILER));
if (MctpKcsTrailer == NULL) {
DEBUG ((DEBUG_ERROR, "%a: Not enough resource for PEC.\n", __func__));
FreePool (MctpKcsHeader);
return EFI_OUT_OF_RESOURCES;
}
// Generate MCTP KCS transport header
MctpKcsHeader->DefiningBody = DEFINING_BODY_DMTF_PRE_OS_WORKING_GROUP;
MctpKcsHeader->NetFunc = MCTP_KCS_NETFN_LUN;
MctpKcsHeader->ByteCount = (UINT8)(MIN (mTransportMaximumPayload, *PacketBodySize + (UINT8)sizeof (MCTP_MESSAGE_HEADER) + (UINT8)sizeof (MCTP_TRANSPORT_HEADER)));
ThisPackage = (UINT8 *)AllocateZeroPool (MctpKcsHeader->ByteCount);
if (ThisPackage == NULL) {
DEBUG ((DEBUG_ERROR, "%a: Not enough resource for package.\n", __func__));
FreePool (MctpKcsHeader);
FreePool (MctpKcsTrailer);
return EFI_OUT_OF_RESOURCES;
}
// Setup MCTP transport header
MctpTransportHeader = (MCTP_TRANSPORT_HEADER *)ThisPackage;
MctpTransportHeader->Bits.Reserved = 0;
MctpTransportHeader->Bits.HeaderVersion = MCTP_KCS_HEADER_VERSION;
MctpTransportHeader->Bits.DestinationEndpointId = MctpDestinationEndpointId;
MctpTransportHeader->Bits.SourceEndpointId = MctpSourceEndpointId;
MctpTransportHeader->Bits.MessageTag = MCTP_MESSAGE_TAG;
MctpTransportHeader->Bits.TagOwner = MCTP_MESSAGE_TAG_OWNER_REQUEST;
MctpTransportHeader->Bits.PacketSequence = mMctpPacketSequence & MCTP_PACKET_SEQUENCE_MASK;
MctpTransportHeader->Bits.StartOfMessage = mStartOfMessage ? 1 : 0;
MctpTransportHeader->Bits.EndOfMessage = mEndOfMessage ? 1 : 0;
// Setup MCTP message header
MctpMessageHeader = (MCTP_MESSAGE_HEADER *)(MctpTransportHeader + 1);
MctpMessageHeader->Bits.MessageType = MctpType;
MctpMessageHeader->Bits.IntegrityCheck = RequestDataIntegrityCheck ? 1 : 0;
// Copy payload
CopyMem ((VOID *)(MctpMessageHeader + 1), (VOID *)*PacketBody, *PacketBodySize);
//
// Generate PEC follow SMBUS 2.0 specification.
MctpKcsTrailer->Pec = HelperManageabilityGenerateCrc8 (MCTP_KCS_PACKET_ERROR_CODE_POLY, 0, ThisPackage, MctpKcsHeader->ByteCount);
*PacketBody = (UINT8 *)ThisPackage;
*PacketBodySize = MctpKcsHeader->ByteCount;
*PacketTrailer = (MANAGEABILITY_TRANSPORT_TRAILER)MctpKcsTrailer;
*PacketHeader = (MANAGEABILITY_TRANSPORT_HEADER)MctpKcsHeader;
*PacketHeaderSize = sizeof (MANAGEABILITY_MCTP_KCS_HEADER);
*PacketTrailerSize = sizeof (MANAGEABILITY_MCTP_KCS_TRAILER);
return EFI_SUCCESS;
} else {
DEBUG ((DEBUG_ERROR, "%a: No implementation of building up packet.", __func__));
ASSERT (FALSE);
}
return EFI_SUCCESS;
}
/**
Common code to submit MCTP message
@param[in] TransportToken Transport token.
@param[in] MctpType MCTP message type.
@param[in] MctpSourceEndpointId MCTP source endpoint ID.
@param[in] MctpDestinationEndpointId MCTP source endpoint ID.
@param[in] RequestDataIntegrityCheck Indicates whether MCTP message has
integrity check byte.
@param[in] RequestData Message Data.
@param[in] RequestDataSize Size of message Data.
@param[in] RequestTimeout Timeout value in milliseconds.
MANAGEABILITY_TRANSPORT_NO_TIMEOUT means no timeout value.
@param[out] ResponseData Message Response Data. The completion code is the first byte of response data.
@param[in, out] ResponseDataSize Size of Message Response Data.
@param[in] ResponseTimeout Timeout value in milliseconds.
MANAGEABILITY_TRANSPORT_NO_TIMEOUT means no timeout value.
@param[out] AdditionalTransferError MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS.
@retval EFI_SUCCESS The message was successfully send to transport interface and a
response was successfully received.
@retval EFI_NOT_FOUND The message was not successfully sent to transport interface or a response
was not successfully received from transport interface.
@retval EFI_NOT_READY MCTP transport interface is not ready for MCTP message.
@retval EFI_DEVICE_ERROR MCTP transport interface Device hardware error.
@retval EFI_TIMEOUT The message time out.
@retval EFI_UNSUPPORTED The message was not successfully sent to the transport interface.
@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
CommonMctpSubmitMessage (
IN MANAGEABILITY_TRANSPORT_TOKEN *TransportToken,
IN UINT8 MctpType,
IN UINT8 MctpSourceEndpointId,
IN UINT8 MctpDestinationEndpointId,
IN BOOLEAN RequestDataIntegrityCheck,
IN UINT8 *RequestData,
IN UINT32 RequestDataSize,
IN UINT32 RequestTimeout,
OUT UINT8 *ResponseData,
IN OUT UINT32 *ResponseDataSize,
IN UINT32 ResponseTimeout,
OUT MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS *AdditionalTransferError
)
{
EFI_STATUS Status;
UINT16 IndexOfPackage;
UINT8 *ThisRequestData;
UINT32 ThisRequestDataSize;
UINT16 MctpTransportHeaderSize;
UINT16 MctpTransportTrailerSize;
MANAGEABILITY_TRANSFER_TOKEN TransferToken;
MANAGEABILITY_TRANSPORT_HEADER MctpTransportHeader;
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__));
return EFI_UNSUPPORTED;
}
Status = TransportToken->Transport->Function.Version1_0->TransportStatus (
TransportToken,
AdditionalTransferError
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a: Transport %s for MCTP has problem - (%r)\n", __func__, mTransportName, Status));
return Status;
}
MultiPackages = NULL;
Status = HelperManageabilitySplitPayload (
sizeof (MCTP_TRANSPORT_HEADER) + sizeof (MCTP_MESSAGE_HEADER),
0,
RequestData,
RequestDataSize,
mTransportMaximumPayload,
&MultiPackages
);
if (EFI_ERROR (Status) || (MultiPackages == NULL)) {
DEBUG ((DEBUG_ERROR, "%a: Fails to split payload into multiple packages - (%r)\n", __func__, Status));
return Status;
}
// Print transmission packages info.
DEBUG ((DEBUG_MANAGEABILITY_INFO, "Manageability Transmission packages:\n"));
ThisPackage = (MANAGEABILITY_TRANSMISSION_PACKAGE_ATTR *)(MultiPackages + 1);
for (IndexOfPackage = 0; IndexOfPackage < MultiPackages->NumberOfPackages; IndexOfPackage++) {
DEBUG ((DEBUG_MANAGEABILITY_INFO, "#%d: \n", IndexOfPackage));
DEBUG ((DEBUG_MANAGEABILITY_INFO, " Packet pointer: 0x%08x\n", ThisPackage->PayloadPointer));
DEBUG ((DEBUG_MANAGEABILITY_INFO, " Packet size : 0x%08x\n", ThisPackage->PayloadSize));
}
ThisPackage = (MANAGEABILITY_TRANSMISSION_PACKAGE_ATTR *)(MultiPackages + 1);
mMctpPacketSequence = 0;
for (IndexOfPackage = 0; IndexOfPackage < MultiPackages->NumberOfPackages; IndexOfPackage++) {
MctpTransportHeader = NULL;
MctpTransportTrailer = NULL;
ThisRequestData = ThisPackage->PayloadPointer;
ThisRequestDataSize = ThisPackage->PayloadSize;
// Setup Start of Message bit and End of Message bit.
if (MultiPackages->NumberOfPackages == 1) {
mStartOfMessage = TRUE;
mEndOfMessage = TRUE;
} else if (IndexOfPackage == 0) {
mStartOfMessage = TRUE;
mEndOfMessage = FALSE;
} else if (IndexOfPackage == MultiPackages->NumberOfPackages - 1) {
mStartOfMessage = FALSE;
mEndOfMessage = TRUE;
} else {
mStartOfMessage = FALSE;
mEndOfMessage = FALSE;
}
Status = SetupMctpRequestTransportPacket (
TransportToken,
MctpType,
MctpSourceEndpointId,
MctpDestinationEndpointId,
RequestDataIntegrityCheck,
&MctpTransportHeader,
&MctpTransportHeaderSize,
&ThisRequestData,
&ThisRequestDataSize,
&MctpTransportTrailer,
&MctpTransportTrailerSize
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a: Fail to build packets - (%r)\n", __func__, Status));
return Status;
}
ZeroMem (&TransferToken, sizeof (MANAGEABILITY_TRANSFER_TOKEN));
TransferToken.TransmitHeader = MctpTransportHeader;
TransferToken.TransmitHeaderSize = MctpTransportHeaderSize;
TransferToken.TransmitTrailer = MctpTransportTrailer;
TransferToken.TransmitTrailerSize = MctpTransportTrailerSize;
// Transmit packet.
if ((ThisRequestData == NULL) || (ThisRequestDataSize == 0)) {
// Transmit parameter were not changed by SetupMctpRequestTransportPacket().
TransferToken.TransmitPackage.TransmitPayload = ThisPackage->PayloadPointer;
TransferToken.TransmitPackage.TransmitSizeInByte = ThisPackage->PayloadSize;
} else {
TransferToken.TransmitPackage.TransmitPayload = ThisRequestData;
TransferToken.TransmitPackage.TransmitSizeInByte = ThisRequestDataSize;
}
TransferToken.TransmitPackage.TransmitTimeoutInMillisecond = MANAGEABILITY_TRANSPORT_NO_TIMEOUT;
// Receive packet.
TransferToken.ReceivePackage.ReceiveBuffer = NULL;
TransferToken.ReceivePackage.ReceiveSizeInByte = 0;
TransferToken.ReceivePackage.TransmitTimeoutInMillisecond = MANAGEABILITY_TRANSPORT_NO_TIMEOUT;
// Print out MCTP packet.
DEBUG ((
DEBUG_MANAGEABILITY_INFO,
"%a: Send MCTP message type: 0x%x, from source endpoint ID: 0x%x to destination ID 0x%x: Request size: 0x%x, Response size: 0x%x\n",
__func__,
MctpType,
MctpSourceEndpointId,
MctpDestinationEndpointId,
TransferToken.TransmitPackage.TransmitSizeInByte,
TransferToken.ReceivePackage.ReceiveSizeInByte
));
if ((MctpTransportHeader != NULL) && (MctpTransportHeaderSize != 0)) {
HelperManageabilityDebugPrint (
(VOID *)TransferToken.TransmitHeader,
(UINT32)TransferToken.TransmitHeaderSize,
"MCTP transport header.\n"
);
}
HelperManageabilityDebugPrint (
(VOID *)TransferToken.TransmitPackage.TransmitPayload,
TransferToken.TransmitPackage.TransmitSizeInByte,
"MCTP full request payload.\n"
);
if ((MctpTransportTrailer != NULL) && (MctpTransportTrailerSize != 0)) {
HelperManageabilityDebugPrint (
(VOID *)TransferToken.TransmitTrailer,
(UINT32)TransferToken.TransmitTrailerSize,
"MCTP transport trailer.\n"
);
}
TransportToken->Transport->Function.Version1_0->TransportTransmitReceive (
TransportToken,
&TransferToken
);
if (MctpTransportHeader != NULL) {
FreePool ((VOID *)MctpTransportHeader);
}
if (MctpTransportTrailer != NULL) {
FreePool ((VOID *)MctpTransportTrailer);
}
if (ThisRequestData != NULL) {
FreePool ((VOID *)ThisRequestData);
ThisRequestData = NULL;
}
//
// Return transfer status.
//
Status = TransferToken.TransferStatus;
*AdditionalTransferError = TransferToken.TransportAdditionalStatus;
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a: Failed to send MCTP command over %s\n", __func__, mTransportName));
FreePool (MultiPackages);
return Status;
}
mMctpPacketSequence++;
ThisPackage++;
}
ResponseBuffer = (UINT8 *)AllocatePool (*ResponseDataSize + sizeof (MCTP_TRANSPORT_HEADER) + sizeof (MCTP_MESSAGE_HEADER));
if (ResponseBuffer == NULL) {
DEBUG ((DEBUG_ERROR, "%a: Not enough memory to allocate MCTP transfer header.\n", __func__));
if (MultiPackages != NULL) {
FreePool (MultiPackages);
}
return EFI_OUT_OF_RESOURCES;
}
// Receive packet.
TransferToken.TransmitPackage.TransmitPayload = NULL;
TransferToken.TransmitPackage.TransmitSizeInByte = 0;
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;
TransferToken.TransmitTrailerSize = 0;
TransferToken.ReceivePackage.TransmitTimeoutInMillisecond = MANAGEABILITY_TRANSPORT_NO_TIMEOUT;
DEBUG ((
DEBUG_MANAGEABILITY_INFO,
"%a: Retrieve MCTP message Response size: 0x%x\n",
__func__,
TransferToken.ReceivePackage.ReceiveSizeInByte
));
TransportToken->Transport->Function.Version1_0->TransportTransmitReceive (
TransportToken,
&TransferToken
);
*AdditionalTransferError = TransferToken.TransportAdditionalStatus;
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;
}
MctpTransportResponseHeader = (MCTP_TRANSPORT_HEADER *)ResponseBuffer;
if (MctpTransportResponseHeader->Bits.HeaderVersion != MCTP_KCS_HEADER_VERSION) {
DEBUG ((
DEBUG_ERROR,
"%a: Error! Response HeaderVersion (0x%02x) doesn't match MCTP_KCS_HEADER_VERSION (0x%02x)\n",
__func__,
MctpTransportResponseHeader->Bits.HeaderVersion,
MCTP_KCS_HEADER_VERSION
));
FreePool (ResponseBuffer);
return EFI_DEVICE_ERROR;
}
if (MctpTransportResponseHeader->Bits.MessageTag != MCTP_MESSAGE_TAG) {
DEBUG ((
DEBUG_ERROR,
"%a: Error! Response MessageTag (0x%02x) doesn't match MCTP_MESSAGE_TAG (0x%02x)\n",
__func__,
MctpTransportResponseHeader->Bits.MessageTag,
MCTP_MESSAGE_TAG
));
FreePool (ResponseBuffer);
return EFI_DEVICE_ERROR;
}
if (MctpTransportResponseHeader->Bits.TagOwner != MCTP_MESSAGE_TAG_OWNER_RESPONSE) {
DEBUG ((
DEBUG_ERROR,
"%a: Error! Response TagOwner (0x%02x) doesn't match MCTP_MESSAGE_TAG_OWNER_RESPONSE (0x%02x)\n",
__func__,
MctpTransportResponseHeader->Bits.TagOwner,
MCTP_MESSAGE_TAG_OWNER_RESPONSE
));
FreePool (ResponseBuffer);
return EFI_DEVICE_ERROR;
}
if (MctpTransportResponseHeader->Bits.SourceEndpointId != MctpDestinationEndpointId) {
DEBUG ((
DEBUG_ERROR,
"%a: Error! Response SrcEID (0x%02x) doesn't match sent EID (0x%02x)\n",
__func__,
MctpTransportResponseHeader->Bits.SourceEndpointId,
MctpDestinationEndpointId
));
FreePool (ResponseBuffer);
return EFI_DEVICE_ERROR;
}
if (MctpTransportResponseHeader->Bits.DestinationEndpointId != MctpSourceEndpointId) {
DEBUG ((
DEBUG_ERROR,
"%a: Error! Response DestEID (0x%02x) doesn't match local EID (0x%02x)\n",
__func__,
MctpTransportResponseHeader->Bits.DestinationEndpointId,
MctpSourceEndpointId
));
FreePool (ResponseBuffer);
return EFI_DEVICE_ERROR;
}
if ((MctpTransportResponseHeader->Bits.StartOfMessage != 1) ||
(MctpTransportResponseHeader->Bits.EndOfMessage != 1) ||
(MctpTransportResponseHeader->Bits.PacketSequence != 0))
{
DEBUG ((
DEBUG_ERROR,
"%a: Error! Multiple-packet MCTP responses are not supported by the current driver\n",
__func__
));
FreePool (ResponseBuffer);
return EFI_UNSUPPORTED;
}
MctpMessageResponseHeader = (MCTP_MESSAGE_HEADER *)(MctpTransportResponseHeader + 1);
if (MctpMessageResponseHeader->Bits.MessageType != MctpType) {
DEBUG ((
DEBUG_ERROR,
"%a: Error! Response MessageType (0x%02x) doesn't match sent MessageType (0x%02x)\n",
__func__,
MctpMessageResponseHeader->Bits.MessageType,
MctpType
));
FreePool (ResponseBuffer);
return EFI_DEVICE_ERROR;
}
if (MctpMessageResponseHeader->Bits.IntegrityCheck != (UINT8)RequestDataIntegrityCheck) {
DEBUG ((
DEBUG_ERROR,
"%a: Error! Response IntegrityCheck (%d) doesn't match sent IntegrityCheck (%d)\n",
__func__,
MctpMessageResponseHeader->Bits.IntegrityCheck,
(UINT8)RequestDataIntegrityCheck
));
FreePool (ResponseBuffer);
return EFI_DEVICE_ERROR;
}
*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);
return Status;
}