static int
_ipmi_monitoring_sdr_ctx_init (ipmi_monitoring_ctx_t c, const char *hostname)
{
  assert (c);
  assert (c->magic == IPMI_MONITORING_MAGIC);

  if (!(c->sdr_ctx = ipmi_sdr_ctx_create ()))
    {
      IPMI_MONITORING_DEBUG (("ipmi_sdr_cache_create: %s", strerror (errno)));
      if (errno == EPERM || errno == EACCES)
        c->errnum = IPMI_MONITORING_ERR_PERMISSION;
      else
        c->errnum = IPMI_MONITORING_ERR_INTERNAL_ERROR;
      return (-1);
    }

  if (_ipmi_monitoring_flags & IPMI_MONITORING_FLAGS_DEBUG_IPMI_PACKETS)
    {
      /* Don't error out, if this fails we can still continue */
      if (ipmi_sdr_ctx_set_flags (c->sdr_ctx, IPMI_SDR_FLAGS_DEBUG_DUMP) < 0)
        IPMI_MONITORING_DEBUG (("ipmi_sdr_ctx_set_flags: %s", ipmi_sdr_ctx_errormsg (c->sdr_ctx)));
      
      if (hostname)
        {
          if (ipmi_sdr_ctx_set_debug_prefix (c->sdr_ctx, hostname) < 0)
            IPMI_MONITORING_DEBUG (("ipmi_sdr_ctx_set_debug_prefix: %s",
                                    ipmi_sdr_ctx_errormsg (c->sdr_ctx)));
        }
    }

  return (0);
}
static int
_ipmimonitoring_legacy_simple_output_header (ipmi_sensors_state_data_t *state_data,
                                             uint16_t record_id)
{
  char id_string[IPMI_SDR_MAX_ID_STRING_LENGTH + 1];
  uint8_t sensor_type;
  uint8_t event_reading_type_code;
  const char * sensor_type_string = NULL;

  assert (state_data);

  memset (id_string, '\0', IPMI_SDR_MAX_ID_STRING_LENGTH + 1);

  if (ipmi_sdr_parse_id_string (state_data->sdr_ctx,
                                NULL,
                                0,
                                id_string,
                                IPMI_SDR_MAX_ID_STRING_LENGTH) < 0)
    {
      pstdout_fprintf (state_data->pstate,
                       stderr,
                       "ipmi_sdr_parse_id_string: %s\n",
                       ipmi_sdr_ctx_errormsg (state_data->sdr_ctx));
      return (-1);
    }

  if (ipmi_sdr_parse_sensor_type (state_data->sdr_ctx,
                                  NULL,
                                  0,
                                  &sensor_type) < 0)
    {
      pstdout_fprintf (state_data->pstate,
                       stderr,
                       "ipmi_sdr_parse_sensor_type: %s\n",
                       ipmi_sdr_ctx_errormsg (state_data->sdr_ctx));
      return (-1);
    }

  if ((state_data->prog_data->args->interpret_oem_data)
      && (ipmi_sdr_parse_event_reading_type_code (state_data->sdr_ctx,
                                                  NULL,
                                                  0,
                                                  &event_reading_type_code) >= 0))
    sensor_type_string = get_oem_sensor_type_output_string (sensor_type,
                                                            event_reading_type_code,
                                                            state_data->oem_data.manufacturer_id,
                                                            state_data->oem_data.product_id);
  else 
    sensor_type_string = get_sensor_type_output_string (sensor_type);
      
  pstdout_printf (state_data->pstate,
                  "%u | %s | %s",
                  record_id,
                  id_string,
                  sensor_type_string);

  return (0);
}
struct config_section *
ipmi_sensors_config_sections_create (ipmi_sensors_config_state_data_t *state_data)
{
  struct ipmi_sensors_config_sdr_callback sdr_callback_arg;

  assert (state_data);

  sdr_callback_arg.state_data = state_data;
  sdr_callback_arg.sections = NULL;

  if (ipmi_sdr_cache_iterate (state_data->sdr_ctx,
			      _sections_sdr_callback,
			      &sdr_callback_arg) < 0)
    {
      pstdout_fprintf (state_data->pstate,
		       stderr,
		       "ipmi_sdr_cache_iterate: %s\n",
		       ipmi_sdr_ctx_errormsg (state_data->sdr_ctx));
      goto cleanup;
    }

  return (sdr_callback_arg.sections);

 cleanup:
  config_sections_destroy (sdr_callback_arg.sections);
  return (NULL);
}
예제 #4
0
int
ipmi_sdr_cache_sdr_version (ipmi_sdr_ctx_t ctx, uint8_t *sdr_version)
{
  if (!ctx || ctx->magic != IPMI_SDR_CTX_MAGIC)
    {
      ERR_TRACE (ipmi_sdr_ctx_errormsg (ctx), ipmi_sdr_ctx_errnum (ctx));
      return (-1);
    }

  if (!sdr_version)
    {
      SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_PARAMETERS);
      return (-1);
    }

  if (ctx->operation != IPMI_SDR_OPERATION_READ_CACHE)
    {
      SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CACHE_READ_INITIALIZATION);
      return (-1);
    }

  *sdr_version = ctx->sdr_version;
  ctx->errnum = IPMI_SDR_ERR_SUCCESS;
  return (0);
}
예제 #5
0
int
ipmi_sdr_cache_record_count (ipmi_sdr_ctx_t ctx, uint16_t *record_count)
{
  if (!ctx || ctx->magic != IPMI_SDR_CTX_MAGIC)
    {
      ERR_TRACE (ipmi_sdr_ctx_errormsg (ctx), ipmi_sdr_ctx_errnum (ctx));
      return (-1);
    }

  if (!record_count)
    {
      SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_PARAMETERS);
      return (-1);
    }

  if (ctx->operation != IPMI_SDR_OPERATION_READ_CACHE)
    {
      SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CACHE_READ_INITIALIZATION);
      return (-1);
    }

  *record_count = ctx->record_count;
  ctx->errnum = IPMI_SDR_ERR_SUCCESS;
  return (0);
}
예제 #6
0
int
ipmi_sdr_cache_most_recent_erase_timestamp (ipmi_sdr_ctx_t ctx, uint32_t *most_recent_erase_timestamp)
{
  if (!ctx || ctx->magic != IPMI_SDR_CTX_MAGIC)
    {
      ERR_TRACE (ipmi_sdr_ctx_errormsg (ctx), ipmi_sdr_ctx_errnum (ctx));
      return (-1);
    }

  if (!most_recent_erase_timestamp)
    {
      SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_PARAMETERS);
      return (-1);
    }

  if (ctx->operation != IPMI_SDR_OPERATION_READ_CACHE)
    {
      SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CACHE_READ_INITIALIZATION);
      return (-1);
    }

  *most_recent_erase_timestamp = ctx->most_recent_erase_timestamp;
  ctx->errnum = IPMI_SDR_ERR_SUCCESS;
  return (0);
}
static int
_ipmi_monitoring_sdr_cache_retrieve (ipmi_monitoring_ctx_t c,
                                     const char *hostname,
                                     char *filename,
				     unsigned int sdr_create_flags)
{
  assert (c);
  assert (c->magic == IPMI_MONITORING_MAGIC);
  assert (c->sdr_ctx);
  assert (c->ipmi_ctx);
  assert (filename && strlen (filename));

  if (ipmi_sdr_cache_create (c->sdr_ctx,
                             c->ipmi_ctx,
                             filename,
			     sdr_create_flags,
                             NULL,
                             NULL) < 0)
    {
      IPMI_MONITORING_DEBUG (("ipmi_sdr_cache_create: %s", ipmi_sdr_ctx_errormsg (c->sdr_ctx)));
      if (ipmi_sdr_ctx_errnum (c->sdr_ctx) == IPMI_SDR_ERR_FILESYSTEM)
        c->errnum = IPMI_MONITORING_ERR_SDR_CACHE_FILESYSTEM;
      else if (ipmi_sdr_ctx_errnum (c->sdr_ctx) == IPMI_SDR_ERR_PERMISSION)
        c->errnum = IPMI_MONITORING_ERR_SDR_CACHE_PERMISSION;
      else if (ipmi_sdr_ctx_errnum (c->sdr_ctx) == IPMI_SDR_ERR_IPMI_ERROR)
        ipmi_monitoring_ipmi_ctx_error_convert (c);
      else if (ipmi_sdr_ctx_errnum (c->sdr_ctx) == IPMI_SDR_ERR_SYSTEM_ERROR)
        c->errnum = IPMI_MONITORING_ERR_SYSTEM_ERROR;
      else
        c->errnum = IPMI_MONITORING_ERR_INTERNAL_ERROR;
      return (-1);
    }

  return (0);
}
예제 #8
0
int
ipmi_sdr_cache_next (ipmi_sdr_ctx_t ctx)
{
  unsigned int record_length;

  if (!ctx || ctx->magic != IPMI_SDR_CTX_MAGIC)
    {
      ERR_TRACE (ipmi_sdr_ctx_errormsg (ctx), ipmi_sdr_ctx_errnum (ctx));
      return (-1);
    }

  if (ctx->operation != IPMI_SDR_OPERATION_READ_CACHE)
    {
      SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CACHE_READ_INITIALIZATION);
      return (-1);
    }

  record_length = (uint8_t)((ctx->sdr_cache + ctx->current_offset.offset)[IPMI_SDR_RECORD_LENGTH_INDEX]);

  if ((ctx->current_offset.offset + record_length + IPMI_SDR_RECORD_HEADER_LENGTH) >= ctx->records_end_offset)
    return (0);

  _sdr_set_current_offset (ctx, ctx->current_offset.offset + IPMI_SDR_RECORD_HEADER_LENGTH + record_length);

  ctx->errnum = IPMI_SDR_ERR_SUCCESS;
  return (1);
}
예제 #9
0
int
ipmi_sdr_stats_entity_instance_unique (ipmi_sdr_ctx_t ctx, uint8_t entity_id)
{
  int rv = -1;

  if (!ctx || ctx->magic != IPMI_SDR_CTX_MAGIC)
    {
      ERR_TRACE (ipmi_sdr_ctx_errormsg (ctx), ipmi_sdr_ctx_errnum (ctx));
      return (-1);
    }

  if (ctx->operation != IPMI_SDR_OPERATION_READ_CACHE)
    {
      SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CACHE_READ_INITIALIZATION);
      return (-1);
    }

  if (!ctx->stats_compiled)
    {
      SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_STATS_NOT_COMPILED);
      return (-1);
    }

  rv = ctx->entity_counts[entity_id].entity_instances_count;
  ctx->errnum = IPMI_SDR_ERR_SUCCESS;
  return (rv);
}
예제 #10
0
int
ipmi_sdr_stats_compile (ipmi_sdr_ctx_t ctx)
{
  int rv = -1;

  if (!ctx || ctx->magic != IPMI_SDR_CTX_MAGIC)
    {
      ERR_TRACE (ipmi_sdr_ctx_errormsg (ctx), ipmi_sdr_ctx_errnum (ctx));
      return (-1);
    }

  if (ctx->operation != IPMI_SDR_OPERATION_READ_CACHE)
    {
      SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CACHE_READ_INITIALIZATION);
      return (-1);
    }

  if (ctx->stats_compiled)
    goto out;

  if (ipmi_sdr_cache_iterate (ctx,
			      _sdr_stat_callback,
			      NULL) < 0)
    goto cleanup;

  ctx->stats_compiled = 1;

 out:
  rv = 0;
  ctx->errnum = IPMI_SDR_ERR_SUCCESS;
 cleanup:
  return (rv);
}
예제 #11
0
int
ipmi_oem_ibm_get_led (ipmi_oem_state_data_t *state_data)
{
  struct ipmi_oem_ibm_get_led_sdr_callback sdr_callback_arg;
  struct sensor_column_width column_width;
  struct ipmi_oem_data oem_data;
  int rv = -1;
  
  assert (state_data);
  assert (!state_data->prog_data->args->oem_options_count);

  if (sdr_cache_create_and_load (state_data->sdr_ctx,
                                 state_data->pstate,
                                 state_data->ipmi_ctx,
                                 state_data->hostname,
 				 &state_data->prog_data->args->common_args) < 0)
    goto cleanup;

  if (calculate_column_widths (state_data->pstate,
                               state_data->sdr_ctx,
                               NULL,
                               0,
                               NULL,
                               0,
                               0, /* non_abbreviated_units */
                               0, /* shared_sensors */
                               0, /* count_event_only_records */
                               0, /* count_device_locator_records */
                               1, /* count_oem_records */
                               0, /* entity_sensor_names */
                               &column_width) < 0)
    goto cleanup;

  if (ipmi_get_oem_data (state_data->pstate,
                         state_data->ipmi_ctx,
                         &oem_data) < 0)
    goto cleanup;

  sdr_callback_arg.state_data = state_data;
  sdr_callback_arg.column_width = &column_width;
  sdr_callback_arg.oem_data = &oem_data;
  sdr_callback_arg.header_output_flag = 0;

  if (ipmi_sdr_cache_iterate (state_data->sdr_ctx,
			      _get_led_sdr_callback,
			      &sdr_callback_arg) < 0)
    {
      pstdout_fprintf (state_data->pstate,
		       stderr,
		       "ipmi_sdr_cache_iterate: %s\n",
		       ipmi_sdr_ctx_errormsg (state_data->sdr_ctx));
      goto cleanup;
    }
  
  rv = 0;
 cleanup:
  return (rv);
}
예제 #12
0
int
ipmi_sdr_cache_search_record_id (ipmi_sdr_ctx_t ctx, uint16_t record_id)
{
  off_t offset;
  int found = 0;

  if (!ctx || ctx->magic != IPMI_SDR_CTX_MAGIC)
    {
      ERR_TRACE (ipmi_sdr_ctx_errormsg (ctx), ipmi_sdr_ctx_errnum (ctx));
      return (-1);
    }

  if (ctx->operation != IPMI_SDR_OPERATION_READ_CACHE)
    {
      SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CACHE_READ_INITIALIZATION);
      return (-1);
    }

  offset = ctx->records_start_offset;
  while (offset < ctx->records_end_offset)
    {
      uint8_t *ptr = ctx->sdr_cache + offset;
      uint16_t record_id_current;
      unsigned int record_length;

      /* Record ID stored little-endian */
      record_id_current = (uint16_t)ptr[IPMI_SDR_RECORD_ID_INDEX_LS] & 0xFF;
      record_id_current |= ((uint16_t)ptr[IPMI_SDR_RECORD_ID_INDEX_MS] & 0xFF) << 8;

      if (record_id == record_id_current)
        {
          found++;
	  _sdr_set_current_offset (ctx, offset);
          break;
        }

      record_length = (uint8_t)((ctx->sdr_cache + offset)[IPMI_SDR_RECORD_LENGTH_INDEX]);

      if ((offset + record_length + IPMI_SDR_RECORD_HEADER_LENGTH) >= ctx->records_end_offset)
	break;

      offset += IPMI_SDR_RECORD_HEADER_LENGTH;
      offset += record_length;
    }

  if (!found)
    {
      SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_NOT_FOUND);
      return (-1);
    }

  ctx->errnum = IPMI_SDR_ERR_SUCCESS;
  return (0);
}
예제 #13
0
static int
_find_sensor_sdr_callback (ipmi_sdr_ctx_t sdr_ctx,
			   uint8_t record_type,
			   const void *sdr_record,
			   unsigned int sdr_record_len,
			   void *arg)
{
  struct ipmi_oem_ibm_find_sensor_sdr_callback *sdr_callback_arg;
  ipmi_oem_state_data_t *state_data;
  uint8_t sdr_sensor_number;

  assert (sdr_ctx);
  assert (sdr_record);
  assert (sdr_record_len);
  assert (arg);

  sdr_callback_arg = (struct ipmi_oem_ibm_find_sensor_sdr_callback *)arg;
  state_data = sdr_callback_arg->state_data;

  /* achu: xCAT only checks for Full records, I'll check compact too though */
  if (record_type != IPMI_SDR_FORMAT_FULL_SENSOR_RECORD
      && record_type != IPMI_SDR_FORMAT_COMPACT_SENSOR_RECORD)
    return (0);

  if (ipmi_sdr_parse_sensor_number (state_data->sdr_ctx,
				    sdr_record,
				    sdr_record_len,
				    &sdr_sensor_number) < 0)
    {
      pstdout_fprintf (state_data->pstate,
		       stderr,
		       "ipmi_sdr_parse_sensor_number: %s\n",
		       ipmi_sdr_ctx_errormsg (state_data->sdr_ctx));
      return (-1);
    }

  if (sdr_callback_arg->sensor_number == sdr_sensor_number)
    {
      if (ipmi_sdr_parse_id_string (state_data->sdr_ctx,
				    sdr_record,
				    sdr_record_len,
				    sdr_callback_arg->id_string,
				    sdr_callback_arg->id_string_len) < 0)
	return (-1);
      
      sdr_callback_arg->found = 1;
      return (1);
    }

  return (0);
}
int
ipmi_sdr_cache_delete (ipmi_sdr_ctx_t ctx, const char *filename)
{
  int rv = -1;

  if (!ctx || ctx->magic != IPMI_SDR_CTX_MAGIC)
    {
      ERR_TRACE (ipmi_sdr_ctx_errormsg (ctx), ipmi_sdr_ctx_errnum (ctx));
      return (-1);
    }

  if (!filename)
    {
      SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_PARAMETERS);
      return (-1);
    }

  if (ctx->operation != IPMI_SDR_OPERATION_UNINITIALIZED)
    {
      if (ctx->operation == IPMI_SDR_OPERATION_READ_CACHE)
        SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CONTEXT_PERFORMING_OTHER_OPERATION);
      else
        SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_INTERNAL_ERROR);
      return (-1);
    }

  ctx->operation = IPMI_SDR_OPERATION_DELETE_CACHE;

  if (unlink (filename) < 0)
    {
      /* If there is no file (ENOENT), its ok */
      if (errno != ENOENT)
        {
          SDR_ERRNO_TO_SDR_ERRNUM (ctx, errno);
	  goto cleanup;
        }
    }

  rv = 0;
  ctx->errnum = IPMI_SDR_ERR_SUCCESS;
 cleanup:
  ctx->operation = IPMI_SDR_OPERATION_UNINITIALIZED;
  return (rv);
}
예제 #15
0
int
ipmi_sdr_cache_seek (ipmi_sdr_ctx_t ctx, unsigned int index)
{
  off_t offset;
  unsigned int i;

  if (!ctx || ctx->magic != IPMI_SDR_CTX_MAGIC)
    {
      ERR_TRACE (ipmi_sdr_ctx_errormsg (ctx), ipmi_sdr_ctx_errnum (ctx));
      return (-1);
    }

  if (ctx->operation != IPMI_SDR_OPERATION_READ_CACHE)
    {
      SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CACHE_READ_INITIALIZATION);
      return (-1);
    }

  if (index >= ctx->record_count)
    {
      SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_PARAMETERS);
      return (-1);
    }

  offset = ctx->records_start_offset;
  for (i = 0; i < index; i++)
    {
      unsigned int record_length;

      record_length = (uint8_t)((ctx->sdr_cache + offset)[IPMI_SDR_RECORD_LENGTH_INDEX]);

      if ((offset + record_length + IPMI_SDR_RECORD_HEADER_LENGTH) >= ctx->records_end_offset)
	break;

      offset += IPMI_SDR_RECORD_HEADER_LENGTH;
      offset += record_length;
    }

  _sdr_set_current_offset (ctx, offset);

  ctx->errnum = IPMI_SDR_ERR_SUCCESS;
  return (0);
}
예제 #16
0
int
ipmi_sdr_cache_first (ipmi_sdr_ctx_t ctx)
{
  if (!ctx || ctx->magic != IPMI_SDR_CTX_MAGIC)
    {
      ERR_TRACE (ipmi_sdr_ctx_errormsg (ctx), ipmi_sdr_ctx_errnum (ctx));
      return (-1);
    }

  if (ctx->operation != IPMI_SDR_OPERATION_READ_CACHE)
    {
      SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CACHE_READ_INITIALIZATION);
      return (-1);
    }

  _sdr_set_current_offset (ctx, ctx->records_start_offset);

  ctx->errnum = IPMI_SDR_ERR_SUCCESS;
  return (0);
}
static int
_ipmi_monitoring_sdr_cache_delete (ipmi_monitoring_ctx_t c,
                                   const char *hostname,
                                   char *filename)
{
  assert (c);
  assert (c->magic == IPMI_MONITORING_MAGIC);
  assert (c->sdr_ctx);

  if (ipmi_sdr_cache_delete (c->sdr_ctx, filename) < 0)
    {
      if (ipmi_sdr_ctx_errnum (c->sdr_ctx) !=  IPMI_SDR_ERR_FILENAME_INVALID)
        {
          IPMI_MONITORING_DEBUG (("ipmi_sdr_cache_delete: %s", ipmi_sdr_ctx_errormsg (c->sdr_ctx)));
          if (ipmi_sdr_ctx_errnum (c->sdr_ctx) == IPMI_SDR_ERR_PERMISSION)
            c->errnum = IPMI_MONITORING_ERR_SDR_CACHE_PERMISSION;
          else
            c->errnum = IPMI_MONITORING_ERR_INTERNAL_ERROR;
          return (-1);
        }
    }

  return (0);
}
예제 #18
0
int
ipmi_sdr_parse_sensor_name (ipmi_sdr_ctx_t ctx,
			    const void *sdr_record,
			    unsigned int sdr_record_len,
			    uint8_t sensor_number,
			    unsigned int flags,
			    char *buf,
			    unsigned int buflen)
{
  char id_string[IPMI_SDR_MAX_ID_STRING_LENGTH + 1];
  char device_id_string[IPMI_SDR_MAX_DEVICE_ID_STRING_LENGTH + 1];
  char *id_string_ptr = NULL;
  uint8_t record_type;
  unsigned int flags_mask = (IPMI_SDR_SENSOR_NAME_FLAGS_IGNORE_SHARED_SENSORS);

  if (!ctx || ctx->magic != IPMI_SDR_CTX_MAGIC)
    {
      ERR_TRACE (ipmi_sdr_ctx_errormsg (ctx), ipmi_sdr_ctx_errnum (ctx));
      return (-1);
    }

  if (ctx->operation != IPMI_SDR_OPERATION_READ_CACHE)
    {
      SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CACHE_READ_INITIALIZATION);
      return (-1);
    }

  if (((sdr_record_len && !sdr_record_len)
       || (!sdr_record && sdr_record_len))
      || (flags & ~flags_mask)
      || !buf
      || !buflen)
    {
      SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_PARAMETERS);
      return (-1);
    }

  memset (buf, '\0', buflen);

  if (ipmi_sdr_parse_record_id_and_type (ctx,
					 sdr_record,
					 sdr_record_len,
                                         NULL,
                                         &record_type) < 0)
    return (-1);

  if (record_type == IPMI_SDR_FORMAT_FULL_SENSOR_RECORD
      || record_type == IPMI_SDR_FORMAT_COMPACT_SENSOR_RECORD
      || record_type == IPMI_SDR_FORMAT_EVENT_ONLY_RECORD)
    {
      memset (id_string, '\0', IPMI_SDR_MAX_ID_STRING_LENGTH + 1);

      if (ipmi_sdr_parse_id_string (ctx,
				    sdr_record,
				    sdr_record_len,
				    id_string,
                                    IPMI_SDR_MAX_ID_STRING_LENGTH) < 0)
	return (-1);

      id_string_ptr = id_string;
    }
  else if (record_type == IPMI_SDR_FORMAT_GENERIC_DEVICE_LOCATOR_RECORD
	   || record_type == IPMI_SDR_FORMAT_FRU_DEVICE_LOCATOR_RECORD
           || record_type == IPMI_SDR_FORMAT_MANAGEMENT_CONTROLLER_DEVICE_LOCATOR_RECORD)
    {
      memset (device_id_string, '\0', IPMI_SDR_MAX_DEVICE_ID_STRING_LENGTH + 1);

      if (ipmi_sdr_parse_device_id_string (ctx,
					   sdr_record,
					   sdr_record_len,
                                           device_id_string,
                                           IPMI_SDR_MAX_DEVICE_ID_STRING_LENGTH) < 0)
	return (-1);
      
      id_string_ptr = device_id_string;
    }
  else
    {
      SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_PARSE_INVALID_SDR_RECORD);
      return (-1);
    }

  /* special case if sensor sharing is involved */
  if ((record_type == IPMI_SDR_FORMAT_COMPACT_SENSOR_RECORD
       || record_type == IPMI_SDR_FORMAT_EVENT_ONLY_RECORD)
      && !(flags & IPMI_SDR_SENSOR_NAME_FLAGS_IGNORE_SHARED_SENSORS))
    {
      if (_get_shared_sensor_name (ctx,
				   sdr_record,
				   sdr_record_len,
				   sensor_number,
				   id_string_ptr,
				   buf,
				   buflen) < 0)
	return (-1);
    }
  else
    snprintf (buf,
	      buflen,
	      "%s",
	      id_string_ptr);

  return (0);
}
예제 #19
0
static int
_sun_get_led_sdr_callback (ipmi_sdr_ctx_t sdr_ctx,
			   uint8_t record_type,
			   const void *sdr_record,
			   unsigned int sdr_record_len,
			   void *arg)
{
  struct ipmi_oem_sun_get_led_sdr_callback *sdr_callback_arg;
  ipmi_oem_state_data_t *state_data;
  uint8_t bytes_rq[IPMI_OEM_MAX_BYTES];
  uint8_t bytes_rs[IPMI_OEM_MAX_BYTES];
  int rs_len;
  uint16_t record_id;
  char fmt[IPMI_OEM_FMT_BUFLEN + 1];
  char device_id_string[IPMI_SDR_MAX_DEVICE_ID_STRING_LENGTH + 1];
  char sensor_name_buf[IPMI_SDR_MAX_SENSOR_NAME_LENGTH + 1];
  char *sensor_name = NULL;
  uint8_t entity_instance_type;
  uint8_t led_mode;
  char *led_mode_str = NULL;

  assert (sdr_ctx);
  assert (sdr_record);
  assert (sdr_record_len);
  assert (arg);

  sdr_callback_arg = (struct ipmi_oem_sun_get_led_sdr_callback *)arg;
  state_data = sdr_callback_arg->state_data;

  /* Sun OEM
   *
   * From Ipmitool (http://ipmitool.sourceforge.net/)
   *
   * Get Led Request
   *
   * 0x2E - OEM network function (is IPMI_NET_FN_OEM_GROUP_RQ)
   * 0x21 - OEM cmd
   * 0x?? - Device Slave Address (in General Device Locator Record)
   *      - Note that the IPMI command requires the entire
   *        byte of the slave address.
   * 0x?? - LED Type (see below [1])
   *      - 0 - ok2rm
   *      - 1 - service
   *      - 2 - activity
   *      - 3 - locate 
   * 0x?? - Controller Address / Device Access Address (in General Device Locator Record)
   *      - 0x20 if the LED is local
   *      - Note that the IPMI command requires the entire
   *        byte of the access address.
   * 0x?? - HW Info (OEM field in General Device Locator Record)
   * 0x?? - Force
   *      - 0 - Go thru controller
   *      - 1 - Directly access device
   *
   * An alternate format is described in the ipmitool comments for Sun
   * Blade Moduler Systems.
   *
   * 0x2E - OEM network function (is IPMI_NET_FN_OEM_GROUP_RQ)
   * 0x21 - OEM cmd
   * 0x?? - Device Slave Address (in General Device Locator Record)
   * 0x?? - LED Type
   * 0x?? - Controller Address / Device Access Address (in General Device Locator Record)
   * 0x?? - HW Info (OEM field in General Device Locator Record)
   * 0x?? - Entity ID
   * 0x?? - Entity Instance
   *      - 7 bit version
   * 0x?? - Force
   *      - 0 - Go thru controller
   *      - 1 - Directly access device
   *
   * Get Led Response
   *
   * 0x21 - OEM cmd
   * 0x?? - Completion Code
   * 0x?? - LED mode
   *
   * achu notes: 
   *
   * [1] - As far as I can tell, the LED type field is useless.  My
   * assumption is that on older Sun systems, or other motherboards I
   * don't have access to, one can specify an LED type, which allows
   * you to enable/disable a particular LED amongst many.  On my Sun
   * Fire 4140, it appears to do nothing and affect nothing.  I will
   * add in a new option later if it becomes necessary for the user to
   * specify an LED type.  In the meantime, I will copy the code use
   * in ipmitool and set this field to the OEM field.
   */

  if (record_type != IPMI_SDR_FORMAT_GENERIC_DEVICE_LOCATOR_RECORD)
    return (0);

  if (ipmi_sdr_parse_entity_id_instance_type (state_data->sdr_ctx,
					      sdr_record,
					      sdr_record_len,
					      NULL,
					      NULL,
					      &entity_instance_type) < 0)
    {
      pstdout_fprintf (state_data->pstate,
		       stderr,
		       "ipmi_sdr_parse_entity_id_and_instance: %s\n",
		       ipmi_sdr_ctx_errormsg (state_data->sdr_ctx));
      return (-1);
    }
      
  /* if it isn't a physical instance, don't continue on */

  if (entity_instance_type == IPMI_SDR_LOGICAL_CONTAINER_ENTITY)
    return (0);
          
  if (ipmi_sdr_parse_record_id_and_type (state_data->sdr_ctx,
					 sdr_record,
					 sdr_record_len,
					 &record_id,
					 NULL) < 0)
    {
      pstdout_fprintf (state_data->pstate,
		       stderr,
		       "ipmi_sdr_parse_record_id_and_type: %s\n",
		       ipmi_sdr_ctx_errormsg (state_data->sdr_ctx));
      return (-1);
    }

  /* achu: the sun oem commands want the full byte, not just the
   * sub-field, so use indexes instead of sdr-parse lib.
   */

  bytes_rq[0] = IPMI_CMD_OEM_SUN_GET_LED;
  bytes_rq[1] = ((uint8_t *)sdr_record)[IPMI_SDR_RECORD_GENERIC_DEVICE_LOCATOR_DEVICE_SLAVE_ADDRESS_INDEX];
  bytes_rq[2] = ((uint8_t *)sdr_record)[IPMI_SDR_RECORD_GENERIC_DEVICE_LOCATOR_OEM_INDEX];
  bytes_rq[3] = ((uint8_t *)sdr_record)[IPMI_SDR_RECORD_GENERIC_DEVICE_LOCATOR_DEVICE_ACCESS_ADDRESS_INDEX];
  bytes_rq[4] = ((uint8_t *)sdr_record)[IPMI_SDR_RECORD_GENERIC_DEVICE_LOCATOR_OEM_INDEX];
  bytes_rq[5] = IPMI_OEM_SUN_LED_FORCE_GO_THRU_CONTROLLER;

  if ((rs_len = ipmi_cmd_raw (state_data->ipmi_ctx,
			      0, /* lun */
			      IPMI_NET_FN_OEM_GROUP_RQ, /* network function */
			      bytes_rq, /* data */
			      6, /* num bytes */
			      bytes_rs,
			      IPMI_OEM_MAX_BYTES)) < 0)
    {
      pstdout_fprintf (state_data->pstate,
		       stderr,
		       "ipmi_cmd_raw: %s\n",
		       ipmi_ctx_errormsg (state_data->ipmi_ctx));
      return (-1);
    }
  
  /* achu: there are probably 1 or 2 completion codes that are
   * acceptable to ignore and continue on, but who knows what they
   * are.
   */

  if (ipmi_oem_check_response_and_completion_code (state_data,
						   bytes_rs,
						   rs_len,
						   3,
						   IPMI_CMD_OEM_SUN_GET_LED,
						   IPMI_NET_FN_OEM_GROUP_RS,
						   NULL) < 0)
    return (-1);
  
  if (!sdr_callback_arg->header_output_flag)
    {
      memset (fmt, '\0', IPMI_OEM_FMT_BUFLEN + 1);
      
      snprintf (fmt,
		IPMI_OEM_FMT_BUFLEN,
		"%%-%ds | %%-%ds | LED Mode\n",
		sdr_callback_arg->column_width->record_id,
		sdr_callback_arg->column_width->sensor_name);
      
      pstdout_printf (state_data->pstate,
		      fmt,
		      SENSORS_HEADER_RECORD_ID_STR,
		      SENSORS_HEADER_NAME_STR);
          
      sdr_callback_arg->header_output_flag++;
    }
      
  led_mode = bytes_rs[2];
      
  if (state_data->prog_data->args->verbose_count)
    {
      memset (sensor_name_buf, '\0', IPMI_SDR_MAX_SENSOR_NAME_LENGTH + 1);
      
      if (ipmi_sdr_parse_entity_sensor_name (state_data->sdr_ctx,
					     NULL,
					     0,
					     0, /* sensor number */
					     IPMI_SDR_SENSOR_NAME_FLAGS_IGNORE_SHARED_SENSORS, /* flags */
					     sensor_name_buf,
					     IPMI_SDR_MAX_SENSOR_NAME_LENGTH) < 0)
	{
	  pstdout_fprintf (state_data->pstate,
			   stderr,
			   "ipmi_sdr_parse_entity_sensor_name: %s\n",
			   ipmi_sdr_ctx_errormsg (state_data->sdr_ctx));
	  return (-1);
	}
          
      sensor_name = sensor_name_buf;
    }
  else
    {
      memset (device_id_string, '\0', IPMI_SDR_MAX_DEVICE_ID_STRING_LENGTH + 1);
      
      if (ipmi_sdr_parse_device_id_string (state_data->sdr_ctx,
					   sdr_record,
					   sdr_record_len,
					   device_id_string,
					   IPMI_SDR_MAX_DEVICE_ID_STRING_LENGTH) < 0)
	{
	  pstdout_fprintf (state_data->pstate,
			   stderr,
			   "ipmi_sdr_parse_device_id_string: %s\n",
			   ipmi_sdr_ctx_errormsg (state_data->sdr_ctx));
	  return (-1);
	}
      
      sensor_name = device_id_string;
    }
      
  switch (led_mode)
    {
    case IPMI_OEM_SUN_LED_MODE_OFF:
      led_mode_str = "Off";
      break;
    case IPMI_OEM_SUN_LED_MODE_ON:
      led_mode_str = "On";
      break;
    case IPMI_OEM_SUN_LED_MODE_STANDBY:
      led_mode_str = "Standby";
      break;
    case IPMI_OEM_SUN_LED_MODE_SLOW:
      led_mode_str = "Slow";
      break;
    case IPMI_OEM_SUN_LED_MODE_FAST:
      led_mode_str = "Fast";
      break;
    default:
      led_mode_str = "Unknown";
    }
  
  snprintf (fmt,
	    IPMI_OEM_FMT_BUFLEN,
	    "%%-%du | %%-%ds | %s\n",
	    sdr_callback_arg->column_width->record_id,
	    sdr_callback_arg->column_width->sensor_name,
	    led_mode_str);
      
  pstdout_printf (state_data->pstate,
		  fmt,
		  record_id,
		  sensor_name);

  return (0);
}
int
ipmi_monitoring_sdr_cache_load (ipmi_monitoring_ctx_t c,
                                const char *hostname,
				unsigned int sdr_create_flags)
{
  char filename[MAXPATHLEN+1];

  assert (c);
  assert (c->magic == IPMI_MONITORING_MAGIC);
  assert (c->ipmi_ctx);

  memset (filename, '\0', MAXPATHLEN + 1);

  if (_ipmi_monitoring_sdr_cache_filename (c, hostname, filename, MAXPATHLEN + 1) < 0)
    goto cleanup;

  if (_ipmi_monitoring_sdr_ctx_init (c, hostname) < 0)
    goto cleanup;

  if (ipmi_sdr_cache_open (c->sdr_ctx,
                           c->ipmi_ctx,
                           filename) < 0)
    {
      if (ipmi_sdr_ctx_errnum (c->sdr_ctx) == IPMI_SDR_ERR_CACHE_READ_CACHE_DOES_NOT_EXIST)
        {
          if (_ipmi_monitoring_sdr_cache_retrieve (c, hostname, filename, sdr_create_flags) < 0)
            goto cleanup;
        }
      else if (ipmi_sdr_ctx_errnum (c->sdr_ctx) == IPMI_SDR_ERR_CACHE_INVALID
               || ipmi_sdr_ctx_errnum (c->sdr_ctx) == IPMI_SDR_ERR_CACHE_OUT_OF_DATE)
        {
          if (_ipmi_monitoring_sdr_cache_delete (c, hostname, filename) < 0)
            goto cleanup;

          if (_ipmi_monitoring_sdr_cache_retrieve (c, hostname, filename, sdr_create_flags) < 0)
            goto cleanup;
        }
      else if (ipmi_sdr_ctx_errnum (c->sdr_ctx) == IPMI_SDR_ERR_FILESYSTEM)
        {
          c->errnum = IPMI_MONITORING_ERR_SDR_CACHE_FILESYSTEM;
          goto cleanup;
        }
      else if (ipmi_sdr_ctx_errnum (c->sdr_ctx) == IPMI_SDR_ERR_PERMISSION)
        {
          c->errnum = IPMI_MONITORING_ERR_SDR_CACHE_PERMISSION;
          goto cleanup;
        }
      else
        {
          IPMI_MONITORING_DEBUG (("ipmi_sdr_cache_open: %s", ipmi_sdr_ctx_errormsg (c->sdr_ctx)));
          c->errnum = IPMI_MONITORING_ERR_INTERNAL_ERROR;
          goto cleanup;
        }

      /* 2nd try after the sdr was retrieved*/
      if (ipmi_sdr_cache_open (c->sdr_ctx,
                               c->ipmi_ctx,
                               filename) < 0)
        {
          if (ipmi_sdr_ctx_errnum (c->sdr_ctx) == IPMI_SDR_ERR_FILESYSTEM)
            {
              c->errnum = IPMI_MONITORING_ERR_SDR_CACHE_FILESYSTEM;
              goto cleanup;
            }
          else if (ipmi_sdr_ctx_errnum (c->sdr_ctx) == IPMI_SDR_ERR_PERMISSION)
            {
              c->errnum = IPMI_MONITORING_ERR_SDR_CACHE_PERMISSION;
              goto cleanup;
            }
          else
            {
              IPMI_MONITORING_DEBUG (("ipmi_sdr_cache_open: %s", ipmi_sdr_ctx_errormsg (c->sdr_ctx)));
              c->errnum = IPMI_MONITORING_ERR_INTERNAL_ERROR;
              goto cleanup;
            }
        }
    }

  return (0);

 cleanup:
  if (strlen (filename))
    ipmi_sdr_cache_delete (c->sdr_ctx, filename);
  ipmi_sdr_ctx_destroy (c->sdr_ctx);
  c->sdr_ctx = NULL;
  return (-1);
}
/* return (0) - no OEM match
 * return (1) - OEM match
 * return (-1) - error, cleanup and return error
 */
