static void _api_kcs_dump_rs (ipmi_ctx_t ctx, const void *pkt, unsigned int pkt_len, uint8_t cmd, uint8_t net_fn, uint8_t group_extension, fiid_obj_t obj_cmd_rs) { fiid_field_t *tmpl_cmd = NULL; if ((tmpl_cmd = fiid_obj_template (obj_cmd_rs))) { _api_kcs_dump (ctx, pkt, pkt_len, cmd, net_fn, group_extension, DEBUG_UTIL_DIRECTION_RESPONSE, tmpl_cmd, tmpl_ipmb_msg_hdr_rs, ctx->tmpl_ipmb_cmd_rs); fiid_template_free (tmpl_cmd); } }
static void _api_ssif_dump_rq (ipmi_ctx_t ctx, const void *pkt, unsigned int pkt_len, uint8_t cmd, uint8_t net_fn, uint8_t group_extension, fiid_obj_t obj_cmd_rq) { fiid_field_t *tmpl_cmd = NULL; if ((tmpl_cmd = fiid_obj_template (obj_cmd_rq))) { _api_ssif_dump (ctx, pkt, pkt_len, cmd, net_fn, group_extension, DEBUG_UTIL_DIRECTION_REQUEST, tmpl_cmd); fiid_template_free (tmpl_cmd); } }
int api_ssif_cmd_ipmb (ipmi_ctx_t ctx, fiid_obj_t obj_cmd_rq, fiid_obj_t obj_cmd_rs) { fiid_obj_t obj_ipmb_msg_hdr_rs = NULL; fiid_obj_t obj_ipmb_msg_trlr = NULL; unsigned retransmission_count = 0; unsigned reread_count = 0; int ret, rv = -1; assert (ctx && ctx->magic == IPMI_CTX_MAGIC && ctx->type == IPMI_DEVICE_SSIF && fiid_obj_valid (obj_cmd_rq) && fiid_obj_packet_valid (obj_cmd_rq) == 1 && fiid_obj_valid (obj_cmd_rs)); if (!(obj_ipmb_msg_hdr_rs = fiid_obj_create (tmpl_ipmb_msg_hdr_rs))) { API_ERRNO_TO_API_ERRNUM (ctx, errno); goto cleanup; } if (!(obj_ipmb_msg_trlr = fiid_obj_create (tmpl_ipmb_msg_trlr))) { API_ERRNO_TO_API_ERRNUM (ctx, errno); goto cleanup; } /* for debugging */ ctx->tmpl_ipmb_cmd_rq = fiid_obj_template (obj_cmd_rq); ctx->tmpl_ipmb_cmd_rs = fiid_obj_template (obj_cmd_rs); if (_api_ssif_ipmb_send (ctx, obj_cmd_rq) < 0) goto cleanup; while (1) { if (_api_ssif_ipmb_recv (ctx, obj_ipmb_msg_hdr_rs, obj_ipmb_msg_trlr, obj_cmd_rs) < 0) { if (ctx->errnum == IPMI_ERR_MESSAGE_TIMEOUT) { reread_count++; if (reread_count > IPMI_SSIF_IPMB_REREAD_COUNT) { API_SET_ERRNUM (ctx, IPMI_ERR_MESSAGE_TIMEOUT); goto cleanup; } /* Wait a little bit to avoid spinning */ usleep (IPMI_SSIF_IPMB_REREAD_WAIT); continue; } goto cleanup; } if ((ret = ipmi_ipmb_check_rq_seq (obj_ipmb_msg_hdr_rs, ctx->io.inband.rq_seq)) < 0) { API_ERRNO_TO_API_ERRNUM (ctx, errno); goto cleanup; } /* if it's the wrong rq_seq, get another packet */ if (!ret) continue; if ((ret = ipmi_ipmb_check_checksum (IPMI_SLAVE_ADDRESS_BMC, obj_ipmb_msg_hdr_rs, obj_cmd_rs, obj_ipmb_msg_trlr)) < 0) { API_ERRNO_TO_API_ERRNUM (ctx, errno); goto cleanup; } /* if the checksum is wrong, assume an error and resend */ if (!ret) { retransmission_count++; if (retransmission_count > IPMI_SSIF_IPMB_RETRANSMISSION_COUNT) { API_SET_ERRNUM (ctx, IPMI_ERR_MESSAGE_TIMEOUT); goto cleanup; } ctx->io.inband.rq_seq = ((ctx->io.inband.rq_seq) + 1) % (IPMI_IPMB_REQUESTER_SEQUENCE_NUMBER_MAX + 1); if (_api_ssif_ipmb_send (ctx, obj_cmd_rq) < 0) goto cleanup; continue; } break; } rv = 0; cleanup: ctx->io.inband.rq_seq = ((ctx->io.inband.rq_seq) + 1) % (IPMI_IPMB_REQUESTER_SEQUENCE_NUMBER_MAX + 1); fiid_obj_destroy (obj_ipmb_msg_hdr_rs); fiid_obj_destroy (obj_ipmb_msg_trlr); fiid_template_free (ctx->tmpl_ipmb_cmd_rq); ctx->tmpl_ipmb_cmd_rq = NULL; fiid_template_free (ctx->tmpl_ipmb_cmd_rs); ctx->tmpl_ipmb_cmd_rs = NULL; return (rv); }
static int _ssif_cmd_read (ipmi_ctx_t ctx, uint8_t cmd, uint8_t group_extension, fiid_obj_t obj_cmd_rs) { uint8_t *pkt = NULL; unsigned int pkt_len; int hdr_len, cmd_len, read_len; fiid_field_t *tmpl = NULL; int ret, rv = -1; unsigned int intf_flags = IPMI_INTERFACE_FLAGS_DEFAULT; assert (ctx && ctx->magic == IPMI_CTX_MAGIC && fiid_obj_valid (obj_cmd_rs)); if (ctx->flags & IPMI_FLAGS_NO_LEGAL_CHECK) intf_flags |= IPMI_INTERFACE_FLAGS_NO_LEGAL_CHECK; if ((hdr_len = fiid_template_len_bytes (tmpl_hdr_kcs)) < 0) { API_ERRNO_TO_API_ERRNUM (ctx, errno); goto cleanup; } if (!(tmpl = fiid_obj_template (obj_cmd_rs))) { API_FIID_OBJECT_ERROR_TO_API_ERRNUM (ctx, obj_cmd_rs); goto cleanup; } if ((cmd_len = fiid_template_len_bytes (tmpl)) < 0) { API_ERRNO_TO_API_ERRNUM (ctx, errno); goto cleanup; } pkt_len = hdr_len + cmd_len; if (!(pkt = malloc (pkt_len))) { API_ERRNO_TO_API_ERRNUM (ctx, errno); goto cleanup; } memset (pkt, '\0', pkt_len); if ((read_len = ipmi_ssif_read (ctx->io.inband.ssif_ctx, pkt, pkt_len)) < 0) { API_SSIF_ERRNUM_TO_API_ERRNUM (ctx, ipmi_ssif_ctx_errnum (ctx->io.inband.ssif_ctx)); goto cleanup; } if (!read_len) { API_SET_ERRNUM (ctx, IPMI_ERR_SYSTEM_ERROR); goto cleanup; } if (ctx->flags & IPMI_FLAGS_DEBUG_DUMP && read_len) _api_ssif_dump_rs (ctx, pkt, read_len, cmd, ctx->target.net_fn, group_extension, obj_cmd_rs); if ((ret = unassemble_ipmi_kcs_pkt (pkt, read_len, ctx->io.inband.rs.obj_hdr, obj_cmd_rs, intf_flags)) < 0) { API_ERRNO_TO_API_ERRNUM (ctx, errno); goto cleanup; } /* IPMI didn't return enough data back to you */ if (!ret) { API_SET_ERRNUM (ctx, IPMI_ERR_IPMI_ERROR); goto cleanup; } rv = 0; cleanup: free (pkt); fiid_template_free (tmpl); return (rv); }
static int _ipmi_kcs_cmd_read (ipmi_kcs_ctx_t ctx, fiid_obj_t obj_cmd_rs) { uint8_t *pkt = NULL; unsigned int pkt_len; int hdr_len, cmd_len, read_len, ret, rv = -1; fiid_obj_t obj_hdr = NULL; fiid_field_t *tmpl = NULL; assert (ctx); assert (ctx->magic == IPMI_KCS_CTX_MAGIC); assert (fiid_obj_valid (obj_cmd_rs)); if ((hdr_len = fiid_template_len_bytes (tmpl_hdr_kcs)) < 0) { KCS_ERRNO_TO_KCS_ERRNUM (ctx, errno); goto cleanup; } if (!(tmpl = fiid_obj_template (obj_cmd_rs))) { KCS_FIID_OBJECT_ERROR_TO_KCS_ERRNUM (ctx, obj_cmd_rs); goto cleanup; } if ((cmd_len = fiid_template_len_bytes (tmpl)) < 0) { KCS_ERRNO_TO_KCS_ERRNUM (ctx, errno); goto cleanup; } if (!(obj_hdr = fiid_obj_create (tmpl_hdr_kcs))) { KCS_ERRNO_TO_KCS_ERRNUM (ctx, errno); goto cleanup; } pkt_len = hdr_len + cmd_len; if (!(pkt = (uint8_t *)malloc (pkt_len))) { KCS_SET_ERRNUM (ctx, IPMI_KCS_ERR_OUT_OF_MEMORY); goto cleanup; } if ((read_len = ipmi_kcs_read (ctx, pkt, pkt_len)) < 0) goto cleanup; if (!read_len) { KCS_SET_ERRNUM (ctx, IPMI_KCS_ERR_SYSTEM_ERROR); goto cleanup; } if ((ret = unassemble_ipmi_kcs_pkt (pkt, read_len, obj_hdr, obj_cmd_rs, IPMI_INTERFACE_FLAGS_DEFAULT)) < 0) { KCS_SET_ERRNUM (ctx, IPMI_KCS_ERR_INTERNAL_ERROR); goto cleanup; } /* IPMI didn't return enough data back to you */ if (!ret) { KCS_SET_ERRNUM (ctx, IPMI_KCS_ERR_IPMI_ERROR); goto cleanup; } rv = 0; cleanup: fiid_template_free (tmpl); fiid_obj_destroy (obj_hdr); free (pkt); return (rv); }