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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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, §ion)) != 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, §ion)) != 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); }
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); }
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 {
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); }
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); }
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); }
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); }