int
ipmi_sensors_oem_intel_node_manager_output_oem_record (ipmi_sensors_state_data_t *state_data)
{
  assert (state_data);
  assert (state_data->prog_data->args->verbose_count >= 2);
  assert (state_data->prog_data->args->interpret_oem_data);

  if (state_data->intel_node_manager.node_manager_data_found)
    {
      uint8_t nm_device_slave_address;
      uint8_t sensor_owner_lun;
      uint8_t channel_number;
      uint8_t nm_health_event_sensor_number;
      uint8_t nm_exception_event_sensor_number;
      uint8_t nm_operational_capabilities_sensor_number;
      uint8_t nm_alert_threshold_exceeded_sensor_number;
      int ret;
      
      if ((ret = ipmi_sdr_oem_parse_intel_node_manager (state_data->sdr_ctx,
							NULL,
							0,
							&nm_device_slave_address,
							&sensor_owner_lun,
							&channel_number,
							&nm_health_event_sensor_number,
							&nm_exception_event_sensor_number,
							&nm_operational_capabilities_sensor_number,
							&nm_alert_threshold_exceeded_sensor_number)) < 0)
	{
	  pstdout_fprintf (state_data->pstate,
			   stderr,
			   "ipmi_sdr_oem_parse_intel_node_manager: %s\n",
			   ipmi_sdr_ctx_errormsg (state_data->sdr_ctx));
	  return (-1);
	}
      
      if (ret)
	{
	  pstdout_printf (state_data->pstate,
			  "Node Manager Device Slave Address: %Xh\n",
			  nm_device_slave_address);
	  pstdout_printf (state_data->pstate,
			  "Sensor Owner LUN: %Xh\n",
			  sensor_owner_lun);
	  pstdout_printf (state_data->pstate,
			  "Channel Number: %Xh\n",
			  channel_number);
	  pstdout_printf (state_data->pstate,
			  "Node Manager Health Event Sensor Number: %u\n",
			  nm_health_event_sensor_number);
	  pstdout_printf (state_data->pstate,
			  "Node Manager Exception Event Sensor Number: %u\n",
			  nm_exception_event_sensor_number);
	  pstdout_printf (state_data->pstate,
			  "Node Manager Operational Capabilities Sensor Number: %u\n",
			  nm_operational_capabilities_sensor_number);
	  pstdout_printf (state_data->pstate,
			  "Node Manager Alert Threshold Exceeded Sensor Number: %u\n",
			  nm_alert_threshold_exceeded_sensor_number);

	  return (1);
	}
    }

  return (0);
}
static int
_sections_sdr_callback (ipmi_sdr_ctx_t sdr_ctx,
			uint8_t record_type,
			const void *sdr_record,
			unsigned int sdr_record_len,
			void *arg)
{
  struct ipmi_sensors_config_sdr_callback *sdr_callback_arg;
  ipmi_sensors_config_state_data_t *state_data;
  struct config_section *section = NULL;
  uint8_t event_reading_type_code;
  int event_reading_type_code_class;
  config_err_t ret;

  assert (sdr_ctx);
  assert (sdr_record);
  assert (sdr_record_len);
  assert (arg);

  sdr_callback_arg = (struct ipmi_sensors_config_sdr_callback *)arg;
  state_data = sdr_callback_arg->state_data;

  /* achu:
   *
   * Technically, the IPMI spec lists that compact record formats
   * also support settable thresholds.  However, since compact
   * records don't contain any information for interpreting
   * threshold sensors (e.g. R exponent) I don't know how they
   * could be of any use.  No vendor that I know of supports
   * threshold sensors via a compact record (excluding possible
   * OEM ones).
   *
   * There's a part of me that believes the readable/setting
   * threshold masks for compact sensor records is a cut and paste
   * typo.  It shouldn't be there.
   */
  
  if (record_type != IPMI_SDR_FORMAT_FULL_SENSOR_RECORD
      && record_type != IPMI_SDR_FORMAT_COMPACT_SENSOR_RECORD)
    {
      if (state_data->prog_data->args->config_args.verbose_count)
	pstdout_fprintf (state_data->pstate,
			 stderr,
			 "## Cannot handle SDR record format '0x%X'\n",
			 record_type);
      return (0);
    }
  
  if (ipmi_sdr_parse_event_reading_type_code (state_data->sdr_ctx,
					      sdr_record,
					      sdr_record_len,
					      &event_reading_type_code) < 0)
    {
      pstdout_fprintf (state_data->pstate,
		       stderr,
		       "ipmi_sdr_parse_event_reading_type_code: %s\n",
		       ipmi_sdr_ctx_errormsg (state_data->sdr_ctx));
      return (-1);
    }

  event_reading_type_code_class = ipmi_event_reading_type_code_class (event_reading_type_code);

  if (event_reading_type_code_class == IPMI_EVENT_READING_TYPE_CODE_CLASS_THRESHOLD)
    {
      if (record_type != IPMI_SDR_FORMAT_FULL_SENSOR_RECORD)
	{
	  if (state_data->prog_data->args->config_args.verbose_count)
	    pstdout_printf (state_data->pstate,
			    "## Unable to handle threshold sensor with compact SDR record\n");
	  return (0);
	}

      if ((ret = ipmi_sensors_config_threshold_section (state_data,
							&section)) != CONFIG_ERR_SUCCESS)
	{
	  if (ret == CONFIG_ERR_FATAL_ERROR)
	    return (-1);
	  return (0);
	}
    }
  else if (event_reading_type_code_class == IPMI_EVENT_READING_TYPE_CODE_CLASS_GENERIC_DISCRETE
	   || event_reading_type_code_class == IPMI_EVENT_READING_TYPE_CODE_CLASS_SENSOR_SPECIFIC_DISCRETE)
    {
      if ((ret = ipmi_sensors_config_discrete_section (state_data,
						       &section)) != CONFIG_ERR_SUCCESS)
	{
	  if (ret == CONFIG_ERR_FATAL_ERROR)
	    return (-1);
	  return (0);
	}
    }
  else
    {
      if (state_data->prog_data->args->config_args.common_args.debug)
	pstdout_fprintf (state_data->pstate,
			 stderr,
			 "## Cannot handle SDR with event reading type code '0x%X'\n",
			 event_reading_type_code);
      return (0);
    }

  if (config_section_append (&sdr_callback_arg->sections, section) < 0)
    return (-1);

  return (0);
}
/* return (1) - is oem intel node manager, fully parsed                                                                                     
 * return (0) - is not oem intel node manager                                                                                               
 * return (-1) - error                                                                                                                      
 */
