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_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); }
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); }
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); }
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_oem_sun_set_led (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; uint8_t led_mode; long value; char *ptr; uint8_t sdr_record[IPMI_SDR_MAX_RECORD_LENGTH]; int sdr_record_len = 0; uint8_t record_type; uint8_t entity_instance_type; int rv = -1; assert (state_data); assert (state_data->prog_data->args->oem_options_count == 2); errno = 0; value = strtol (state_data->prog_data->args->oem_options[0], &ptr, 10); if (errno || ptr[0] != '\0' || value < 0 || value < IPMI_SDR_RECORD_ID_FIRST || value > IPMI_SDR_RECORD_ID_LAST) { pstdout_fprintf (state_data->pstate, stderr, "%s:%s invalid record_id\n", state_data->prog_data->args->oem_id, state_data->prog_data->args->oem_command); goto cleanup; } record_id = value; if (strcasecmp (state_data->prog_data->args->oem_options[1], "off") && strcasecmp (state_data->prog_data->args->oem_options[1], "on") && strcasecmp (state_data->prog_data->args->oem_options[1], "standby") && strcasecmp (state_data->prog_data->args->oem_options[1], "slow") && strcasecmp (state_data->prog_data->args->oem_options[1], "fast")) { pstdout_fprintf (state_data->pstate, stderr, "%s:%s invalid OEM option argument '%s'\n", state_data->prog_data->args->oem_id, state_data->prog_data->args->oem_command, state_data->prog_data->args->oem_options[1]); goto cleanup; } if (!strcasecmp (state_data->prog_data->args->oem_options[1], "off")) led_mode = IPMI_OEM_SUN_LED_MODE_OFF; else if (!strcasecmp (state_data->prog_data->args->oem_options[1], "on")) led_mode = IPMI_OEM_SUN_LED_MODE_ON; else if (!strcasecmp (state_data->prog_data->args->oem_options[1], "standby")) led_mode = IPMI_OEM_SUN_LED_MODE_STANDBY; else if (!strcasecmp (state_data->prog_data->args->oem_options[1], "slow")) led_mode = IPMI_OEM_SUN_LED_MODE_SLOW; else /* !strcasecmp (state_data->prog_data->args->oem_options[1], "fast") */ led_mode = IPMI_OEM_SUN_LED_MODE_FAST; 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; /* Sun OEM * * From Ipmitool (http://ipmitool.sourceforge.net/) * * Set Led Request * * 0x2E - OEM network function (is IPMI_NET_FN_OEM_GROUP_RQ) * 0x22 - 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?? - LED Mode * 0x?? - Force * - 0 - Go thru controller * - 1 - Directly access device * 0x?? - Role * - Ipmitool comments state "Used by BMC for authorization purposes" * - achu: I have no idea what this is for, set to 0 like in code * * 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) * 0x22 - 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?? - LED Mode * 0x?? - Entity ID * 0x?? - Entity Instance * - 7 bit version * 0x?? - Force * - 0 - Go thru controller * - 1 - Directly access device * 0x?? - Role * - Ipmitool comments state "Used by BMC for authorization purposes" * - achu: I have no idea what this is for, set to 0 like in code * * Set Led Response * * 0x22 - OEM cmd * 0x?? - Completion Code * * 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 (ipmi_sdr_cache_search_record_id (state_data->sdr_ctx, record_id) < 0) { pstdout_fprintf (state_data->pstate, stderr, "ipmi_sdr_cache_search_record_id: %s\n", ipmi_sdr_ctx_errormsg (state_data->sdr_ctx)); goto cleanup; } if ((sdr_record_len = ipmi_sdr_cache_record_read (state_data->sdr_ctx, sdr_record, IPMI_SDR_MAX_RECORD_LENGTH)) < 0) { pstdout_fprintf (state_data->pstate, stderr, "ipmi_sdr_cache_record_read: %s\n", ipmi_sdr_ctx_errormsg (state_data->sdr_ctx)); goto cleanup; } if (ipmi_sdr_parse_record_id_and_type (state_data->sdr_ctx, sdr_record, sdr_record_len, NULL, &record_type) < 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 (record_type != IPMI_SDR_FORMAT_GENERIC_DEVICE_LOCATOR_RECORD) { pstdout_fprintf (state_data->pstate, stderr, "Record ID points to invalid record type: %Xh\n", record_type); goto cleanup; } 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)); goto cleanup; } if (entity_instance_type != IPMI_SDR_PHYSICAL_ENTITY) { pstdout_fprintf (state_data->pstate, stderr, "Record ID points to non physical entity\n"); goto cleanup; } /* 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_SET_LED; bytes_rq[1] = sdr_record[IPMI_SDR_RECORD_GENERIC_DEVICE_LOCATOR_DEVICE_SLAVE_ADDRESS_INDEX]; bytes_rq[2] = sdr_record[IPMI_SDR_RECORD_GENERIC_DEVICE_LOCATOR_OEM_INDEX]; bytes_rq[3] = sdr_record[IPMI_SDR_RECORD_GENERIC_DEVICE_LOCATOR_DEVICE_ACCESS_ADDRESS_INDEX]; bytes_rq[4] = sdr_record[IPMI_SDR_RECORD_GENERIC_DEVICE_LOCATOR_OEM_INDEX]; bytes_rq[5] = led_mode; bytes_rq[6] = IPMI_OEM_SUN_LED_FORCE_GO_THRU_CONTROLLER; bytes_rq[7] = 0; /* see comments above, just set to 0 */ if ((rs_len = ipmi_cmd_raw (state_data->ipmi_ctx, 0, /* lun */ IPMI_NET_FN_OEM_GROUP_RQ, /* network function */ bytes_rq, /* data */ 8, /* 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)); goto cleanup; } if (ipmi_oem_check_response_and_completion_code (state_data, bytes_rs, rs_len, 2, IPMI_CMD_OEM_SUN_SET_LED, IPMI_NET_FN_OEM_GROUP_RS, NULL) < 0) goto cleanup; rv = 0; cleanup: return (rv); }
int ipmi_sensor_read (ipmi_sensor_read_ctx_t ctx, const void *sdr_record, unsigned int sdr_record_len, uint8_t shared_sensor_number_offset, uint8_t *sensor_reading_raw, double **sensor_reading, uint16_t *sensor_event_bitmask) { double *tmp_sensor_reading = NULL; uint64_t val; int rv = -1; fiid_obj_t obj_cmd_rs = NULL; uint8_t sensor_event_bitmask1 = 0; uint8_t sensor_event_bitmask2 = 0; int sensor_event_bitmask1_flag = 0; int sensor_event_bitmask2_flag = 0; uint16_t record_id = 0; uint8_t record_type = 0; uint8_t sensor_number = 0; uint8_t event_reading_type_code = 0; uint8_t sensor_owner_id_type = 0; uint8_t sensor_owner_id = 0; uint8_t sensor_owner_lun = 0; uint8_t channel_number = 0; uint8_t slave_address = 0; uint8_t reading_state, sensor_scanning; uint8_t local_sensor_reading_raw; unsigned int ctx_flags_orig; int event_reading_type_code_class = 0; if (!ctx || ctx->magic != IPMI_SENSOR_READ_CTX_MAGIC) { ERR_TRACE (ipmi_sensor_read_ctx_errormsg (ctx), ipmi_sensor_read_ctx_errnum (ctx)); return (-1); } if (!sdr_record || !sdr_record_len || !sensor_reading || !sensor_event_bitmask) { SENSOR_READ_SET_ERRNUM (ctx, IPMI_SENSOR_READ_ERR_PARAMETERS); return (-1); } *sensor_reading = NULL; *sensor_event_bitmask = 0; if (ipmi_sdr_parse_record_id_and_type (ctx->sdr_ctx, sdr_record, sdr_record_len, &record_id, &record_type) < 0) { SENSOR_READ_SET_ERRNUM (ctx, IPMI_SENSOR_READ_ERR_SDR_ENTRY_ERROR); goto cleanup; } if (record_type != IPMI_SDR_FORMAT_FULL_SENSOR_RECORD && record_type != IPMI_SDR_FORMAT_COMPACT_SENSOR_RECORD) { SENSOR_READ_SET_ERRNUM (ctx, IPMI_SENSOR_READ_ERR_INVALID_SDR_RECORD_TYPE); goto cleanup; } if (ipmi_sdr_parse_sensor_owner_id (ctx->sdr_ctx, sdr_record, sdr_record_len, &sensor_owner_id_type, &sensor_owner_id) < 0) { SENSOR_READ_SET_ERRNUM (ctx, IPMI_SENSOR_READ_ERR_SDR_ENTRY_ERROR); goto cleanup; } if (ipmi_sdr_parse_sensor_owner_lun (ctx->sdr_ctx, sdr_record, sdr_record_len, &sensor_owner_lun, &channel_number) < 0) { SENSOR_READ_SET_ERRNUM (ctx, IPMI_SENSOR_READ_ERR_SDR_ENTRY_ERROR); goto cleanup; } if (ipmi_sdr_parse_sensor_number (ctx->sdr_ctx, sdr_record, sdr_record_len, &sensor_number) < 0) { SENSOR_READ_SET_ERRNUM (ctx, IPMI_SENSOR_READ_ERR_SDR_ENTRY_ERROR); goto cleanup; } if (shared_sensor_number_offset) { uint8_t share_count; if (record_type != IPMI_SDR_FORMAT_COMPACT_SENSOR_RECORD) { SENSOR_READ_SET_ERRNUM (ctx, IPMI_SENSOR_READ_ERR_INVALID_SDR_RECORD_TYPE); goto cleanup; } if (ipmi_sdr_parse_sensor_record_sharing (ctx->sdr_ctx, sdr_record, sdr_record_len, &share_count, NULL, NULL, NULL) < 0) { SENSOR_READ_SET_ERRNUM (ctx, IPMI_SENSOR_READ_ERR_SDR_ENTRY_ERROR); goto cleanup; } if (share_count <= 1) { SENSOR_READ_SET_ERRNUM (ctx, IPMI_SENSOR_READ_ERR_INVALID_SDR_RECORD_TYPE); goto cleanup; } if ((sensor_number + share_count) < (sensor_number + shared_sensor_number_offset)) { SENSOR_READ_SET_ERRNUM (ctx, IPMI_SENSOR_READ_ERR_PARAMETERS); goto cleanup; } sensor_number += shared_sensor_number_offset; } if (ipmi_sdr_parse_event_reading_type_code (ctx->sdr_ctx, sdr_record, sdr_record_len, &event_reading_type_code) < 0) { SENSOR_READ_SET_ERRNUM (ctx, IPMI_SENSOR_READ_ERR_SDR_ENTRY_ERROR); goto cleanup; } if (sensor_owner_id_type == IPMI_SDR_SENSOR_OWNER_ID_TYPE_SYSTEM_SOFTWARE_ID) { SENSOR_READ_SET_ERRNUM (ctx, IPMI_SENSOR_READ_ERR_SENSOR_IS_SYSTEM_SOFTWARE); goto cleanup; } slave_address = (sensor_owner_id << 1) | sensor_owner_id_type; if (!(obj_cmd_rs = fiid_obj_create (tmpl_cmd_get_sensor_reading_rs))) { SENSOR_READ_ERRNO_TO_SENSOR_READ_ERRNUM (ctx, errno); goto cleanup; } /* * IPMI Workaround (achu) * * See comments below concerning sensor_event_bitmask. */ if (ipmi_ctx_get_flags (ctx->ipmi_ctx, &ctx_flags_orig) < 0) { SENSOR_READ_SET_ERRNUM (ctx, IPMI_SENSOR_READ_ERR_INTERNAL_ERROR); goto cleanup; } if (ipmi_ctx_set_flags (ctx->ipmi_ctx, ctx_flags_orig | IPMI_FLAGS_NO_VALID_CHECK) < 0) { SENSOR_READ_SET_ERRNUM (ctx, IPMI_SENSOR_READ_ERR_INTERNAL_ERROR); goto cleanup; } /* IPMI Workaround * * Discovered on Fujitsu RX300 * Discovered on Fujitsu RX300S2 * * On some motherboards, the sensor owner is invalid. The sensor * owner as atually the BMC. */ if (!(ctx->flags & IPMI_SENSOR_READ_FLAGS_ASSUME_BMC_OWNER)) { if (slave_address == IPMI_SLAVE_ADDRESS_BMC) { if (_get_sensor_reading (ctx, sensor_number, obj_cmd_rs) < 0) goto cleanup; } else { if (_get_sensor_reading_ipmb (ctx, slave_address, sensor_owner_lun, channel_number, sensor_number, obj_cmd_rs) < 0) goto cleanup; } } else { if (_get_sensor_reading (ctx, sensor_number, obj_cmd_rs) < 0) goto cleanup; } /* * IPMI Workaround (achu) * * See comments below concerning sensor_event_bitmask. */ if (ipmi_ctx_set_flags (ctx->ipmi_ctx, ctx_flags_orig) < 0) { SENSOR_READ_SET_ERRNUM (ctx, IPMI_SENSOR_READ_ERR_INTERNAL_ERROR); goto cleanup; } if (FIID_OBJ_GET (obj_cmd_rs, "reading_state", &val) < 0) { SENSOR_READ_FIID_OBJECT_ERROR_TO_SENSOR_READ_ERRNUM (ctx, obj_cmd_rs); goto cleanup; } reading_state = val; if (reading_state == IPMI_SENSOR_READING_STATE_UNAVAILABLE) { SENSOR_READ_SET_ERRNUM (ctx, IPMI_SENSOR_READ_ERR_SENSOR_READING_UNAVAILABLE); goto cleanup; } /* IPMI Workaround * * Discovered on Dell Poweredge 2900 * Discovered on Dell Poweredge 2950 * Discovered on Dell Poweredge R410 * Discovered on Dell Poweredge R610 * * On some motherboards, the sensor scanning bit is invalid for sensors. */ if (!(ctx->flags & IPMI_SENSOR_READ_FLAGS_IGNORE_SCANNING_DISABLED)) { if (FIID_OBJ_GET (obj_cmd_rs, "sensor_scanning", &val) < 0) { SENSOR_READ_FIID_OBJECT_ERROR_TO_SENSOR_READ_ERRNUM (ctx, obj_cmd_rs); goto cleanup; } sensor_scanning = val; if (sensor_scanning == IPMI_SENSOR_SCANNING_ON_THIS_SENSOR_DISABLE) { SENSOR_READ_SET_ERRNUM (ctx, IPMI_SENSOR_READ_ERR_SENSOR_SCANNING_DISABLED); goto cleanup; } } /* achu: * * Note: I don't bother checking the "all_event_messages" flag from * the get_sensor_reading response. If that stuff is turned off, * the bitmasks should be zeroed out. * * Hopefully this doesn't bite me later on. * * Call the normal fiid_obj_get instead of the wrapper, if the field * isn't set, we want to know and not error out. */ if ((sensor_event_bitmask1_flag = fiid_obj_get (obj_cmd_rs, "sensor_event_bitmask1", &val)) < 0) { SENSOR_READ_FIID_OBJECT_ERROR_TO_SENSOR_READ_ERRNUM (ctx, obj_cmd_rs); goto cleanup; } sensor_event_bitmask1 = val; if ((sensor_event_bitmask2_flag = fiid_obj_get (obj_cmd_rs, "sensor_event_bitmask2", &val)) < 0) { SENSOR_READ_FIID_OBJECT_ERROR_TO_SENSOR_READ_ERRNUM (ctx, obj_cmd_rs); goto cleanup; } sensor_event_bitmask2 = val; /* * IPMI Workaround (achu) * * Discovered on Dell 2950. * * It seems the sensor_event_bitmask (16 bits) may not be returned * by the server at all for some sensors, despite a minimum of 8 * bits being required. Under this situation, there's not much that * can be done. Since there is no sensor_event_bitmask, we just * assume that no states have been asserted and the * sensor_event_bitmask = 0; */ if (!sensor_event_bitmask1_flag && !sensor_event_bitmask2_flag) (*sensor_event_bitmask) = 0; else if (sensor_event_bitmask1_flag && sensor_event_bitmask2_flag) (*sensor_event_bitmask) = sensor_event_bitmask1 | (sensor_event_bitmask2 << 8); else if (sensor_event_bitmask1_flag && !sensor_event_bitmask2_flag) (*sensor_event_bitmask) = sensor_event_bitmask1; else { SENSOR_READ_SET_ERRNUM (ctx, IPMI_SENSOR_READ_ERR_IPMI_ERROR); goto cleanup; } if (FIID_OBJ_GET (obj_cmd_rs, "sensor_reading", &val) < 0) { SENSOR_READ_FIID_OBJECT_ERROR_TO_SENSOR_READ_ERRNUM (ctx, obj_cmd_rs); goto cleanup; } local_sensor_reading_raw = val; if (sensor_reading_raw) (*sensor_reading_raw) = local_sensor_reading_raw; 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) { int8_t r_exponent, b_exponent; int16_t m, b; uint8_t linearization, analog_data_format; if (ipmi_sdr_parse_sensor_decoding_data (ctx->sdr_ctx, sdr_record, sdr_record_len, &r_exponent, &b_exponent, &m, &b, &linearization, &analog_data_format) < 0) { SENSOR_READ_SET_ERRNUM (ctx, IPMI_SENSOR_READ_ERR_SDR_ENTRY_ERROR); goto cleanup; } /* if the sensor is not analog, this is most likely a bug in the * SDR, since we shouldn't be decoding a non-threshold sensor. */ if (!IPMI_SDR_ANALOG_DATA_FORMAT_VALID (analog_data_format)) { SENSOR_READ_SET_ERRNUM (ctx, IPMI_SENSOR_READ_ERR_SENSOR_NON_ANALOG); rv = 0; goto cleanup; } /* if the sensor is non-linear, I just don't know what to do, * let the tool figure out what to output. */ if (!IPMI_SDR_LINEARIZATION_IS_LINEAR (linearization)) { SENSOR_READ_SET_ERRNUM (ctx, IPMI_SENSOR_READ_ERR_SENSOR_NON_LINEAR); rv = 0; goto cleanup; } if (!(tmp_sensor_reading = (double *)malloc (sizeof (double)))) { SENSOR_READ_SET_ERRNUM (ctx, IPMI_SENSOR_READ_ERR_OUT_OF_MEMORY); goto cleanup; } if (ipmi_sensor_decode_value (r_exponent, b_exponent, m, b, linearization, analog_data_format, local_sensor_reading_raw, tmp_sensor_reading) < 0) { SENSOR_READ_SET_ERRNUM (ctx, IPMI_SENSOR_READ_ERR_INTERNAL_ERROR); goto cleanup; } *sensor_reading = tmp_sensor_reading; } rv = 1; } 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) { /* * IPMI Workaround (achu) * * Discovered on HP Proliant DL380 G7 * Discovered on HP ProLiant ML310 G5 * * SDR records for some sensors give conflicting information. A * threshold based sensor lists an event/reading type code for a * discrete sensor. The analog data format indicates an * analog/threshold based sensor, however no threshold limits * for the sensor are listed in the SDR. * * To deal with this, if the analog data format and units * strongly suggest that a reading should occur with this * sensor, get the reading and return it. * * Note that this can only occur for full records, since * decoding data does not exist in compact records. */ if (ctx->flags & IPMI_SENSOR_READ_FLAGS_DISCRETE_READING && record_type == IPMI_SDR_FORMAT_FULL_SENSOR_RECORD) { int8_t r_exponent, b_exponent; int16_t m, b; uint8_t linearization, analog_data_format; uint8_t sensor_units_percentage; uint8_t sensor_units_modifier; uint8_t sensor_units_rate; uint8_t sensor_base_unit_type; uint8_t sensor_modifier_unit_type; if (ipmi_sdr_parse_sensor_decoding_data (ctx->sdr_ctx, sdr_record, sdr_record_len, &r_exponent, &b_exponent, &m, &b, &linearization, &analog_data_format) < 0) { SENSOR_READ_SET_ERRNUM (ctx, IPMI_SENSOR_READ_ERR_SDR_ENTRY_ERROR); goto cleanup; } if (ipmi_sdr_parse_sensor_units (ctx->sdr_ctx, sdr_record, sdr_record_len, &sensor_units_percentage, &sensor_units_modifier, &sensor_units_rate, &sensor_base_unit_type, &sensor_modifier_unit_type) < 0) { SENSOR_READ_SET_ERRNUM (ctx, IPMI_SENSOR_READ_ERR_SDR_ENTRY_ERROR); goto cleanup; } /* if the sensor is not analog, this is normal expected * case, fallthrough to normal expectations */ if (!IPMI_SDR_ANALOG_DATA_FORMAT_VALID (analog_data_format)) { rv = 1; goto cleanup; } /* if the sensor units are not specified, this is the normal expected * case, fallthrough to normal expectations */ if (sensor_units_percentage != IPMI_SDR_PERCENTAGE_YES && sensor_base_unit_type == IPMI_SENSOR_UNIT_UNSPECIFIED) { rv = 1; goto cleanup; } /* if the sensor is non-linear, I just don't know what to do, * let the tool figure out what to output. */ if (!IPMI_SDR_LINEARIZATION_IS_LINEAR (linearization)) { SENSOR_READ_SET_ERRNUM (ctx, IPMI_SENSOR_READ_ERR_SENSOR_NON_LINEAR); rv = 0; goto cleanup; } if (!(tmp_sensor_reading = (double *)malloc (sizeof (double)))) { SENSOR_READ_SET_ERRNUM (ctx, IPMI_SENSOR_READ_ERR_OUT_OF_MEMORY); goto cleanup; } if (ipmi_sensor_decode_value (r_exponent, b_exponent, m, b, linearization, analog_data_format, local_sensor_reading_raw, tmp_sensor_reading) < 0) { SENSOR_READ_SET_ERRNUM (ctx, IPMI_SENSOR_READ_ERR_INTERNAL_ERROR); goto cleanup; } *sensor_reading = tmp_sensor_reading; } rv = 1; } else if (event_reading_type_code_class == IPMI_EVENT_READING_TYPE_CODE_CLASS_OEM) /* nothing to do, sensor_event_bitmask already set */ rv = 1; else rv = 0; cleanup: fiid_obj_destroy (obj_cmd_rs); if (rv <= 0) free (tmp_sensor_reading); return (rv); }
int ipmi_sensors_simple_output (ipmi_sensors_state_data_t *state_data, uint8_t sensor_number, double *sensor_reading, int event_message_output_type, uint16_t sensor_event_bitmask, char **event_message_list, unsigned int event_message_list_len) { uint16_t record_id; uint8_t record_type; assert (state_data); assert (IPMI_SENSORS_EVENT_VALID (event_message_output_type)); if (ipmi_sdr_parse_record_id_and_type (state_data->sdr_ctx, NULL, 0, &record_id, &record_type) < 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 (!state_data->output_headers) { _output_headers (state_data); state_data->output_headers++; } switch (record_type) { case IPMI_SDR_FORMAT_FULL_SENSOR_RECORD: if (state_data->prog_data->args->legacy_output) return (_legacy_simple_output_full_record (state_data, record_id, sensor_reading, event_message_output_type, sensor_event_bitmask, event_message_list, event_message_list_len)); else if (state_data->prog_data->args->ipmimonitoring_legacy_output) return (_ipmimonitoring_legacy_simple_output_full_record (state_data, record_id, sensor_reading, event_message_output_type, sensor_event_bitmask, event_message_list, event_message_list_len)); else return (_simple_output_full_record (state_data, record_id, sensor_number, sensor_reading, event_message_output_type, sensor_event_bitmask, event_message_list, event_message_list_len)); case IPMI_SDR_FORMAT_COMPACT_SENSOR_RECORD: if (state_data->prog_data->args->legacy_output) return (_legacy_simple_output_compact_record (state_data, record_id, event_message_output_type, sensor_event_bitmask, event_message_list, event_message_list_len)); else if (state_data->prog_data->args->ipmimonitoring_legacy_output) return (_ipmimonitoring_legacy_simple_output_compact_record (state_data, record_id, event_message_output_type, sensor_event_bitmask, event_message_list, event_message_list_len)); else return (_simple_output_compact_record (state_data, record_id, sensor_number, event_message_output_type, sensor_event_bitmask, event_message_list, event_message_list_len)); default: /* don't output any other types in simple mode */ break; } return (0); }