STATUS asd_msg_on_msg_recv()

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;
}