int
ipmi_sdr_oem_parse_intel_node_manager (ipmi_sdr_ctx_t ctx,
                                       const void *sdr_record,
                                       unsigned int sdr_record_len,
                                       uint8_t *nm_device_slave_address,
                                       uint8_t *sensor_owner_lun,
                                       uint8_t *channel_number,
                                       uint8_t *nm_health_event_sensor_number,
                                       uint8_t *nm_exception_event_sensor_number,
                                       uint8_t *nm_operational_capabilities_sensor_number,
                                       uint8_t *nm_alert_threshold_exceeded_sensor_number)
{
  uint8_t sdr_record_buf[IPMI_SDR_MAX_RECORD_LENGTH];
  int sdr_record_buf_len;
  fiid_obj_t obj_oem_record = NULL;
  int expected_record_len;
  void *sdr_record_to_use;
  unsigned int sdr_record_len_to_use;
  uint64_t val;
  int rv = -1;

  if (!ctx || ctx->magic != IPMI_SDR_CTX_MAGIC)
    {
      ERR_TRACE (ipmi_sdr_ctx_errormsg (ctx), ipmi_sdr_ctx_errnum (ctx));
      return (-1);
    }

  if (!sdr_record || !sdr_record_len)
    {
      if (ctx->operation == IPMI_SDR_OPERATION_READ_CACHE
          && !sdr_record
          && !sdr_record_len)
        {
          if ((sdr_record_buf_len = ipmi_sdr_cache_record_read (ctx,
                                                                sdr_record_buf,
                                                                IPMI_SDR_MAX_RECORD_LENGTH)) < 0)
            {
              SDR_SET_INTERNAL_ERRNUM (ctx);
              return (-1);
            }
          sdr_record_to_use = sdr_record_buf;
          sdr_record_len_to_use = sdr_record_buf_len;
        }
      else
        {
          SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_PARAMETERS);
          return (-1);
        }
    }
  else
    {
      sdr_record_to_use = (void *)sdr_record;
      sdr_record_len_to_use = sdr_record_len;
    }

  if ((expected_record_len = fiid_template_len_bytes (tmpl_sdr_oem_intel_node_manager_record)) < 0)
    {
      SDR_ERRNO_TO_SDR_ERRNUM (ctx, errno);
      goto cleanup;
    }
  
  if (sdr_record_len_to_use < expected_record_len)
    {
      rv = 0;
      goto cleanup;
    }

  if (!(obj_oem_record = fiid_obj_create (tmpl_sdr_oem_intel_node_manager_record)))
    {
      SDR_ERRNO_TO_SDR_ERRNUM (ctx, errno);
      goto cleanup;
    }

  if (fiid_obj_set_all (obj_oem_record,
                        sdr_record_to_use,
                        expected_record_len) < 0)
    {
      SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_oem_record);
      goto cleanup;
    }

  /* achu: Node Manager documentation states that OEM ID in the
   * SDR record should be Intel's, but I've seen motherboards w/o
   * it, so don't bother checking.
   */

  if (FIID_OBJ_GET (obj_oem_record,
                    "record_subtype",
                    &val) < 0)
    {
      SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_oem_record);
      goto cleanup;
    }
  
  if (val != IPMI_SDR_OEM_INTEL_NODE_MANAGER_RECORD_SUBTYPE_NM_DISCOVERY)
    {
      rv = 0;
      goto cleanup;
    }

  if (FIID_OBJ_GET (obj_oem_record,
                    "version_number",
                    &val) < 0)
    {
      SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_oem_record);
      goto cleanup;
    }

  if (val != IPMI_SDR_OEM_INTEL_NODE_MANAGER_DISCOVERY_VERSION)
    {
      rv = 0;
      goto cleanup;
    }
     
  if (nm_device_slave_address)
    {
      if (FIID_OBJ_GET (obj_oem_record,
                        "nm_device_slave_address",
                        &val) < 0)
        {
          SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_oem_record);
          goto cleanup;
        }
      (*nm_device_slave_address) = val;
    }

  if (sensor_owner_lun)
    {
      if (FIID_OBJ_GET (obj_oem_record,
                        "sensor_owner_lun",
                        &val) < 0)
        {
          SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_oem_record);
          goto cleanup;
        }
      (*sensor_owner_lun) = val;
    }

  if (channel_number)
    {
      if (FIID_OBJ_GET (obj_oem_record,
                        "channel_number",
                        &val) < 0)
        {
          SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_oem_record);
          goto cleanup;
        }
      (*channel_number) = val;
    }

  if (nm_health_event_sensor_number)
    {
      if (FIID_OBJ_GET (obj_oem_record,
                        "nm_health_event_sensor_number",
                        &val) < 0)
        {
          SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_oem_record);
          goto cleanup;
        }
      (*nm_health_event_sensor_number) = val;
    }

  if (nm_exception_event_sensor_number)
    {
      if (FIID_OBJ_GET (obj_oem_record,
                        "nm_exception_event_sensor_number",
                        &val) < 0)
        {
          SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_oem_record);
          goto cleanup;
        }
      (*nm_exception_event_sensor_number) = val;
    }

  if (nm_operational_capabilities_sensor_number)
    {
      if (FIID_OBJ_GET (obj_oem_record,
                        "nm_operational_capabilities_sensor_number",
                        &val) < 0)
        {
          SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_oem_record);
          goto cleanup;
        }
      (*nm_operational_capabilities_sensor_number) = val;
    }
  
  if (nm_alert_threshold_exceeded_sensor_number)
    {
      if (FIID_OBJ_GET (obj_oem_record,
                        "nm_alert_threshold_exceeded_sensor_number",
                        &val) < 0)
        {
          SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_oem_record);
          goto cleanup;
        }
      (*nm_alert_threshold_exceeded_sensor_number) = val;
    }

  sdr_check_read_status (ctx);

  rv = 1;
  ctx->errnum = IPMI_SDR_ERR_SUCCESS;
 cleanup:
  fiid_obj_destroy (obj_oem_record);
  return (rv);
}
int
ipmi_sdr_cache_create (ipmi_sdr_ctx_t ctx,
                       ipmi_ctx_t ipmi_ctx,
                       const char *filename,
                       int cache_create_flags,
                       Ipmi_Sdr_Cache_Create_Callback create_callback,
                       void *create_callback_data)
{
    int open_flags;
    uint8_t sdr_version;
    uint16_t record_count, reservation_id, record_id, next_record_id;
    uint32_t most_recent_addition_timestamp, most_recent_erase_timestamp;
    unsigned int record_count_written = 0;
    unsigned int total_bytes_written = 0;
    uint16_t *record_ids = NULL;
    unsigned int record_ids_count = 0;
    unsigned int cache_create_flags_mask = (IPMI_SDR_CACHE_CREATE_FLAGS_OVERWRITE
                                            | IPMI_SDR_CACHE_CREATE_FLAGS_DUPLICATE_RECORD_ID
                                            | IPMI_SDR_CACHE_CREATE_FLAGS_ASSUME_MAX_SDR_RECORD_COUNT);
    uint8_t trailer_checksum = 0;
    int fd = -1;
    int rv = -1;

    if (!ctx || ctx->magic != IPMI_SDR_CTX_MAGIC)
    {
        ERR_TRACE (ipmi_sdr_ctx_errormsg (ctx), ipmi_sdr_ctx_errnum (ctx));
        return (-1);
    }

    /* Version cannot be 0h according to the IPMI spec */
    if (!ipmi_ctx
            || !filename
            || (strlen (filename) > MAXPATHLEN)
            || (cache_create_flags & ~cache_create_flags_mask))
    {
        SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_PARAMETERS);
        return (-1);
    }

    if (ctx->operation != IPMI_SDR_OPERATION_UNINITIALIZED)
    {
        if (ctx->operation == IPMI_SDR_OPERATION_READ_CACHE)
            SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CONTEXT_PERFORMING_OTHER_OPERATION);
        else
            SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_INTERNAL_ERROR);
        return (-1);
    }

    ctx->operation = IPMI_SDR_OPERATION_CREATE_CACHE;

    if (cache_create_flags & IPMI_SDR_CACHE_CREATE_FLAGS_OVERWRITE)
        open_flags = O_CREAT | O_TRUNC | O_WRONLY;
    else
        open_flags = O_CREAT | O_EXCL | O_WRONLY;

    if ((fd = open (filename, open_flags, 0644)) < 0)
    {
        if (!(cache_create_flags & IPMI_SDR_CACHE_CREATE_FLAGS_OVERWRITE)
                && errno == EEXIST)
            SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CACHE_CREATE_CACHE_EXISTS);
        else if (errno == EPERM
                 || errno == EACCES
                 || errno == EISDIR
                 || errno == EROFS)
            SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_PERMISSION);
        else if (errno == ENAMETOOLONG
                 || errno == ENOENT
                 || errno == ELOOP)
            SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_FILENAME_INVALID);
        else if (errno == ENOSPC
                 || errno == EMFILE
                 || errno == ENFILE)
            SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_FILESYSTEM);
        else
            SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_SYSTEM_ERROR);
        goto cleanup;
    }

    if (sdr_info (ctx,
                  ipmi_ctx,
                  &sdr_version,
                  &record_count,
                  &most_recent_addition_timestamp,
                  &most_recent_erase_timestamp) < 0)
        goto cleanup;

    if (!record_count)
    {
        SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CACHE_CREATE_INVALID_RECORD_COUNT);
        goto cleanup;
    }

    if (_sdr_cache_header_write (ctx,
                                 ipmi_ctx,
                                 fd,
                                 &total_bytes_written,
                                 sdr_version,
                                 record_count,
                                 most_recent_addition_timestamp,
                                 most_recent_erase_timestamp) < 0)
        goto cleanup;

    /* Version cannot be 0h according to the IPMI spec, but we accept it regardless */
    ctx->sdr_version = sdr_version;
    ctx->record_count = record_count;
    ctx->most_recent_addition_timestamp = most_recent_addition_timestamp;
    ctx->most_recent_erase_timestamp = most_recent_erase_timestamp;

    if (cache_create_flags & IPMI_SDR_CACHE_CREATE_FLAGS_DUPLICATE_RECORD_ID)
    {
        if (!(record_ids = (uint16_t *)malloc (ctx->record_count * sizeof (uint16_t))))
        {
            SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_OUT_OF_MEMORY);
            goto cleanup;
        }
        record_ids_count = 0;
    }

    if (_sdr_cache_reservation_id (ctx,
                                   ipmi_ctx,
                                   &reservation_id) < 0)
        goto cleanup;

    next_record_id = IPMI_SDR_RECORD_ID_FIRST;
    while (next_record_id != IPMI_SDR_RECORD_ID_LAST)
    {
        uint8_t record_buf[IPMI_SDR_MAX_RECORD_LENGTH];
        int record_len;

        if (record_count_written >= ctx->record_count)
        {
            /* IPMI Workaround
             *
             * Discovered on unspecified Inspur motherboard
             *
             * SDR record reading is broken, the IPMI_SDR_RECORD_ID_LAST
             * record id never occurs.  So this workaround allows the
             * user to not error out and avoids this loop from looping
             * infinitely.
             *
             */

            if (cache_create_flags & IPMI_SDR_CACHE_CREATE_FLAGS_ASSUME_MAX_SDR_RECORD_COUNT)
                break;

            SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CACHE_CREATE_INVALID_RECORD_COUNT);
            goto cleanup;
        }

        record_id = next_record_id;
        if ((record_len = _sdr_cache_get_record (ctx,
                          ipmi_ctx,
                          record_id,
                          record_buf,
                          IPMI_SDR_MAX_RECORD_LENGTH,
                          &reservation_id,
                          &next_record_id)) < 0)
            goto cleanup;

        if (record_len)
        {
            if (ctx->flags & IPMI_SDR_FLAGS_DEBUG_DUMP)
            {
                const char *record_str;

                if ((record_str = sdr_record_type_str (ctx,
                                                       record_buf,
                                                       record_len)))
                {
                    char hdrbuf[IPMI_SDR_CACHE_DEBUG_BUFLEN];

                    debug_hdr_str (DEBUG_UTIL_TYPE_NONE,
                                   DEBUG_UTIL_DIRECTION_NONE,
                                   DEBUG_UTIL_FLAGS_DEFAULT,
                                   record_str,
                                   hdrbuf,
                                   IPMI_SDR_CACHE_DEBUG_BUFLEN);

                    ipmi_dump_sdr_record (STDERR_FILENO,
                                          ctx->debug_prefix,
                                          hdrbuf,
                                          NULL,
                                          record_buf,
                                          record_len);
                }
            }

            if (_sdr_cache_record_write (ctx,
                                         fd,
                                         &total_bytes_written,
                                         record_ids,
                                         &record_ids_count,
                                         record_buf,
                                         record_len,
                                         &trailer_checksum) < 0)
                goto cleanup;

            record_count_written++;

            if (create_callback)
                (*create_callback)(ctx->sdr_version,
                                   ctx->record_count,
                                   ctx->most_recent_addition_timestamp,
                                   ctx->most_recent_erase_timestamp,
                                   record_id,
                                   create_callback_data);
        }
    }

    if (record_count_written != ctx->record_count)
    {
        /*
         * IPMI Workaround (achu)
         *
         * Discovered on Fujitsu RX 100
         * Discovered on Fujitsu RX300/200-S8
         *
         * The record_count listed from the Get SDR Repository Info command
         * is not consistent with the length of SDR records stored.
         *
         * We will assume that if we reached the end of the SDR record
         * list (i.e. next_record_id == 0xFFFF), a non-zero number of
         * records were written, it's ok and we can continue on.
         */
        if (next_record_id == IPMI_SDR_RECORD_ID_LAST
                && record_count_written)
        {
            unsigned int total_bytes_written_temp = 0;

            ctx->record_count = record_count_written;

            /* need to seek back to the beginning of the file and
             * re-write the header info with the correct number of
             * records
             */

            if (lseek (fd, 0, SEEK_SET) < 0)
            {
                SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_SYSTEM_ERROR);
                goto cleanup;
            }

            if (_sdr_cache_header_write (ctx,
                                         ipmi_ctx,
                                         fd,
                                         &total_bytes_written_temp,
                                         ctx->sdr_version,
                                         ctx->record_count,
                                         ctx->most_recent_addition_timestamp,
                                         ctx->most_recent_erase_timestamp) < 0)
                goto cleanup;

            /* need to seek back to the end of the file to write the
             * trailer below
             */
            if (lseek (fd, 0, SEEK_END) < 0)
            {
                SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_SYSTEM_ERROR);
                goto cleanup;
            }
        }
        else
        {
            SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CACHE_CREATE_INVALID_RECORD_COUNT);
            goto cleanup;
        }
    }

    if (_sdr_cache_trailer_write (ctx,
                                  ipmi_ctx,
                                  fd,
                                  total_bytes_written,
                                  trailer_checksum) < 0)
        goto cleanup;

    if (fsync (fd) < 0)
    {
        SDR_ERRNO_TO_SDR_ERRNUM (ctx, errno);
        goto cleanup;
    }

    if (close (fd) < 0)
    {
        SDR_ERRNO_TO_SDR_ERRNUM (ctx, errno);
        goto cleanup;
    }
    fd = -1;

    rv = 0;
    ctx->errnum = IPMI_SDR_ERR_SUCCESS;
