summaryrefslogtreecommitdiff
path: root/util/oem_lenovo.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/oem_lenovo.c')
-rw-r--r--util/oem_lenovo.c365
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 */