common/pldm/pldm_oem.c (104 lines of code) (raw):

#include "pldm.h" #include "ipmi.h" #include <logging/log.h> #include <string.h> #include <sys/printk.h> #include <sys/slist.h> #include <sys/util.h> #include <zephyr.h> LOG_MODULE_DECLARE(pldm, LOG_LEVEL_DBG); uint8_t check_iana(uint8_t *iana) { if (!iana) return PLDM_ERROR; for (uint8_t i = 0; i < IANA_LEN; i++) { if (iana[i] != ((FIANA >> (i * 8)) & 0xFF)) return PLDM_ERROR; } return PLDM_SUCCESS; } uint8_t set_iana(uint8_t *buf, uint8_t buf_len) { if (!buf || buf_len != IANA_LEN) return PLDM_ERROR; for (uint8_t i = 0; i < IANA_LEN; i++) buf[i] = (FIANA >> (i * 8)) & 0xFF; return PLDM_SUCCESS; } static uint8_t cmd_echo(void *mctp_inst, uint8_t *buf, uint16_t len, uint8_t *resp, uint16_t *resp_len, void *ext_params) { if (!mctp_inst || !buf || !resp || !resp_len) return PLDM_ERROR; struct _cmd_echo_req *req_p = (struct _cmd_echo_req *)buf; struct _cmd_echo_resp *resp_p = (struct _cmd_echo_resp *)resp; if (check_iana(req_p->iana) == PLDM_ERROR) { resp_p->completion_code = PLDM_BASE_CODES_ERROR_INVALID_DATA; return PLDM_SUCCESS; } set_iana(resp_p->iana, sizeof(resp_p->iana)); resp_p->completion_code = PLDM_BASE_CODES_SUCCESS; memcpy(&resp_p->first_data, &req_p->first_data, len); *resp_len = len + 1; return PLDM_SUCCESS; } static uint8_t ipmi_cmd(void *mctp_inst, uint8_t *buf, uint16_t len, uint8_t *resp, uint16_t *resp_len, void *ext_params) { if (!mctp_inst || !buf || !resp || !resp_len || !ext_params) return PLDM_ERROR; struct _ipmi_cmd_req *req_p = (struct _ipmi_cmd_req *)buf; if (len < (sizeof(*req_p) - 1)) { LOG_WRN("request len %d is invalid", len); struct _ipmi_cmd_resp *resp_p = (struct _ipmi_cmd_resp *)resp; resp_p->completion_code = PLDM_BASE_CODES_ERROR_INVALID_LENGTH; set_iana(resp_p->iana, sizeof(resp_p->iana)); *resp_len += sizeof(resp_p->iana); LOG_WRN("*resp_len = %d...", *resp_len); return PLDM_ERROR; } if (check_iana(req_p->iana) == PLDM_ERROR) { LOG_WRN("iana %08x is uncorret", (uint32_t)req_p->iana); struct _ipmi_cmd_resp *resp_p = (struct _ipmi_cmd_resp *)resp; resp_p->completion_code = PLDM_BASE_CODES_ERROR_INVALID_DATA; set_iana(resp_p->iana, sizeof(resp_p->iana)); return PLDM_SUCCESS; } LOG_DBG("ipmi over pldm, len = %d\n", len); LOG_DBG("netfn %x, cmd %x", req_p->netfn_lun, req_p->cmd); LOG_HEXDUMP_DBG(buf, len, "ipmi cmd data"); ipmi_msg_cfg msg = { 0 }; /* Setup ipmi data */ msg.buffer.netfn = req_p->netfn_lun >> 2; msg.buffer.cmd = req_p->cmd; msg.buffer.data_len = len - sizeof(*req_p) + 1; memcpy(msg.buffer.data, &req_p->first_data, msg.buffer.data_len); /* For ipmi/ipmb service to know the source is pldm */ msg.buffer.InF_source = PLDM_IFs; /* * Store the mctp_inst/pldm header/mctp_ext_params in the last of buffer data * those will use for the ipmi/ipmb service that is done the request. */ uint16_t pldm_hdr_ofs = sizeof(msg.buffer.data) - sizeof(pldm_hdr); uint16_t mctp_ext_params_ofs = pldm_hdr_ofs - sizeof(mctp_ext_params); uint16_t mctp_inst_ofs = mctp_ext_params_ofs - sizeof(mctp_inst); /* store the address of mctp_inst in the buffer */ memcpy(msg.buffer.data + mctp_inst_ofs, &mctp_inst, 4); /* store the ext_params in the buffer */ memcpy(msg.buffer.data + mctp_ext_params_ofs, ext_params, sizeof(mctp_ext_params)); /* store the pldm header in the buffer */ memcpy(msg.buffer.data + pldm_hdr_ofs, buf - sizeof(pldm_hdr), sizeof(pldm_hdr)); while (k_msgq_put(&ipmi_msgq, &msg, K_NO_WAIT) != 0) { k_msgq_purge(&ipmi_msgq); LOG_WRN("Retrying put ipmi msgq\n"); } return PLDM_LATER_RESP; } static pldm_cmd_handler pldm_oem_cmd_tbl[] = { { PLDM_OEM_CMD_ECHO, cmd_echo }, { PLDM_OEM_IPMI_BRIDGE, ipmi_cmd } }; uint8_t pldm_oem_handler_query(uint8_t code, void **ret_fn) { if (!ret_fn) return PLDM_ERROR; pldm_cmd_proc_fn fn = NULL; uint8_t i; for (i = 0; i < ARRAY_SIZE(pldm_oem_cmd_tbl); i++) { if (pldm_oem_cmd_tbl[i].cmd_code == code) { fn = pldm_oem_cmd_tbl[i].fn; break; } } *ret_fn = (void *)fn; return fn ? PLDM_SUCCESS : PLDM_ERROR; }