core/mctp/cmd_interface_protocol_mctp.c (96 lines of code) (raw):
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
#include <stddef.h>
#include <string.h>
#include "cmd_interface_protocol_mctp.h"
#include "mctp_base_protocol.h"
#include "mctp_logging.h"
#include "common/unused.h"
/**
* Populate the MCTP message header on a message. The message payload pointer must already have
* been adjusted to provide room for the header.
*
* @param message_type The message type to assign in the header.
* @param message The message descriptor for the the message needing a header.
*/
static void cmd_interface_protocol_mctp_populate_header (uint32_t message_type,
struct cmd_interface_msg *message)
{
struct mctp_base_protocol_message_header *header =
(struct mctp_base_protocol_message_header*) message->payload;
header->msg_type = message_type;
header->integrity_check = 0;
}
int cmd_interface_protocol_mctp_parse_message (const struct cmd_interface_protocol *protocol,
struct cmd_interface_msg *message, uint32_t *message_type)
{
const struct mctp_base_protocol_message_header *header;
if ((protocol == NULL) || (message == NULL) || (message_type == NULL)) {
return MCTP_BASE_PROTOCOL_INVALID_ARGUMENT;
}
if (message->payload_length < sizeof (*header)) {
return MCTP_BASE_PROTOCOL_MSG_TOO_SHORT;
}
if (cmd_interface_msg_get_max_response (message) < MCTP_BASE_PROTOCOL_MIN_TRANSMISSION_UNIT) {
return MCTP_BASE_PROTOCOL_MAX_RESP_TOO_SMALL;
}
header = (const struct mctp_base_protocol_message_header*) message->payload;
if (header->msg_type != MCTP_BASE_PROTOCOL_MSG_TYPE_VENDOR_DEF) {
/* No supported standard message types allow message integrity checking and require that the
* integrity check bit be set to 0. */
if (header->integrity_check != 0) {
return MCTP_BASE_PROTOCOL_INVALID_MSG;
}
if (header->msg_type == MCTP_BASE_PROTOCOL_MSG_TYPE_CONTROL_MSG) {
/* MCTP control messages are not allowed to be larger than minimum transmission unit
* size. */
cmd_interface_msg_set_max_response (message, MCTP_BASE_PROTOCOL_MIN_TRANSMISSION_UNIT);
}
/* TODO: MCTP control message structures currently assume presence of the message header,
* so it needs to be left in place. Update MCTP control message handling to remove this
* header and eliminate this processing exception here. */
if (header->msg_type != MCTP_BASE_PROTOCOL_MSG_TYPE_CONTROL_MSG) {
cmd_interface_msg_remove_protocol_header (message, sizeof (*header));
}
}
else {
/* Do not make assumptions about the integrity check requirements or capabilities of vendor
* defined messages. Additionally, don't remove the MCTP message header. Defer all header
* processing to a handler for the vendor message. */
}
*message_type = header->msg_type;
return 0;
}
int cmd_interface_protocol_mctp_handle_request_result (
const struct cmd_interface_protocol *protocol, int result, uint32_t message_type,
struct cmd_interface_msg *message)
{
if ((protocol == NULL) || (message == NULL)) {
return MCTP_BASE_PROTOCOL_INVALID_ARGUMENT;
}
if (message_type != MCTP_BASE_PROTOCOL_MSG_TYPE_VENDOR_DEF) {
/* TODO: Just like in the pre-processing phase, this exception needs to be eliminated and
* the protocol header added back to MCTP control messages. */
if (message_type != MCTP_BASE_PROTOCOL_MSG_TYPE_CONTROL_MSG) {
cmd_interface_msg_add_protocol_header (message,
sizeof (struct mctp_base_protocol_message_header));
}
/* Only update the header in the case of a successful response. */
if (result == 0) {
cmd_interface_protocol_mctp_populate_header (message_type, message);
}
else if (message_type == MCTP_BASE_PROTOCOL_MSG_TYPE_CONTROL_MSG) {
debug_log_create_entry (DEBUG_LOG_SEVERITY_ERROR, DEBUG_LOG_COMPONENT_MCTP,
MCTP_LOGGING_MCTP_CONTROL_REQ_FAIL, result, message->channel_id);
}
}
else {
/* Vendor defined protocol processing is assumed to have already been done. Don't do
* anything additional here. */
}
/* Since no responses are being generated in this layer, just pass-through the result code. */
return result;
}
/**
* Initialize a protocol handler for MCTP messages.
*
* @param mctp The MCTP handler to initialize.
*
* @return 0 if the handler was initialized successfully or an error code.
*/
int cmd_interface_protocol_mctp_init (struct cmd_interface_protocol_mctp *mctp)
{
if (mctp == NULL) {
return MCTP_BASE_PROTOCOL_INVALID_ARGUMENT;
}
memset (mctp, 0, sizeof (struct cmd_interface_protocol_mctp));
mctp->base.parse_message = cmd_interface_protocol_mctp_parse_message;
mctp->base.handle_request_result = cmd_interface_protocol_mctp_handle_request_result;
return 0;
}
/**
* Release the resources used by an MCTP message protocol handler.
*
* @param mctp The MCTP handler to release.
*/
void cmd_interface_protocol_mctp_release (const struct cmd_interface_protocol_mctp *mctp)
{
UNUSED (mctp);
}
/**
* Add an MCTP message protocol header to the message buffer.
*
* @param mctp The MCTP message protocol handler.
* @param message_type The message type to assign in the MCTP header.
* @param message The message descriptor containing the payload that should be encapsulated with an
* MCTP message header.
*
* @return 0 if the MCTP message header was added successfully or an error code.
*/
int cmd_interface_protocol_mctp_add_header (const struct cmd_interface_protocol_mctp *mctp,
uint8_t message_type, struct cmd_interface_msg *message)
{
const size_t header_len = sizeof (struct mctp_base_protocol_message_header);
if ((mctp == NULL) || (message == NULL)) {
return MCTP_BASE_PROTOCOL_INVALID_ARGUMENT;
}
if (cmd_interface_msg_get_protocol_length (message) < header_len) {
return MCTP_BASE_PROTOCOL_NO_HEADER_SPACE;
}
cmd_interface_msg_add_protocol_header (message, header_len);
cmd_interface_protocol_mctp_populate_header (message_type, message);
return 0;
}