--- ipmi-oem/src/ipmi-oem-fujitsu.h.ORIG 2010-08-15 20:18:44.000000000 +0200 +++ ipmi-oem/src/ipmi-oem-fujitsu.h 2010-08-15 22:08:23.000000000 +0200 @@ -36,4 +36,6 @@ int ipmi_oem_fujitsu_get_error_led (ipmi_oem_state_data_t *state_data); +int ipmi_oem_fujitsu_get_sel_entry_long_text (ipmi_oem_state_data_t *state_data); + #endif --- ipmi-oem/src/ipmi-oem-fujitsu.c.ORIG 2010-08-15 20:18:50.000000000 +0200 +++ ipmi-oem/src/ipmi-oem-fujitsu.c 2010-08-16 01:45:30.000000000 +0200 @@ -1290,3 +1292,193 @@ cleanup: return (rv); } + +#define IPMI_OEM_FUJITSU_SEL_NUMBER_MIN 1 +#define IPMI_OEM_FUJITSU_SEL_NUMBER_MAX 0xFFFE +#define min(a,b) ((a)<(b) ? (a) : (b)) + +int +ipmi_oem_fujitsu_get_sel_entry_long_text (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 sel_number; + uint16_t next_record_id, actual_record_id; + uint8_t record_type; + uint32_t timestamp; + uint8_t severity; + uint8_t data_len; + char *text; + int text_len; + const char *severity_text; + long tmp; + char *ptr; + int rv = -1; + struct tm tm; + char timestr[512]; + time_t t; + + assert (state_data); + assert (state_data->prog_data->args->oem_options_count == 1); + + tmp = strtol (state_data->prog_data->args->oem_options[0], + &ptr, + 0); + if (tmp < -1 + || tmp > UCHAR_MAX*UCHAR_MAX + || (*ptr) != '\0') + { + 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[0]); + goto cleanup; + } + + if (!((tmp >= IPMI_OEM_FUJITSU_SEL_NUMBER_MIN + && tmp <= IPMI_OEM_FUJITSU_SEL_NUMBER_MAX) || tmp == 0 || tmp == -1)) + { + pstdout_fprintf (state_data->pstate, + stderr, + "%s:%s invalid OEM option argument '%s' : out of range\n", + state_data->prog_data->args->oem_id, + state_data->prog_data->args->oem_command, + state_data->prog_data->args->oem_options[0]); + goto cleanup; + } + + if (tmp == -1) + tmp = 0xFFFF; + + sel_number = tmp; + + /* Fujitsu OEM + * + * http://manuals.ts.fujitsu.com/file/4390/irmc_s2-ug-en.pdf + * + * Request + * + * 0x2E - OEM network function + * 0xF5 - OEM cmd + * 0x?? - Fujitsu IANA (LSB first) + * 0x?? - Fujitsu IANA + * 0x?? - Fujitsu IANA + * 0x43 - Command Specifier + * 0x?? - Record ID (LSB first) + * 0x?? - Record ID ; 0x0000 = "first record", 0xFFFF = "last record" + * 0x?? - Offset (in response SEL text) + * 0x?? - MaxResponseDataSize (size of converted SEL data 16:n in response, maximum is 100) + * + * Response + * + * 0xF5 - OEM cmd + * 0x?? - Completion code + * 0x?? - Fujitsu IANA (LSB first) + * 0x?? - Fujitsu IANA + * 0x?? - Fujitsu IANA + * 0x?? - Next Record ID (LSB) + * 0x?? - Next Record ID (MSB) + * 0x?? - Actual Record ID (LSB) + * 0x?? - Actual Record ID (MSB) + * 0x?? - Record type + * 0x?? - timestamp (LSB first) + * 0x?? - timestamp + * 0x?? - timestamp + * 0x?? - timestamp + * 0x?? - severity + * bit 7 - CSS component + * bit 6-4 - 000 = INFORMATIONAL + * 001 = MINOR + * 010 = MAJOR + * 011 = CRITICAL + * 1xx = unknown + * bit 3-0 - reserved + * 0x?? - data length (of the whole text) + * 0x?? - converted SEL data + requested number of bytes starting at requested offset (MaxResponseDataSize-1 bytes of data) + ..... + * 0x00 - trailing '\0' character + */ + + bytes_rq[0] = IPMI_CMD_OEM_FUJITSU_SYSTEM; + bytes_rq[1] = (IPMI_IANA_ENTERPRISE_ID_FUJITSU & 0x0000FF); + bytes_rq[2] = (IPMI_IANA_ENTERPRISE_ID_FUJITSU & 0x00FF00) >> 8; + bytes_rq[3] = (IPMI_IANA_ENTERPRISE_ID_FUJITSU & 0xFF0000) >> 16; + bytes_rq[4] = IPMI_OEM_FUJITSU_COMMAND_SPECIFIER_GET_SEL_ENTRY_LONG_TEXT; + bytes_rq[5] = (sel_number & 0x00FF); + bytes_rq[6] = (sel_number & 0xFF00) >> 8; + bytes_rq[7] = 0; + bytes_rq[8] = min(IPMI_OEM_MAX_BYTES-17, 100); + + if ((rs_len = ipmi_cmd_raw (state_data->ipmi_ctx, + 0, /* lun */ + IPMI_NET_FN_OEM_GROUP_RQ, /* network function */ + bytes_rq, /* data */ + 9, /* 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, + 21, + IPMI_CMD_OEM_FUJITSU_SYSTEM, + IPMI_NET_FN_OEM_GROUP_RS, + NULL) < 0) + goto cleanup; + + next_record_id = bytes_rs[5] + (bytes_rs[6] << 8); + actual_record_id = bytes_rs[7] + (bytes_rs[8] << 8); + record_type = bytes_rs[9]; + timestamp = bytes_rs[10] + (bytes_rs[11] << 8) + (bytes_rs[12] << 16) + (bytes_rs[13] << 24); + severity = bytes_rs[14]; + data_len = bytes_rs[15]; + text = (char *)&(bytes_rs[16]); + bytes_rs[IPMI_OEM_MAX_BYTES-1]='\0'; + + text_len = strlen(text); + + switch (severity >> 3) { + case 0: severity_text = "INFORMATIONAL:"; break; + case 1: severity_text = "MINOR:"; break; + case 2: severity_text = "MAJOR:"; break; + case 3: severity_text = "CRITICAL:"; break; + case 4: + case 5: + case 6: + case 7: severity_text = ""; break; + case 8: severity_text = "INFORMATIONAL/CSS:"; break; + case 9: severity_text = "MINOR/CSS:"; break; + case 10: severity_text = "MAJOR/CSS:"; break; + case 11: severity_text = "CRITICAL/CSS:"; break; + case 12: + case 13: + case 14: + case 15: severity_text = "unknown/CSS:"; break; + } + + memset(&tm, 0, sizeof(tm)); + t = timestamp; + localtime_r(&t, &tm); + strftime(timestr, sizeof(timestr), "%b-%d-%Y | %H:%M:%S", &tm); + + pstdout_printf (state_data->pstate, + "%u | %s | %s %s%s\n", + (int)actual_record_id, + timestr, + severity_text, text, data_len == text_len ? "" : " ... (text incomplete)"); + rv = 0; + cleanup: + return (rv); +} + --- ipmi-oem/src/ipmi-oem.c.ORIG 2010-08-15 22:05:39.000000000 +0200 +++ ipmi-oem/src/ipmi-oem.c 2010-08-15 22:10:31.000000000 +0200 @@ -431,6 +431,13 @@ ipmi_oem_fujitsu_get_error_led }, { + "get-sel-entry-long-text", + "", + 1, + IPMI_OEM_COMMAND_FLAGS_DEFAULT, + ipmi_oem_fujitsu_get_sel_entry_long_text + }, + { NULL, NULL, 0,