cleanup:
    ctx->operation = IPMI_SDR_OPERATION_UNINITIALIZED;
    if (fd >= 0)
    {
        /* If the cache create never completed, try to remove the file */
        /* ignore potential error, cleanup path */
        unlink (filename);
        /* ignore potential error, cleanup path */
        close (fd);
    }
    free (record_ids);
    sdr_init_ctx (ctx);
    return (rv);
}
예제 #25
0
config_err_t
create_section_name (ipmi_sensors_config_state_data_t *state_data,
                     char *section_name,
                     unsigned int section_name_len)
{
  char id_string[IPMI_SDR_MAX_ID_STRING_LENGTH + 1];
  uint16_t record_id;
  config_err_t rv = CONFIG_ERR_FATAL_ERROR;
  config_err_t ret;

  assert (state_data);
  assert (section_name);
  assert (section_name_len);

  memset (section_name, '\0', section_name_len);
  memset (id_string, '\0', IPMI_SDR_MAX_ID_STRING_LENGTH + 1);

  if (ipmi_sdr_parse_record_id_and_type (state_data->sdr_ctx,
					 NULL,
					 0,
                                         &record_id,
                                         NULL) < 0)
    {
      pstdout_fprintf (state_data->pstate,
                       stderr,
                       "ipmi_sdr_parse_record_id_and_type: %s\n",
                       ipmi_sdr_ctx_errormsg (state_data->sdr_ctx));
      goto cleanup;
    }

  if (ipmi_sdr_parse_id_string (state_data->sdr_ctx,
				NULL,
				0,
                                id_string,
                                IPMI_SDR_MAX_ID_STRING_LENGTH) < 0)
    {
      pstdout_fprintf (state_data->pstate,
                       stderr,
                       "ipmi_sdr_parse_id_string: %s\n",
                       ipmi_sdr_ctx_errormsg (state_data->sdr_ctx));
      goto cleanup;
    }

  if ((ret = convert_id_string (state_data, id_string)) != CONFIG_ERR_SUCCESS)
    {
      if (state_data->prog_data->args->config_args.common_args.debug)
        pstdout_fprintf (state_data->pstate,
                         stderr,
                         "convert_id_string: %s\n",
                         strerror (errno));
      rv = ret;
      goto cleanup;
    }

  /* We will name sections by record_id then name, since id_strings
   * could be identical.
   */
  if (strlen (id_string) > 0)
    snprintf (section_name,
              CONFIG_MAX_SECTION_NAME_LEN,
              "%u_%s",
              record_id,
              id_string);
  else
    /* I guess its conceivable the sensor won't have a name, so we
     * make one up.
     */
    snprintf (section_name,
              CONFIG_MAX_SECTION_NAME_LEN,
              "%u_%s",
              record_id,
              "Unknown_Sensor_Name");

  rv = CONFIG_ERR_SUCCESS;
 cleanup:
  return (rv);
}
예제 #26
0
int
ipmi_sdr_cache_search_sensor (ipmi_sdr_ctx_t ctx, uint8_t sensor_number, uint8_t sensor_owner_id)
{
  off_t offset;
  int found = 0;

  if (!ctx || ctx->magic != IPMI_SDR_CTX_MAGIC)
    {
      ERR_TRACE (ipmi_sdr_ctx_errormsg (ctx), ipmi_sdr_ctx_errnum (ctx));
      return (-1);
    }

  if (ctx->operation != IPMI_SDR_OPERATION_READ_CACHE)
    {
      SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CACHE_READ_INITIALIZATION);
      return (-1);
    }

  offset = ctx->records_start_offset;
  while (offset < ctx->records_end_offset)
    {
      uint8_t *ptr = ctx->sdr_cache + offset;
      uint8_t record_type_current;
      unsigned int record_length;

      record_type_current = ptr[IPMI_SDR_RECORD_TYPE_INDEX];

      if (record_type_current == IPMI_SDR_FORMAT_FULL_SENSOR_RECORD
          || record_type_current == IPMI_SDR_FORMAT_COMPACT_SENSOR_RECORD
          || record_type_current == IPMI_SDR_FORMAT_EVENT_ONLY_RECORD)
        {
          uint8_t sensor_number_current;
          uint8_t sensor_owner_id_current;

          sensor_owner_id_current = ptr[IPMI_SDR_RECORD_SENSOR_OWNER_ID_INDEX];
          sensor_number_current = ptr[IPMI_SDR_RECORD_SENSOR_NUMBER_INDEX];

          if (sensor_owner_id_current == sensor_owner_id
              && sensor_number_current == sensor_number)
            {
              found++;
	      _sdr_set_current_offset (ctx, offset);
              break;
            }

          /* Compact sensor records can do record sharing, so check
           * for this case if the sensor_owner_id matches up.
           */
          if (sensor_owner_id_current == sensor_owner_id
              && (record_type_current == IPMI_SDR_FORMAT_COMPACT_SENSOR_RECORD
                  || record_type_current == IPMI_SDR_FORMAT_EVENT_ONLY_RECORD))
            {
              uint8_t share_count;
              
	      if (record_type_current == IPMI_SDR_FORMAT_COMPACT_SENSOR_RECORD)
		{
		  share_count = ptr[IPMI_SDR_RECORD_COMPACT_SHARE_COUNT];
		  share_count &= IPMI_SDR_RECORD_COMPACT_SHARE_COUNT_BITMASK;
		  share_count >>= IPMI_SDR_RECORD_COMPACT_SHARE_COUNT_SHIFT;
		}
	      else
		{
예제 #27
0
static int
_find_sensor (ipmi_oem_state_data_t *state_data,
              uint8_t sensor_number,
              char *id_string,
              unsigned int id_string_len)
{
  struct ipmi_oem_ibm_find_sensor_sdr_callback sdr_callback_arg;
  struct common_cmd_args common_args;
  ipmi_sdr_ctx_t tmp_sdr_ctx = NULL;
  int rv = -1;

  assert (state_data);
  assert (id_string);
  assert (id_string_len);

  /* Make temporary sdr cache to search for sensor
   *
   * Redo loading of SDR cache since this is being called from a loop
   * using the state_data sdr_ctx.
   */
  if (!(tmp_sdr_ctx = ipmi_sdr_ctx_create ()))
    {
      pstdout_perror (state_data->pstate, "ipmi_sdr_ctx_create()");
      goto cleanup;
    }

  sdr_callback_arg.state_data = state_data;
  sdr_callback_arg.sensor_number = sensor_number;
  sdr_callback_arg.id_string = id_string;
  sdr_callback_arg.id_string_len = id_string_len;
  sdr_callback_arg.found = 0;

  /* Should not cause sdr recreation, since this is the second time we're calling it */
  memcpy (&common_args, &state_data->prog_data->args->common_args, sizeof (struct common_cmd_args));
  common_args.quiet_cache = 1;
  common_args.sdr_cache_recreate = 0;

  if (sdr_cache_create_and_load (tmp_sdr_ctx,
                                 state_data->pstate,
                                 state_data->ipmi_ctx,
                                 state_data->hostname,
				 &common_args) < 0)
    goto cleanup;

  if (ipmi_sdr_cache_iterate (tmp_sdr_ctx,
			      _find_sensor_sdr_callback,
			      &sdr_callback_arg) < 0)
    {
      pstdout_fprintf (state_data->pstate,
		       stderr,
		       "ipmi_sdr_cache_iterate: %s\n",
		       ipmi_sdr_ctx_errormsg (state_data->sdr_ctx));
      goto cleanup;
    }

  if (!sdr_callback_arg.found)
    snprintf (id_string,
              id_string_len,
              "Sensor Number = %02Xh",
              sensor_number);
  rv = 0;
 cleanup:
  ipmi_sdr_ctx_destroy (tmp_sdr_ctx);
  return (rv);
}
예제 #28
0
static int
_get_led_sdr_callback (ipmi_sdr_ctx_t sdr_ctx,
		       uint8_t record_type,
		       const void *sdr_record,
		       unsigned int sdr_record_len,
		       void *arg)
{
  struct ipmi_oem_ibm_get_led_sdr_callback *sdr_callback_arg;
  ipmi_oem_state_data_t *state_data;
  uint8_t bytes_rq[IPMI_OEM_MAX_BYTES];
  uint8_t bytes_rs[IPMI_OEM_MAX_BYTES];
  int rs_len;
  uint8_t oem_data_buf[IPMI_SDR_MAX_RECORD_LENGTH];
  int oem_data_buf_len;
  uint16_t record_id;
  char fmt[IPMI_OEM_FMT_BUFLEN + 1];
  char led_name[IPMI_OEM_IBM_LED_NAME_BUFLEN + 1];
  char led_pointer_name[IPMI_OEM_IBM_LED_NAME_BUFLEN + 1];
  char id_string[IPMI_OEM_IBM_LED_ID_STRING_BUFLEN + 1];
  char led_info[IPMI_OEM_IBM_LED_INFO_BUFLEN + 1];
  char *led_state_str = NULL;
  uint8_t sensor_type;
  uint8_t led_id_ls;
  uint8_t led_id_ms;
  uint16_t led_id;
  uint8_t led_state;
  uint8_t led_active_type;
  uint16_t led_pointer_id;
  uint8_t sensor_number;
  int available_led;

  assert (sdr_ctx);
  assert (sdr_record);
  assert (sdr_record_len);
  assert (arg);

  sdr_callback_arg = (struct ipmi_oem_ibm_get_led_sdr_callback *)arg;
  state_data = sdr_callback_arg->state_data;

  /* IBM OEM
   *
   * From xCAT (http://xcat.sourceforge.net/)
   *
   * Get Led Request
   *
   * 0x3A - OEM network function (is IPMI_NET_FN_OEM_IBM_LED_RQ)
   * 0xC0 - OEM cmd
   * 0x?? - LED ID (MS Byte)
   * 0x?? - LED ID (LS Byte)
   *
   * Get Led Response
   *
   * 0xC0 - OEM cmd
   * 0x?? - Completion Code
   * 0x?? - ??
   * 0x?? - LED Active vs. Inactive
   *      - non-zero = active
   *      - 0 = inactive
   * 0x?? - ??
   * 0x?? - LED Pointer ID (MS Byte)
   * 0x?? - LED Pointer ID (LS Byte) / Sensor Number
   *      - Pointer ID means indicating problem elsewhere
   * 0x?? - LED Active Type
   *      - 1 - Indicates LED Active to indicate LED Pointer ID Active
   *      - 2 - Indicates LED Active due to Sensor w/ Sensor Number
   *      - 3 - User manually activated LED
   *      - 4 - BIOS or Administrator lit LED
   */

  if (record_type != IPMI_SDR_FORMAT_OEM_RECORD)
    return (0);

  if (ipmi_sdr_parse_record_id_and_type (state_data->sdr_ctx,
					 sdr_record,
					 sdr_record_len,
					 &record_id,
					 NULL) < 0)
    {
      pstdout_fprintf (state_data->pstate,
		       stderr,
		       "ipmi_sdr_parse_record_id_and_type: %s\n",
		       ipmi_sdr_ctx_errormsg (state_data->sdr_ctx));
      return (-1);
    }

  if ((oem_data_buf_len = ipmi_sdr_parse_oem_data (state_data->sdr_ctx,
						   sdr_record,
						   sdr_record_len,
						   oem_data_buf,
						   IPMI_SDR_MAX_RECORD_LENGTH)) < 0)
    {
      pstdout_fprintf (state_data->pstate,
		       stderr,
		       "ipmi_sdr_parse_oem_data: %s\n",
		       ipmi_sdr_ctx_errormsg (state_data->sdr_ctx));
      return (-1);
    }
      
  /* If not enough data, skip it */
  if (oem_data_buf_len < IPMI_SDR_RECORD_OEM_IBM_LED_OEM_DATA_MIN_LENGTH)
    return (0);

  sensor_type = oem_data_buf[IPMI_SDR_RECORD_OEM_IBM_SENSOR_TYPE_OEM_DATA_INDEX];
      
  /* If not LED sensor type, skip it */
  if (sensor_type != IPMI_SDR_RECORD_OEM_IBM_LED_SENSOR_TYPE)
    return (0);

  /* IBM systems use inconsistent endian, guess endian by assuming
   * LED IDs are numerically started at 0
   */
      
  if (oem_data_buf[IPMI_SDR_RECORD_OEM_IBM_LED_ID_LS_OEM_DATA_INDEX] > oem_data_buf[IPMI_SDR_RECORD_OEM_IBM_LED_ID_MS_OEM_DATA_INDEX])
    {
      led_id_ls = oem_data_buf[IPMI_SDR_RECORD_OEM_IBM_LED_ID_LS_OEM_DATA_INDEX];
      led_id_ms = oem_data_buf[IPMI_SDR_RECORD_OEM_IBM_LED_ID_MS_OEM_DATA_INDEX];
    }
  else
    {
      led_id_ls = oem_data_buf[IPMI_SDR_RECORD_OEM_IBM_LED_ID_MS_OEM_DATA_INDEX];
      led_id_ms = oem_data_buf[IPMI_SDR_RECORD_OEM_IBM_LED_ID_LS_OEM_DATA_INDEX];
    }

  led_id = led_id_ls | (led_id_ms << 8);

  bytes_rq[0] = IPMI_CMD_OEM_IBM_GET_LED;
  bytes_rq[1] = led_id_ms;
  bytes_rq[2] = led_id_ls;
      
  if ((rs_len = ipmi_cmd_raw (state_data->ipmi_ctx,
			      0, /* lun */
			      IPMI_NET_FN_OEM_IBM_LED_RQ, /* network function */
			      bytes_rq, /* data */
			      3, /* num bytes */
			      bytes_rs,
			      IPMI_OEM_MAX_BYTES)) < 0)
    {
      pstdout_fprintf (state_data->pstate,
		       stderr,
		       "ipmi_cmd_raw: %s\n",
		       ipmi_ctx_errormsg (state_data->ipmi_ctx));
      return (-1);
    }
      
  /* If get parameter out of range, assume LED ID endian wrong and try again */
  if (rs_len >= 2 && bytes_rs[1] == IPMI_COMP_CODE_PARAMETER_OUT_OF_RANGE)
    {
      bytes_rq[0] = IPMI_CMD_OEM_IBM_GET_LED;
      bytes_rq[1] = led_id_ls;
      bytes_rq[2] = led_id_ms;

      if ((rs_len = ipmi_cmd_raw (state_data->ipmi_ctx,
				  0, /* lun */
				  IPMI_NET_FN_OEM_IBM_LED_RQ, /* network function */
				  bytes_rq, /* data */
				  3, /* num bytes */
				  bytes_rs,
				  IPMI_OEM_MAX_BYTES)) < 0)
	{
	  pstdout_fprintf (state_data->pstate,
			   stderr,
			   "ipmi_cmd_raw: %s\n",
			   ipmi_ctx_errormsg (state_data->ipmi_ctx));
	  return (-1);
	}
    }

  /* achu: there are probably 1 or 2 completion codes that are
   * acceptable to ignore and continue on, but who knows what they
   * are.
   */

  /* Assume this error code means LED not available */
  if (rs_len >= 2 && bytes_rs[1] == IPMI_COMP_CODE_PARAMETER_OUT_OF_RANGE)
    available_led = 0;
  else
    {
      if (ipmi_oem_check_response_and_completion_code (state_data,
						       bytes_rs,
						       rs_len,
						       8,
						       IPMI_CMD_OEM_IBM_GET_LED,
						       IPMI_NET_FN_OEM_IBM_LED_RS,
						       NULL) < 0)
	return (-1);
      
      available_led = 1;
    }

  if (!sdr_callback_arg->header_output_flag)
    {
      memset (fmt, '\0', IPMI_OEM_FMT_BUFLEN + 1);
      
      snprintf (fmt,
		IPMI_OEM_FMT_BUFLEN,
		"%%-%ds | LED               | State    | LED Information\n",
		sdr_callback_arg->column_width->record_id);
      
      pstdout_printf (state_data->pstate,
		      fmt,
		      SENSORS_HEADER_RECORD_ID_STR);
      
      sdr_callback_arg->header_output_flag++;
    }
      
  memset (led_name, '\0', IPMI_OEM_IBM_LED_NAME_BUFLEN + 1);
  memset (led_pointer_name, '\0', IPMI_OEM_IBM_LED_NAME_BUFLEN + 1);
  memset (id_string, '\0', IPMI_OEM_IBM_LED_ID_STRING_BUFLEN + 1);
  memset (led_info, '\0', IPMI_OEM_IBM_LED_INFO_BUFLEN + 1);
      
  if (_get_led_name (state_data,
		     sdr_callback_arg->oem_data,
		     led_id,
		     led_name,
		     IPMI_OEM_IBM_LED_NAME_BUFLEN) < 0)
    return (-1);
      
  if (available_led)
    {
      led_state = bytes_rs[3];
      led_active_type = bytes_rs[7];
      led_pointer_id = (bytes_rs[5] << 8) | bytes_rs[6];
      sensor_number = bytes_rs[6];

      if (led_state == IPMI_OEM_IBM_LED_STATE_INACTIVE)
	led_state_str = "Inactive";
      else
	led_state_str = "Active";
      
      if (led_state != IPMI_OEM_IBM_LED_STATE_INACTIVE)
	{
	  /* Location LED special case */
	  if (!led_id)
	    {
	      snprintf (led_info,
			IPMI_OEM_IBM_LED_INFO_BUFLEN,
			"System Error Condition");
	    }
	  else if (led_active_type == IPMI_OEM_IBM_LED_ACTIVE_BY_LED)
	    {
	      if (_get_led_name (state_data,
				 sdr_callback_arg->oem_data,
				 led_pointer_id,
				 led_pointer_name,
				 IPMI_OEM_IBM_LED_NAME_BUFLEN) < 0)
		return (-1);
	      
	      snprintf (led_info,
			IPMI_OEM_IBM_LED_INFO_BUFLEN,
			"'%s' Active",
			led_pointer_name);
	    }
	  else if (led_active_type == IPMI_OEM_IBM_LED_ACTIVE_BY_SENSOR)
	    {
	      /* achu: sensor numbers may not be unique.  I'm copying
	       * this algorithm from xCAT so I assume it's safe for
	       * IBM machines b/c IBM lays out their SDRs in a fashion
	       * that this search is safe and won't result in an
	       * incorrect output.
	       */
	      if (_find_sensor (state_data,
				sensor_number,
				id_string,
				IPMI_OEM_IBM_LED_ID_STRING_BUFLEN) < 0)
		return (-1);
	      
	      snprintf (led_info,
			IPMI_OEM_IBM_LED_INFO_BUFLEN,
			"Sensor '%s' error",
			id_string);
	    }
	  else if (led_active_type == IPMI_OEM_IBM_LED_ACTIVE_BY_USER)
	    {
	      snprintf (led_info,
			IPMI_OEM_IBM_LED_INFO_BUFLEN,
			"LED Activated by User");
	    }
	  else if (led_active_type == IPMI_OEM_IBM_LED_ACTIVE_BY_BIOS_OR_ADMINISTRATOR)
	    {
	      snprintf (led_info,
			IPMI_OEM_IBM_LED_INFO_BUFLEN,
			"LED Activated by BIOS or Administrator");
	    }
	}
    }
  else
    led_state_str = "N/A";
      
  snprintf (fmt,
	    IPMI_OEM_FMT_BUFLEN,
	    "%%-%du | %%-%ds | %%-%ds | %s\n",
	    sdr_callback_arg->column_width->record_id,
	    IPMI_OEM_IBM_LED_NAME_COLUMN_SIZE,
	    IPMI_OEM_IBM_LED_STATE_COLUMN_SIZE,
	    led_info);
      
  pstdout_printf (state_data->pstate,
		  fmt,
		  record_id,
		  led_name,
		  led_state_str,
		  led_info);

  return (0);
}
예제 #29
0
int
ipmi_sdr_cache_open (ipmi_sdr_ctx_t ctx,
                     ipmi_ctx_t ipmi_ctx,
                     const char *filename)
{
  uint8_t sdr_version;
  uint16_t record_count;
  uint32_t most_recent_addition_timestamp, most_recent_erase_timestamp;
  char sdr_version_buf;
  char sdr_cache_magic_buf[4];
  char sdr_cache_version_buf[4];
  char record_count_buf[2];
  char most_recent_addition_timestamp_buf[4];
  char most_recent_erase_timestamp_buf[4];
  struct stat stat_buf;

  if (!ctx || ctx->magic != IPMI_SDR_CTX_MAGIC)
    {
      ERR_TRACE (ipmi_sdr_ctx_errormsg (ctx), ipmi_sdr_ctx_errnum (ctx));
      return (-1);
    }

  if (!filename)
    {
      SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_PARAMETERS);
      return (-1);
    }

  if (ctx->operation != IPMI_SDR_OPERATION_UNINITIALIZED)
    {
      if (ctx->operation == IPMI_SDR_OPERATION_READ_CACHE)
        SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CACHE_READ_ALREADY_INITIALIZED);
      else
        SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_INTERNAL_ERROR);
      return (-1);
    }

  if (stat (filename, &stat_buf) < 0)
    {
      SDR_ERRNO_TO_SDR_ERRNUM (ctx, errno);
      goto cleanup;
    }

  /* File Size must be atleast magic_buf + file_version_buf +
   * sdr_version_buf + record_count_buf +
   * most_recent_addition_timestamp_buf +
   * most_recent_erase_timestamp-buf in size.
   */

  ctx->file_size = stat_buf.st_size;
  if (ctx->file_size < (4 + 4 + 1 + 2 + 4 + 4))
    {
      SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CACHE_INVALID);
      goto cleanup;
    }

  if ((ctx->fd = open (filename, O_RDONLY)) < 0)
    {
      SDR_ERRNO_TO_SDR_ERRNUM (ctx, errno);
      goto cleanup;
    }

  ctx->sdr_cache = (uint8_t *)mmap (NULL,
                                    ctx->file_size,
                                    PROT_READ,
                                    MAP_PRIVATE,
                                    ctx->fd,
                                    0);
  if (!ctx->sdr_cache || ctx->sdr_cache == ((void *) -1))
    {
      ERRNO_TRACE (errno);
      SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_SYSTEM_ERROR);
      goto cleanup;
    }

  memcpy (sdr_cache_magic_buf, ctx->sdr_cache + ctx->records_start_offset, 4);
  ctx->records_start_offset += 4;
  memcpy (sdr_cache_version_buf, ctx->sdr_cache + ctx->records_start_offset, 4);
  ctx->records_start_offset += 4;
  memcpy (&sdr_version_buf, ctx->sdr_cache + ctx->records_start_offset, 1);
  ctx->records_start_offset += 1;
  memcpy (record_count_buf, ctx->sdr_cache + ctx->records_start_offset, 2);
  ctx->records_start_offset += 2;
  memcpy (most_recent_addition_timestamp_buf, ctx->sdr_cache + ctx->records_start_offset, 4);
  ctx->records_start_offset += 4;
  memcpy (most_recent_erase_timestamp_buf, ctx->sdr_cache + ctx->records_start_offset, 4);
  ctx->records_start_offset += 4;

  if ((uint8_t)sdr_cache_magic_buf[0] != IPMI_SDR_CACHE_FILE_MAGIC_0
      || (uint8_t)sdr_cache_magic_buf[1] != IPMI_SDR_CACHE_FILE_MAGIC_1
      || (uint8_t)sdr_cache_magic_buf[2] != IPMI_SDR_CACHE_FILE_MAGIC_2
      || (uint8_t)sdr_cache_magic_buf[3] != IPMI_SDR_CACHE_FILE_MAGIC_3)
    {
      SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CACHE_INVALID);
      goto cleanup;
    }

  if (((uint8_t)sdr_cache_version_buf[0] != IPMI_SDR_CACHE_FILE_VERSION_1_0
       || (uint8_t)sdr_cache_version_buf[1] != IPMI_SDR_CACHE_FILE_VERSION_1_1
       || (uint8_t)sdr_cache_version_buf[2] != IPMI_SDR_CACHE_FILE_VERSION_1_2
       || (uint8_t)sdr_cache_version_buf[3] != IPMI_SDR_CACHE_FILE_VERSION_1_3)
      && ((uint8_t)sdr_cache_version_buf[0] != IPMI_SDR_CACHE_FILE_VERSION_1_2_0
	  || (uint8_t)sdr_cache_version_buf[1] != IPMI_SDR_CACHE_FILE_VERSION_1_2_1
	  || (uint8_t)sdr_cache_version_buf[2] != IPMI_SDR_CACHE_FILE_VERSION_1_2_2
	  || (uint8_t)sdr_cache_version_buf[3] != IPMI_SDR_CACHE_FILE_VERSION_1_2_3))
    {
      SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CACHE_INVALID);
      goto cleanup;
    }

  ctx->sdr_version = (uint8_t)sdr_version_buf;
  ctx->record_count = ((uint16_t)record_count_buf[0] & 0xFF);
  ctx->record_count |= ((uint16_t)record_count_buf[1] & 0xFF) << 8;
  ctx->most_recent_addition_timestamp = ((uint32_t)most_recent_addition_timestamp_buf[0] & 0xFF);
  ctx->most_recent_addition_timestamp |= ((uint32_t)most_recent_addition_timestamp_buf[1] & 0xFF) << 8;
  ctx->most_recent_addition_timestamp |= ((uint32_t)most_recent_addition_timestamp_buf[2] & 0xFF) << 16;
  ctx->most_recent_addition_timestamp |= ((uint32_t)most_recent_addition_timestamp_buf[3] & 0xFF) << 24;
  ctx->most_recent_erase_timestamp = ((uint32_t)most_recent_erase_timestamp_buf[0] & 0xFF);
  ctx->most_recent_erase_timestamp |= ((uint32_t)most_recent_erase_timestamp_buf[1] & 0xFF) << 8;
  ctx->most_recent_erase_timestamp |= ((uint32_t)most_recent_erase_timestamp_buf[2] & 0xFF) << 16;
  ctx->most_recent_erase_timestamp |= ((uint32_t)most_recent_erase_timestamp_buf[3] & 0xFF) << 24;

  if (ipmi_ctx)
    {
      if (sdr_info (ctx,
		    ipmi_ctx,
		    &sdr_version,
		    &record_count,
		    &most_recent_addition_timestamp,
		    &most_recent_erase_timestamp) < 0)
	goto cleanup;

      if (ctx->sdr_version != sdr_version
	  || ctx->most_recent_addition_timestamp != most_recent_addition_timestamp
	  || ctx->most_recent_erase_timestamp != most_recent_erase_timestamp)
	{
	  SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CACHE_OUT_OF_DATE);
	  goto cleanup;
	}
    }

  if ((uint8_t)sdr_cache_version_buf[0] == IPMI_SDR_CACHE_FILE_VERSION_1_2_0
      && (uint8_t)sdr_cache_version_buf[1] == IPMI_SDR_CACHE_FILE_VERSION_1_2_1
      && (uint8_t)sdr_cache_version_buf[2] == IPMI_SDR_CACHE_FILE_VERSION_1_2_2
      && (uint8_t)sdr_cache_version_buf[3] == IPMI_SDR_CACHE_FILE_VERSION_1_2_3)
    {
      uint8_t header_checksum_buf[512];
      unsigned int header_checksum_buf_len = 0;
      uint8_t header_checksum, header_checksum_cache;
      uint8_t trailer_checksum, trailer_checksum_cache;
      char total_bytes_written_buf[4];
      unsigned int total_bytes_written;
      unsigned int header_bytes_len;
      unsigned int trailer_bytes_len;

      /* File Size must be atleast magic_buf + file_version_buf +
       * sdr_version_buf + record_count_buf +
       * most_recent_addition_timestamp_buf +
       * most_recent_erase_timestamp-buf + header_checksum + trailer
       * bytes written + trailer records checksum.
       */
      
      header_bytes_len = 4 + 4 + 1 + 2 + 4 + 4 + 1;
      trailer_bytes_len = 4 + 1;

      if (ctx->file_size < (header_bytes_len + trailer_bytes_len))
	{
	  SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CACHE_INVALID);
	  goto cleanup;
	}

      memcpy (&header_checksum_cache, ctx->sdr_cache + ctx->records_start_offset, 1);
      ctx->records_start_offset += 1;

      memcpy(&header_checksum_buf[header_checksum_buf_len], sdr_cache_magic_buf, 4);
      header_checksum_buf_len += 4;
      memcpy(&header_checksum_buf[header_checksum_buf_len], sdr_cache_version_buf, 4);
      header_checksum_buf_len += 4;
      memcpy(&header_checksum_buf[header_checksum_buf_len], &sdr_version_buf, 1);
      header_checksum_buf_len += 1;
      memcpy(&header_checksum_buf[header_checksum_buf_len], record_count_buf, 2);
      header_checksum_buf_len += 2;
      memcpy(&header_checksum_buf[header_checksum_buf_len], most_recent_addition_timestamp_buf, 4);
      header_checksum_buf_len += 4;
      memcpy(&header_checksum_buf[header_checksum_buf_len], most_recent_erase_timestamp_buf, 4);
      header_checksum_buf_len += 4;
      
      header_checksum = ipmi_checksum (header_checksum_buf, header_checksum_buf_len);
      if (header_checksum != header_checksum_cache)
	{
	  SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CACHE_INVALID);
	  goto cleanup;
	}

      /* total_bytes_written is written before checksum */
      /* checksum of records is last byte written */
      memcpy (total_bytes_written_buf, ctx->sdr_cache + ctx->file_size - 5, 4);
      memcpy (&trailer_checksum_cache, ctx->sdr_cache + ctx->file_size - 1, 1);

      total_bytes_written = ((uint32_t)total_bytes_written_buf[0] & 0xFF);
      total_bytes_written |= ((uint32_t)total_bytes_written_buf[1] & 0xFF) << 8;
      total_bytes_written |= ((uint32_t)total_bytes_written_buf[2] & 0xFF) << 16;
      total_bytes_written |= ((uint32_t)total_bytes_written_buf[3] & 0xFF) << 24;

      if (total_bytes_written != ctx->file_size)
	{
	  SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CACHE_INVALID);
	  goto cleanup;
	}

      /* -1 for checksum */
      trailer_checksum = ipmi_checksum (ctx->sdr_cache + ctx->records_start_offset,
					total_bytes_written - ctx->records_start_offset - 1);

      if (trailer_checksum != trailer_checksum_cache)
	{
	  SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CACHE_INVALID);
	  goto cleanup;
	}

      ctx->records_end_offset = ctx->file_size - trailer_bytes_len;
    }
  else /* (uint8_t)sdr_cache_version_buf[0] == IPMI_SDR_CACHE_FILE_VERSION_1_0
	  && (uint8_t)sdr_cache_version_buf[1] == IPMI_SDR_CACHE_FILE_VERSION_1_1
	  && (uint8_t)sdr_cache_version_buf[2] == IPMI_SDR_CACHE_FILE_VERSION_1_2
	  && (uint8_t)sdr_cache_version_buf[3] == IPMI_SDR_CACHE_FILE_VERSION_1_3 */
    ctx->records_end_offset = ctx->file_size;

  _sdr_set_current_offset (ctx, ctx->records_start_offset);
  ctx->operation = IPMI_SDR_OPERATION_READ_CACHE;
  ctx->errnum = IPMI_SDR_ERR_SUCCESS;
  return (0);

 cleanup:
  /* ignore potential error, cleanup path */
  if (ctx->fd >= 0)
    close (ctx->fd);
  /* ignore potential error, cleanup path */
  if (ctx->sdr_cache)
    munmap ((void *)ctx->sdr_cache, ctx->file_size);
  sdr_init_ctx (ctx);
  return (-1);
}
예제 #30
0
int
ipmi_sdr_parse_entity_sensor_name (ipmi_sdr_ctx_t ctx,
				   const void *sdr_record,
				   unsigned int sdr_record_len,
				   uint8_t sensor_number,
				   unsigned int flags,
				   char *buf,
				   unsigned int buflen)
{
  char id_string[IPMI_SDR_MAX_ID_STRING_LENGTH + 1];
  char device_id_string[IPMI_SDR_MAX_DEVICE_ID_STRING_LENGTH + 1];
  char entity_name_buf[IPMI_SDR_ENTITY_NAME_BUFLEN + 1];
  char *id_string_ptr = NULL;
  uint8_t entity_id, entity_instance, entity_instance_type;
  const char *entity_id_str;
  uint8_t record_type;
  unsigned int flags_mask = (IPMI_SDR_SENSOR_NAME_FLAGS_IGNORE_SHARED_SENSORS
			     | IPMI_SDR_SENSOR_NAME_FLAGS_ALWAYS_OUTPUT_INSTANCE_NUMBER);

  if (!ctx || ctx->magic != IPMI_SDR_CTX_MAGIC)
    {
      ERR_TRACE (ipmi_sdr_ctx_errormsg (ctx), ipmi_sdr_ctx_errnum (ctx));
      return (-1);
    }

  if (ctx->operation != IPMI_SDR_OPERATION_READ_CACHE)
    {
      SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CACHE_READ_INITIALIZATION);
      return (-1);
    }

  if (((sdr_record_len && !sdr_record_len)
       || (!sdr_record && sdr_record_len))
      || (flags & ~flags_mask)
      || !buf
      || !buflen)
    {
      SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_PARAMETERS);
      return (-1);
    }

  memset (buf, '\0', buflen);
  memset (entity_name_buf, '\0', IPMI_SDR_ENTITY_NAME_BUFLEN + 1);

  if (ipmi_sdr_parse_record_id_and_type (ctx,
					 sdr_record,
					 sdr_record_len,
                                         NULL,
                                         &record_type) < 0)
    return (-1);

  if (record_type == IPMI_SDR_FORMAT_FULL_SENSOR_RECORD
      || record_type == IPMI_SDR_FORMAT_COMPACT_SENSOR_RECORD
      || record_type == IPMI_SDR_FORMAT_EVENT_ONLY_RECORD)
    {
      memset (id_string, '\0', IPMI_SDR_MAX_ID_STRING_LENGTH + 1);

      if (ipmi_sdr_parse_id_string (ctx,
				    sdr_record,
				    sdr_record_len,
				    id_string,
                                    IPMI_SDR_MAX_ID_STRING_LENGTH) < 0)
	return (-1);

      id_string_ptr = id_string;
    }
  else if (record_type == IPMI_SDR_FORMAT_GENERIC_DEVICE_LOCATOR_RECORD
           || record_type == IPMI_SDR_FORMAT_MANAGEMENT_CONTROLLER_DEVICE_LOCATOR_RECORD)
    {
      memset (device_id_string, '\0', IPMI_SDR_MAX_DEVICE_ID_STRING_LENGTH + 1);

      if (ipmi_sdr_parse_device_id_string (ctx,
					   sdr_record,
					   sdr_record_len,
                                           device_id_string,
                                           IPMI_SDR_MAX_DEVICE_ID_STRING_LENGTH) < 0)
	return (-1);
      
      id_string_ptr = device_id_string;
    }
  else
    {
      SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_PARSE_INVALID_SDR_RECORD);
      return (-1);
    }

  if (ipmi_sdr_parse_entity_id_instance_type (ctx,
					      sdr_record,
					      sdr_record_len,
                                              &entity_id,
                                              &entity_instance,
                                              &entity_instance_type) < 0)
    return (-1);

  /* Table 39-1
   *
   * "It is recommended that console software subtract 60h when
   * presenting device-relative Entity Instance values, and present
   * the Entity Instance number along with an ID for the device
   * providing the interface to the entity."
   *
   * achu: For the time being we do not output the device providing
   * the interface, only the right instance number.  Adjust later if
   * necessary.
   */

  if (IPMI_ENTITY_INSTANCE_DEVICE_RELATIVE (entity_instance))
    entity_instance -= IPMI_ENTITY_INSTANCE_DEVICE_RELATIVE_MIN;

  entity_id_str = ipmi_get_entity_id_string (entity_id);

  /* a few special cases, for entity_ids are special, the vendor has
   * specifically stated there is no "entity" associated with this sdr
   * record
   */
  if (entity_id == IPMI_ENTITY_ID_UNSPECIFIED
      || entity_id == IPMI_ENTITY_ID_OTHER
      || entity_id == IPMI_ENTITY_ID_UNKNOWN)
    snprintf (buf,
	      buflen,
	      "%s",
	      id_string_ptr);
  else
    {
      if (ipmi_sdr_stats_compile (ctx) < 0)
	return (-1);

      if (ipmi_sdr_stats_entity_instance_unique (ctx, entity_id) > 1)
        {
          /* special case if sensor sharing is involved */
          if ((record_type == IPMI_SDR_FORMAT_COMPACT_SENSOR_RECORD
               || record_type == IPMI_SDR_FORMAT_EVENT_ONLY_RECORD)
              && !(flags & IPMI_SDR_SENSOR_NAME_FLAGS_IGNORE_SHARED_SENSORS))
            {
	      uint8_t share_count;
	      uint8_t entity_instance_sharing;
	      char sensor_name_buf[IPMI_SDR_MAX_SENSOR_NAME_LENGTH + 1];

	      if (ipmi_sdr_parse_sensor_record_sharing (ctx,
							sdr_record,
							sdr_record_len,
							&share_count,
							NULL,
							NULL,
							&entity_instance_sharing) < 0)
		return (-1);
      
	      if (share_count > 1
		  && entity_instance_sharing == IPMI_SDR_ENTITY_INSTANCE_INCREMENTS_FOR_EACH_SHARED_RECORD)
		{
		  uint8_t sensor_number_base;
      
		  if (ipmi_sdr_parse_sensor_number (ctx,
						    sdr_record,
						    sdr_record_len,
						    &sensor_number_base) < 0)
		    return (-1);
      
		  /* I guess it's a bug if the sensor number passed in is bad */
		  if (sensor_number >= sensor_number_base)
		    entity_instance += (sensor_number - sensor_number_base);
		  else
		    goto fallthrough;
		}

	      memset (sensor_name_buf, '\0', IPMI_SDR_MAX_SENSOR_NAME_LENGTH + 1);
	      
	      if (_get_shared_sensor_name (ctx,
					   sdr_record,
					   sdr_record_len,
					   sensor_number,
					   id_string_ptr,
					   sensor_name_buf,
					   IPMI_SDR_MAX_SENSOR_NAME_LENGTH) < 0)
		return (-1);

	      snprintf (entity_name_buf,
			IPMI_SDR_ENTITY_NAME_BUFLEN,
			"%s %u",
			entity_id_str,
			entity_instance);

	      /* In odd chance the strings end up identical */
	      if (!strcasecmp (entity_name_buf, sensor_name_buf))
		snprintf (buf,
			  buflen,
			  "%s",
			  sensor_name_buf);
	      else
		snprintf (buf,
			  buflen,
			  "%s %s",
			  entity_name_buf,
			  sensor_name_buf);
	    }
	  else
	    {
	    fallthrough:
	      snprintf (entity_name_buf,
			IPMI_SDR_ENTITY_NAME_BUFLEN,
			"%s %u",
			entity_id_str,
			entity_instance);
	      
	      /* In odd chance the strings end up identical */
	      if (!strcasecmp (entity_name_buf, id_string_ptr))
		snprintf (buf,
			  buflen,
			  "%s",
			  id_string_ptr);
	      else
		snprintf (buf,
			  buflen,
			  "%s %s",
			  entity_name_buf,
			  id_string_ptr);
	    }
	}
      else
	{
	  if (flags & IPMI_SDR_SENSOR_NAME_FLAGS_ALWAYS_OUTPUT_INSTANCE_NUMBER)
	    {
	      snprintf (entity_name_buf,
			IPMI_SDR_ENTITY_NAME_BUFLEN,
			"%s %u",
			entity_id_str,
			entity_instance);
	      
	      /* In odd chance the strings end up identical */
	      if (!strcasecmp (entity_name_buf, id_string_ptr))
		snprintf (buf,
			  buflen,
			  "%s",
			  id_string_ptr);
	      else
		snprintf (buf,
			  buflen,
			  "%s %s",
			  entity_name_buf,
			  id_string_ptr);
	    }
	  else
	    {
	      /* In odd chance the strings end up identical */
	      if (!strcasecmp (entity_id_str, id_string_ptr))
		snprintf (buf,
			  buflen,
			  "%s",
			  id_string_ptr);
	      else
		snprintf (buf,
			  buflen,
			  "%s %s",
			  entity_id_str,
			  id_string_ptr);
	    }
	}
    }

  return (0);
}