diff --git a/ipmitool/ChangeLog b/ipmitool/ChangeLog index ddaaeb2..d6e387b 100644 --- a/ipmitool/ChangeLog +++ b/ipmitool/ChangeLog @@ -4,6 +4,7 @@ version 1.8.7 * Increase argument size for raw commands in shell/exec * Fix handling of LUNs for LAN interfaces * Add IPMIv2 SOL loopback test + * Add support for IBM OEM SEL messages version 1.8.6 * Fix memory corruption when sending encrypted SOL traffic diff --git a/ipmitool/lib/ipmi_oem.c b/ipmitool/lib/ipmi_oem.c index 4807e14..8fc0863 100644 --- a/ipmitool/lib/ipmi_oem.c +++ b/ipmitool/lib/ipmi_oem.c @@ -37,6 +37,7 @@ #include static int ipmi_oem_supermicro(struct ipmi_intf * intf); +static int ipmi_oem_ibm(struct ipmi_intf * intf); static struct ipmi_oem_handle ipmi_oem_list[] = { { @@ -56,6 +57,11 @@ static struct ipmi_oem_handle ipmi_oem_list[] = { name: "icts", desc: "IPMI 2.0 ICTS compliance support", }, + { + name: "ibm", + desc: "IBM OEM support", + setup: ipmi_oem_ibm, + }, { 0 }, }; @@ -67,6 +73,13 @@ ipmi_oem_supermicro(struct ipmi_intf * intf) return 0; } +static int +ipmi_oem_ibm(struct ipmi_intf * intf) +{ + ipmi_oem_ibm_init(); + return 0; +} + /* ipmi_oem_print - print list of OEM handles */ void diff --git a/ipmitool/lib/ipmi_sel.c b/ipmitool/lib/ipmi_sel.c index 095459e..b656d7d 100644 --- a/ipmitool/lib/ipmi_sel.c +++ b/ipmitool/lib/ipmi_sel.c @@ -49,6 +49,148 @@ extern int verbose; static int sel_extended = 0; +static FILE * fp; +static int oem_ibm_nrecs = 0; +struct ipmi_oem_ibm_msg_rec { + int value[14]; + char *string[14]; + char *text; +} *oem_ibm_msg; + +#define SEL_BYTE(n) (n-3) /* So we can refer to byte positions in log entries (byte 3 is at index 0, etc) */ + +/* + * Reads values found in message translation file. XX is a wildcard, R means reserved. + * Returns -1 for XX, -2 for R, -3 for non-hex (string), or positive integer from a hex value. + */ +static int ipmi_oem_ibm_readval(char *str) +{ + int ret; + if (!strcmp(str, "XX")) { + return -1; + } + if (!strcmp(str, "R")) { + return -2; + } + if (sscanf(str, "0x%x", &ret) != 1) { + return -3; + } + return ret; +} + +/* + * This is where the magic happens. SEL_BYTE is a bit ugly, but it allows + * reference to byte positions instead of array indexes which (hopefully) + * helps make the code easier to read. + */ +static int ipmi_oem_ibm_match(uint8_t *evt, struct ipmi_oem_ibm_msg_rec rec) +{ + if (evt[2] == rec.value[SEL_BYTE(3)] && + ((rec.value[SEL_BYTE(4)] < 0) || (evt[3] == rec.value[SEL_BYTE(4)])) && + ((rec.value[SEL_BYTE(5)] < 0) || (evt[4] == rec.value[SEL_BYTE(5)])) && + ((rec.value[SEL_BYTE(6)] < 0) || (evt[5] == rec.value[SEL_BYTE(6)])) && + ((rec.value[SEL_BYTE(7)] < 0) || (evt[6] == rec.value[SEL_BYTE(7)])) && + ((rec.value[SEL_BYTE(11)] < 0) || (evt[10] == rec.value[SEL_BYTE(11)])) && + ((rec.value[SEL_BYTE(12)] < 0) || (evt[11] == rec.value[SEL_BYTE(12)]))) { + return 1; + } else { + return 0; + } +} + +void ipmi_oem_ibm_init(void) +{ + FILE * fp; + int i, j, k, n, byte; + char *filename; + char buf[15][150]; + + if ((filename = getenv("IPMI_OEM_IBM_DATAFILE")) == NULL) { + printf ("Unable to read IPMI_OEM_IBM_DATAFILE from environment\n"); + return; + } + + fp = fopen(filename, "r"); + if (fp == NULL) { + printf ("could not open %s file\n", filename); + return; + } + + /* count number of records (lines) in input file */ + oem_ibm_nrecs = 0; + while (fscanf(fp, "%*[^\n]\n", buf[0]) == 0) { + oem_ibm_nrecs++; + } + + rewind(fp); + oem_ibm_msg = (struct ipmi_oem_ibm_msg_rec *)calloc(oem_ibm_nrecs, + sizeof(struct ipmi_oem_ibm_msg_rec)); + + for (i=0; i < oem_ibm_nrecs; i++) { + n=fscanf(fp, "\"%[^\"]\",\"%[^\"]\",\"%[^\"]\",\"%[^\"]\",\"" + "%[^\"]\",\"%[^\"]\",\"%[^\"]\",\"%[^\"]\",\"" + "%[^\"]\",\"%[^\"]\",\"%[^\"]\",\"%[^\"]\",\"" + "%[^\"]\",\"%[^\"]\",\"%[^\"]\"\n", + buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], + buf[6], buf[7], buf[8], buf[9], buf[10], buf[11], + buf[12], buf[13], buf[14]); + + if (n != 15) { + printf ("Encountered problems reading line %d of %s\n", + i+1, filename); + fclose(fp); + fp = NULL; + oem_ibm_nrecs = 0; + /* free all the memory allocated so far */ + for (j=0; jsel_type.oem_nots_type.oem_defined[data_count]); } + ipmi_oem_ibm_message(evt, 0); printf ("\n"); return; } @@ -912,6 +1054,7 @@ ipmi_sel_print_std_entry_verbose(struct ipmi_intf * intf, struct sel_event_recor for(data_count=0;data_count < SEL_OEM_NOTS_DATA_LEN;data_count++) printf("%02x", evt->sel_type.oem_nots_type.oem_defined[data_count]); printf(" [%s]\n\n",hex2ascii (evt->sel_type.oem_nots_type.oem_defined, SEL_OEM_NOTS_DATA_LEN)); + ipmi_oem_ibm_message(evt, 1); } return; }