diff options
Diffstat (limited to 'util/oem_lenovo.c')
-rw-r--r-- | util/oem_lenovo.c | 365 |
1 files changed, 365 insertions, 0 deletions
diff --git a/util/oem_lenovo.c b/util/oem_lenovo.c new file mode 100644 index 0000000..9c5079f --- /dev/null +++ b/util/oem_lenovo.c @@ -0,0 +1,365 @@ +/* + * oem_lenovo.c + * Handle Lenovo OEM command functions + * + * Author: Andy Cress arcress at users.sourceforge.net + * Change history: + * 11/21/2016 ARCress - created + * + *--------------------------------------------------------------------- + */ +/*M* +Copyright (c) 2016 Andy Cress +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + a.. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + b.. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + c.. Neither the name of the copyright holder nor the names of contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *M*/ +#ifdef WIN32 +#include <windows.h> +#include "getopt.h" +#else +#if defined(HPUX) +/* getopt is defined in stdio.h */ +#elif defined(MACOS) +/* getopt is defined in unistd.h */ +#include <unistd.h> +#include <sys/time.h> +#else +#include <getopt.h> +#endif +#endif +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include "ipmicmd.h" +#include "ievents.h" +#include "oem_lenovo.h" + +void set_loglevel(int level); /*prototype */ + +static char * progver = "3.01"; +static char * progname = "ioemlenovo"; +static int verbose = 0; +static char fdebug = 0; +static uchar g_bus = PUBLIC_BUS; +static uchar g_sa = BMC_SA; +static uchar g_lun = BMC_LUN; +static uchar g_addrtype = ADDR_SMI; +static int vend_id = 0; +static int prod_id = 0; + +extern uchar bitnum(ushort value); /*isensor.c*/ + +/* + * decode_sensor_lenovo + * inputs: + * sdr = the SDR buffer + * reading = the 3 or 4 bytes of data from GetSensorReading + * pstring = points to the output string buffer + * slen = size of the output buffer + * outputs: + * rv = 0 if this sensor was successfully interpreted here, + * non-zero otherwise, to use default interpretations. + * pstring = contains the sensor reading interpretation string (if rv==0) + */ +int decode_sensor_lenovo(uchar *sdr,uchar *reading,char *pstring, int slen) +{ + int rv = -1; + uchar stype, etype, entity; + uchar bval; + ushort rval; + char *pstr = NULL; + int b; + + if (sdr == NULL || reading == NULL) return(rv); + if (pstring == NULL || slen == 0) return(rv); + /* sdr[3] is 0x01 for Full, 0x02 for Compact */ + bval = reading[2]; + if (sdr[3] == 0x01) return(rv); /*skip if full sensor*/ + entity = sdr[8]; + stype = sdr[12]; + etype = sdr[13]; + rval = reading[2] | ((reading[3] & 0x7f) << 8); + b = bitnum(rval); + if (fdebug) printf("oem_lenovo: sensor type=%x evt=%x entity=%x rval=%04x\n", + stype,etype,entity,rval); + switch(stype) { + case 0x07: /* All CPUs */ + if (etype == 0x6F) { + switch(b) { + case 0x00: pstr = "OK"; break; + case 0x02: pstr = "BIST_Fail"; break; + case 0x05: pstr = "Config_Error"; break; + case 0x06: pstr = "Uncorr_Error"; break; + case 0x08: pstr = "Disabled"; break; + default: pstr = "OK*"; break; + } + snprintf(pstring,slen,"%04x %s",bval,pstr); + rv = 0; + } + break; + case 0x0F: /* ABR Status, Firmware Error, Sys Boot Status, etc. */ + if (etype == 0x6F) { /* should be entity 0x22 */ + if (bval == 0x00) pstr = "OK"; + else if (bval & 0x01) pstr = "FirmwareError"; /*bit 0*/ + else if ((bval & 0x02) != 0) pstr = "FirmwareHang"; /*bit 1*/ + else pstr = "OK*"; + snprintf(pstring,slen,"%04x %s",bval,pstr); + rv = 0; + } + break; + case 0x1B: /* Front USB, nvDIMM Cable, etc. */ + if (etype == 0x6F) { + /* 0x01 = connected/OK, 0x02 = cable connect error */ + switch(bval) { + case 0x01: pstr = "OK"; break; + case 0x02: pstr = "CableError"; break; + default: pstr = "OK*"; break; + } + snprintf(pstring,slen,"%04x %s",rval,pstr); + rv = 0; + } + break; + case 0x1E: /* No Boot Device */ + if (etype == 0x6F) { + switch(b) { + case 0x00: pstr = "OK"; break; /*No Media*/ + default: pstr = "Asserted"; break; + } + snprintf(pstring,slen,"%04x %s",rval,pstr); + rv = 0; + } + case 0x21: /*All PCI Error, PCI 1, Internal RAID, No Op ROM, etc.*/ + if (etype == 0x6F) { + if (bval == 0x00) pstr = "OK"; + else pstr = "Fault"; + snprintf(pstring,slen,"%04x %s",bval,pstr); + rv = 0; + } + break; + case 0x25: /* DASD Backplane*/ + /*spec says 00 = Present, 01 = Absent, but not match results*/ + /* +0066 SDR Comp 02 6f 20 a 25 snum 20 DASD Backplane 1 = 0001 OK* +0067 SDR Comp 02 6f 20 a 25 snum 21 DASD Backplane 2 = 0000 Absent +0068 SDR Comp 02 6f 20 a 25 snum 22 DASD Backplane 3 = 0000 Absent +0069 SDR Comp 02 6f 20 a 25 snum 23 DASD Backplane 4 = 0000 Absent +006a SDR Comp 02 6f 20 a 25 snum 24 DASD Backplane 5 = 0000 Absent +006b SDR Comp 02 6f 20 a 25 snum 25 DASD Backplane 6 = 0000 Absent + */ + rv = -1; + break; + case 0x2B: /* ROM Recovery, Bkup Auto Update, IMM*/ + if (etype == 0x6F) { + switch(bval) { + case 0x00: pstr = "OK"; break; + case 0x01: pstr = "Changed"; break; /*entity 0x22*/ + case 0x05: pstr = "Invalid"; break; /*entity 0x21*/ + case 0x07: pstr = "ChangedOK"; break; /*entity 21,22*/ + default: pstr = "_"; break; + } + snprintf(pstring,slen,"%04x %s",rval,pstr); + rv = 0; + } + break; + case 0x02: /* SysBrd Vol Fault: et 07 8004=error */ + if (etype == 0x07) { + if ((bval & 0x04) != 0) pstr = "Faulty"; + else pstr = "OK"; + snprintf(pstring,slen,"%04x %s",bval,pstr); + rv = 0; + } + break; + case 0x28: /* Low Security Jmp et 08 8002=error*/ + if (etype == 0x08) { + if ((bval & 0x02) != 0) pstr = "Faulty"; + else pstr = "OK"; + snprintf(pstring,slen,"%04x %s",bval,pstr); + rv = 0; + } + break; + default: break; + } + // if (rv == 0) strncpy(pstring, pstr, slen); + return(rv); +} + +/* + * decode_sel_lenovo + * inputs: + * evt = the 16-byte IPMI SEL event + * outbuf = points to the output string buffer + * outsz = size of the output buffer + * outputs: + * rv = 0 if this event was successfully interpreted here, + * non-zero otherwise, to use default interpretations. + * outbuf = will contain the interpreted event text string (if rv==0) + */ +int decode_sel_lenovo(uchar *evt, char *outbuf, int outsz, char fdesc, + char fdbg) +{ + int rv = -1; + ushort id; + uchar rectype; + ulong timestamp; + char mybuf[64]; + char *type_str = ""; + char *pstr = NULL; + int sevid; + ushort genid; + uchar snum; + uchar data1, data2, data3; + + fdebug = fdbg; + sevid = SEV_INFO; + id = evt[0] + (evt[1] << 8); + rectype = evt[2]; + snum = evt[11]; + timestamp = evt[3] + (evt[4] << 8) + (evt[5] << 16) + (evt[6] << 24); + genid = evt[7] | (evt[8] << 8); + data1 = evt[13]; + data2 = evt[14]; + data3 = evt[15]; + if (rectype == 0x02) + { + sprintf(mybuf,"%02x [%02x %02x %02x]", evt[12],data1,data2,data3); + switch(evt[10]) { /*sensor type*/ + case 0xC0: /* OEM type */ + type_str = "OEM_type"; + pstr = "OEM Sensor "; + sevid = SEV_MAJ; + rv = -1; + break; + default: /*other sensor types*/ + break; + } + } + if (rv == 0) { + format_event(id,timestamp, sevid, genid, type_str, + snum,NULL,pstr,mybuf,outbuf,outsz); + } + return(rv); +} + +static void usage(void) +{ + printf("Usage: %s <command> [arg]\n",progname); + printf("These commands may not work on all Lenovo systems\n"); +} + +static int ipmi_oemlenovo_main(int argc, char **argv) +{ + int rv = 0; + + if (strncmp(argv[0],"other",9) == 0) { + usage(); + rv = ERR_USAGE; + } else { + usage(); + rv = ERR_USAGE; + } + return(rv); +} + +#ifdef METACOMMAND +int i_oemlenovo(int argc, char **argv) +#else +#ifdef WIN32 +int __cdecl +#else +int +#endif +main(int argc, char **argv) +#endif +{ + int rv = 0; + uchar devrec[16]; + int c, i; + char *s1; + + printf("%s ver %s\n", progname,progver); + set_loglevel(LOG_NOTICE); + parse_lan_options('V',"4",0); /*default to admin priv*/ + + while ( (c = getopt( argc, argv,"m:xzEF:J:N:P:R:T:U:V:YZ:?")) != EOF ) + switch(c) { + case 'm': /* specific IPMB MC, 3-byte address, e.g. "409600" */ + g_bus = htoi(&optarg[0]); /*bus/channel*/ + g_sa = htoi(&optarg[2]); /*device slave address*/ + g_lun = htoi(&optarg[4]); /*LUN*/ + g_addrtype = ADDR_IPMB; + if (optarg[6] == 's') { + g_addrtype = ADDR_SMI; s1 = "SMI"; + } else { g_addrtype = ADDR_IPMB; s1 = "IPMB"; } + ipmi_set_mc(g_bus,g_sa,g_lun,g_addrtype); + printf("Use MC at %s bus=%x sa=%x lun=%x\n", + s1,g_bus,g_sa,g_lun); + break; + case 'x': fdebug = 2; /* normal (dbglog if isol) */ + verbose = 1; + break; + case 'z': fdebug = 3; /*full debug (for isol)*/ + verbose = 1; + break; + case 'N': /* nodename */ + case 'U': /* remote username */ + case 'P': /* remote password */ + case 'R': /* remote password */ + case 'E': /* get password from IPMI_PASSWORD environment var */ + case 'F': /* force driver type */ + case 'T': /* auth type */ + case 'J': /* cipher suite */ + case 'V': /* priv level */ + case 'Y': /* prompt for remote password */ + case 'Z': /* set local MC address */ + parse_lan_options(c,optarg,fdebug); + break; + default: + usage(); + return(ERR_USAGE); + break; + } + for (i = 0; i < optind; i++) { argv++; argc--; } + if (argc == 0) { + usage(); + return(ERR_USAGE); + } + + rv = ipmi_getdeviceid(devrec,16,fdebug); + if (rv == 0) { + char ipmi_maj, ipmi_min; + ipmi_maj = devrec[4] & 0x0f; + ipmi_min = devrec[4] >> 4; + vend_id = devrec[6] + (devrec[7] << 8) + (devrec[8] << 16); + prod_id = devrec[9] + (devrec[10] << 8); + show_devid( devrec[2], devrec[3], ipmi_maj, ipmi_min); + } + + rv = ipmi_oemlenovo_main(argc, argv); + + ipmi_close_(); + return(rv); +} +/* end oem_lenovo.c */ |