summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZdenek Styblik <zdenek.styblik@gmail.com>2013-12-17 04:56:18 +0000
committerZdenek Styblik <zdenek.styblik@gmail.com>2013-12-17 04:56:18 +0000
commit2d7fe326874a9f151173619b7c714d12cb4d2880 (patch)
tree608c4539b9459c83754eedc686a41180c12762c4
parent3a852a884922494cc8daf56dbd6056bfd34f10c8 (diff)
downloadipmitool-2d7fe326874a9f151173619b7c714d12cb4d2880.tar.gz
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.
-rw-r--r--ipmitool/include/ipmitool/ipmi.h3
-rw-r--r--ipmitool/include/ipmitool/ipmi_sel.h51
-rw-r--r--ipmitool/lib/ipmi_sel.c146
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 */