/* 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_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); }