in common/recipes-core/asd_1.4.7/files/daemon/asd_msg.c [326:688]
STATUS asd_msg_on_msg_recv(ASD_MSG* state)
{
STATUS result = ST_OK;
if (!state)
{
result = ST_ERR;
return result;
}
struct asd_message* msg = &state->in_msg.msg;
struct asd_message* msg_out = &state->out_msg;
int data_size = get_message_size(msg);
if (msg->header.enc_bit)
{
result = ST_ERR;
ASD_log(ASD_LogLevel_Error, ASD_LogStream_SDK, ASD_LogOption_None,
"ASD message encryption not supported.");
send_error_message(state, msg, ASD_MSG_CRYPY_NOT_SUPPORTED);
return result;
}
if (msg->header.type == AGENT_CONTROL_TYPE)
{
if (memcpy_s(&state->out_msg.header, sizeof(struct message_header),
&msg->header, sizeof(struct message_header)))
{
ASD_log(ASD_LogLevel_Error, ASD_LogStream_JTAG, ASD_LogOption_None,
"memcpy_s: msg header to out msg header copy buffer "
"failed.");
result = ST_ERR;
}
// The plugin stores the command in the cmd_stat parameter.
// For the response, the plugin expects the same value in the
// first byte of the buffer.
state->out_msg.buffer[0] = (unsigned char)msg->header.cmd_stat;
state->out_msg.header.size_lsb = 1;
state->out_msg.header.size_msb = 0;
state->out_msg.header.cmd_stat = ASD_SUCCESS;
switch (msg->header.cmd_stat)
{
case NUM_IN_FLIGHT_MESSAGES_SUPPORTED_CMD:
state->out_msg.buffer[1] = NUM_IN_FLIGHT_BUFFERS_TO_USE;
state->out_msg.header.size_lsb += 1;
break;
case MAX_DATA_SIZE_CMD:
state->out_msg.buffer[1] = (MAX_DATA_SIZE)&0xFF;
state->out_msg.buffer[2] = (MAX_DATA_SIZE >> 8) & 0xFF;
state->out_msg.header.size_lsb = 3;
state->out_msg.header.size_msb = 0;
state->out_msg.header.cmd_stat = ASD_SUCCESS;
break;
case SUPPORTED_JTAG_CHAINS_CMD:
state->out_msg.buffer[1] = SUPPORTED_JTAG_CHAINS;
state->out_msg.header.size_lsb = 2;
state->out_msg.header.size_msb = 0;
break;
case SUPPORTED_I2C_BUSES_CMD:
{
unsigned char supported_buses = 0;
if (state->buscfg->enable_i2c || state->buscfg->enable_i3c)
{
for (int i = 0; i < MAX_IxC_BUSES; i++)
{
switch (state->buscfg->bus_config_type[i])
{
case BUS_CONFIG_I2C:
case BUS_CONFIG_I3C:
state->out_msg.buffer[2 + supported_buses++] =
state->buscfg->bus_config_map[i];
break;
case BUS_CONFIG_NOT_ALLOWED:
default:
break;
}
}
state->out_msg.buffer[1] = supported_buses;
state->out_msg.header.size_lsb = supported_buses + 2;
state->out_msg.header.size_msb = 0;
}
else
{
state->out_msg.buffer[1] = 0;
state->out_msg.header.size_lsb = 2;
state->out_msg.header.size_msb = 0;
}
break;
}
case SUPPORTED_REMOTE_PROBES_CMD:
if (!state->vprobe_handler->initialized)
{
if (vProbe_initialize(state->vprobe_handler) != ST_OK)
{
result = ST_ERR;
ASD_log(ASD_LogLevel_Error, ASD_LogStream_SDK,
ASD_LogOption_None,
"Failed to initialize the vprobe handler");
send_error_message(state, msg,
ASD_FAILURE_INIT_VPROBE_HANDLER);
return result;
}
}
state->out_msg.buffer[1] = state->vprobe_handler->remoteProbes;
state->out_msg.header.size_lsb = 2;
state->out_msg.header.size_msb = 0;
break;
case REMOTE_PROBES_CONFIG_CMD:
if (state->vprobe_handler->remoteConfigs > 0)
{
uint16_t config_size = 0;
if (strcpy_s(&state->out_msg.buffer[1],
sizeof(state->out_msg.buffer) - 1,
state->vprobe_handler->probesConfig))
{
ASD_log(ASD_LogLevel_Error, ASD_LogStream_JTAG,
ASD_LogOption_None,
"strcpy_s: remote probe config to out msg "
"buffer copy failed.");
result = ST_ERR;
}
config_size = (uint16_t)(
strnlen(state->vprobe_handler->probesConfig,
sizeof(state->vprobe_handler->probesConfig)) +
1);
state->out_msg.header.size_lsb =
(uint8_t)(config_size & 0xFF);
state->out_msg.header.size_msb =
(uint8_t)(config_size >> 8);
}
break;
case OBTAIN_DOWNSTREAM_VERSION_CMD:
// The +/-1 references below are to account for the
// write of cmd_stat to buffer position 0 above
if (memcpy_s(&state->out_msg.buffer[1], sizeof(asd_version),
asd_version, sizeof(asd_version)))
{
ASD_log(ASD_LogLevel_Error, ASD_LogStream_JTAG,
ASD_LogOption_None,
"memcpy_s: asd_version to out msg buffer copy "
"failed.");
result = ST_ERR;
}
state->out_msg.header.size_lsb += sizeof(asd_version);
if (memcpy_s(&state->out_msg.buffer[sizeof(asd_version)], 1,
"_", 1))
{
ASD_log(ASD_LogLevel_Error, ASD_LogStream_JTAG,
ASD_LogOption_None,
"memcpy_s: asd_version to out msg buffer copy "
"failed.");
result = ST_ERR;
}
if (memcpy_s(&state->out_msg.buffer[sizeof(asd_version) + 1],
state->bmc_version_size, state->bmc_version,
state->bmc_version_size))
{
ASD_log(ASD_LogLevel_Error, ASD_LogStream_JTAG,
ASD_LogOption_None,
"memcpy_s: asd_version to out msg buffer copy "
"failed.");
result = ST_ERR;
}
state->out_msg.header.size_lsb += state->bmc_version_size;
if (memcpy_s(
&state->out_msg.buffer[sizeof(asd_version) +
state->bmc_version_size + 1],
1, "\0", 1))
{
ASD_log(ASD_LogLevel_Error, ASD_LogStream_JTAG,
ASD_LogOption_None,
"memcpy_s: asd_version to out msg buffer copy "
"failed.");
result = ST_ERR;
}
break;
case AGENT_CONFIGURATION_CMD:
{
// An agent configuration command was sent.
// The next byte is the Agent Config type.
struct packet_data packet;
packet.next_data = (unsigned char*)&msg->buffer;
packet.used = 0;
packet.total = (unsigned int)data_size;
u_int8_t* config_type = get_packet_data(&packet, 1);
if (!config_type)
break;
if (*config_type == AGENT_CONFIG_TYPE_LOGGING)
{
// We will store the logging stream only
// for the sake of sending it back to
// the IPC plugin. Technically the
// protocol is defined in such a way as
// where the BMC could emit log messages
// for several streams, but since we
// only have it implemented with one
// stream, we wont do much with this
// stored stream.
u_int8_t* logging = get_packet_data(&packet, 1);
if (!logging)
break;
state->asd_cfg->remote_logging.value = *logging;
#ifdef ENABLE_DEBUG_LOGGING
ASD_log(
ASD_LogLevel_Debug, ASD_LogStream_SDK,
ASD_LogOption_No_Remote,
"Remote logging command received. Stream: %d Level: %d",
state->asd_cfg->remote_logging.logging_stream,
state->asd_cfg->remote_logging.logging_level);
#endif
}
else if (*config_type == AGENT_CONFIG_TYPE_GPIO)
{
u_int8_t* gpio_config = get_packet_data(&packet, 1);
if (!gpio_config)
break;
#ifdef ENABLE_DEBUG_LOGGING
ASD_log(
ASD_LogLevel_Debug, ASD_LogStream_SDK,
ASD_LogOption_None,
"Remote config command received. GPIO config: 0x%02x",
*gpio_config);
#endif
}
else if (*config_type == AGENT_CONFIG_TYPE_JTAG_SETTINGS)
{
u_int8_t* mode = get_packet_data(&packet, 1);
if (!mode)
break;
if ((*mode & JTAG_DRIVER_MODE_MASK) ==
JTAG_DRIVER_MODE_HARDWARE)
state->asd_cfg->jtag.mode = JTAG_DRIVER_MODE_HARDWARE;
else
state->asd_cfg->jtag.mode = JTAG_DRIVER_MODE_SOFTWARE;
if ((*mode & JTAG_CHAIN_SELECT_MODE_MASK) ==
JTAG_CHAIN_SELECT_MODE_MULTI)
state->jtag_chain_mode = JTAG_CHAIN_SELECT_MODE_MULTI;
else
state->jtag_chain_mode = JTAG_CHAIN_SELECT_MODE_SINGLE;
#ifdef ENABLE_DEBUG_LOGGING
ASD_log(
ASD_LogLevel_Debug, ASD_LogStream_SDK,
ASD_LogOption_No_Remote,
"Remote config command received. JTAG Driver Mode: %s"
"and Jtag Chain Select Mode: %s",
state->asd_cfg->jtag.mode == JTAG_DRIVER_MODE_SOFTWARE
? "Software"
: "Hardware",
state->jtag_chain_mode == JTAG_CHAIN_SELECT_MODE_SINGLE
? "Single"
: "Multi");
#endif
}
break;
}
case LOOPBACK_CMD:
ASD_log(ASD_LogLevel_Trace, ASD_LogStream_Network,
ASD_LogOption_None, "LOOPBACK MODE.");
uint16_t delay = (msg->buffer[0]) + (msg->buffer[0] << 8);
uint16_t size =
(msg->header.size_lsb) + (msg->header.size_msb << 8);
if (size > MAX_DATA_SIZE)
{
size = MAX_DATA_SIZE;
}
msg_out->header = msg->header;
for (uint16_t index = 0; index < size; index++)
{
msg_out->buffer[index] = msg->buffer[index];
}
// We convert from microseconds to milliseconds.
usleep((__useconds_t)(delay * 1000));
break;
default:
{
#ifdef ENABLE_DEBUG_LOGGING
ASD_log(ASD_LogLevel_Debug, ASD_LogStream_SDK,
ASD_LogOption_None,
"Unsupported Agent Control command received %d",
msg->header.cmd_stat);
#endif
}
}
if (send_response(state, &state->out_msg) != ST_OK)
{
ASD_log(ASD_LogLevel_Error, ASD_LogStream_SDK,
ASD_LogOption_No_Remote,
"Failed to send agent control message response.");
}
}
else
{
if (!state->handlers_initialized)
{
if (JTAG_initialize(state->jtag_handler,
state->asd_cfg->jtag.mode ==
JTAG_DRIVER_MODE_SOFTWARE) != ST_OK)
{
result = ST_ERR;
ASD_log(ASD_LogLevel_Error, ASD_LogStream_SDK,
ASD_LogOption_None,
"Failed to initialize the jtag handler");
send_error_message(state, msg, ASD_FAILURE_INIT_JTAG_HANDLER);
return result;
}
if (state->buscfg->enable_i2c)
{
if (i2c_initialize(state->i2c_handler) != ST_OK)
{
result = ST_ERR;
ASD_log(ASD_LogLevel_Error, ASD_LogStream_SDK,
ASD_LogOption_None,
"Failed to initialize the i2c handler");
send_error_message(state, msg,
ASD_FAILURE_INIT_I2C_HANDLER);
return result;
}
}
if (state->buscfg->enable_i3c)
{
if (i3c_initialize(state->i3c_handler) != ST_OK)
{
result = ST_ERR;
ASD_log(ASD_LogLevel_Error, ASD_LogStream_SDK,
ASD_LogOption_None,
"Failed to initialize the i3c handler");
send_error_message(state, msg,
ASD_FAILURE_INIT_I2C_HANDLER);
return result;
}
}
if (target_initialize(state->target_handler,
state->xdp_fail_enable) == ST_OK)
{
state->handlers_initialized = true;
if (state->target_handler->xdp_present == true)
{
send_error_message(state, msg, ASD_FAILURE_XDP_PRESENT);
}
}
else
{
result = ST_ERR;
ASD_log(ASD_LogLevel_Error, ASD_LogStream_SDK,
ASD_LogOption_None,
"Failed to initialize the target handler");
if (JTAG_deinitialize(state->jtag_handler) != ST_OK)
{
ASD_log(ASD_LogLevel_Error, ASD_LogStream_SDK,
ASD_LogOption_None,
"Failed to de-initialize the JTAG handler");
}
send_error_message(state, msg, ASD_FAILURE_XDP_PRESENT);
return result;
}
}
process_message(state);
}
return result;
}