From 2d7fe326874a9f151173619b7c714d12cb4d2880 Mon Sep 17 00:00:00 2001 From: Zdenek Styblik Date: Tue, 17 Dec 2013 04:56:18 +0000 Subject: [PATCH] ID: 85 - Supermicro memory ecc error display Commit adds memory ECC error display for Supermicro boards and adds a Supermicro oem sensor type for SEL. --- ipmitool/include/ipmitool/ipmi.h | 3 +- ipmitool/include/ipmitool/ipmi_sel.h | 51 ++++++++++ ipmitool/lib/ipmi_sel.c | 146 ++++++++++++++++++++++++++- 3 files changed, 196 insertions(+), 4 deletions(-) diff --git a/ipmitool/include/ipmitool/ipmi.h b/ipmitool/include/ipmitool/ipmi.h index e74c252..1fd3e2a 100644 --- a/ipmitool/include/ipmitool/ipmi.h +++ b/ipmitool/include/ipmitool/ipmi.h @@ -281,7 +281,8 @@ typedef enum IPMI_OEM { IPMI_OEM_KONTRON = 15000, IPMI_OEM_PPS = 16394, IPMI_OEM_AMI = 20974, - IPMI_OEM_NOKIA_SIEMENS_NETWORKS = 28458 + IPMI_OEM_NOKIA_SIEMENS_NETWORKS = 28458, + IPMI_OEM_SUPERMICRO_47488 = 47488 } IPMI_OEM; extern const struct valstr completion_code_vals[]; diff --git a/ipmitool/include/ipmitool/ipmi_sel.h b/ipmitool/include/ipmitool/ipmi_sel.h index 3077eb9..a125f85 100644 --- a/ipmitool/include/ipmitool/ipmi_sel.h +++ b/ipmitool/include/ipmitool/ipmi_sel.h @@ -107,6 +107,7 @@ struct standard_spec_sel_rec{ #define SENSOR_TYPE_OEM_NFATAL_ERROR 0xC2 #define SENSOR_TYPE_OEM_FATAL_ERROR 0xC3 #define SENSOR_TYPE_TXT_CMD_ERROR 0x20 +#define SENSOR_TYPE_SUPERMICRO_OEM 0xD0 /* End of Macro for DELL Specific */ #define SEL_OEM_TS_DATA_LEN 6 #define SEL_OEM_NOTS_DATA_LEN 13 @@ -676,6 +677,56 @@ static struct ipmi_event_sensor_types sensor_specific_types[] __attribute__((unu { 0x00, 0x00, 0x00, 0x00, NULL, NULL }, }; +static uint16_t supermicro_x9dal[] = { + 0x0635 +}; + +static uint16_t supermicro_x9db[] = { + 0x0733, 0x0722, 0x0703, 0x0721, 0x0716, 0x0637 +}; + +static uint16_t supermicro_x9sb[] = { + 0x0651 +}; + +static uint16_t supermicro_x9[] = { + 0x0635, 0x0733, 0x0722, 0x0703, 0x0721, 0x0716, 0x0637, 0x0651 +}; + +static uint16_t supermicro_b8[] = { + 0x000A, 0x061c, 0x0620, 0x0101, 0x061f, 0x0612, 0x061e +}; + +static uint16_t supermicro_h8[] = { + 0xa111, 0x0408, 0x0811, 0x1411, 0x0911, 0x1211, 0x1011, 0xcd11, 0x1111, 0xbe11, 0xce11, 0xbd11, + 0xbc11, 0xa911, 0xaa11, 0xbd11, 0xcb11, 0xad11, 0xa811, 0xac11, 0xaf11, 0xa511, 0xa011, 0x1611, + 0x2511, 0xbf11, 0x1511, 0x2211, 0x2411, 0x1911, 0xab11, 0xd011, 0xae11, 0xca11, 0x0409, 0xa211, + 0xa311, 0x1311, 0xba11, 0xa711, 0xd111, 0x1711, 0xcf11, 0x2011, 0x1811 +}; + +static uint16_t supermicro_p8[] = { + 0x6480, 0x7380, 0x6280, 0x7480, 0x5980 +}; + +static uint16_t supermicro_x8[] = { + 0xa880, 0x0403, 0x0100, 0x0601, 0x0001, 0x0404, 0x0606, 0x0608, 0x0632, 0x0400, 0x0401, 0x0006, + 0x040a, 0xf280, 0x060f, 0x0609, 0x0008, 0x0613, 0x061b, 0x0007, 0x0600, 0x060c, 0x060d, 0x0614, + 0x060c, 0x0003, 0x040b, 0x0621, 0x0610, 0x0638, 0xf380, 0x060b, 0x040d, 0x0605, 0x062d, 0x060e, + 0x061a, 0xf580, 0x062e, 0x0009 +}; + +static uint16_t supermicro_X8[] = { + 0x000A, 0x061c, 0x0620, 0x0101, 0x061f, 0x0612, 0x061e, 0xa111, 0x0408, 0x0811, 0x1411, 0x0911, + 0x1211, 0x1011, 0xcd11, 0x1111, 0xbe11, 0xce11, 0xbd11, 0xbc11, 0xa911, 0xaa11, 0xbd11, 0xcb11, + 0xad11, 0xa811, 0xac11, 0xaf11, 0xa511, 0xa011, 0x1611, 0x2511, 0xbf11, 0x1511, 0x2211, 0x2411, + 0x1911, 0xab11, 0xd011, 0xae11, 0xca11, 0x0409, 0xa211, 0xa311, 0x1311, 0xba11, 0xa711, 0xd111, + 0x1711, 0xcf11, 0x2011, 0x1811, 0x6480, 0x7380, 0x6280, 0x7480, 0x5980, 0xa880, 0x0403, 0x0100, + 0x0601, 0x0001, 0x0404, 0x0606, 0x0608, 0x0632, 0x0400, 0x0401, 0x0006, 0x040a, 0xf280, 0x060f, + 0x0609, 0x0008, 0x0613, 0x061b, 0x0007, 0x0600, 0x060c, 0x060d, 0x0614, 0x060c, 0x0003, 0x040b, + 0x0621, 0x0610, 0x0638, 0xf380, 0x060b, 0x040d, 0x0605, 0x062d, 0x060e, 0x061a, 0xf580, 0x062e, + 0x0009 +}; + int ipmi_sel_main(struct ipmi_intf *, int, char **); void ipmi_sel_print_std_entry(struct ipmi_intf * intf, struct sel_event_record * evt); void ipmi_sel_print_std_entry_verbose(struct ipmi_intf * intf, struct sel_event_record * evt); diff --git a/ipmitool/lib/ipmi_sel.c b/ipmitool/lib/ipmi_sel.c index b06a81a..63ecbcf 100644 --- a/ipmitool/lib/ipmi_sel.c +++ b/ipmitool/lib/ipmi_sel.c @@ -322,7 +322,6 @@ ipmi_get_oem(struct ipmi_intf * intf) return IPM_DEV_MANUFACTURER_ID(devid->manufacturer_id); } - static int ipmi_sel_add_entry(struct ipmi_intf * intf, struct sel_event_record * rec) { @@ -526,6 +525,115 @@ get_newisys_evt_desc(struct ipmi_intf * intf, struct sel_event_record * rec) return description; } +char * +get_supermicro_evt_desc(struct ipmi_intf *intf, struct sel_event_record *rec) +{ + struct ipmi_rs *rsp; + struct ipmi_rq req; + char *desc = NULL; + char *str; + int chipset_type = 1; + int data1; + int data2; + int data3; + int length; + int sensor_type; + uint8_t i = 0; + uint16_t oem_id = 0; + /* Get the OEM event Bytes of the SEL Records byte 13, 14, 15 to + * data1,data2,data3 + */ + data1 = rec->sel_type.standard_type.event_data[0]; + data2 = rec->sel_type.standard_type.event_data[1]; + data3 = rec->sel_type.standard_type.event_data[2]; + /* Check for the Standard Event type == 0x6F */ + if (rec->sel_type.standard_type.event_type != 0x6F) { + return NULL; + } + /* Allocate mem for te Description string */ + desc = (char *)malloc(SIZE_OF_DESC); + if (desc == NULL) { + lprintf(LOG_ERR, "ipmitool: malloc failure"); + return NULL; + } + memset(desc,0,SIZE_OF_DESC); + sensor_type = rec->sel_type.standard_type.sensor_type; + switch (sensor_type) { + case SENSOR_TYPE_MEMORY: + memset(&req, 0, sizeof (req)); + req.msg.netfn = IPMI_NETFN_APP; + req.msg.lun = 0; + req.msg.cmd = BMC_GET_DEVICE_ID; + req.msg.data = NULL; + req.msg.data_len = 0; + + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + lprintf(LOG_ERR, " Error getting system info"); + if (desc != NULL) { + free(desc); + desc = NULL; + } + return NULL; + } else if (rsp->ccode > 0) { + lprintf(LOG_ERR, " Error getting system info: %s", + val2str(rsp->ccode, completion_code_vals)); + if (desc != NULL) { + free(desc); + desc = NULL; + } + return NULL; + } + /* check the chipset type */ + oem_id = ipmi_get_oem_id(intf); + if (oem_id == 0) { + return NULL; + } + length = sizeof(supermicro_X8); + for (i = 0; i < length; i++) { + if (oem_id == supermicro_X8[i]) { + chipset_type = 0; + break; + } + } + length = sizeof(supermicro_x9); + for (i = 0; i < length; i++) { + if (oem_id == supermicro_x9[i]) { + chipset_type = 2; + break; + } + } + if (chipset_type == 0) { + snprintf(desc, SIZE_OF_DESC, "@DIMM%2X(CPU%x)", + data2, + (data3 & 0x03) + 1); + } else if (chipset_type == 1) { + snprintf(desc, SIZE_OF_DESC, "@DIMM%c%c(CPU%x)", + (data2 >> 4) + 0x40 + (data3 & 0x3) * 4, + (data2 & 0xf) + 0x27, (data3 & 0x03) + 1); + } else if (chipset_type == 2) { + snprintf(desc, SIZE_OF_DESC, "@DIMM%c%c(CPU%x)", + (data2 >> 4) + 0x40 + (data3 & 0x3) * 3, + (data2 & 0xf) + 0x27, (data3 & 0x03) + 1); + } else { + snprintf(desc, SIZE_OF_DESC, ""); + } + break; + case SENSOR_TYPE_SUPERMICRO_OEM: + if (data1 == 0x80 && data3 == 0xFF) { + if (data2 == 0x0) { + snprintf(desc, SIZE_OF_DESC, "BMC unexpected reset"); + } else if (data2 == 0x1) { + snprintf(desc, SIZE_OF_DESC, "BMC cold reset"); + } else if (data2 == 0x2) { + snprintf(desc, SIZE_OF_DESC, "BMC warm reset"); + } + } + break; + } + return desc; +} + /* * Function : Decoding the SEL OEM Bytes for the DELL Platforms. * Description : The below fucntion will decode the SEL Events OEM Bytes for the Dell specific Sensors only. @@ -1067,6 +1175,10 @@ ipmi_get_oem_desc(struct ipmi_intf * intf, struct sel_event_record * rec) case IPMI_OEM_DELL: // Dell Decoding of the OEM Bytes from SEL Record. desc = get_dell_evt_desc(intf, rec); break; + case IPMI_OEM_SUPERMICRO: + case IPMI_OEM_SUPERMICRO_47488: + desc = get_supermicro_evt_desc(intf, rec); + break; case IPMI_OEM_UNKNOWN: default: break; @@ -1092,7 +1204,6 @@ ipmi_get_event_desc(struct ipmi_intf * intf, struct sel_event_record * rec, char *desc = ipmi_get_oem_desc(intf, rec); return; } else if (rec->sel_type.standard_type.event_type == 0x6f) { - if( rec->sel_type.standard_type.sensor_type >= 0xC0 && rec->sel_type.standard_type.sensor_type < 0xF0) { IPMI_OEM iana = ipmi_get_oem(intf); @@ -1116,12 +1227,27 @@ ipmi_get_event_desc(struct ipmi_intf * intf, struct sel_event_record * rec, char sfx = ipmi_get_oem_desc(intf, rec); } break; + case IPMI_OEM_SUPERMICRO: + case IPMI_OEM_SUPERMICRO_47488: + evt = sensor_specific_types; + code = rec->sel_type.standard_type.sensor_type; + sfx = ipmi_get_oem_desc(intf, rec); + break; /* add your oem sensor assignation here */ } if( evt == NULL ){ lprintf(LOG_DEBUG, "oem sensor type %x using standard type supplied description", rec->sel_type.standard_type.sensor_type ); } + } else { + switch (ipmi_get_oem(intf)) { + case IPMI_OEM_SUPERMICRO: + case IPMI_OEM_SUPERMICRO_47488: + evt = sensor_specific_types; + code = rec->sel_type.standard_type.sensor_type; + sfx = ipmi_get_oem_desc(intf, rec); + break; + } } if( evt == NULL ){ evt = sensor_specific_types; @@ -1210,6 +1336,9 @@ ipmi_get_event_desc(struct ipmi_intf * intf, struct sel_event_record * rec, char if(0x01 == offset) flag = 0x01; break; + case SENSOR_TYPE_SUPERMICRO_OEM: + flag = 0x02; + break; default: break; } @@ -1222,6 +1351,10 @@ ipmi_get_event_desc(struct ipmi_intf * intf, struct sel_event_record * rec, char return; } memset(*desc, 0, 48 + SIZE_OF_DESC); + if (flag == 0x02) { + sprintf(*desc, "%s", sfx); + return; + } sprintf(*desc, "(%s)",sfx); } free(sfx); @@ -1776,10 +1909,17 @@ ipmi_sel_print_std_entry(struct ipmi_intf * intf, struct sel_event_record * evt) } } else if (evt->sel_type.standard_type.event_type == 0x6f) { + int print_sensor = 1; + switch (ipmi_get_oem(intf)) { + case IPMI_OEM_SUPERMICRO: + case IPMI_OEM_SUPERMICRO_47488: + print_sensor = 0; + break; + } /* * Sensor-Specific Discrete */ - if (evt->sel_type.standard_type.sensor_type == 0xC && + if (print_sensor && evt->sel_type.standard_type.sensor_type == 0xC && /*TODO*/ evt->sel_type.standard_type.sensor_num == 0 && (evt->sel_type.standard_type.event_data[0] & 0x30) == 0x20) { /* break down memory ECC reporting if we can */