int
api_inteldcmi_cmd_ipmb (ipmi_ctx_t ctx,
                        fiid_obj_t obj_cmd_rq,
                        fiid_obj_t obj_cmd_rs)
{
  assert (ctx
          && ctx->magic == IPMI_CTX_MAGIC
          && ctx->type == IPMI_DEVICE_INTELDCMI
          && fiid_obj_valid (obj_cmd_rq)
          && fiid_obj_packet_valid (obj_cmd_rq) == 1
          && fiid_obj_valid (obj_cmd_rs));

  if (ipmi_inteldcmi_cmd_ipmb (ctx->io.inband.inteldcmi_ctx,
                               ctx->target.channel_number,
                               ctx->target.rs_addr,
                               ctx->target.lun,
                               ctx->target.net_fn,
                               obj_cmd_rq,
                               obj_cmd_rs) < 0)
    {
      API_INTELDCMI_ERRNUM_TO_API_ERRNUM (ctx, ipmi_inteldcmi_ctx_errnum (ctx->io.inband.inteldcmi_ctx));
      return (-1);
    }

  return (0);
}
Beispiel #2
0
static int
_api_ipmi_cmd_post (ipmi_ctx_t ctx, fiid_obj_t obj_cmd_rs)
{
  int ret;

  assert (ctx
	  && ctx->magic == IPMI_CTX_MAGIC
	  && fiid_obj_valid (obj_cmd_rs));

  if (ctx->flags & IPMI_FLAGS_NO_LEGAL_CHECK)
    {
      uint64_t val;

      /* Do not check completion code if data not available
       * (i.e. FIID_ERR_DATA_NOT_AVAILABLE completion code).
       *
       * Fallthrough to normal error if it's an alternate fiid error
       * (invalid packet, field not found, etc.)
       */
      
      if (FIID_OBJ_GET (obj_cmd_rs, "comp_code", &val) < 0)
	{
	  if (fiid_obj_errnum (obj_cmd_rs) == FIID_ERR_DATA_NOT_AVAILABLE)
	    goto skip_comp_code_check;
	}
    }

  if ((ret = ipmi_check_completion_code_success (obj_cmd_rs)) < 0)
    {
      API_ERRNO_TO_API_ERRNUM (ctx, errno);
      return (-1);
    }
  
  if (!ret)
    {
      API_BAD_RESPONSE_TO_API_ERRNUM (ctx, obj_cmd_rs);
      return (-1);
    }

 skip_comp_code_check:

  if (!(ctx->flags & IPMI_FLAGS_NO_VALID_CHECK)
      && !(ctx->flags & IPMI_FLAGS_NO_LEGAL_CHECK))
    {
      if ((ret = fiid_obj_packet_valid (obj_cmd_rs)) < 0)
        {
          API_FIID_OBJECT_ERROR_TO_API_ERRNUM (ctx, obj_cmd_rs);
          return (-1);
        }

      if (!ret)
        {
          API_SET_ERRNUM (ctx, IPMI_ERR_IPMI_ERROR);
          return (-1);
        }
    }

  return (0);
}
int
ipmi_openipmi_cmd_ipmb (ipmi_openipmi_ctx_t ctx,
                        uint8_t channel_number,
                        uint8_t rs_addr,
                        uint8_t lun,
                        uint8_t net_fn,
                        fiid_obj_t obj_cmd_rq,
                        fiid_obj_t obj_cmd_rs)
{
  if (!ctx || ctx->magic != IPMI_OPENIPMI_CTX_MAGIC)
    {
      ERR_TRACE (ipmi_openipmi_ctx_errormsg (ctx), ipmi_openipmi_ctx_errnum (ctx));
      return (-1);
    }

  if (!IPMI_CHANNEL_NUMBER_VALID (channel_number)
      || !IPMI_BMC_LUN_VALID (lun)
      || !IPMI_NET_FN_RQ_VALID (net_fn)
      || !fiid_obj_valid (obj_cmd_rq)
      || !fiid_obj_valid (obj_cmd_rs)
      || fiid_obj_packet_valid (obj_cmd_rq) <= 0)
    {
      OPENIPMI_SET_ERRNUM (ctx, IPMI_OPENIPMI_ERR_PARAMETERS);
      return (-1);
    }

  if (!ctx->io_init)
    {
      OPENIPMI_SET_ERRNUM (ctx, IPMI_OPENIPMI_ERR_IO_NOT_INITIALIZED);
      return (-1);
    }

  if (_openipmi_write (ctx,
                       channel_number,
                       rs_addr,
                       lun,
                       net_fn,
                       obj_cmd_rq,
                       1) < 0)
    return (-1);

  if (_openipmi_read (ctx,
                      obj_cmd_rs) < 0)
    return (-1);

  return (0);
}
int
api_ssif_cmd (ipmi_ctx_t ctx,
	      fiid_obj_t obj_cmd_rq,
	      fiid_obj_t obj_cmd_rs)
{
  uint8_t cmd = 0;             /* used for debugging */
  uint8_t group_extension = 0; /* used for debugging */
  uint64_t val;

  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 (ctx->flags & IPMI_FLAGS_DEBUG_DUMP)
    {
      /* ignore error, continue on */
      if (FIID_OBJ_GET (obj_cmd_rq, "cmd", &val) < 0)
        API_FIID_OBJECT_ERROR_TO_API_ERRNUM (ctx, obj_cmd_rq);
      else
        cmd = val;

      if (IPMI_NET_FN_GROUP_EXTENSION (ctx->target.net_fn))
        {
          /* ignore error, continue on */
          if (FIID_OBJ_GET (obj_cmd_rq,
                            "group_extension_identification",
                            &val) < 0)
            API_FIID_OBJECT_ERROR_TO_API_ERRNUM (ctx, obj_cmd_rq);
          else
            group_extension = val;
        }
    }

  if (_ssif_cmd_write (ctx, cmd, group_extension, obj_cmd_rq) < 0)
    return (-1);

  if (_ssif_cmd_read (ctx, cmd, group_extension, obj_cmd_rs) < 0)
    return (-1);

  return (0);
}
int
ipmiconsole_check_packet (ipmiconsole_ctx_t c, ipmiconsole_packet_type_t p)
{
    fiid_obj_t obj_cmd;
    int rv;

    assert (c);
    assert (c->magic == IPMICONSOLE_CTX_MAGIC);
    assert (IPMICONSOLE_PACKET_TYPE_RESPONSE (p));

    obj_cmd = ipmiconsole_packet_object (c, p);
    if ((rv = fiid_obj_packet_valid (obj_cmd)) < 0)
    {
        IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_packet_valid: %s",
                                   fiid_obj_errormsg (obj_cmd)));
        return (-1);
    }

    if (!rv)
        IPMICONSOLE_CTX_DEBUG (c, ("invalid packet received; p = %d", p));

    return (rv);
}
int
ipmi_kcs_cmd (ipmi_kcs_ctx_t ctx,
              uint8_t lun,
              uint8_t net_fn,
              fiid_obj_t obj_cmd_rq,
              fiid_obj_t obj_cmd_rs)
{
  if (!ctx || ctx->magic != IPMI_KCS_CTX_MAGIC)
    {
      ERR_TRACE (ipmi_kcs_ctx_errormsg (ctx), ipmi_kcs_ctx_errnum (ctx));
      return (-1);
    }

  if (!IPMI_BMC_LUN_VALID (lun)
      || !IPMI_NET_FN_RQ_VALID (net_fn)
      || !fiid_obj_valid (obj_cmd_rq)
      || !fiid_obj_valid (obj_cmd_rs)
      || fiid_obj_packet_valid (obj_cmd_rq) <= 0)
    {
      KCS_SET_ERRNUM (ctx, IPMI_KCS_ERR_PARAMETERS);
      return (-1);
    }

  if (!ctx->io_init)
    {
      KCS_SET_ERRNUM (ctx, IPMI_KCS_ERR_IO_NOT_INITIALIZED);
      return (-1);
    }

  if (_ipmi_kcs_cmd_write (ctx, lun, net_fn, obj_cmd_rq) < 0)
    return (-1);

  if (_ipmi_kcs_cmd_read (ctx, obj_cmd_rs) < 0)
    return (-1);

  return (0);
}
int
api_openipmi_cmd (ipmi_ctx_t ctx,
                  fiid_obj_t obj_cmd_rq,
                  fiid_obj_t obj_cmd_rs)
{
  assert (ctx
          && ctx->magic == IPMI_CTX_MAGIC
          && ctx->type == IPMI_DEVICE_OPENIPMI
          && fiid_obj_valid (obj_cmd_rq)
          && fiid_obj_packet_valid (obj_cmd_rq) == 1
          && fiid_obj_valid (obj_cmd_rs));
  
  if (ipmi_openipmi_cmd (ctx->io.inband.openipmi_ctx,
                         ctx->target.lun,
                         ctx->target.net_fn,
                         obj_cmd_rq,
                         obj_cmd_rs) < 0)
    {
      API_OPENIPMI_ERRNUM_TO_API_ERRNUM (ctx, ipmi_openipmi_ctx_errnum (ctx->io.inband.openipmi_ctx));
      return (-1);
    }

  return (0);
}
int
ipmi_sunbmc_cmd (ipmi_sunbmc_ctx_t ctx,
                 uint8_t lun,
                 uint8_t net_fn,
                 fiid_obj_t obj_cmd_rq,
                 fiid_obj_t obj_cmd_rs)
{
  if (!ctx || ctx->magic != IPMI_SUNBMC_CTX_MAGIC)
    {
      ERR_TRACE (ipmi_sunbmc_ctx_errormsg (ctx), ipmi_sunbmc_ctx_errnum (ctx));
      return (-1);
    }

  if (!IPMI_BMC_LUN_VALID (lun)
      || !IPMI_NET_FN_RQ_VALID (net_fn)
      || !fiid_obj_valid (obj_cmd_rq)
      || !fiid_obj_valid (obj_cmd_rs)
      || fiid_obj_packet_valid (obj_cmd_rq) <= 0)
    {
      SUNBMC_SET_ERRNUM (ctx, IPMI_SUNBMC_ERR_PARAMETERS);
      return (-1);
    }

  if (!ctx->io_init)
    {
      SUNBMC_SET_ERRNUM (ctx, IPMI_SUNBMC_ERR_IO_NOT_INITIALIZED);
      return (-1);
    }

  if (ctx->putmsg_intf)
    {
      if (_sunbmc_write (ctx,
                         lun,
                         net_fn,
                         obj_cmd_rq) < 0)
        return (-1);

      if (_sunbmc_read (ctx,
                        obj_cmd_rs) < 0)
        return (-1);
    }
  else
    {
#if defined(HAVE_SYS_STROPTS_H)
      struct strioctl istr;
      bmc_reqrsp_t reqrsp;
      uint8_t rq_buf_temp[IPMI_SUNBMC_BUFLEN];
      uint8_t rq_buf[IPMI_SUNBMC_BUFLEN];
      uint8_t rq_cmd;
      unsigned int rq_buf_len;
      uint8_t rs_buf[IPMI_SUNBMC_BUFLEN];
      int len;

      memset (&istr, '\0', sizeof (struct strioctl));
      memset (&reqrsp, '\0', sizeof (bmc_reqrsp_t));

      /* Due to API differences, we need to extract the cmd out of the
       * request.
       */
      memset (rq_buf_temp, '\0', IPMI_SUNBMC_BUFLEN);

      if ((len = fiid_obj_get_all (obj_cmd_rq,
                                   rq_buf_temp,
                                   IPMI_SUNBMC_BUFLEN)) <= 0)
        {
          SUNBMC_SET_ERRNUM (ctx, IPMI_SUNBMC_ERR_INTERNAL_ERROR);
          return (-1);
        }

      rq_cmd = rq_buf_temp[0];
      if (len > 1)
        {
          /* -1 b/c of cmd */
          memcpy (rq_buf, &rq_buf_temp[1], len - 1);
          rq_buf_len = len - 1;
        }
      else
        rq_buf_len = 0;

      reqrsp.req.fn = net_fn;
      reqrsp.req.lun = lun;
      reqrsp.req.cmd = rq_cmd;

      istr.ic_cmd = IOCTL_IPMI_KCS_ACTION;
      istr.ic_timout = 0;       /* spelled 'timout', not a typo */
      istr.ic_len = sizeof (struct bmc_reqrsp);
      istr.ic_dp = (char *)&reqrsp;

      if (ioctl (ctx->device_fd,
                 I_STR,
                 &istr) < 0)
        {
          SUNBMC_ERRNO_TO_SUNBMC_ERRNUM (ctx, errno);
          return (-1);
        }

      rs_buf[0] = reqrsp.rsp.cmd;
      rs_buf[1] = reqrsp.rsp.ccode;
      /* -2 b/c of cmd and ccode */
#if 0
      /* achu: to remove warnings, IPMI_SUNBMC_BUFLEN > amount uint8_t can hold */
      if (reqrsp.rsp.datalength >= (IPMI_SUNBMC_BUFLEN - 2))
        reqrsp.rsp.datalength = IPMI_SUNBMC_BUFLEN - 2;
#endif
      /* remove header data stuff in front we don't care about */
      if (reqrsp.rsp.datalength > 3)
        reqrsp.rsp.datalength -= 3;
      else
        reqrsp.rsp.datalength = 0;
      memcpy (rs_buf + 2, reqrsp.rsp.data, reqrsp.rsp.datalength);

      if (fiid_obj_set_all (obj_cmd_rs,
                            rs_buf,
                            reqrsp.rsp.datalength + 2) < 0)
        {
          SUNBMC_SET_ERRNUM (ctx, IPMI_SUNBMC_ERR_INTERNAL_ERROR);
          return (-1);
        }
#else /* !defined(HAVE_SYS_STROPTS_H) */
      /* otherwise, device is not supported */
      SUNBMC_SET_ERRNUM (ctx, IPMI_SUNBMC_ERR_DEVICE_NOT_SUPPORTED);
      return (-1);
#endif /* !defined(HAVE_SYS_STROPTS_H) */
    }

  return (0);
}
static int
_sunbmc_write (ipmi_sunbmc_ctx_t ctx,
               uint8_t lun,
               uint8_t net_fn,
               fiid_obj_t obj_cmd_rq)
{
#if defined(HAVE_SYS_STROPTS_H)
  struct strbuf sbuf;
  bmc_msg_t *msg = NULL;
  bmc_req_t *req = NULL;
  unsigned int msg_len;
  uint8_t rq_buf_temp[IPMI_SUNBMC_BUFLEN];
  uint8_t rq_buf[IPMI_SUNBMC_BUFLEN];
  uint8_t rq_cmd;
  unsigned int rq_buf_len;
  int len;
#endif /* !defined(HAVE_SYS_STROPTS_H) */
  int rv = -1;

  assert (ctx);
  assert (ctx->magic == IPMI_SUNBMC_CTX_MAGIC);
  assert (IPMI_BMC_LUN_VALID (lun));
  assert (IPMI_NET_FN_RQ_VALID (net_fn));
  assert (fiid_obj_valid (obj_cmd_rq));
  assert (fiid_obj_packet_valid (obj_cmd_rq) == 1);
  assert (ctx->io_init);
  assert (ctx->putmsg_intf);

#if defined(HAVE_SYS_STROPTS_H)
  memset (&sbuf, '\0', sizeof (struct strbuf));

  /* Due to API differences, we need to extract the cmd out of the
   * request.
   */
  memset (rq_buf_temp, '\0', IPMI_SUNBMC_BUFLEN);

  if ((len = fiid_obj_get_all (obj_cmd_rq,
                               rq_buf_temp,
                               IPMI_SUNBMC_BUFLEN)) <= 0)
    {
      SUNBMC_SET_ERRNUM (ctx, IPMI_SUNBMC_ERR_INTERNAL_ERROR);
      goto cleanup;
    }

  rq_cmd = rq_buf_temp[0];
  if (len > 1)
    {
      memcpy (rq_buf, &rq_buf_temp[1], len - 1);
      rq_buf_len = len - 1;
    }
  else
    rq_buf_len = 0;

  /* achu: see header for for how this is calculated */
  msg_len = offsetof (bmc_msg_t, msg);
  msg_len += sizeof (bmc_req_t);
  msg_len += (rq_buf_len > SEND_MAX_PAYLOAD_SIZE) ? (rq_buf_len - SEND_MAX_PAYLOAD_SIZE) : 0;

  if (!(msg = (bmc_msg_t *)malloc (msg_len)))
    {
      SUNBMC_SET_ERRNUM (ctx, IPMI_SUNBMC_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }

  msg->m_type = BMC_MSG_REQUEST;
  msg->m_id = ctx->putmsg_intf_msg_id;

  req = (bmc_req_t *)&(msg->msg[0]);
  req->fn = net_fn;
  req->lun = lun;
  req->cmd = rq_cmd;
  req->datalength = rq_buf_len;
  memcpy (req->data, rq_buf, rq_buf_len);

  sbuf.len = msg_len;
  sbuf.buf = (char *)msg;

  if (putmsg (ctx->device_fd, NULL, &sbuf, 0) < 0)
    {
      SUNBMC_ERRNO_TO_SUNBMC_ERRNUM (ctx, errno);
      goto cleanup;
    }

#else /* !defined(HAVE_SYS_STROPTS_H) */
  /* otherwise, device is not supported */
  SUNBMC_SET_ERRNUM (ctx, IPMI_SUNBMC_ERR_DEVICE_NOT_SUPPORTED);
  goto cleanup;
#endif /* !(defined(HAVE_BMC_INTF_H) && defined(HAVE_SYS_STROPTS_H)) */

  rv = 0;
 cleanup:
#if defined(HAVE_SYS_STROPTS_H)
  free (msg);
#endif /* !defined(HAVE_SYS_STROPTS_H) */
  return (rv);
}
static int
_openipmi_write (ipmi_openipmi_ctx_t ctx,
                 uint8_t channel_number,
                 uint8_t rs_addr,
                 uint8_t lun,
                 uint8_t net_fn,
                 fiid_obj_t obj_cmd_rq,
                 unsigned int is_ipmb)
{
  uint8_t rq_buf_temp[IPMI_OPENIPMI_BUFLEN];
  uint8_t rq_buf[IPMI_OPENIPMI_BUFLEN];
  uint8_t rq_cmd;
  unsigned int rq_buf_len;
  int len;
  struct ipmi_system_interface_addr system_interface_addr;
  struct ipmi_ipmb_addr ipmb_addr;
  struct ipmi_req rq_packet;

  assert (ctx);
  assert (ctx->magic == IPMI_OPENIPMI_CTX_MAGIC);
  assert (IPMI_CHANNEL_NUMBER_VALID (channel_number));
  assert (IPMI_BMC_LUN_VALID (lun));
  assert (IPMI_NET_FN_RQ_VALID (net_fn));
  assert (fiid_obj_valid (obj_cmd_rq));
  assert (fiid_obj_packet_valid (obj_cmd_rq) == 1);

  /* Due to API differences, we need to extract the cmd out of the
   * request.
   */
  memset (rq_buf_temp, '\0', IPMI_OPENIPMI_BUFLEN);

  if ((len = fiid_obj_get_all (obj_cmd_rq,
                               rq_buf_temp,
                               IPMI_OPENIPMI_BUFLEN)) <= 0)
    {
      OPENIPMI_SET_ERRNUM (ctx, IPMI_OPENIPMI_ERR_INTERNAL_ERROR);
      return (-1);
    }

  rq_cmd = rq_buf_temp[0];
  if (len > 1)
    {
      /* -1 b/c of cmd */
      memcpy (rq_buf, &rq_buf_temp[1], len - 1);
      rq_buf_len = len - 1;
    }
  else
    rq_buf_len = 0;

  if (!is_ipmb)
    {
      system_interface_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; /* openipmi macro */
      system_interface_addr.channel = IPMI_CHANNEL_NUMBER_SYSTEM_INTERFACE; /* freeipmi macro */
      system_interface_addr.lun = lun;

      rq_packet.addr = (unsigned char *)&system_interface_addr;
      rq_packet.addr_len = sizeof (struct ipmi_system_interface_addr);
    }
  else
    {
      ipmb_addr.addr_type = IPMI_IPMB_ADDR_TYPE; /* openipmi macro */
      ipmb_addr.channel = channel_number;
      ipmb_addr.slave_addr = rs_addr;
      ipmb_addr.lun = lun;

      rq_packet.addr = (unsigned char *)&ipmb_addr;
      rq_packet.addr_len = sizeof (struct ipmi_ipmb_addr);
    }

  rq_packet.msgid = 0;
  rq_packet.msg.netfn = net_fn;
  rq_packet.msg.cmd = rq_cmd;
  rq_packet.msg.data_len = rq_buf_len;
  rq_packet.msg.data = rq_buf;

  if (ioctl (ctx->device_fd,
             IPMICTL_SEND_COMMAND,
             &rq_packet) < 0)
    {
      OPENIPMI_ERRNO_TO_OPENIPMI_ERRNUM (ctx, errno);
      return (-1);
    }

  return (0);
}
Beispiel #11
0
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);
}
Beispiel #12
0
static int
_api_ssif_ipmb_send (ipmi_ctx_t ctx,
		     fiid_obj_t obj_cmd_rq)
{
  struct ipmi_ctx_target target_save;
  uint8_t buf[IPMI_MAX_PKT_LEN];
  fiid_obj_t obj_ipmb_msg_hdr_rq = NULL;
  fiid_obj_t obj_ipmb_msg_rq = NULL;
  fiid_obj_t obj_send_cmd_rs = NULL;
  int len, 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);

  if (!(obj_ipmb_msg_hdr_rq = fiid_obj_create (tmpl_ipmb_msg_hdr_rq)))
    {
      API_ERRNO_TO_API_ERRNUM (ctx, errno);
      goto cleanup;
    }
  if (!(obj_ipmb_msg_rq = fiid_obj_create (tmpl_ipmb_msg)))
    {
      API_ERRNO_TO_API_ERRNUM (ctx, errno);
      goto cleanup;
    }
  if (!(obj_send_cmd_rs = fiid_obj_create (tmpl_cmd_send_message_rs)))
    {
      API_ERRNO_TO_API_ERRNUM (ctx, errno);
      goto cleanup;
    }

  if (fill_ipmb_msg_hdr (ctx->target.rs_addr,
                         ctx->target.net_fn,
                         ctx->target.lun,
                         IPMI_SLAVE_ADDRESS_BMC,
                         IPMI_BMC_IPMB_LUN_SMS_MSG_LUN,
                         ctx->io.inband.rq_seq,
                         obj_ipmb_msg_hdr_rq) < 0)
    {
      API_ERRNO_TO_API_ERRNUM (ctx, errno);
      goto cleanup;
    }

  if (assemble_ipmi_ipmb_msg (obj_ipmb_msg_hdr_rq,
                              obj_cmd_rq,
                              obj_ipmb_msg_rq,
			      IPMI_INTERFACE_FLAGS_DEFAULT) < 0)
    {
      API_ERRNO_TO_API_ERRNUM (ctx, errno);
      goto cleanup;
    }

  memset (buf, '\0', IPMI_MAX_PKT_LEN);
  if ((len = fiid_obj_get_all (obj_ipmb_msg_rq,
                               buf,
                               IPMI_MAX_PKT_LEN)) < 0)
    {
      API_FIID_OBJECT_ERROR_TO_API_ERRNUM (ctx, obj_ipmb_msg_rq);
      goto cleanup;
    }

  /* send_message will send to the BMC, so clear out target information */
  memcpy (&target_save, &ctx->target, sizeof (target_save));
  ctx->target.channel_number_is_set = 0;
  ctx->target.rs_addr_is_set = 0;
  
  ret = ipmi_cmd_send_message (ctx,
			       target_save.channel_number,
			       IPMI_SEND_MESSAGE_AUTHENTICATION_NOT_REQUIRED,
			       IPMI_SEND_MESSAGE_ENCRYPTION_NOT_REQUIRED,
			       IPMI_SEND_MESSAGE_TRACKING_OPERATION_NO_TRACKING,
			       buf,
			       len,
			       obj_send_cmd_rs);

  /* restore target info */
  memcpy (&ctx->target, &target_save, sizeof (target_save));

  if (ret < 0)
    {
      /* assume these mean can't send message, bad slave address, etc. */
      if (ipmi_check_completion_code (obj_send_cmd_rs, IPMI_COMP_CODE_SEND_MESSAGE_LOST_ARBITRATION) == 1
          || ipmi_check_completion_code (obj_send_cmd_rs, IPMI_COMP_CODE_SEND_MESSAGE_BUS_ERROR) == 1
          || ipmi_check_completion_code (obj_send_cmd_rs, IPMI_COMP_CODE_SEND_MESSAGE_NAK_ON_WRITE) == 1)
        API_SET_ERRNUM (ctx, IPMI_ERR_MESSAGE_TIMEOUT);
      else
        API_BAD_RESPONSE_TO_API_ERRNUM (ctx, obj_send_cmd_rs);
      goto cleanup;
    }

  rv = 0;
 cleanup:
  fiid_obj_destroy (obj_ipmb_msg_hdr_rq);
  fiid_obj_destroy (obj_ipmb_msg_rq);
  fiid_obj_destroy (obj_send_cmd_rs);
  return (rv);
}
Beispiel #13
0
int
api_ssif_cmd (ipmi_ctx_t ctx,
	      fiid_obj_t obj_cmd_rq,
	      fiid_obj_t obj_cmd_rs)
{
  uint8_t cmd = 0;             /* used for debugging */
  uint8_t group_extension = 0; /* used for debugging */
  uint64_t val;
  struct timespec request, remain;
  uint8_t retry = IPMI_SSIF_RETRY_DEFAULT;
  
  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 (ctx->flags & IPMI_FLAGS_DEBUG_DUMP)
    {
      /* ignore error, continue on */
      if (FIID_OBJ_GET (obj_cmd_rq, "cmd", &val) < 0)
        API_FIID_OBJECT_ERROR_TO_API_ERRNUM (ctx, obj_cmd_rq);
      else
        cmd = val;

      if (IPMI_NET_FN_GROUP_EXTENSION (ctx->target.net_fn))
        {
          /* ignore error, continue on */
          if (FIID_OBJ_GET (obj_cmd_rq,
                            "group_extension_identification",
                            &val) < 0)
            API_FIID_OBJECT_ERROR_TO_API_ERRNUM (ctx, obj_cmd_rq);
          else
            group_extension = val;
        }
    }

  if (_ssif_cmd_write (ctx, cmd, group_extension, obj_cmd_rq) < 0)
    return (-1);

  /******************************************************************************
    12.9 SMBus NACKs and Error Recovery:
    ====================================
    The BMC can NACK the SMBus host controller if it is not ready to accept a new 
    transaction. Typically, this will be exhibited by the BMC NACK'ing its slave 
    address. 
    
    If the BMC NACKs a single part transaction, software can simply retry it. 
    If a 'middle' or 'end' transaction is NACK'd, software should not retry the 
    particular but should restart the multi-part read or write from the beginning
    Start transaction for the transfer.
  *******************************************************************************/
  if (_ssif_cmd_read (ctx, cmd, group_extension, obj_cmd_rs) < 0)
    {
      while (1)
        {
          request.tv_sec = 0; 
          request.tv_nsec = IPMI_SSIF_TIMEOUT_DEFAULT;
          if (nanosleep (&request, &remain) < 0 )
            return (-1);

          if (_ssif_cmd_read (ctx, cmd, group_extension, obj_cmd_rs) < 0)
            {
              if (retry == 0)
                return (-1);
        
              retry--;        
            }
            else
              break;
        }
    }

  return (0);
}
Beispiel #14
0
static int
_ipmi_kcs_cmd_write (ipmi_kcs_ctx_t ctx,
                     uint8_t lun,
                     uint8_t net_fn,
                     fiid_obj_t obj_cmd_rq)
{
  uint8_t *pkt = NULL;
  unsigned int pkt_len;
  int hdr_len, cmd_len, rv = -1;
  fiid_obj_t obj_hdr = NULL;

  assert (ctx);
  assert (ctx->magic == IPMI_KCS_CTX_MAGIC);
  assert (IPMI_BMC_LUN_VALID (lun));
  assert (IPMI_NET_FN_RQ_VALID (net_fn));
  assert (fiid_obj_valid (obj_cmd_rq));
  assert (fiid_obj_packet_valid (obj_cmd_rq) == 1);

  if ((hdr_len = fiid_template_len_bytes (tmpl_hdr_kcs)) < 0)
    {
      KCS_ERRNO_TO_KCS_ERRNUM (ctx, errno);
      goto cleanup;
    }

  if ((cmd_len = fiid_obj_len_bytes (obj_cmd_rq)) < 0)
    {
      KCS_FIID_OBJECT_ERROR_TO_KCS_ERRNUM (ctx, obj_cmd_rq);
      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 (fill_hdr_ipmi_kcs (lun,
                         net_fn,
                         obj_hdr) < 0)
    {
      KCS_SET_ERRNUM (ctx, IPMI_KCS_ERR_INTERNAL_ERROR);
      goto cleanup;
    }

  if (assemble_ipmi_kcs_pkt (obj_hdr,
                             obj_cmd_rq,
                             pkt,
                             pkt_len,
                             IPMI_INTERFACE_FLAGS_DEFAULT) < 0)
    {
      KCS_SET_ERRNUM (ctx, IPMI_KCS_ERR_INTERNAL_ERROR);
      goto cleanup;
    }

  if (ipmi_kcs_write (ctx, pkt, pkt_len) < 0)
    goto cleanup;

  rv = 0;
 cleanup:
  fiid_obj_destroy (obj_hdr);
  free (pkt);
  return (rv);
}