From: Abner Chang <abner.ch...@amd.com> MctpProtocol that transmits MCTP message over manageability transport interface library.
Signed-off-by: Abner Chang <abner.ch...@amd.com> Cc: Isaac Oram <isaac.w.o...@intel.com> Cc: Abdul Lateef Attar <abdat...@amd.com> Cc: Nickle Wang <nick...@nvidia.com> Cc: Igor Kulchytskyy <ig...@ami.com> --- .../Include/Dsc/Manageability.dsc | 1 + .../MctpProtocol/Dxe/MctpProtocolDxe.inf | 53 ++ .../Include/Protocol/MctpProtocol.h | 102 ++++ .../MctpProtocol/Common/MctpProtocolCommon.h | 139 ++++++ .../MctpProtocol/Common/MctpProtocolCommon.c | 472 ++++++++++++++++++ .../Universal/MctpProtocol/Dxe/MctpProtocol.c | 218 ++++++++ 6 files changed, 985 insertions(+) create mode 100644 Features/ManageabilityPkg/Universal/MctpProtocol/Dxe/MctpProtocolDxe.inf create mode 100644 Features/ManageabilityPkg/Include/Protocol/MctpProtocol.h create mode 100644 Features/ManageabilityPkg/Universal/MctpProtocol/Common/MctpProtocolCommon.h create mode 100644 Features/ManageabilityPkg/Universal/MctpProtocol/Common/MctpProtocolCommon.c create mode 100644 Features/ManageabilityPkg/Universal/MctpProtocol/Dxe/MctpProtocol.c diff --git a/Features/ManageabilityPkg/Include/Dsc/Manageability.dsc b/Features/ManageabilityPkg/Include/Dsc/Manageability.dsc index 2a354ad898..17f067c6d0 100644 --- a/Features/ManageabilityPkg/Include/Dsc/Manageability.dsc +++ b/Features/ManageabilityPkg/Include/Dsc/Manageability.dsc @@ -33,4 +33,5 @@ [Components.X64] ManageabilityPkg/Universal/IpmiProtocol/Smm/IpmiProtocolSmm.inf ManageabilityPkg/Universal/PldmSmbiosTransferDxe/PldmSmbiosTransferDxe.inf + ManageabilityPkg/Universal/MctpProtocol/Dxe/MctpProtocolDxe.inf diff --git a/Features/ManageabilityPkg/Universal/MctpProtocol/Dxe/MctpProtocolDxe.inf b/Features/ManageabilityPkg/Universal/MctpProtocol/Dxe/MctpProtocolDxe.inf new file mode 100644 index 0000000000..483fbcc04b --- /dev/null +++ b/Features/ManageabilityPkg/Universal/MctpProtocol/Dxe/MctpProtocolDxe.inf @@ -0,0 +1,53 @@ +## @file +# MCTP Protocol DXE Driver. +# +# Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.<BR> +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION = 0x0001001d + BASE_NAME = MctpDxe + FILE_GUID = 58AF169A-AA3F-462B-B0F1-25FBE6C97978 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = DxeMctpEntry + UNLOAD_IMAGE = MctpUnloadImage + +# +# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 +# + +[Sources] + MctpProtocol.c + ../Common/MctpProtocolCommon.c + ../Common/MctpProtocolCommon.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + ManageabilityPkg/ManageabilityPkg.dec + +[LibraryClasses] + BaseMemoryLib + DebugLib + MemoryAllocationLib + ManageabilityTransportHelperLib + ManageabilityTransportLib + UefiDriverEntryPoint + UefiBootServicesTableLib + +[Guids] + gManageabilityProtocolMctpGuid + +[Protocols] + gEdkiiMctpProtocolGuid + +[FixedPcd] + gManageabilityPkgTokenSpaceGuid.PcdMctpKcsMemoryMappedIo + gManageabilityPkgTokenSpaceGuid.PcdMctpKcsBaseAddress + gManageabilityPkgTokenSpaceGuid.PcdMctpSourceEndpointId + gManageabilityPkgTokenSpaceGuid.PcdMctpDestinationEndpointId + +[Depex] + TRUE diff --git a/Features/ManageabilityPkg/Include/Protocol/MctpProtocol.h b/Features/ManageabilityPkg/Include/Protocol/MctpProtocol.h new file mode 100644 index 0000000000..85e42f157d --- /dev/null +++ b/Features/ManageabilityPkg/Include/Protocol/MctpProtocol.h @@ -0,0 +1,102 @@ +/** @file + Protocol of EDKII MCTP Protocol. + + Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef EDKII_MCTP_PROTOCOL_H_ +#define EDKII_MCTP_PROTOCOL_H_ + +#include <IndustryStandard/Mctp.h> + +typedef struct _EDKII_MCTP_PROTOCOL EDKII_MCTP_PROTOCOL; + +#define EDKII_MCTP_PROTOCOL_GUID \ + { \ + 0xE93465C1, 0x9A31, 0x4C96, 0x92, 0x56, 0x22, 0x0A, 0xE1, 0x80, 0xB4, 0x1B \ + } + +#define EDKII_MCTP_PROTOCOL_VERSION_MAJOR 1 +#define EDKII_MCTP_PROTOCOL_VERSION_MINOR 0 +#define EDKII_MCTP_PROTOCOL_VERSION ((EDKII_MCTP_PROTOCOL_VERSION_MAJOR << 8) |\ + EDKII_MCTP_PROTOCOL_VERSION_MINOR) + +/** + This service enables submitting message via EDKII MCTP protocol. + + @param[in] This EDKII_MCTP_PROTOCOL instance. + @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 +**/ +typedef +EFI_STATUS +(EFIAPI *MCTP_SUBMIT_COMMAND)( + IN EDKII_MCTP_PROTOCOL *This, + 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 + ); + +// +// EDKII_MCTP_PROTOCOL Version 1.0 +// +typedef struct { + MCTP_SUBMIT_COMMAND MctpSubmitCommand; +} EDKII_MCTP_PROTOCOL_V1_0; + +/// +/// Definitions of EDKII_MCTP_PROTOCOL. +/// This is a union that can accommodate the new functionalities defined +/// in MCTP Base specification in the future. +/// The new added function must has its own EDKII_MCTP_PROTOCOL +/// structure with the incremental version number. +/// e.g., EDKII_MCTP_PROTOCOL_V1_1. +/// +/// The new function must be added base on the last version of +/// EDKII_MCTP_PROTOCOL to keep the backward compatibility. +/// +typedef union { + EDKII_MCTP_PROTOCOL_V1_0 *Version1_0; +} EDKII_MCTP_PROTOCOL_FUNCTION; + +struct _EDKII_MCTP_PROTOCOL { + UINT16 ProtocolVersion; + EDKII_MCTP_PROTOCOL_FUNCTION Functions; +}; + +extern EFI_GUID gEdkiiMctpProtocolGuid; + +#endif // EDKII_MCTP_PROTOCOL_H_ diff --git a/Features/ManageabilityPkg/Universal/MctpProtocol/Common/MctpProtocolCommon.h b/Features/ManageabilityPkg/Universal/MctpProtocol/Common/MctpProtocolCommon.h new file mode 100644 index 0000000000..72eded719d --- /dev/null +++ b/Features/ManageabilityPkg/Universal/MctpProtocol/Common/MctpProtocolCommon.h @@ -0,0 +1,139 @@ +/** @file + MCTP Manageability Protocol common header file. + + Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef MANAGEABILITY_MCTP_COMMON_H_ +#define MANAGEABILITY_MCTP_COMMON_H_ + +#include <IndustryStandard/IpmiKcs.h> +#include <Library/ManageabilityTransportLib.h> + +#define MCTP_KCS_BASE_ADDRESS PcdGet32(PcdMctpKcsBaseAddress) + +// For I/O mapped I/O +#define MCTP_KCS_REG_DATA_IN_IO MCTP_KCS_BASE_ADDRESS + IPMI_KCS_DATA_IN_REGISTER_OFFSET +#define MCTP_KCS_REG_DATA_OUT_IO MCTP_KCS_BASE_ADDRESS + IPMI_KCS_DATA_OUT_REGISTER_OFFSET +#define MCTP_KCS_REG_COMMAND_IO MCTP_KCS_BASE_ADDRESS + IPMI_KCS_COMMAND_REGISTER_OFFSET +#define MCTP_KCS_REG_STATUS_IO MCTP_KCS_BASE_ADDRESS + IPMI_KCS_STATUS_REGISTER_OFFSET + +// For memory mapped I/O +#define MCTP_KCS_REG_DATA_IN_MEMMAP MCTP_KCS_BASE_ADDRESS + (IPMI_KCS_DATA_IN_REGISTER_OFFSET * 4) +#define MCTP_KCS_REG_DATA_OUT_MEMMAP MCTP_KCS_BASE_ADDRESS + (IPMI_KCS_DATA_OUT_REGISTER_OFFSET * 4) +#define MCTP_KCS_REG_COMMAND_MEMMAP MCTP_KCS_BASE_ADDRESS + (IPMI_KCS_COMMAND_REGISTER_OFFSET * 4) +#define MCTP_KCS_REG_STATUS_MEMMAP MCTP_KCS_BASE_ADDRESS + (IPMI_KCS_STATUS_REGISTER_OFFSET * 4) + +/** + 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 +SetupMctpTransportHardwareInformation ( + 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] 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 + ); + +/** + 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 + ); + +#endif diff --git a/Features/ManageabilityPkg/Universal/MctpProtocol/Common/MctpProtocolCommon.c b/Features/ManageabilityPkg/Universal/MctpProtocol/Common/MctpProtocolCommon.c new file mode 100644 index 0000000000..db572ec85a --- /dev/null +++ b/Features/ManageabilityPkg/Universal/MctpProtocol/Common/MctpProtocolCommon.c @@ -0,0 +1,472 @@ +/** @file + + MCTP 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/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", __FUNCTION__)); + 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.", __FUNCTION__)); + 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; + UINT8 *Pec; + 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", __FUNCTION__)); + 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", __FUNCTION__)); + return EFI_OUT_OF_RESOURCES; + } + + Pec = (UINT8 *)AllocateZeroPool (sizeof (UINT8)); + if (Pec == NULL) { + DEBUG ((DEBUG_ERROR, "%a: Not enough resource for PEC.\n", __FUNCTION__)); + 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", __FUNCTION__)); + FreePool (MctpKcsHeader); + FreePool (Pec); + 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 = PcdGet8 (PcdMctpDestinationEndpointId); + MctpTransportHeader->Bits.SourceEndpointIdId = PcdGet8 (PcdMctpSourceEndpointId); + 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. + *Pec = HelperManageabilityGenerateCrc8 (MCTP_KCS_PACKET_ERROR_CODE_POLY, 0, ThisPackage, MctpKcsHeader->ByteCount); + + *PacketBody = (UINT8 *)ThisPackage; + *PacketBodySize = MctpKcsHeader->ByteCount; + *PacketTrailer = (MANAGEABILITY_TRANSPORT_TRAILER)Pec; + *PacketHeader = (MANAGEABILITY_TRANSPORT_HEADER)MctpKcsHeader; + *PacketHeaderSize = sizeof (MANAGEABILITY_MCTP_KCS_HEADER); + *PacketTrailerSize = 1; + return EFI_SUCCESS; + } else { + DEBUG ((DEBUG_ERROR, "%a: No implementation of building up packet.", __FUNCTION__)); + 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; + + if (TransportToken == NULL) { + DEBUG ((DEBUG_ERROR, "%a: No transport toke for MCTP\n", __FUNCTION__)); + 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", __FUNCTION__, 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", __FUNCTION__, mTransportName, 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", __FUNCTION__, 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", + __FUNCTION__, + 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", __FUNCTION__, mTransportName)); + FreePool (MultiPackages); + return Status; + } + + mMctpPacketSequence++; + ThisPackage++; + } + + // Receive packet. + TransferToken.TransmitPackage.TransmitPayload = NULL; + TransferToken.TransmitPackage.TransmitSizeInByte = 0; + TransferToken.ReceivePackage.ReceiveBuffer = ResponseData; + TransferToken.ReceivePackage.ReceiveSizeInByte = *ResponseDataSize; + 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", + __FUNCTION__, + TransferToken.ReceivePackage.ReceiveSizeInByte + )); + TransportToken->Transport->Function.Version1_0->TransportTransmitReceive ( + TransportToken, + &TransferToken + ); + + // + // Return transfer status. + // + *AdditionalTransferError = TransferToken.TransportAdditionalStatus; + *ResponseDataSize = TransferToken.ReceivePackage.ReceiveSizeInByte; + Status = TransferToken.TransferStatus; + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Failed to send MCTP command over %s: %r\n", __FUNCTION__, mTransportName, Status)); + return Status; + } + + return Status; +} diff --git a/Features/ManageabilityPkg/Universal/MctpProtocol/Dxe/MctpProtocol.c b/Features/ManageabilityPkg/Universal/MctpProtocol/Dxe/MctpProtocol.c new file mode 100644 index 0000000000..a1cac61e27 --- /dev/null +++ b/Features/ManageabilityPkg/Universal/MctpProtocol/Dxe/MctpProtocol.c @@ -0,0 +1,218 @@ +/** @file + This file provides edk2 MCTP 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/ManageabilityTransportLib.h> +#include <Library/ManageabilityTransportHelperLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Protocol/MctpProtocol.h> + +#include <IndustryStandard/Mctp.h> + +#include "MctpProtocolCommon.h" + +extern MANAGEABILITY_TRANSPORT_HARDWARE_INFORMATION mHardwareInformation; + +MANAGEABILITY_TRANSPORT_TOKEN *mTransportToken = NULL; +CHAR16 *mTransportName; +UINT32 mTransportMaximumPayload; + +/** + This service enables submitting message via EDKII MCTP protocol. + + @param[in] This EDKII_MCTP_PROTOCOL instance. + @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 +EFIAPI +MctpSubmitMessage ( + IN EDKII_MCTP_PROTOCOL *This, + 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; + + if ((RequestData == NULL) && (ResponseData == NULL)) { + DEBUG ((DEBUG_ERROR, "%a: Both RequestData and ResponseData are NULL\n", __FUNCTION__)); + return EFI_INVALID_PARAMETER; + } + + Status = CommonMctpSubmitMessage ( + mTransportToken, + MctpType, + MctpSourceEndpointId, + MctpDestinationEndpointId, + RequestDataIntegrityCheck, + RequestData, + RequestDataSize, + RequestTimeout, + ResponseData, + ResponseDataSize, + ResponseTimeout, + AdditionalTransferError + ); + return Status; +} + +EDKII_MCTP_PROTOCOL_V1_0 mMctpProtocolV10 = { + MctpSubmitMessage +}; + +EDKII_MCTP_PROTOCOL mMctpProtocol; + +/** + The entry point of the MCTP DXE driver. + + @param[in] ImageHandle - Handle of this driver image + @param[in] SystemTable - Table containing standard EFI services + + @retval EFI_SUCCESS - edkii MCTP Protocol is installed successfully. + @retval Otherwise - Other errors. +**/ +EFI_STATUS +EFIAPI +DxeMctpEntry ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_HANDLE Handle; + MANAGEABILITY_TRANSPORT_CAPABILITY TransportCapability; + MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS TransportAdditionalStatus; + + Status = HelperAcquireManageabilityTransport ( + &gManageabilityProtocolMctpGuid, + &mTransportToken + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Failed to acquire transport interface for MCTP 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; + } + + mTransportMaximumPayload = MANAGEABILITY_TRANSPORT_PAYLOAD_SIZE_FROM_CAPABILITY (TransportCapability); + if (mTransportMaximumPayload == (1 << MANAGEABILITY_TRANSPORT_CAPABILITY_MAXIMUM_PAYLOAD_NOT_AVAILABLE)) { + DEBUG ((DEBUG_MANAGEABILITY_INFO, "%a: Transport interface maximum payload is undefined.\n", __FUNCTION__)); + } else { + mTransportMaximumPayload -= 1; + DEBUG ((DEBUG_MANAGEABILITY_INFO, "%a: Transport interface for MCTP protocol has maximum payload 0x%x.\n", __FUNCTION__, mTransportMaximumPayload)); + } + + mTransportName = HelperManageabilitySpecName (mTransportToken->Transport->ManageabilityTransportSpecification); + DEBUG ((DEBUG_ERROR, "%a: MCTP protocol over %s.\n", __FUNCTION__, mTransportName)); + + // + // Setup hardware information according to the transport interface. + Status = SetupMctpTransportHardwareInformation ( + mTransportToken, + &mHardwareInformation + ); + if (EFI_ERROR (Status)) { + if (Status == EFI_UNSUPPORTED) { + DEBUG ((DEBUG_ERROR, "%a: No hardware information of %s transport interface.\n", __FUNCTION__, mTransportName)); + } else { + DEBUG ((DEBUG_ERROR, "%a: Failed to setup hardware information of %s transport interface.\n", __FUNCTION__, mTransportName)); + } + + return Status; + } + + // Initial transport interface with the hardware information assigned. + Status = HelperInitManageabilityTransport ( + mTransportToken, + mHardwareInformation, + &TransportAdditionalStatus + ); + if (EFI_ERROR (Status)) { + return Status; + } + + mMctpProtocol.ProtocolVersion = EDKII_MCTP_PROTOCOL_VERSION; + mMctpProtocol.Functions.Version1_0 = &mMctpProtocolV10; + Handle = NULL; + Status = gBS->InstallProtocolInterface ( + &Handle, + &gEdkiiMctpProtocolGuid, + EFI_NATIVE_INTERFACE, + (VOID **)&mMctpProtocol + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Failed to install EDKII MCTP protocol - %r\n", __FUNCTION__, Status)); + } + + return Status; +} + +/** + This is the unload handler for MCTP protocol module. + + Release the MANAGEABILITY_TRANSPORT_TOKEN acquired at entry point. + + @param[in] ImageHandle The drivers' driver image. + + @retval EFI_SUCCESS The image is unloaded. + @retval Others Failed to unload the image. + +**/ +EFI_STATUS +EFIAPI +MctpUnloadImage ( + IN EFI_HANDLE ImageHandle + ) +{ + EFI_STATUS Status; + + Status = EFI_SUCCESS; + if (mTransportToken != NULL) { + Status = ReleaseTransportSession (mTransportToken); + } + + return Status; +} -- 2.37.1.windows.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#103363): https://edk2.groups.io/g/devel/message/103363 Mute This Topic: https://groups.io/mt/98404963/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-