611 lines
18 KiB
C
611 lines
18 KiB
C
/** @file
|
|
Management Component Transport Protocol
|
|
|
|
;******************************************************************************
|
|
;* Copyright (c) 2012 - 2018, Insyde Software Corp. All Rights Reserved.
|
|
;*
|
|
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
|
|
;* transmit, broadcast, present, recite, release, license or otherwise exploit
|
|
;* any part of this publication in any form, by any means, without the prior
|
|
;* written permission of Insyde Software Corporation.
|
|
;*
|
|
;******************************************************************************
|
|
*/
|
|
|
|
#include "Mctp.h"
|
|
|
|
|
|
/**
|
|
Set MCTP transport binding protocol
|
|
|
|
@param [in] This Pointer to EFI_MCTP_PROTOCOL
|
|
@param MctpBus
|
|
|
|
@retval EFI_SUCCESS Successful
|
|
@return Other values Errror
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
MctpSetMctpBus (
|
|
IN EFI_MCTP_PROTOCOL *This,
|
|
EFI_MCTP_BUS_PROTOCOL *MctpBus
|
|
)
|
|
{
|
|
MCTP_CONTEXT *MctpContext;
|
|
|
|
if (MctpBus == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
MctpContext = MCTP_CONTEXT_FROM_THIS (This);
|
|
MctpContext->MctpBus = MctpBus;
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
|
|
VOID
|
|
EFIAPI
|
|
MctpSetResponseMode(
|
|
IN EFI_MCTP_PROTOCOL *This
|
|
)
|
|
{
|
|
MCTP_CONTEXT *Context;
|
|
Context = MCTP_CONTEXT_FROM_THIS (This);
|
|
Context->ResponseMode = TRUE;
|
|
}
|
|
|
|
VOID
|
|
EFIAPI
|
|
MctpSetRequestMode(
|
|
IN EFI_MCTP_PROTOCOL *This
|
|
)
|
|
{
|
|
MCTP_CONTEXT *Context;
|
|
Context = MCTP_CONTEXT_FROM_THIS (This);
|
|
Context->ResponseMode = FALSE;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
EFIAPI
|
|
MctpNewMessageReceived (
|
|
IN EFI_MCTP_PROTOCOL *This
|
|
)
|
|
{
|
|
MCTP_CONTEXT *MctpContext;
|
|
MctpContext = MCTP_CONTEXT_FROM_THIS (This);
|
|
|
|
return MctpContext->MctpBus->NewMessageReceived(MctpContext->MctpBus);
|
|
|
|
}
|
|
|
|
/**
|
|
Send MCTP Message to the management controller
|
|
|
|
@param [in] This Pointer to EFI_MCTP_PROTOCOL
|
|
@param [in] Message MCTP Message not including MCTP Header
|
|
@param [in] MessageSize Message Size not including MCTP Header
|
|
|
|
@retval EFI_SUCCESS Successful
|
|
@return Other values Errror
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
MctpSendMessage (
|
|
IN EFI_MCTP_PROTOCOL *This,
|
|
IN VOID *Message,
|
|
IN UINTN MessageSize
|
|
)
|
|
{
|
|
UINTN Index;
|
|
UINTN RemainingBytes;
|
|
MCTP_HEADER MctpHeader;
|
|
MCTP_CONTEXT *MctpContext;
|
|
UINTN PayloadSize;
|
|
UINT8 *Buffer;
|
|
EFI_STATUS Status;
|
|
|
|
MctpContext = MCTP_CONTEXT_FROM_THIS (This);
|
|
|
|
if (MctpContext->ResponseMode) {
|
|
MctpHeader = MctpContext->ResponseHeader;
|
|
MctpHeader.TagOwner = 0;
|
|
} else {
|
|
MctpHeader.Reserved = 0;
|
|
MctpHeader.HeaderVersion = MCTP_HEADER_VERSION;
|
|
MctpHeader.DestinationEid = MctpContext->McEndpointId;
|
|
MctpHeader.SourceEid = MctpContext->HostEndpointId;
|
|
MctpHeader.TagOwner = 1;
|
|
MctpContext->MessageTag = (MctpContext->MessageTag + 1) % 8;
|
|
MctpHeader.MessageTag = MctpContext->MessageTag;
|
|
}
|
|
|
|
MctpContext->PacketSequence = 0;
|
|
Index = 0;
|
|
if (Message == NULL) {
|
|
RemainingBytes = 0;
|
|
} else {
|
|
RemainingBytes = MessageSize;
|
|
}
|
|
|
|
do {
|
|
if (Index == 0) {
|
|
MctpHeader.StartOfMessage = 1;
|
|
} else {
|
|
MctpHeader.StartOfMessage = 0;
|
|
}
|
|
|
|
if (RemainingBytes > MCTP_BASELINE_TRANSMISSION_UNIT) {
|
|
PayloadSize = MCTP_BASELINE_TRANSMISSION_UNIT;
|
|
MctpHeader.EndOfMessage = 0;
|
|
} else {
|
|
PayloadSize = RemainingBytes ;
|
|
MctpHeader.EndOfMessage = 1;
|
|
}
|
|
|
|
MctpHeader.PacketSequence = MctpContext->PacketSequence;
|
|
MctpContext->PacketSequence = (MctpContext->PacketSequence + 1) % 4;
|
|
|
|
if (Message == NULL) {
|
|
Buffer = NULL;
|
|
} else {
|
|
Buffer = &(((UINT8 *)Message)[Index]);
|
|
}
|
|
Status = MctpContext->MctpBus->SendMctpPacket (MctpContext->MctpBus,
|
|
NULL,
|
|
MctpHeader,
|
|
Buffer,
|
|
PayloadSize
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
break;
|
|
}
|
|
|
|
if (RemainingBytes <= MCTP_BASELINE_TRANSMISSION_UNIT) {
|
|
break;
|
|
}
|
|
|
|
RemainingBytes -= MCTP_BASELINE_TRANSMISSION_UNIT;
|
|
Index += MCTP_BASELINE_TRANSMISSION_UNIT;
|
|
} while (1);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
/**
|
|
Receiving MCTP message from management controller
|
|
|
|
@param [in] This
|
|
@param [in, out] Message The received message
|
|
@param [in, out] MessageSize Number of bytes received
|
|
|
|
@retval EFI_SUCCESS successful
|
|
@return others Error
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
MctpReceiveMessage (
|
|
IN EFI_MCTP_PROTOCOL *This,
|
|
IN OUT VOID *Message,
|
|
IN OUT UINTN *MessageSize
|
|
)
|
|
|
|
{
|
|
MCTP_HEADER MctpHeader;
|
|
MCTP_CONTEXT *MctpContext;
|
|
UINTN PayloadSize;
|
|
UINTN TransferSize;
|
|
UINT8 PacketSequence = 0;
|
|
UINT8 MessageTag = 0;
|
|
EFI_STATUS Status;
|
|
UINT8 Buffer[MCTP_BASELINE_TRANSMISSION_UNIT];
|
|
|
|
MctpContext = MCTP_CONTEXT_FROM_THIS (This);
|
|
|
|
TransferSize = 0;
|
|
do {
|
|
PayloadSize = MCTP_BASELINE_TRANSMISSION_UNIT;
|
|
Status = MctpContext->MctpBus->ReceiveMctpPacket (MctpContext->MctpBus,
|
|
NULL,
|
|
&MctpHeader,
|
|
Buffer,
|
|
&PayloadSize
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
break;
|
|
}
|
|
|
|
if (TransferSize + PayloadSize > *MessageSize) {
|
|
return EFI_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
if (TransferSize == 0) {
|
|
//
|
|
// The First Packet
|
|
//
|
|
if (MctpHeader.StartOfMessage != 1) {
|
|
return EFI_PROTOCOL_ERROR;
|
|
}
|
|
PacketSequence = MctpHeader.PacketSequence;
|
|
MessageTag = MctpHeader.MessageTag;
|
|
if (MctpContext->ResponseMode) {
|
|
MctpContext->ResponseHeader = MctpHeader;
|
|
}
|
|
} else {
|
|
PacketSequence = (PacketSequence + 1) % 4;
|
|
if ( (MctpHeader.PacketSequence != PacketSequence) ||
|
|
(MctpHeader.MessageTag != MessageTag) ) {
|
|
return EFI_PROTOCOL_ERROR;
|
|
}
|
|
}
|
|
gBS->CopyMem ((UINT8 *)Message + TransferSize, Buffer, PayloadSize);
|
|
TransferSize += PayloadSize;
|
|
} while (MctpHeader.EndOfMessage == 0);
|
|
*MessageSize = TransferSize;
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/**
|
|
Set Endpoint ID of the management controller
|
|
|
|
@param [in] This pointer to EFI_MCTP_PROTOCOL
|
|
@param [in] Address MCTP physical address
|
|
@param [in] Operation 00: Set EID, 01: Force EID, 10: Reset EID, 11: Set Discovered Flag
|
|
@param [in] EndpointId Endpoint ID to be assigned
|
|
@param [out] Response
|
|
|
|
@retval EFI_SUCCESS successful
|
|
@return others Error
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
MctpSetEndpointId (
|
|
IN EFI_MCTP_PROTOCOL *This,
|
|
IN VOID *Address,
|
|
IN UINT8 Operation,
|
|
IN UINT8 EndpointId,
|
|
OUT MCTP_SET_EID_RESPONSE_DATA *Response
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
MCTP_HEADER MctpHeader = {
|
|
MCTP_HEADER_VERSION, // Header version
|
|
0, // reserved
|
|
0, // Destination Endpoint ID
|
|
0, // Source Endpoint ID
|
|
0, // Message Tag
|
|
1, // Tag Owner
|
|
0, // Packet Sequence
|
|
1, // Start of Message
|
|
1 // End of Message
|
|
};
|
|
|
|
MCTP_SET_EID_REQUEST_DATA MctpRequest = {
|
|
{
|
|
MCTP_MESSAGE_TYPE_MCTP_CONTROL, // Message Type
|
|
0, // Instance ID
|
|
0, // Reserved
|
|
0, // Datagram bit
|
|
1, // Request bit
|
|
MCTP_CONTROL_SET_ENDPOINT_ID // Command code
|
|
},
|
|
0, // Operation
|
|
0 // Endpoint ID
|
|
};
|
|
MCTP_CONTEXT *MctpContext;
|
|
EFI_MCTP_BUS_PROTOCOL *MctpBus;
|
|
UINTN TransferSize;
|
|
|
|
|
|
MctpContext = MCTP_CONTEXT_FROM_THIS (This);
|
|
MctpBus = MctpContext->MctpBus;
|
|
MctpContext->TransactionInProgress = TRUE;
|
|
|
|
MctpHeader.SourceEid = MctpContext->HostEndpointId;
|
|
MctpContext->MessageTag = (MctpContext->MessageTag + 1) % 8;
|
|
MctpHeader.MessageTag = MctpContext->MessageTag;
|
|
MctpContext->PacketSequence = (MctpContext->PacketSequence + 1) % 4;
|
|
MctpHeader.PacketSequence = MctpContext->PacketSequence;
|
|
|
|
MctpRequest.Operation = Operation;
|
|
MctpRequest.EndpointId = EndpointId;
|
|
|
|
This->SetRequestMode(This);
|
|
Status = MctpBus->SendMctpPacket ( MctpBus,
|
|
Address,
|
|
MctpHeader,
|
|
&MctpRequest,
|
|
sizeof (MctpRequest)
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
MctpContext->TransactionInProgress = FALSE;
|
|
return Status;
|
|
}
|
|
|
|
TransferSize = sizeof (MCTP_SET_EID_RESPONSE_DATA);
|
|
Status = MctpBus->ReceiveMctpPacket ( MctpBus,
|
|
Address,
|
|
&MctpHeader,
|
|
Response,
|
|
&TransferSize
|
|
);
|
|
|
|
if (Status == EFI_SUCCESS) {
|
|
MctpContext->McEndpointId = EndpointId;
|
|
}
|
|
MctpContext->TransactionInProgress = FALSE;
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Get Endpoint ID of the management controller
|
|
|
|
@param [in] This Pointer to EFI_MCTP_PROTOCOL
|
|
@param [in] Address MCTP physical address
|
|
@param [out] Response The resonse data
|
|
|
|
@retval EFI_SUCCESS successful
|
|
@return others Error
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
MctpGetEndpointId (
|
|
IN EFI_MCTP_PROTOCOL *This,
|
|
IN VOID *Address,
|
|
OUT MCTP_GET_EID_RESPONSE_DATA *Response
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
MCTP_HEADER MctpHeader = {
|
|
MCTP_HEADER_VERSION, // Header version
|
|
0, // reserved
|
|
0, // Destination Endpoint ID
|
|
0, // Source Endpoint ID
|
|
0, // Message Tag
|
|
1, // Tag Owner
|
|
0, // Packet Sequence
|
|
1, // Start of Message
|
|
1 // End of Message
|
|
};
|
|
|
|
|
|
MCTP_CONTROL_HEADER MctpRequest = {
|
|
MCTP_MESSAGE_TYPE_MCTP_CONTROL, // Message Type
|
|
0, // Instance ID
|
|
0, // Reserved
|
|
0, // Datagram bit
|
|
1, // Request bit
|
|
MCTP_CONTROL_GET_ENDPOINT_ID // Command code
|
|
};
|
|
MCTP_CONTEXT *MctpContext;
|
|
EFI_MCTP_BUS_PROTOCOL *MctpBus;
|
|
UINTN TransferSize;
|
|
|
|
|
|
MctpContext = MCTP_CONTEXT_FROM_THIS (This);
|
|
MctpContext->TransactionInProgress = TRUE;
|
|
MctpBus = MctpContext->MctpBus;
|
|
|
|
MctpHeader.SourceEid = MctpContext->HostEndpointId;
|
|
MctpContext->MessageTag = (MctpContext->MessageTag + 1) % 8;
|
|
MctpHeader.MessageTag = MctpContext->MessageTag;
|
|
MctpContext->PacketSequence = (MctpContext->PacketSequence + 1) % 4;
|
|
MctpHeader.PacketSequence = MctpContext->PacketSequence;
|
|
|
|
This->SetRequestMode(This);
|
|
Status = MctpBus->SendMctpPacket ( MctpBus,
|
|
Address,
|
|
MctpHeader,
|
|
&MctpRequest,
|
|
sizeof (MctpRequest)
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
MctpContext->TransactionInProgress = FALSE;
|
|
return Status;
|
|
}
|
|
|
|
TransferSize = sizeof (MCTP_GET_EID_RESPONSE_DATA);
|
|
Status = MctpBus->ReceiveMctpPacket ( MctpBus,
|
|
Address,
|
|
&MctpHeader,
|
|
Response,
|
|
&TransferSize
|
|
);
|
|
|
|
if (Status == EFI_SUCCESS) {
|
|
MctpContext->McEndpointId = Response->EndpointId;
|
|
}
|
|
MctpContext->TransactionInProgress = FALSE;
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Get supported MCTP versions of the management controller
|
|
|
|
@param [in] This Pointer to EFI_MCTP_PROTOCOL
|
|
@param [in] MessageType The specified MCTP Message Type
|
|
@param [out] Response MCTP response for MCTP Get Version Support
|
|
|
|
@retval EFI_SUCCESS successful
|
|
@return others Error
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
MctpGetVersionSupport (
|
|
IN EFI_MCTP_PROTOCOL *This,
|
|
IN UINT8 MessageType,
|
|
OUT MCTP_GET_VERSION_RESPONSE_DATA *Response
|
|
)
|
|
{
|
|
|
|
MCTP_GET_VERSION_REQUEST_DATA MctpRequest =
|
|
{
|
|
{
|
|
MCTP_MESSAGE_TYPE_MCTP_CONTROL, // Message Type
|
|
0, // Instance ID
|
|
0, // Reserved
|
|
0, // Datagram bit
|
|
1, // Request bit
|
|
MCTP_CONTROL_GET_MCTP_VERSION_SUPPORT // Command code
|
|
},
|
|
0
|
|
};
|
|
MCTP_CONTEXT *MctpContext;
|
|
UINTN TransferSize;
|
|
EFI_STATUS Status;
|
|
|
|
MctpRequest.MessageType = MessageType;
|
|
MctpContext = MCTP_CONTEXT_FROM_THIS (This);
|
|
MctpContext->TransactionInProgress = TRUE;
|
|
|
|
This->SetRequestMode(This);
|
|
Status = This->SendMessage(This, &MctpRequest, sizeof (MctpRequest));
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
MctpContext->TransactionInProgress = FALSE;
|
|
return Status;
|
|
}
|
|
|
|
TransferSize = sizeof(MCTP_GET_VERSION_RESPONSE_DATA);
|
|
Status = This->ReceiveMessage (This, Response, &TransferSize);
|
|
|
|
MctpContext->TransactionInProgress = FALSE;
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/**
|
|
Get supported MCTP Types of the management controller
|
|
|
|
@param [in] This Pointer to EFI_MCTP_PROTOCOL
|
|
@param [out] Response MCTP response for MCTP Get Message Type Support
|
|
|
|
@retval EFI_SUCCESS successful
|
|
@return others Error
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
MctpGetMessgeTypeSupport (
|
|
IN EFI_MCTP_PROTOCOL *This,
|
|
OUT MCTP_GET_MESSAGE_TYPE_SUPPORT_RESPONSE_DATA *Response
|
|
)
|
|
{
|
|
MCTP_CONTEXT *MctpContext;
|
|
MCTP_CONTROL_HEADER MctpRequest =
|
|
{
|
|
MCTP_MESSAGE_TYPE_MCTP_CONTROL, // Message Type
|
|
0, // Instance ID
|
|
0, // Reserved
|
|
0, // Datagram bit
|
|
1, // Request bit
|
|
MCTP_CONTROL_GET_MESSAGE_TYPE_SUPPORT // Command code
|
|
};
|
|
UINTN TransferSize;
|
|
EFI_STATUS Status;
|
|
|
|
This->SetRequestMode(This);
|
|
MctpContext = MCTP_CONTEXT_FROM_THIS (This);
|
|
MctpContext->TransactionInProgress = TRUE;
|
|
Status = This->SendMessage(This, &MctpRequest, sizeof (MctpRequest));
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
TransferSize = sizeof (MCTP_GET_MESSAGE_TYPE_SUPPORT_RESPONSE_DATA);
|
|
Status = This->ReceiveMessage (This, Response, &TransferSize);
|
|
|
|
MctpContext->TransactionInProgress = FALSE;
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
EFI_MCTP_PROTOCOL initialization
|
|
|
|
@param MctpContext
|
|
@param MctpBus
|
|
|
|
@retval EFI_SUCCESS MctpContext initialized successfully
|
|
|
|
@return Other value Unknown error
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
SetupMctpProtocol (
|
|
MCTP_CONTEXT *MctpContext,
|
|
EFI_MCTP_BUS_PROTOCOL *MctpBus
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
DASH_IO_CFG_PROTOCOL *DashIoCfg;
|
|
MCTP_GET_EID_RESPONSE_DATA GetResponse;
|
|
MCTP_SET_EID_RESPONSE_DATA SetResponse;
|
|
UINT8 OriginalMcEndpointId;
|
|
|
|
|
|
Status = gBS->LocateProtocol (&gDashIoCfgProtocolGuid, NULL, (VOID **)&DashIoCfg);
|
|
if(EFI_ERROR(Status)) {
|
|
return Status;
|
|
}
|
|
|
|
MctpContext->Signature = MCTP_SIGNATURE;
|
|
MctpContext->HostEndpointId = DashIoCfg->GetHostEndpointId();
|
|
MctpContext->McEndpointId = DashIoCfg->GetMcEndpointId();
|
|
MctpContext->Mctp.SetRequestMode = MctpSetRequestMode;
|
|
MctpContext->Mctp.SetResponseMode = MctpSetResponseMode;
|
|
MctpContext->Mctp.NewMessageReceived = MctpNewMessageReceived;
|
|
MctpContext->Mctp.ReceiveMessage = MctpReceiveMessage;
|
|
MctpContext->Mctp.SendMessage = MctpSendMessage;
|
|
MctpContext->Mctp.SetMctpBus = MctpSetMctpBus;
|
|
MctpContext->Mctp.SetEndpointId = MctpSetEndpointId;
|
|
MctpContext->Mctp.GetEndpointId = MctpGetEndpointId;
|
|
MctpContext->Mctp.GetVersionSupport = MctpGetVersionSupport;
|
|
MctpContext->Mctp.GetMessageTypeSupport = MctpGetMessgeTypeSupport;
|
|
MctpContext->MctpBus = MctpBus;
|
|
MctpContext->ResponseMode = FALSE;
|
|
|
|
OriginalMcEndpointId = MctpContext->McEndpointId;
|
|
Status = MctpGetEndpointId (&MctpContext->Mctp, NULL, &GetResponse);
|
|
if (Status == EFI_SUCCESS) {
|
|
if (OriginalMcEndpointId == GetResponse.EndpointId) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
} else {
|
|
DEBUG ((EFI_D_ERROR, "Get Mctp Endpoint Id failed %r\n", Status));
|
|
}
|
|
|
|
if (DashIoCfg->UartGetVendorId() == REALTEK_VENDOR_ID){
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
Status = MctpSetEndpointId (&MctpContext->Mctp, NULL, 1, OriginalMcEndpointId, &SetResponse);
|
|
if (Status != EFI_SUCCESS) {
|
|
DEBUG ((EFI_D_ERROR, "Set Mctp Endpoint Id failed %r\n", Status));
|
|
}
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
|
|
|