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/PldmProtocolCommon.h
create mode 100644 Features/ManageabilityPkg/Universal/PldmProtocol/Common/PldmProtocolCommon.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.inf
ManageabilityPkg/Universal/MctpProtocol/Dxe/MctpProtocolDxe.inf
diff --git a/Features/ManageabilityPkg/Universal/PldmProtocol/Dxe/PldmProtocolDxe.inf b/Features/ManageabilityPkg/Universal/PldmProtocol/Dxe/PldmProtocolDxe.inf
new file mode 100644
index 0000000000..006f77b09a
--- /dev/null
+++ b/Features/ManageabilityPkg/Universal/PldmProtocol/Dxe/PldmProtocolDxe.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/PldmProtocolCommon.h b/Features/ManageabilityPkg/Universal/PldmProtocol/Common/PldmProtocolCommon.h
new file mode 100644
index 0000000000..231d6e802e
--- /dev/null
+++ b/Features/ManageabilityPkg/Universal/PldmProtocol/Common/PldmProtocolCommon.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/PldmProtocolCommon.c b/Features/ManageabilityPkg/Universal/PldmProtocol/Common/PldmProtocolCommon.c
new file mode 100644
index 0000000000..bb4d3f61a0
--- /dev/null
+++ b/Features/ManageabilityPkg/Universal/PldmProtocol/Common/PldmProtocolCommon.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_AVAILABLE)) {
+ 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
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#103146): https://edk2.groups.io/g/devel/message/103146
Mute This Topic: https://groups.io/mt/98339123/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
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
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#103287): https://edk2.groups.io/g/devel/message/103287
Mute This Topic: https://groups.io/mt/98339123/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
© 2016 - 2026 Red Hat, Inc.