diff options
| author | Jörg Frings-Fürst <debian@jff.email> | 2023-03-15 20:36:27 +0100 | 
|---|---|---|
| committer | Jörg Frings-Fürst <debian@jff.email> | 2023-03-15 20:36:27 +0100 | 
| commit | d602f4fb516292c297072bd924289eea37b45fa2 (patch) | |
| tree | 7c30ed558709e44b7a9cbb6b9558b744c880a796 /util | |
| parent | 19b878add9337a1328f974d685c1b236e126e91a (diff) | |
New upstream version 3.1.9upstream/3.1.9
Diffstat (limited to 'util')
| -rw-r--r-- | util/Makefile.in | 5 | ||||
| -rw-r--r-- | util/ievents.c | 2 | ||||
| -rw-r--r-- | util/igetevent.c | 2 | ||||
| -rw-r--r-- | util/ipmiutil.c | 2 | ||||
| -rw-r--r-- | util/ireset.c | 2 | ||||
| -rw-r--r-- | util/isensor.c | 10 | ||||
| -rw-r--r-- | util/isensor.c-old | 3907 | ||||
| -rw-r--r-- | util/mem_if.c | 11 | 
8 files changed, 3930 insertions, 11 deletions
| diff --git a/util/Makefile.in b/util/Makefile.in index 2909704..50f821c 100644 --- a/util/Makefile.in +++ b/util/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.16.1 from Makefile.am. +# Makefile.in generated by automake 1.16.2 from Makefile.am.  # @configure_input@ -# Copyright (C) 1994-2018 Free Software Foundation, Inc. +# Copyright (C) 1994-2020 Free Software Foundation, Inc.  # This Makefile.in is free software; the Free Software Foundation  # gives unlimited permission to copy and/or distribute it, @@ -378,6 +378,7 @@ pkgconfigdir = @pkgconfigdir@  prefix = @prefix@  program_transform_name = @program_transform_name@  psdir = @psdir@ +runstatedir = @runstatedir@  sbindir = @sbindir@  sharedstatedir = @sharedstatedir@  srcdir = @srcdir@ diff --git a/util/ievents.c b/util/ievents.c index e5d34f7..17b41a4 100644 --- a/util/ievents.c +++ b/util/ievents.c @@ -80,7 +80,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  extern char *progver;  /*from ipmiutil.c*/  static char * progname  = "ipmiutil events";  #else -static char *progver   = "3.18"; +static char *progver   = "3.19";  static char *progname  = "ievents";  #endif  static char fsensdesc = 0;   /* 1= get extended sensor descriptions*/ diff --git a/util/igetevent.c b/util/igetevent.c index f4c75d6..dd806c4 100644 --- a/util/igetevent.c +++ b/util/igetevent.c @@ -1183,7 +1183,7 @@ main(int argc, char **argv)  	  ipath = getenv("ipmiutildir");  /*ipmiutil directory path*/  	  if (ipath != NULL) {  	     if (strlen(ipath)+12 < sizeof(idxfile)) { -	        sprintf(idxfile,"%s\\%s",ipath,"\\",IDXFILE); +	        sprintf(idxfile,"%s\\%s",ipath,IDXFILE);  	     }  	  }         } diff --git a/util/ipmiutil.c b/util/ipmiutil.c index 980c57e..409cb9f 100644 --- a/util/ipmiutil.c +++ b/util/ipmiutil.c @@ -57,7 +57,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  #include "ipmiutil.h"  static char *progname  = "ipmiutil"; -char *progver   = "3.18"; +char *progver   = "3.19";  // static char fdebug = 0;  /*int ipmiutil(int argc, char **argv); */ diff --git a/util/ireset.c b/util/ireset.c index c668996..d311142 100644 --- a/util/ireset.c +++ b/util/ireset.c @@ -631,11 +631,13 @@ main(int argc, char **argv)        } else if (vendid == VENDOR_INTEL) {   /* Intel */  	  if (prodid != 0x0100)  /* ia64 Itanium2 is different */  	      platform = platIntel;  /* else handle as Intel Sahalee */ +#ifdef OBSOLETE	  	  if (is_romley(vendid,prodid) || (prodid == 0x003E)) {    		/* Romley or Thurley/S5520UR */  	      platform = platS5500;  /* not like Intel Sahalee */  	      set_max_kcs_loops(URNLOOPS); /*longer KCS timeout*/  	  } +#endif        } else if (vendid == VENDOR_KONTRON) {   /* Kontron */            fignore_opterr = 1;  /* ignore boot options errors */  	  /* supports Chassis Soft Power command 0x05, so not platIntel */ diff --git a/util/isensor.c b/util/isensor.c index eded150..a3fc650 100644 --- a/util/isensor.c +++ b/util/isensor.c @@ -81,6 +81,7 @@   * 01/25/08 ARCress  v2.7    allow float input with -u thresholds,    *                           add -p persist logic for -u thresholds.   * 09/20/19 ARCress  v3.15   workaround for Pigeon Point bad sa in SDR + * 07/08/22 ARCress  v3.19   fix -i get_idx_range to show last idx in range   */  /*M*  Copyright (c) 2002-2006 Intel Corporation.  @@ -609,16 +610,17 @@ int get_idx_range(char *str)  {      // int i = 0;      char *p; +	char *p2;      p = strchr(str,'-');      if (p == NULL) p = strchr(str,','); -    if (p != NULL) { +    if (p != NULL) {  /*range*/         *p = 0;         p++;         sensor_idx1 = parse_idx(str); -       sensor_idxN = parse_idx(p); -    } else { +       sensor_idxN = parse_idx(p) + 1; /*end if >=, so + 1*/ +    } else {  /*single sensor*/         sensor_idx1 = parse_idx(str); -       sensor_idxN = sensor_idx1; +       sensor_idxN = sensor_idx1; /*end if >=*/      }      return(0);  } diff --git a/util/isensor.c-old b/util/isensor.c-old new file mode 100644 index 0000000..eded150 --- /dev/null +++ b/util/isensor.c-old @@ -0,0 +1,3907 @@ +/* + * isensor.c + * + * This tool reads the SDR records to return sensor information.  + * It can use either the Intel /dev/imb driver or VALinux /dev/ipmikcs. + * + * Author:  arcress at users.sourceforge.net + * Copyright (c) 2002-2006 Intel Corporation.  + * Copyright (c) 2009 Kontron America, Inc. + * + * 07/25/02 Andy Cress created + * 10/09/02 Andy Cress v1.1 added decodeValue(RawToFloat) routine  + * 10/11/02 Andy Cress v1.2 added expon routine  + * 10/30/02 Andy Cress v1.3 added SDR types 08 & 14 + * 12/04/02 Andy Cress v1.4 changed dstatus descriptions + * 01/29/03 Andy Cress v1.5 added MV OpenIPMI driver support + *          Hannes Schulz <schulz@schwaar.com> + *                1) correct raw readings to floatval + *                2) allow extra SDR bytes returned from HP netserver 1000r + *          Guo Min <guo.min@intel.com> + *                add -l option for simpler list display + * 02/25/03 Andy Cress v1.6 misc cleanup + * 05/02/03 Andy Cress v1.7 add PowerOnHours + * 07/28/03 Andy Cress v1.8 added -t option for threshold values, + *                          added sample Discovery routine (unfinished), + *                          added ipmi_getdeviceid for completeness. + * 09/05/03 Andy Cress v1.9 show SDR OEM subtypes,  + *                          fix GetSDR multi-part get for OEM SDRs + *                          stop if SDR Repository is empty + * 09/23/03 Andy Cress v1.10 Add options to set thresholds + * 10/14/03 Andy Cress v1.11 Fixed sdr offset for ShowThreshold values + * 01/15/04 Andy Cress v1.12 Fixed SetThreshold to set hysteresis,  + *                           Fixed sens_cap testing in ShowThresh(Full) + * 01/30/04 Andy Cress v1.13 Changed field display order, added header, + *                           check for sdr sz below min, added WIN32. + * 02/19/04 Andy Cress v1.14 Added SDR type 3 parsing for mBMC + * 02/27/04 Andy Cress v1.15 Added check for superuser, more mBMC logic + * 03/11/04 Andy Cress v1.16 Added & removed private mBMC code for set  + *                           thresholds due to licensing issues + * 04/13/04 Andy Cress v1.17 Added -r to show raw SDRs also + * 05/05/04 Andy Cress v1.18 call ipmi_close before exit, + *                           fix sresp in GetSDR for WIN32. + * 07/07/04 Andy Cress v1.19 Added -a to reArm sensor, + *                           show debug raw reading values only in hex + * 08/18/04 Andy Cress v1.20 Added decoding for DIMM status + * 11/01/04 Andy Cress v1.21 add -N / -R for remote nodes,   + *                           added -U for remote username + * 11/19/04 Andy Cress v1.22 added more decoding for compact reading types, + *                           added -w option to wrap thresholds + * 11/24/04 ARCress  v1.23   added sens_type to display output + * 12/10/04 ARCress  v1.24   added support for device sdrs also, + *                           fixed sens_cap byte, + * 01/10/05 ARCress  v1.25   change ShowThresh order, highest to lowest, + *                           change signed exponent type in RawToFloat + * 01/13/05 ARCress  v1.26   added time display if fwrap + * 01/28/05 ARCress  v1.27   mod for Power Redundancy SDR status + * 02/15/05 ARCress  v1.28   added FloatToRaw for -h/-l threshold set funcs,  + *                           always take -n sensor_num as hex (like displayed) + * 03/07/05 ARCress  v1.29   added "LAN Leash Lost" decoding in decode_comp_ + *                           added -v to show max/min & hysteresis. + * 03/22/05 ARCress  v1.30   added OEM subtype 0x60 for BMC TAM + * 03/26/05 ARCress  v1.31   added battery type to decode_comp_reading + * 04/21/05 ARCress  v1.32   added error message if -n sensor_num not found, + *                           added more decoding for Power Redund sensor + * 06/20/05 ARCress  v1.33   if GetSDRRepository cc=0xc1 switch fdevsdrs mode, + *                           also detect fdevsdrs better for ATCA. + * 07/28/05 ARCress  v1.34   check for Reading init state,  + *                           add extra byte to decode_comp_reading() + * 09/12/05 ARCress  v1.35   don't check superuser for fipmi_lan + * 01/26/06 ARCress  v1.36   added -i option to only show one sensor index + * 03/14/06 ARCress  v1.37   added -p option to save persistent thresholds + * 04/06/06 ARCress  v1.38   show auto/manual rearm + * 07/17/06 ARCress  v1.39   add -V, add -L, handle RepInfo rc=0xc1  + * 11/28/06 ARCress  v1.46   added -c -m for ATCA child MCs + * 08/15/07 ARCress  v1.58   filter display if -n sensor_num + * 08/29/07 ARCress  v1.59   fixed Battery sensor interpretation + * 10/31/07 ARCress  v2.3    retry GetSDR if cc=0xC5 (lost reservationID) + * 01/14/08 ARCress  v2.6    add -u param for setting unique thresholds,  + *                           always show float when setting thresholds, + *                           fixup in decoding Proc,PS Comp readings + * 01/25/08 ARCress  v2.7    allow float input with -u thresholds,  + *                           add -p persist logic for -u thresholds. + * 09/20/19 ARCress  v3.15   workaround for Pigeon Point bad sa in SDR + */ +/*M* +Copyright (c) 2002-2006 Intel Corporation.  +Copyright (c) 2009 Kontron America, Inc. +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 Intel nor the names of its 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*/ +#include <stdio.h> +#include <stdlib.h> +#include <math.h>   // for:  double pow(double x, double y); +#include <string.h> +#include <time.h> +#ifdef WIN32 +#include <windows.h> +#include "getopt.h" +#elif defined(DOS) +#include <dos.h> +#include "getopt.h" +#else +#include <sys/stat.h> +#if defined(HPUX) +/* getopt is defined in stdio.h */ +#elif defined(MACOS) +/* getopt is defined in unistd.h */ +#include <unistd.h> +#else +#include <getopt.h> +#endif +#endif +#if defined(LINUX) +#include <unistd.h> +#include <sys/types.h> +#endif +#include "ipmicmd.h" +#include "isensor.h" + +#define PICMG_CHILD  1 /* show child MCs if -b */ +#define MIN_SDR_SZ  8  +#define SZCHUNK 16    /* SDR chunksize was 8, now 16 */ +#define INIT_SNUM  0xff  +#define N_SGRP   16 +#define THR_EMPTY  999 + +/* prototypes */ +int get_LastError( void );  /* ipmilan.c */ +extern int use_devsdrs(int picmg);  /* ipmicmd.c */ +extern int get_MemDesc(int array, int dimm, char *desc, int *psz); /*mem_if.c*/ +extern char *get_sensor_type_desc(uchar stype); /*ievents.c*/ +#ifdef METACOMMAND +#include "oem_intel.h" +/*     void show_oemsdr_intel(uchar *sdr); in oem_intel.h */ +/*     int decode_sensor_intel();          in oem_intel.h */ +/*     int is_romley(int vend, int prod);  in oem_intel.h */ +extern int decode_sensor_kontron(uchar *sdr,uchar *reading,char *pstring, +				int slen);  /*see oem_kontron.c*/ +extern int decode_sensor_fujitsu(uchar *sdr,uchar *reading,char *pstring, +				int slen);  /*see oem_fujitsu.c*/ +extern int decode_sensor_sun(uchar *sdr,uchar *reading,char *pstring, +				int slen);  /*see oem_sun.c*/ +extern int decode_sensor_supermicro(uchar *sdr,uchar *reading,char *pstring, +				int slen, int fsimple, char fdbg);  /*see oem_supermicro.c*/ +extern int decode_sensor_quanta(uchar *sdr,uchar *reading,char *pstring, +				int slen);  /*see oem_quanta.c*/ +extern int decode_sensor_dell(uchar *sdr,uchar *reading,char *pstring, +				int slen);  /*see oem_dell.c*/ +extern int decode_sensor_lenovo(uchar *sdr,uchar *reading,char *pstring, +				int slen);  /*see oem_lenovo.c*/ +extern int decode_sensor_asus(uchar *sdr,uchar *reading,char *pstring,int slen); +extern int decode_sensor_hp(uchar *sdr,uchar *reading,char *pstring, +				int slen);  /*see oem_hp.c*/ +extern void show_oemsdr_hp(uchar *sdr);  +#else +int is_romley(int vend, int prod) {  +   if ((vend == VENDOR_INTEL) && ((prod >= 0x0048) && (prod <= 0x005e))) +	return(1); +   return(0);  +} +int is_grantley(int vend, int prod) {  +   if ((vend == VENDOR_INTEL) && (prod == 0x0071)) +	return(1); +   return(0);  +} +int is_thurley(int vend, int prod) {  +   if ((vend == VENDOR_INTEL) && ((prod >= 0x003A) && (prod <= 0x0040))) +	return(1); +   return(0);  +} +#endif +#ifdef ALONE +#define NENTID  53 +static char *entity_id_str[NENTID] = { +/* 00 */ "unspecified", +/* 01 */ "other", +/* 02 */ "unknown", +/* 03 */ "processor", +/* 04 */ "disk", +/* 05 */ "peripheral bay", +/* 06 */ "management module", +/* 07 */ "system board", +/* 08 */ "memory module", +/* 09 */ "processor module", +/* 10 */ "power supply", +/* 11 */ "add-in card", +/* 12 */ "front panel bd", +/* 13 */ "back panel board", +/* 14 */ "power system bd", +/* 15 */ "drive backplane", +/* 16 */ "expansion board", +/* 17 */ "Other system board", +/* 18 */ "processor board", +/* 19 */ "power unit", +/* 20 */ "power module", +/* 21 */ "power distr board", +/* 22 */ "chassis back panel bd", +/* 23 */ "system chassis", +/* 24 */ "sub-chassis", +/* 25 */ "Other chassis board", +/* 26 */ "Disk Drive Bay", +/* 27 */ "Peripheral Bay", +/* 28 */ "Device Bay", +/* 29 */ "fan", +/* 30 */ "cooling unit", +/* 31 */ "cable/interconnect", +/* 32 */ "memory device ", +/* 33 */ "System Mgt Software", +/* 34 */ "BIOS", +/* 35 */ "Operating System", +/* 36 */ "system bus", +/* 37 */ "Group", +/* 38 */ "Remote Mgt Comm Device", +/* 39 */ "External Environment", +/* 40 */ "battery", +/* 41 */ "Processing blade", +/* 43 */ "Processor/memory module", +/* 44 */ "I/O module", +/* 45 */ "Processor/IO module", +/* 46 */ "Mgt Controller Firmware", +/* 47 */ "IPMI Channel", +/* 48 */ "PCI Bus", +/* 49 */ "PCI Express Bus", +/* 50 */ "SCSI Bus", +/* 51 */ "SATA/SAS bus", +/* 52 */ "Processor FSB" +}; +char *decode_entity_id(int id) {  +   if (id < NENTID) return ("");  +   else return(entity_id_str[id]); } +#else +/* char *decode_entity_id(int id);  *isensor.h, from ievents.c*/ +#endif +/************************ + *  Global Data + ************************/ +#ifdef METACOMMAND +extern char * progver;  /*from ipmiutil.c*/ +static char * progname  = "ipmiutil sensor"; +#else +static char * progver   = "3.15"; +static char * progname  = "isensor"; +#endif +#ifdef WIN32 +static char savefile[] = "%ipmiutildir%\\thresholds.cmd"; +#else +static char savefile[] = "/var/lib/ipmiutil/thresholds.sh"; +// static char savefile[] = "/usr/share/ipmiutil/thresholds.sh"; +#endif +extern char fdebug;      /*from ipmicmd.c*/ +int sens_verbose    = 0; /* =1 show max/min & hysteresis also */ +static int fdevsdrs = 0; +static int fReserveOK = 1; +static int fDoReserve = 1; +static int fsimple     = 0; /*=1 simple, canonical output*/ +static int fshowthr = 0;   /* =1 show thresholds, =2 show thr in ::: fmt */ +static int fwrap    = 0; +static int frawsdr  = 0; +static int frearm   = 0; +static int fshowidx = 0;   /* only show a specific SDR index/range */ +static int fshowgrp = 0;   /* =1 show group of sensors by sensor type */ +static int fdoloop  = 0;   /* =1 if user specified number of loops */ +static int fpicmg   = 0; +static int fchild   = 0;   /* =1 show child SDRs */ +static int fset_mc  = 0;   /* =1 -m to set_mc   */ +static int fbadsdr  = 0;   /* =1 to ignore bad SDR mc  */ +static int fdump    = 0;   +static int frestore = 0;   +static int fjumpstart = 0;   +static int fgetmem  = 0;   +static int fprivset = 0;   +static char fremote = 0;   +static int  nloops  = 1;   /* num times to show repeated sensor readings */ +static int  loopsec  = 1;  /* wait N sec between loops, default 1 */ +static char bdelim = BDELIM;  /* delimiter for canonical output */ +static char tmpstr[20];    /* temp string */ +static char *binfile = NULL; +static int   fsetthresh = 0; +static int   fsavethresh = 0; +static uchar  sensor_grps[N_SGRP] = {0, 0};  /*sensor type groups*/ +static ushort sensor_idx1 = 0xffff; +static ushort sensor_idxN = 0xffff; +static uchar  sensor_num = INIT_SNUM; +static uchar  sensor_hi = 0xff; +static uchar  sensor_lo = 0xff; +static uchar  sensor_thr[6]  = {0,0,0,0,0,0}; +static double sensor_thrf[6] = {0,0,0,0,0,0}; +static double sensor_hi_f = 0; +static double sensor_lo_f = 0; +static int fmBMC = 0; +static int fRomley = 0; +static int fGrantley = 0; +static char chEol = '\n';  /* newline by default, space if option -w */ +static uchar resid[2] = {0,0}; +static uchar g_bus = PUBLIC_BUS; +static uchar g_sa  = 0; +static uchar g_lun = BMC_LUN; +static uchar g_addrtype = ADDR_SMI; +static int vend_id = 0; +static int prod_id; + +/* sensor_dstatus + * This is used to decode the sensor reading types and meanings. + * Use IPMI Table 36-1 and 36-2 for this. + */ +#define N_DSTATUS 101 +#define STR_CUSTOM     58 +#define STR_OEM        71 +#define STR_AC_LOST    76 +#define STR_PS_FAIL    77 +#define STR_PS_CONFIG  78 +#define STR_HSC_OFF    79 +#define STR_REBUILDING 80 +#define STR_OTHER      81 +static char oem_string[50] = "OEM"; +static char *sensor_dstatus[N_DSTATUS] = { +/* 0 00h */ "OK  ", +/* Threshold event states */ +/* 1 01h */ "Warn-lo",   // "Warning-lo", +/* 2 02h */ "Crit-lo",   // "Critical-lo", +/* 3 04h */ "BelowCrit", // "BelowCrit-lo", +/* 4 08h */ "Warn-hi",   // "Warning-hi", +/* 5 10h */ "Crit-hi",   // "Critical-hi", +/* 6 20h */ "AboveCrit", // "AboveCrit-hi", +/* 7 40h */ "Init ",  /*in init state, no reading*/ +/* 8 80h */ "OK* ", +/*  Hotswap Controller event states, also Availability */ +/* 9 HSC */ "Present", /*present,inserted*/ +/*10 HSC */ "Absent", /*absent,removed,empty,missing*/ +/*11 HSC */ "Ready", +/*12 HSC */ "Faulty", +/*  Digital/Discrete event states */ +/*13 D-D */ "Asserted", +/*14 D-D */ "Deassert", +/*15 D-D */ "Predict ", +/*  Availability event states */ +/*16 Avl */ "Disabled", +/*17 Avl */ "Enabled ", +/*18 Avl */ "Redundant", +/*19 Avl */ "RedunLost", +/*20 Avl */ "RedunDegr", +/* ACPI Device Power States */ +/*21 ACPI*/ "Off    ", /*D3*/ +/*22 ACPI*/ "Working", /*D1*/ +/*23 ACPI*/ "Sleeping", /*D2/S2*/ +/*24 ACPI*/ "On",      /*D0*/ +/* Critical Interrupt event states */ +/*25 CrI */ "FP_NMI  ", +/*26 CrI */ "Bus_TimOut", +/*27 CrI */ "IOch_NMI", +/*28 CrI */ "SW_NMI  ", +/*29 CrI */ "PCI_PERR", +/*30 CrI */ "PCI_SERR", +/*31 CrI */ "EISA_TimOut", +/*32 CrI */ "Bus_Warn ", /*Correctable*/ +/*33 CrI */ "Bus_Error", /*Uncorrectable*/ +/*34 CrI */ "Fatal_NMI", +/*35 CrI */ "Bus_Fatal", /*0x0A*/ +/*36 CrI */ "Bus_Degraded", /*0x0B*/ +/* Physical Security event states */ +/*37 Phys*/ "LanLeashLost", +/*38 Phys*/ "ChassisIntrus", +/* Memory states  */ +/*39 Mem */ "ECCerror", +/*40 Mem */ "ParityErr", +/* Discrete sensor invalid readings (error or init state) */ +/*41 D-D */ "Unknown", +/*42 D-D */ "NotAvailable", +/* Discrete sensor OEM reading states */ +/*43 OEM */ "Enabled ", +/*44 OEM */ "Disabled", +/* Session Audit states */ +/*45 OEM */ "Activated ", +/*46 OEM */ "Deactivated", +/*47 HSC */ "Unused  ",  +/* Processor event states */ +/*48 Proc*/ "IERR", +/*49 Proc*/ "ThermalTrip", +/*50 Proc*/ "FRB1Failure", +/*51 Proc*/ "FRB2Failure", +/*52 Proc*/ "FRB3Failure", +/*53 Proc*/ "ConfigError", +/*54 Proc*/ "SMBIOSError", +/*55 Proc*/ "ProcPresent", +/*56 Proc*/ "ProcDisabled", +/*57 Proc*/ "TermPresent", +/* Custom data string, 15 bytes */ +/*58 Custom*/ "CustomData12345",  +/* Event Log */  +/*59 EvLog*/ "MemLogDisab", +/*60 EvLog*/ "TypLogDisab", +/*61 EvLog*/ "LogCleared", +/*62 EvLog*/ "AllLogDisab", +/*63 EvLog*/ "SelFull", +/*64 EvLog*/ "SelNearFull", +/* more Digital Discrete */  +/*65 D-D */  "Exceeded", +/*66 Alert*/ "AlertPage", +/*67 Alert*/ "AlertLAN", +/*68 Alert*/ "AlertPET", +/*69 Alert*/ "AlertSNMP", +/*70 Alert*/ "None", +/*71 OEM str*/ &oem_string[0], +/* Version Change */ +/*72 Change*/ "HW Changed", +/*73 Change*/ "SW Changed", +/*74 Change*/ "HW incompatibility", +/*75 Change*/ "Change Error", +/* Power Supply event states */ +/*76 PS  */   "AC_Lost  ", +/*77 PS  */   "PS_Failed", +/* Power Supply event states */ +/*78 PS  */   "Config_Err", +/*79 HSC */   "Offline", +/*80 HSC */   "Rebuilding", +/*81 other*/  " _ ", +/*82 Avl */ "NonRedund_Sufficient", +/*83 Avl */ "NonRedund_Insufficient", +/*84 Usage */ "Idle", +/*85 Usage */ "Active", +/*86 Usage */ "Busy", +/*87 Trans */ "Non-Critical", +/*88 Trans */ "Critical", +/*89 Trans */ "Non-Recoverable", +/*90 Trans */ "Monitor", +/*91 Trans */ "Informational", +/*92 State */ "Running", +/*93 State */ "In_Test", +/*94 State */ "Power_Off", +/*95 State */ "Online", +/*96 State */ "Offline", +/*97 State */ "Off_Duty", +/*98 State */ "Degraded", +/*99 State */ "PowerSave", +/*100 State */ "InstallError" +}; + +static char *raid_states[9] = {  /*for sensor type 0x0d drive status */ +  "Faulty", +  "Rebuilding", +  "InFailedArray",   +  "InCriticalArray",   +  "ParityCheck",   +  "PredictedFault",   +  "Un-configured",   +  "HotSpare", +  "NoRaid" }; + +#define NSENSTYPES   0x2a +#ifdef OLD +/* see ievents.c */ +static const char *sensor_types[NSENSTYPES] = {  /*IPMI 2.0 Table 42-3*/ +/* 00h */ "reserved", +/* 01h */ "Temperature", +/* 02h */ "Voltage", +/* 03h */ "Current", +/* 04h */ "Fan", +/* 05h */ "Platform Chassis Intrusion", +/* 06h */ "Platform Security Violation", +/* 07h */ "Processor", +/* 08h */ "Power Supply", +/* 09h */ "Power Unit", +/* 0Ah */ "Cooling Device", +/* 0Bh */ "FRU Sensor", +/* 0Ch */ "Memory", +/* 0Dh */ "Drive Slot", +/* 0Eh */ "POST Memory Resize", +/* 0Fh */ "System Firmware", +/* 10h */ "SEL Disabled", +/* 11h */ "Watchdog 1", +/* 12h */ "System Event",          /* offset 0,1,2 */ +/* 13h */ "Critical Interrupt",    /* offset 0,1,2 */ +/* 14h */ "Button",                /* offset 0,1,2 */ +/* 15h */ "Board", +/* 16h */ "Microcontroller", +/* 17h */ "Add-in Card", +/* 18h */ "Chassis", +/* 19h */ "Chip Set", +/* 1Ah */ "Other FRU", +/* 1Bh */ "Cable / Interconnect", +/* 1Ch */ "Terminator", +/* 1Dh */ "System Boot Initiated", +/* 1Eh */ "Boot Error", +/* 1Fh */ "OS Boot", +/* 20h */ "OS Critical Stop", +/* 21h */ "Slot / Connector", +/* 22h */ "ACPI Power State", +/* 23h */ "Watchdog 2", +/* 24h */ "Platform Alert", +/* 25h */ "Entity Presence", +/* 26h */ "Monitor ASIC", +/* 27h */ "LAN", +/* 28h */ "Management Subsystem Health", +/* 29h */ "Battery", +}; +#endif + +#define NUNITS  30 +static char *unit_types[] = { +/* 00 */ "unspecified", +/* 01 */ "degrees C", +/* 02 */ "degrees F", +/* 03 */ "degrees K", +/* 04 */ "Volts", +/* 05 */ "Amps", +/* 06 */ "Watts", +/* 07 */ "Joules", +/* 08 */ "Coulombs", +/* 09 */ "VA", +/* 10 */ "Nits", +/* 11 */ "lumen", +/* 12 */ "lux", +/* 13 */ "Candela", +/* 14 */ "kPa", +/* 15 */ "PSI", +/* 16 */ "Newton", +/* 17 */ "CFM", +/* 18 */ "RPM", +/* 19 */ "Hz", +/* 20 */ "microseconds", +/* 21 */ "milliseconds", +/* 22 */ "seconds", +/* 23 */ "minutes", +/* 24 */ "hours", +/* 25 */ "days", +/* 26 */ "weeks", +/* 27 */ "mil", +/* 28 */ "inches", +/* 29 */ "feet", +/* 42 */ "cycles"   +}; +/* 68 * "megabit", */ +/* 72 * "megabyte", */ +/* 90 * "uncorrectable error" (last defined)*/ +static char *unit_types_short[] = { +/* 00 */ "?", /*unknown, not specified*/ +/* 01 */ "C", +/* 02 */ "F", +/* 03 */ "K", +/* 04 */ "V", +/* 05 */ "A", +/* 06 */ "W", +/* 07 */ "J", +/* 08 */ "Coul", +/* 09 */ "VA", +/* 10 */ "Nits", +/* 11 */ "lumen", +/* 12 */ "lux", +/* 13 */ "Cand", +/* 14 */ "kPa", +/* 15 */ "PSI", +/* 16 */ "Newton", +/* 17 */ "CFM", +/* 18 */ "RPM", +/* 19 */ "Hz", +/* 20 */ "usec", +/* 21 */ "msec", +/* 22 */ "sec", +/* 23 */ "min", +/* 24 */ "hrs", +/* 25 */ "days", +/* 26 */ "wks", +/* 27 */ "mil", +/* 28 */ "in", +/* 29 */ "ft", +/* 42 */ "cyc"   +}; + +ushort parse_idx(char *str) +{ +    int i, n; +    char istr[5]; +    if (strncmp(str,"0x",2) == 0) str += 2; +    n = strlen_(str); +    if (n == 4) { +        i = (htoi(str) << 8) + htoi(&str[2]); +    } else if (n == 3) { +        istr[0] = '0'; +        memcpy(&istr[1],str,3); +        i = (htoi(istr) << 8) + htoi(&istr[2]); +    } else i = htoi(str);      /*was atoi()*/ +    printf("idx = 0x%x\n",i); +    return((ushort)i); +} + +int get_idx_range(char *str) +{ +    // int i = 0; +    char *p; +    p = strchr(str,'-'); +    if (p == NULL) p = strchr(str,','); +    if (p != NULL) { +       *p = 0; +       p++; +       sensor_idx1 = parse_idx(str); +       sensor_idxN = parse_idx(p); +    } else { +       sensor_idx1 = parse_idx(str); +       sensor_idxN = sensor_idx1; +    } +    return(0); +} + +char *get_unit_type(int iunits, int ibase, int imod, int fshort) +{ +    char *pstr = NULL; +    char **punittypes; +    static char unitstr[32]; +    int jbase, jmod; +    uchar umod; + +    punittypes = unit_types; +    if (fshort) punittypes = unit_types_short; +    if (fdebug) printf("get_unit_type(%x,%d,%d,%d)\n",iunits,ibase,imod,fshort); +    umod = (iunits & 0x06) >> 1; +    if (ibase < NUNITS) jbase = ibase; +    else { +	if (fdebug) printf("units base %02x > %d\n",ibase,NUNITS); +        if (ibase == 42) jbase = NUNITS;  /*"cycles"*/ +	else jbase = 0;  +    } +    if (imod < NUNITS) jmod = imod; +    else { +	if (fdebug) printf("units mod %02x > %d\n",imod,NUNITS); +	jmod = 0;  +    } +    switch (umod) { +	case 2: +	   snprintf(unitstr,sizeof(unitstr),"%s * %s", +			punittypes[jbase],punittypes[jmod]); +	   pstr = unitstr; +	   break; +	case 1: +	   snprintf(unitstr,sizeof(unitstr),"%s/%s", +			punittypes[jbase],punittypes[jmod]); +	   pstr = unitstr; +	   break; +	case 0: +	default: +           pstr = punittypes[jbase]; +	   break; +    } +    if ((umod == 0) && (iunits > 0)) { +	   /* special cases for other SensorUnits1 bits */ +	   if ((iunits & 0x01) != 0) {  /*percentage*/ +	      if (fshort) pstr = "%"; +	      else pstr = "percent"; +	   } else if (iunits == 0xC0) {  /*no analog reading*/ +	      pstr = "na"; +	   } else if (iunits == 0x18) { +	      /* For Tyan fans:  base=42, units=24.(0x18) -> cycles/hour */ +	      snprintf(unitstr,sizeof(unitstr),"%s/hour",punittypes[jbase]); +	      pstr = unitstr; +	   }  +    } +    return(pstr); +} + +char *decode_capab(uchar c) +{ +   static char cstr[50]; +   char *arm; +   char *thr; +   char *evt; +   // char *hys; +   uchar b; +   /* decode sens_capab bits */ +   if ((c & 0x40) == 0) arm = "man"; /*manual rearm*/ +   else arm = "auto";  /*automatic rearm*/ +   /* skip hysteresis bits (0x30) */ +   b = ((c & 0x0c) >> 2); +   switch(b) { +   case 0x00: thr = "none"; break;  /*no thresholds*/ +   case 0x01: thr = "read"; break; +   case 0x02: thr = "write"; break; /*read & write*/ +   case 0x03:  +   default:   thr = "fixed"; break;  +   } +   b = (c & 0x03) ; +   switch(b) { +   case 0x00: evt = "state"; break;  /*threshold or discrete state*/ +   case 0x01: evt = "entire"; break; /*entire sensor only*/ +   case 0x02: evt = "disab"; break;  /*global disable only*/ +   case 0x03: +   default:   evt = "none"; break;   /*no events*/ +   } +   sprintf(cstr,"arm=%s thr=%s evts=%s",arm,thr,evt); +   return(cstr); +} + + +int get_group_id(char *pstr) +{ +   int i, j, n, sz, len; +   char *p; +   int rv = -1; +		    +   sz = strlen_(pstr); +   p = &pstr[0]; +   n = 0; +   for (i = 0; i <= sz; i++) { +      if (n >= N_SGRP) break; +      switch(pstr[i]) { +	 case ',':  /*delimiter*/ +	 case '\n': +	 case '\0': +	    pstr[i] = 0;  /*stringify this word*/ +            len = strlen_(p); +	    for (j = 0; j < NSENSTYPES; j++) { +		if (strncasecmp(get_sensor_type_desc(j),p,len) ==  0) { +		   sensor_grps[n++] = (uchar)j; +		   rv = 0; +		   break;  +		} +	    } /*endfor(j)*/ +	    if (i+1 < sz) p = &pstr[i+1];  /*set p for next word*/ +	    if (j >= NSENSTYPES) { /* sensor type not found */ +		rv = -1;  +		i = sz;  /*exit loop*/ +	    } +	    break; +	 default: +	    break; +      } /*end switch*/ +   }  /*end for(i)*/ +   if (rv == 0) rv = n; +   else rv = -1; +   return(rv); +} + +static int validate_thresholds(void *pthrs, char flag, uchar *sdr) +{ +   double *thrf; +   uchar *thr; +   int rv = 0; +   uchar bits; + +   if (sdr == NULL) bits = 0xff; /*assume all are used*/ +   else bits = sdr[18];  /*18=indicates which are readable/used */ + +   if (bits == 0) { +      printf("No threshold values can be set for this sensor.\n"); +      return(3); +   } +   if (flag == 1) { /*float*/ +      thrf = (double *)pthrs; +      if (fdebug)  +         printf("validate_thresh: bits=%02x, values: %f>=%f>=%f, %f<=%f<=%f\n", +		bits, thrf[0],thrf[1],thrf[2], thrf[3],thrf[4],thrf[5]); +      if ((bits & 0x02) != 0) { /*thrf[1] lo-crit is valid*/ +        if ((thrf[1] > thrf[0]) && ((bits & 0x01) != 0)) rv = 1; +        if ((thrf[2] > thrf[1]) && ((bits & 0x04) != 0)) rv = 1; /*lo is wrong*/ +      }  +      if ((bits & 0x10) != 0) { /*thrf[4] hi-crit is valid*/ +        if ((thrf[4] < thrf[3]) && ((bits & 0x08) != 0)) rv = 2; +        if ((thrf[5] < thrf[4]) && ((bits & 0x20) != 0)) rv = 2; /*hi is wrong*/ +      } +      if (rv != 0) { +	  printf("Threshold values: %f>=%f>=%f, %f<=%f<=%f\n", +		thrf[0], thrf[1], thrf[2], thrf[3], thrf[4], thrf[5]); +          printf("Invalid threshold order in %s range.\n", +				((rv == 1)? "lo": "hi")); +      } +   } else { +      thr = (uchar *)pthrs; +      if ((bits & 0x02) != 0) { /*thr[1] lo-crit is valid*/ +        if ((thr[1] > thr[0]) && ((bits & 0x01) != 0)) rv = 1; +        if ((thr[2] > thr[1]) && ((bits & 0x04) != 0)) rv = 1; /*lo is wrong*/ +      }  +      if ((bits & 0x10) != 0) { /*thr[4] hi-crit is valid*/ +        if ((thr[4] < thr[3]) && ((bits & 0x08) != 0)) rv = 2; +        if ((thr[5] < thr[4]) && ((bits & 0x20) != 0)) rv = 2; /*hi is wrong*/ +      } +      if (rv != 0) { +         printf("Threshold values: %02x>=%02x>=%02x %02x<=%02x<=%02x\n", +		thr[0], thr[1], thr[2], thr[3], thr[4], thr[5]); +         printf("Invalid threshold order within -u (%s)\n", +				((rv == 1)? "lo": "hi")); +      } +   } +   return(rv); +} + +int  +GetSDRRepositoryInfo(int *nret, int *fdev) +{ +   uchar resp[MAX_BUFFER_SIZE]; +   int sresp = MAX_BUFFER_SIZE; +   int rc; +   int nSDR; +   int freespace; +   ushort cmd; +   uchar cc = 0; +   int   i; + +   memset(resp,0,6);  /* init first part of buffer */ +   if (nret != NULL) *nret = 0; +   if (fdev != NULL) fdevsdrs = *fdev; +   if (fdevsdrs) cmd = GET_DEVSDR_INFO; +   else cmd = GET_SDR_REPINFO; +   rc = ipmi_cmd_mc(cmd, NULL, 0, resp,&sresp, &cc, fdebug); +   if (fdebug) printf("ipmi_cmd[%04x] repinf(%d) status=%d cc=%x\n", +			cmd, fdevsdrs,rc,cc); +   /* some drivers return cc in rc */ +   if ((rc == 0xc1) || (rc == 0xd4)) cc = rc;  +   else if (rc != 0) return(rc); +   if (cc != 0) { +      if ((cc == 0xc1) ||  /*0xC1 (193.) means unsupported command */ +          (cc == 0xd4))    /*0xD4 means insufficient privilege (Sun/HP)*/ +      { +         /* Must be reporting wrong bit for fdevsdrs,  +          * so switch & retry */ +         if (fdevsdrs) {  +            fdevsdrs = 0; +            cmd = GET_SDR_REPINFO; +         } else {   +            fdevsdrs = 1; +            cmd = GET_DEVSDR_INFO; +         } +         sresp = MAX_BUFFER_SIZE; +         rc = ipmi_cmd_mc(cmd, NULL, 0, resp,&sresp, &cc, fdebug); +         if (fdebug)  +             printf("ipmi_cmd[%04x] repinf status=%d cc=%x\n",cmd,rc,cc); +         if (rc != ACCESS_OK) return(rc); +         if (cc != 0) return(cc); +      } else return(cc); +   } + +   if (fdevsdrs) { +      nSDR = resp[0]; +      freespace = 1;   +      fReserveOK = 1; +   } else { +      nSDR = resp[1] + (resp[2] << 8); +      freespace = resp[3] + (resp[4] << 8); +      if ((resp[13] & 0x02) == 0) fReserveOK = 0; +      else fReserveOK = 1; +   } +   if (nret != NULL) *nret = nSDR; +   if (fdev != NULL) *fdev = fdevsdrs; +   if (fdebug) { +      //successful, show data +      printf("SDR Repository (len=%d): ",sresp); +      for (i = 0; i < sresp; i++) printf("%02x ",resp[i]); +      printf("\n"); +      printf("SDR Info: fdevsdrs=%d nSDRs=%d free space = %x ReserveOK=%d\n", +		fdevsdrs,nSDR,freespace,fReserveOK); +   } + +   return(0); +}  /*end GetSDRRepositoryInfo()*/ + + +int  +GetSensorThresholds(uchar sens_num, uchar *thr_data) +{ +	uchar resp[MAX_BUFFER_SIZE]; +	int sresp = MAX_BUFFER_SIZE; +	uchar inputData[6]; +	int rc; +	uchar cc = 0; + +	inputData[0] = sens_num; +	rc = ipmi_cmd_mc(GET_SENSOR_THRESHOLD, inputData,1, resp,&sresp, &cc,fdebug); +	if (fdebug) +		printf("GetSensorThreshold[%02x] rc = %d, resp(%d) %02x %02x %02x %02x %02x %02x %02x\n", +			sens_num,rc, sresp,resp[0],resp[1],resp[2],resp[3], +			resp[4],resp[5],resp[6]); +	if (rc != ACCESS_OK) return(rc); +	if (cc != 0) return(cc); +	if (sresp == 0) return(-2); +	memcpy(thr_data,resp,sresp); +	return(0); +} + +int +RearmSensor(uchar sens_num) +{ +	uchar resp[MAX_BUFFER_SIZE]; +	int sresp = MAX_BUFFER_SIZE; +	uchar inputData[8]; +	int rc; +	uchar cc = 0; + +	memset(inputData,0,6); +	memset(resp,0,6); +	inputData[0] = sens_num; +	rc = ipmi_cmd_mc(GET_SEVT_ENABLE, inputData, 1, resp,&sresp, &cc, fdebug); +	if (rc == 0 && cc != 0) rc = cc; +	if (rc != 0 || fdebug) +		printf("GetSensorEventEnable(%02x) rc = %d, cc = %x %02x %02x %02x\n", +			sens_num,rc,cc,resp[0],resp[1],resp[3]); +	if (rc == 0 && resp[0] != 0xc0) { +		printf("EventEnable(%02x) = %02x, is not 0xc0\n", +			sens_num,resp[0]); +		memset(inputData,0,6); +		inputData[0] = sens_num; +		inputData[1] = resp[0] | 0xc0; +		inputData[2] = resp[1]; +		inputData[3] = resp[2]; +		inputData[4] = resp[3]; +		inputData[5] = resp[4]; +		rc = ipmi_cmd_mc(SET_SEVT_ENABLE, inputData, 6, resp,&sresp, +				&cc, fdebug); +		if (rc == 0 && cc != 0) rc = cc; +		if (rc != 0 || fdebug) +		printf("SetSensorEventEnable(%02x) rc = %d, cc = %x\n", +			sens_num,rc,cc); +	} + +	memset(inputData,0,6); +	inputData[0] = sens_num; +	inputData[1] = 0;  /* rearm all events for this sensor */ +	rc = ipmi_cmd_mc(REARM_SENSOR, inputData, 6, resp,&sresp, &cc, fdebug); +	if (fdebug) +		printf("RearmSensor(%02x) rc = %d, cc = %x %02x %02x\n", +			sens_num,rc,cc,resp[0],resp[1]); +	if (rc == 0 && cc != 0) rc = cc; + +	/* Could also do a global rearm via SetEventReceiver. */ + +	return(rc); +}  /*end RearmSensor*/ + +int  +SetSensorThresholds(uchar sens_num, uchar hi, uchar lo,  +			uchar *thr_data, uchar *thr_set) +{ +	uchar resp[MAX_BUFFER_SIZE]; +	int sresp = MAX_BUFFER_SIZE; +	uchar inputData[8]; +	int rc; +	uchar cc = 0; +	uchar sets = 0; +	int i; + +	/*  +	 * Set the sensor Hysteresis before setting the threshold. +	 */ +	memset(inputData,0,8); +	inputData[0] = sens_num; +	inputData[1] = 0xff; +	rc = ipmi_cmd_mc(GET_SENSOR_HYSTERESIS,inputData,2, resp,&sresp, &cc,fdebug); +	if (fdebug) +		printf("GetSensorHysteresis(%02x) rc = %d, cc = %x %02x %02x\n", +			sens_num,rc,cc,resp[0],resp[1]); +	if (rc != ACCESS_OK) return(rc); +	inputData[0] = sens_num; +	inputData[1] = 0xff; +	inputData[2] = resp[0]; +	inputData[3] = resp[1]; +	rc = ipmi_cmd_mc(SET_SENSOR_HYSTERESIS,inputData,4, resp,&sresp, &cc,fdebug); +	if (fdebug) +		printf("SetSensorHysteresis(%02x) rc = %d, cc = %x\n", +			sens_num,rc,cc); +	if (rc != ACCESS_OK) return(rc); +	 +	/*  +	 * The application should validate that values are ordered,  +	 * e.g.  upper critical should be greater than upper  +	 * non-critical. +	 * Due to the limited command line parameter interface,  +	 * use the hi & lo values to set each of the thresholds. +	 * For a full implemenation, these thresholds should be set +	 * individually. +	 */ +	memset(inputData,0,8); +	inputData[0] = sens_num; +	sets = thr_data[0]; +        if (thr_set != NULL) {  /* use specific thr_set values */ +           memcpy(&inputData[2],thr_set,6); +        } else {  /*default, use hi/lo params */ +	   if (lo == 0xff) sets &= 0x38;  /* don't set lowers */ +	   else { +	      inputData[2] = lo;      /* lower non-crit  (& 0x01)  */ +	      inputData[3] = lo - 1;  /* lower critical  (& 0x02) */ +	      inputData[4] = lo - 2;  /* lower non-recov (& 0x04) */ +	   } +	   if (hi == 0xff) sets &= 0x07;  /* don't set uppers */ +	   else { +	      inputData[5] = hi;      /* upper non-crit  (& 0x08) */ +	      inputData[6] = hi + 1;  /* upper critical  (& 0x10) */ +	      inputData[7] = hi + 2;  /* upper non-recov (& 0x20) */ +	   } +        }  +	inputData[1] = sets;  /* which ones to set */ +	{   /* show from/to changes */ +		printf("GetThreshold[%02x]: %02x ",sens_num,sens_num); +		for (i = 0; i < 7; i++) printf("%02x ",thr_data[i]); +		printf("\n"); +		printf("SetThreshold[%02x]: ",sens_num); +		for (i = 0; i < 8; i++) printf("%02x ",inputData[i]); +		printf("\n"); +	} +	rc = ipmi_cmd_mc(SET_SENSOR_THRESHOLD, inputData, 8, resp,&sresp, &cc, fdebug); +	if (fdebug) +		printf("SetSensorThreshold(%02x) rc = %d, cc = %x\n", +			sens_num,rc,cc); +	if (rc == 0 && cc != 0) rc = cc; +	/* mBMC gets cc = 0xD5 (213.) here, setting thresholds disabled. */ +	return(rc); +} + +int  +GetSensorReading(uchar sens_num, void *psdr, uchar *sens_data) +{ +	uchar resp[MAX_BUFFER_SIZE]; +	int sresp = MAX_BUFFER_SIZE; +	uchar inputData[6]; +        SDR02REC *sdr = NULL; +        int mc; +	int rc; +	uchar cc = 0; +	uchar lun = 0; +	uchar chan = 0; + +        if (psdr != NULL && fbadsdr == 0) { +           sdr = (SDR02REC *)psdr; +           mc = sdr->sens_ownid; +	   if (mc != BMC_SA) {  /* not BMC, e.g. HSC or ME sensor */ +	      uchar a = ADDR_IPMB; +	      if (mc == HSC_SA) a = ADDR_SMI; +	      chan = (sdr->sens_ownlun & 0xf0) >> 4; +	      lun = (sdr->sens_ownlun & 0x03); +              ipmi_set_mc(chan,(uchar)mc, lun,a); +           } +        } else mc = BMC_SA; +	inputData[0] = sens_num; +	rc = ipmi_cmd_mc(GET_SENSOR_READING,inputData,1, resp,&sresp,&cc,fdebug); +	if (fdebug)  +	    printf("GetSensorReading mc=%x,%x,%x status=%d cc=%x sz=%d resp: %02x %02x %02x %02x\n", +		     chan,mc,lun,rc,cc,sresp,resp[0],resp[1],resp[2],resp[3]); +        if (mc != BMC_SA) ipmi_restore_mc(); +	if ((rc == 0) && (cc != 0)) { +	    if (fdebug) printf("GetSensorReading error %x %s\n",cc, +				decode_cc((ushort)0,(uchar)cc)); +            rc = cc; +        } +        if (rc != 0) return(rc); + +	if (resp[1] & 0x20) { /* init state, reading invalid */ +	   if (fdebug)  +		printf("sensor[%x] in init state, no reading\n", sens_num); +           sens_data[1] = resp[1]; +           sens_data[2] = 0x40;  /*set bit num for init state*/ +        } else {     /*valid reading, copy it*/ +	   /* only returns 4 bytes, no matter what type */ +	   memcpy(sens_data,resp,4); +	} +	return(0); +}  /*end GetSensorReading()*/ + +int  +GetSensorReadingFactors(uchar snum, uchar raw, int *m, int *b, int *  b_exp,  +			int *r, int *a) +{ +	uchar resp[MAX_BUFFER_SIZE]; +	int sresp = MAX_BUFFER_SIZE; +	uchar inputData[6]; +	int rc; +	uchar cc = 0; +	int  toler, a_exp; + +	inputData[0] = snum; +	inputData[1] = raw; +	rc = ipmi_cmd_mc(GET_SENSOR_READING_FACTORS, inputData, 2,  +                      resp,&sresp, &cc, fdebug); +	if (fdebug) printf("GetSensorReadingFactors status = %d\n",rc); +	if (rc != ACCESS_OK) return(rc); +	if (cc != 0) return(cc); + +        /* successful, copy values */ +	*m = resp[1] + ((resp[2] & 0xc0) << 2); +	toler = resp[2] & 0x3f; +	*b = resp[3] + ((resp[4] & 0xc0) << 2); +	*a = (resp[4] & 0x3f) + ((resp[5] & 0xf0) << 4); +	a_exp = (resp[5] & 0xc0) >> 2; +	*r = (resp[6] &0xf0) >> 4; +	*b_exp = resp[6] & 0x0f; +	if (fdebug) { +	      printf("factors: next=%x m=%d b=%d b_exp=%d a=%d a_exp=%d r=%d\n", +			resp[0],*m,*b,*b_exp,*a,a_exp,*r); +	} +	return(0); +} + +int GetSensorType(uchar snum, uchar *stype, uchar *rtype) +{ +	uchar resp[MAX_BUFFER_SIZE]; +	int sresp = MAX_BUFFER_SIZE; +	uchar inputData[6]; +	int rc; +	uchar cc = 0; + +	inputData[0] = snum; +	rc = ipmi_cmd_mc(GET_SENSOR_TYPE, inputData, 1,  +                      resp,&sresp, &cc, fdebug); +	if (fdebug) printf("GetSensorType: ipmi_cmd rv = %d, cc = %x\n",rc,cc); +	if (rc != ACCESS_OK) return(rc); +	if (cc != 0) return(cc); +        /* successful, copy values */ +	if (stype != NULL) *stype = resp[0]; +	if (rtype != NULL) *rtype = resp[1] & 0x7f; +	return(rc); +} + +void set_reserve(int val) +{ +   fDoReserve = val; +} + +int sdr_get_reservation(uchar *res_id, int fdev) +{ +   int sresp; +   uchar resp[MAX_BUFFER_SIZE]; +   uchar cc = 0; +   ushort cmd; +   int rc = -1; + +   if (fDoReserve == 1) { +	fDoReserve = 0; /* only reserve SDR the first time */ +        sresp = sizeof(resp);; +	if (fdev) cmd = RESERVE_DEVSDR_REP; +	else cmd = RESERVE_SDR_REP; +	rc = ipmi_cmd_mc(cmd, NULL, 0, resp, &sresp, &cc, fdebug); +	if (rc == 0 && cc != 0) rc = cc; +	if (rc == 0) {  /* ok, so set the reservation id */ +	   resid[0] = resp[0];  +	   resid[1] = resp[1]; +        } +	/* A reservation is cancelled by the next reserve request. */ +        if (fdebug) +	   printf("ipmi_cmd RESERVE status=%d cc=%x id=%02x%02x\n", +		  rc,cc,resid[0],resid[1]); +   } else rc = 0; +   /* if not first time, or if error, return existing resid. */ +   res_id[0] = resid[0]; +   res_id[1] = resid[1]; +   return(rc); +} /*end sdr_get_reservation*/ + +int sdr_clear_repo(int fdev) +{ +   int sresp; +   uchar resp[MAX_BUFFER_SIZE]; +   uchar inputData[6]; +   uchar cc = 0; +   int rc = -1; +   ushort cmd; +   uchar resv[2] = {0,0}; + +   if (fReserveOK)  +	rc = sdr_get_reservation(resv,fdev); + +   cmd = 0x27 + (NETFN_STOR << 8);  /*Clear SDR Repository*/ +   inputData[0] = resv[0];     /*res id LSB*/ +   inputData[1] = resv[1];     /*res id MSB*/ +   inputData[2] = 'C'; +   inputData[3] = 'L';  +   inputData[4] = 'R'; +   inputData[5] = 0xAA;   +   sresp = sizeof(resp);; +   rc = ipmi_cmd_mc(cmd, inputData, 6, resp, &sresp,&cc, fdebug); +   if (fdebug) printf("sdr_clear_repo: rc = %d, cc = %x, sz=%d\n",rc,cc,sresp); +   if (rc == 0 && cc != 0) rc = cc; + +   if (rc == 0 && (resp[0] & 1) != 1) { +	if (fdebug) printf("Wait for sdr_clear_repo to complete\n"); +	os_usleep(1,0); +   } +   return(rc); +} + +int sdr_add_record(uchar *sdr, int fdev) +{ +   int sresp; +   uchar resp[MAX_BUFFER_SIZE]; +   uchar inputData[6+SZCHUNK]; +   uchar cc = 0; +   int rc = -1; +   ushort cmd; +   uchar resv[2] = {0,0}; +   int reclen, len, i; +   int recid, chunksz; +   uchar prog; + +   reclen = sdr[4] + 5; +   recid = sdr[0] + (sdr[1] << 8); +   /* OEM SDRs can be min 8 bytes, less is an error. */ +   if (reclen < 8) return(LAN_ERR_BADLENGTH);   +   if (fReserveOK)  +	rc = sdr_get_reservation(resv,fdev); +   if (fdebug) printf("sdr_add_record[%x]: reclen = %d, reserve rc = %d\n", +			recid,reclen,rc); + +   cmd = 0x25 + (NETFN_STOR << 8); /*PartialAddSdr*/ +   recid = 0;  /*first chunk must be added as 0000*/ +   chunksz = SZCHUNK; +   for (i = 0; i < reclen; ) +   { +      prog = 0; +      len = chunksz; +      if ((i+chunksz) >= reclen) { /*last record*/ +	  len = reclen - i; +	  prog = 1; +      } +      inputData[0] = resv[0]; /*res id LSB*/ +      inputData[1] = resv[1]; /*res id MSB*/ +      inputData[2] = recid & 0x00ff;         /*record id LSB*/ +      inputData[3] = (recid >> 8) & 0x00ff;  /*record id MSB*/ +      inputData[4] = (uchar)i;       /*offset */ +      inputData[5] = prog;    /*progress: 1=last record*/ +      memcpy(&inputData[6],&sdr[i],len); +      sresp = sizeof(resp); +      rc = ipmi_cmd_mc(cmd, inputData, 6+len, resp, &sresp,&cc, fdebug); +      if (fdebug)  +         printf("sdr_add_record[%x,%x]: rc = %d, cc = %x, sz=%d\n", +			recid,i,rc,cc,sresp); +      if (rc == 0 && cc != 0) rc = cc; +      if (rc != 0) break; +      if (recid == 0 && rc == 0)   /*first time, so set recid*/ +         recid = resp[0] + (resp[1] << 8); +      i += len; +   } +   return(rc); +} + +int GetSDR(int r_id, int *r_next, uchar *recdata, int srecdata, int *rlen) +{ +	int sresp; +	uchar resp[MAX_BUFFER_SIZE+SZCHUNK]; +	uchar respchunk[SZCHUNK+10]; +	uchar inputData[6]; +	uchar cc = 0; +	int rc = -1; +	int  i, chunksz, thislen, off; +	int reclen; +	ushort cmd; +	uchar resv[2] = {0,0}; +   +	chunksz = SZCHUNK; +        reclen = srecdata; /*max size of SDR record*/ +	off = 0; +        *rlen = 0; +        *r_next = 0xffff;  /*default*/ +	if (fReserveOK)  +	   rc = sdr_get_reservation(resv,fdevsdrs); +	if (fdevsdrs) cmd = GET_DEVICE_SDR; +	else cmd = GET_SDR; +	if (reclen == 0xFFFF) {  /* get it all in one call */ +	   inputData[0] = resv[0];     /*res id LSB*/ +	   inputData[1] = resv[1];     /*res id MSB*/ +	   inputData[2] = r_id & 0x00ff;        /*record id LSB*/ +	   inputData[3] = (r_id & 0xff00) >> 8;	/*record id MSB*/ +	   inputData[4] = 0;      /*offset */ +	   inputData[5] = 0xFF;  /*bytes to read, ff=all*/ +	   sresp = sizeof(resp);; +	   if (fdebug) printf("ipmi_cmd SDR id=%d read_all, len=%d\n", +				r_id,sresp); +	   rc = ipmi_cmd_mc(cmd, inputData, 6, recdata, &sresp,&cc, fdebug); +	   /* This will usually return cc = 0xCA (invalid length). */ +	   if (fdebug) printf("ipmi_cmd SDR data status = %d, cc = %x, sz=%d\n", +				rc,cc,sresp); +	   reclen = sresp; +	   *r_next = recdata[0] + (recdata[1] << 8); +	} else    /* if (reclen > chunksz) do multi-part chunks */ +	for (off = 0; off < reclen; ) +	{ +	   thislen = chunksz; +	   if ((off+chunksz) > reclen) thislen = reclen - off; +	   inputData[0] = resv[0];     /*res id LSB*/ +	   inputData[1] = resv[1];     /*res id MSB*/ +	   inputData[2] = r_id & 0x00ff; 	/*record id LSB*/ +	   inputData[3] = (r_id & 0xff00) >> 8;	/*record id MSB*/ +	   inputData[4] = (uchar)off;      /*offset */ +	   inputData[5] = (uchar)thislen;  /*bytes to read, ff=all*/ +	   sresp = sizeof(respchunk); +	   rc = ipmi_cmd_mc(cmd, inputData, 6, respchunk, &sresp,&cc, fdebug); +	   if (fdebug)  +               printf("ipmi_cmd SDR[%x] off=%d ilen=%d status=%d cc=%x sz=%d\n", +			r_id,off,thislen,rc,cc,sresp); +	   if (off == 0 && cc == 0xCA && thislen == SZCHUNK) {  +		/* maybe shorter than SZCHUNK, try again */ +	        chunksz = 0x06; +	        if (fdebug) printf("sdr[%x] try again with chunksz=%d\n", +					r_id,chunksz); +	        continue; +	   } +           if (off > chunksz) { +              /* already have first part of the SDR, ok to truncate */ +              if (rc == -3) { /* if LAN_ERR_RECV_FAIL */ +                  if (fdebug) printf("sdr[%x] error rc=%d len=%d truncated\n", +                                       r_id,rc,sresp); +                  sresp = 0; +                  rc = 0; +              } +              if (cc == 0xC8 || cc == 0xCA) { /* length errors */ +                  /* handle certain MCs that report wrong length, +                   * at least use what we already have (sresp==0) */ +                  if (fdebug) printf("sdr[%x] error cc=%02x len=%d truncated\n", +                                       r_id,cc,sresp); +                  cc = 0; +              } +           } +	   if (rc != ACCESS_OK) return(rc); +	   if (cc != 0) return(cc); +	   /* if here, successful, chunk was read */ +           if (sresp < (thislen+2)) { +              /* There are some SDRs that may report the wrong length, and +               * return less bytes than they reported, so just truncate. */ +              if (fdebug) printf("sdr[%x] off=%d, expected %d, got %d\n", +                                r_id,off,thislen+2,sresp); +              if (sresp >= 2) thislen = sresp - 2; +              else thislen = 0; +              reclen = off + thislen;  /* truncate, stop reading */ +              fprintf(stderr,"SDR record %x is malformed, length %d is less than minimum %d\n",r_id,sresp,thislen+2); +			  rc = ERR_SDR_MALFORMED; +           } +	   /* successful */ +	   memcpy(&resp[off],&respchunk[2],thislen); +	   if (off == 0 && sresp >= 5) { +		*r_next = respchunk[0] + (respchunk[1] << 8); +                reclen = respchunk[6] + 5;  /*get actual record size*/ +                if (reclen > srecdata) { +                  if (fdebug) printf("sdr[%x] chunk0, reclen=%d srecdata=%d\n", +                                        r_id, reclen, srecdata); +                  reclen = srecdata; /*truncate*/ +                } +           } +	   off += thislen; +           *rlen = off; +	} +	if (fdebug) { +           printf("GetSDR[%04x] next=%x (len=%d): ",r_id,*r_next,reclen);  +	   for (i = 0; i < reclen; i++) printf("%02x ",resp[i]); +	   printf("\n"); +	   } +	memcpy(recdata,&resp[0],reclen); +        *rlen = reclen; +	return(rc); +}  /*end GetSDR*/ + +static int nsdrs = 0;    /*number of sdrs*/ +static int sz_sdrs = 0;  /*actual size used with sdrs*/ +static uchar *psdrcache = NULL; + +void free_sdr_cache(uchar *ptr) +{ +   if (ptr != NULL) free(ptr); +   if ((ptr != psdrcache) && (psdrcache != NULL))  +		    free(psdrcache); +   psdrcache = NULL; +} + +int get_sdr_file(char *sdrfile, uchar **sdrlist) +{ +   int rv = -1; +   FILE *fp = NULL; +   int i, n, num, nsdr, isdr, len; +   uchar *sdrbuf; +   char buff[255]; +   uchar hbuf[85]; +   char fvalid; + +   fp = fopen(sdrfile,"r"); +   if (fp == NULL) { +         printf("Cannot open file %s\n",sdrfile); +         return(ERR_FILE_OPEN); +   } +   /* determine number of SDRs by number of lines in the file */ +   num = 0; +   while (fgets(buff, 255, fp)) { num++; } +   if (fdebug) { +     printf("Reading %d SDRs from file %s\n",num,sdrfile); +     if ((psdrcache != NULL) && (nsdrs > 0)) {  /*already have sdrcache*/ +	printf("get_sdr_file: Already have cache\n"); /*fdebug*/ +	free_sdr_cache(psdrcache); /*free previous sdrcache*/ +     } +   } +   sdrbuf = malloc(num * SDR_SZ);  +   if (sdrbuf == NULL) { +	fclose(fp); +	return(rv); +   } +   fseek(fp, 0L, SEEK_SET);  +   *sdrlist = sdrbuf;  +   psdrcache = sdrbuf; +   nsdrs = num; +   isdr = 0; +   nsdr = 0; +   while (fgets(buff, 255, fp)) { +   	len = strlen_(buff); +   	fvalid = 0; +   	if (buff[0] >= '0' && (buff[0] <= '9')) fvalid = 1; +   	else if (buff[0] >= 'a' && (buff[0] <= 'f')) fvalid = 1; +   	else if (buff[0] >= 'A' && (buff[0] <= 'F')) fvalid = 1; +   	if (fvalid == 0) continue; +	i = 0; +   	for (n = 0; n < len; ) { +           if (buff[n] < 0x20) break; /* '\n', etc. */ +           hbuf[i++] = htoi(&buff[n]); +	   n += 3; +   	} +	memcpy(&sdrbuf[isdr],hbuf,i); +	isdr += i; +	nsdr++; +   } /*end while*/ +   if (fdebug) printf("Read %d SDRs, %d bytes\n",nsdr,isdr); +   fclose(fp); +   rv = 0; +   return(rv); +} + +int get_sdr_cache(uchar **pret) +{ +   int rv = -1; +   int i, n, sz, len, asz; +   int recid, recnext; +   uchar *pcache; +   uchar *psdr; + +   if (pret == NULL) return(rv); +   fdevsdrs = use_devsdrs(fpicmg); + +   if ((psdrcache != NULL) && (nsdrs > 0)) {  /*already have sdrcache*/ +        *pret = psdrcache; +	if (fdebug) printf("get_sdr_cache: already have cache (%p)\n",*pret); +	return(0); +   } +   else if (fdebug) printf("get_sdr_cache: Allocating cache\n"); + +   rv = GetSDRRepositoryInfo(&n,&fdevsdrs); +   if (rv != 0) return(rv); +   if (n == 0) {   +	/* this is an error, probably because fdevsdrs is wrong.*/ +	if (fdebug) printf("get_sdr_cache: nsdrs=0, retrying\n"); +	fdevsdrs = (fdevsdrs ^ 1); +	n = 150; /*try some default num SDRs*/ +   } + +   sz = n * SDR_SZ;  /*estimate max size for n sdrs*/ +   pcache = malloc(sz); +   if (pcache == NULL) return(rv); +   psdrcache = pcache; +   *pret = pcache; +   memset(pcache,0,sz); +   recid = 0; +   asz = 0; +   for (i = 0; i <= n; i++) +   { +	if (recid == 0xffff) break; +	// psdr = &pcache[i * SDR_SZ];	 +        psdr = &pcache[asz]; +	rv = GetSDR(recid,&recnext,psdr,SDR_SZ,&len); +	if (fdebug)  +	   printf("GetSDR[%x] rv = %d len=%d next=%x\n",recid,rv,len,recnext); +	if (rv != 0) { +	   if (rv == 0xC5) { set_reserve(1); i--; } /*retry*/ +	   else break; +	} else {  /*success*/ +	   /* if sdrlen!=len, adjust */ +	   if ((len > 5) && (len != (psdr[4] + 5)) ) { +		if (fdebug) printf("SDR[%x] adjust len from %d to %d\n", +					recid,psdr[4]+5,len); +		psdr[4] = len - 5; +	   } +	   asz += len; +	   if (recnext == recid) recid = 0xffff; +	   else recid = recnext; +	} +   } +   nsdrs = n; +   sz_sdrs = asz;  /* save the size for later*/ +   if (fdebug) { +	printf("get_sdr_cache, n=%d sz=%d asz=%d\n",n,sz,asz); +	if (i < n) printf("get_sdr_cache error, i=%d < n=%d, rv=%d\n",i,n,rv); +   } +   return(rv); +} + +int find_nsdrs(uchar *pcache) +{ +   int num = 0; +   ulong asz = 0; +   int i, len; +   uchar *sdr; +   ushort recid = 0; + +   if (pcache == NULL) return(num); +   for (i = 0; (int)asz < sz_sdrs; i++) +   { +	sdr = &pcache[asz]; +	if (sdr[2] != 0x51) {  /* Dell SDR length error */ +	    printf("SDR[%x] length error at %ld\n",recid,asz); +	    sdr = &pcache[++asz]; /*try it if off-by-one*/ +	} +	len = sdr[4] + 5; +	recid = sdr[0] + (sdr[1] << 8); +	if (fdebug) printf("SDR[%x] len=%d i=%d offset=%lx\n",recid,len,i,asz); +	asz += len; +   } +   num = i; +   return(num); +} + +int find_sdr_by_snum(uchar *psdr, uchar *pcache, uchar snum, uchar sa) +{ +   int rv = -1; +   uchar *sdr; +   int i, k, len; +   int asz = 0; +   if (psdr == NULL) return(rv); +   if (pcache == NULL) return(rv); +   for (i = 0; i <= nsdrs; i++) +   { +	// sdr = &pcache[i * SDR_SZ];	 +	sdr = &pcache[asz];	 +	len = sdr[4] + 5; +	asz += len; +	switch(sdr[3]) { +	case 0x01: k = 7; break; /*full sensor*/ +	case 0x02: k = 7; break; /*compact sensor*/ +	case 0x03: k = 7; break;/*compact sensor*/ +	default:   k = 0; break; +	} +	if (k == 0) continue; +	else { +	    if ((sdr[5] == sa) && (sdr[k] == snum)) { +		memcpy(psdr,sdr,len); +		return(0); +	    } +	} +   } +   return(rv); +} + +int find_sdr_by_tag(uchar *psdr, uchar *pcache, char *tag, uchar dbg) +{ +   int rv = -1; +   uchar *sdr; +   int i, k, n, len; +   int asz = 0; +   if (psdr == NULL) return(rv); +   if (pcache == NULL) return(rv); +   if (tag == NULL) return(rv); +   if (dbg) fdebug = 1; +   n = strlen_(tag); +   if (fdebug) printf("find_sdr_by_tag(%s) nsdrs=%d\n",tag,nsdrs); +   for (i = 0; i <= nsdrs; i++) +   { +	// sdr = &pcache[i * SDR_SZ];	 +	sdr = &pcache[asz]; +	len = sdr[4] + 5; +	asz += len; +	switch(sdr[3]) { /* set tag offset by SDR type */ +	case 0x01: k = 48; break; /*full SDR*/ +	case 0x02: k = 32; break; /*compact SDR*/ +	case 0x03: k = 17; break; /*event-only SDR*/ +	case 0x10: k = 16; break; /*device locator SDR*/ +	case 0x11: k = 16; break; /*FRU device locator SDR*/ +	case 0x12: k = 16; break; /*IPMB device locator SDR*/ +	default:   k = 0; break;  /*else do not have an ID string/tag*/ +	} +	if (k == 0) { +	   if (fdebug) printf("sdr[%d] idx=%02x%02x num=%x type=%x skip\n", +				i,sdr[1],sdr[0],sdr[7],sdr[3]); +	   continue; +	} else { +	    if (len > SDR_SZ) len = SDR_SZ; +	    if (fdebug) { +		char tmp[17]; +		memset(tmp,0,sizeof(tmp)); +		memcpy(tmp,&sdr[k],(len - k)); +		tmp[16] = 0;  /*force stringify*/ +		printf("sdr[%d] idx=%02x%02x num=%x tag: %s\n",i,sdr[1],sdr[0], +			sdr[7],tmp); +	    } +	    if (strncmp(tag,(char *)&sdr[k],n) == 0) { +		memcpy(psdr,sdr,len); +		return(0); +	    } +	} +   } +   return(rv); +} + + +int find_sdr_next(uchar *psdr, uchar *pcache, ushort id) +{ +   int rv = -1; +   uchar *sdr; +   int i, imatch, len; +   ushort recid; +   int asz = 0; +   if (psdr == NULL) return(rv); +   if (pcache == NULL) return(rv); +   imatch = nsdrs; +   for (i = 0; i < nsdrs; i++) +   { +	// sdr = &pcache[i * SDR_SZ]; +	sdr = &pcache[asz]; +	if (sdr[2] != 0x51)   /* Dell SDR off-by-one error */ +	    sdr = &pcache[++asz];  +	len = sdr[4] + 5; +	recid = sdr[0] + (sdr[1] << 8); +	asz += len; +	// if (fdebug) printf("SDR[%x] len=%d id=%x i=%d imatch=%d\n", +	//			recid,len,id,i,imatch); +	if (recid == id) imatch = i + 1; /*matches prev, return next one*/ +	else if (id == 0) { rv = 0; break; } /* 0000 = first one */ +	if (i == imatch) { rv = 0; break; } +   } +   if (rv == 0) memcpy(psdr,sdr,len); +   return(rv); +} + +int find_sdr_by_id(uchar *psdr, uchar *pcache, ushort id) +{ +   int rv = -1; +   uchar *sdr; +   int i, imatch, len; +   ushort recid; +   int asz = 0; +   if (psdr == NULL) return(rv); +   if (pcache == NULL) return(rv); +   imatch = nsdrs; +   for (i = 0; i < nsdrs; i++) +   { +	sdr = &pcache[asz]; +	len = sdr[4] + 5; +	recid = sdr[0] + (sdr[1] << 8); +	asz += len; +	if (recid == id) { rv = 0; break; } +	else if (id == 0) { rv = 0; break; } /* 0000 = first one */ +   } +   if (rv == 0) memcpy(psdr,sdr,len); +   return(rv); +} + +uchar +bitnum(ushort value) +{ +   uchar ret = 0; +   int i; +   /* returns the highest bit number number set in this word. */ +   /* Bit numbers are 1-based in this routine, 0 means no bits set. */ +   /* scan 15 bits (0x7FFF). */ +   for (i = 0; i < 15; i++) { +	if (value & 0x01) ret = i+1;  /*was ret++;*/ +	value = (value >> 1); +   } +   return(ret); +} + +static double +expon(int x, int y) +{ +   double res; +   int i; +   /* compute exponent: x to the power y */ +   res = 1; +   if (y > 0) { +	for (i = 0; i < y; i++) res = res * x; +   } else if (y < 0) { +	for (i = 0; i > y; i--) res = res / x; +   } /* else if if (y == 0) do nothing, res=1 */ +   return(res); +} + +double +RawToFloat(uchar raw, uchar *psdr) +{ +   double floatval; +   int m, b, a; +   uchar  ax;  +   int  rx, b_exp; +   SDR01REC *sdr; +   int signval; + +   sdr = (SDR01REC *)psdr; +   floatval = (double)raw;  /*default*/ + +   // if (raw == 0xff) floatval = 0; else  +   if (sdr->rectype == 0x01) {  /* SDR rectype == full */ +	if (fdebug) +	   printf("units=%x base=%d mod=%d (raw=%x, nom_rd=%x)\n", +		sdr->sens_units,sdr->sens_base,sdr->sens_mod, +		raw, sdr->nom_reading); +	m = sdr->m + ((sdr->m_t & 0xc0) << 2); +	b = sdr->b + ((sdr->b_a & 0xc0) << 2); +	if (b & 0x0200) b = (b - 0x0400);  /*negative*/ +	if (m & 0x0200) m = (m - 0x0400);  /*negative*/ +	rx = (sdr->rx_bx & 0xf0) >> 4; +	if (rx & 0x08) rx = (rx - 0x10); /*negative, fix sign w ARM compilers*/ +	a = (sdr->b_a & 0x3f) + ((sdr->a_ax & 0xf0) << 2); +	ax = (sdr->a_ax & 0x0c) >> 2; +	b_exp = (sdr->rx_bx & 0x0f); +	if (b_exp & 0x08) b_exp = (b_exp - 0x10);  /*negative*/ +		//b_exp |= 0xf0;        /* negative 8-bit */ +	if ((sdr->sens_units & 0xc0) == 0) {  /*unsigned*/ +		floatval = (double)raw; +	} else {  /*signed*/ +		if (raw & 0x80) signval = (raw - 0x100); +		else signval = raw; +		floatval = (double)signval; +	} +	floatval *= (double) m; +#ifdef MATH_OK +	floatval += (b * pow (10,b_exp)); +	floatval *= pow (10,rx); +#else +	floatval += (b * expon (10,b_exp)); +	floatval *= expon (10,rx); +#endif +	if (fdebug) +	   printf("decode1: m=%d b=%d b_exp=%x rx=%d, a=%d ax=%d l=%x, floatval=%f\n", +			m,b,b_exp,rx,a,ax,sdr->linear,floatval); +	switch(sdr->linear) { +	case 0:   /*linear*/ +	   break; +	case 7:   /*invert 1/x*/ +	   /* skip if zero to avoid dividing by zero */ +	   if (raw != 0) floatval = 1 / floatval; +	   break; +	case 1:   /*ln*/ +	case 2:   /*log10, log2, e, exp10, exp2, */ +	case 3:   /*log2*/ +	case 4:   /*e*/ +	case 5:   /*exp10*/ +	case 6:   /*exp2*/ +	case 8:   /*sqr(x)*/ +	case 9:   /*cube(x)*/ +	case 10:  /*sqrt(x)*/ +	case 11:  /*cube-1(x)*/ +        default: +	   if (fdebug) printf("linear mode %x not implemented\n",sdr->linear); +	   break; +	}  /*end-switch linear*/ +   } + +#ifdef NOT_LINEAR +   /* else if (sdr->linear != 7) */ +   { +     double be, re; +     rc = GetSensorType(sdr->sens_num,&stype,&rtype); +     if (fdebug) +	printf("decode: rc=%x, stype=%x, rtype=%x\n",rc,stype,rtype); +     if (rc != 0) return(floatval); + +     /* GetSensorReadingFactors */ +     rc = GetSensorReadingFactors(sdr->sens_num,raw,&m,&b,&b_exp,&r,&a); +     if (rc == 0) { +	// floatval = ((m * raw) + (b * be)) * re; +     }  +     if (fdebug) printf("decode: rc=%x, floatval=%f\n",rc,floatval); +   } +#endif + +   return(floatval); +} + +#define IpmiAnalogDataFormatUnsigned 0 +#define IpmiAnalogDataFormat1Compl   1 +#define IpmiAnalogDataFormat2Compl   2 + +uchar +FloatToRaw(double val, uchar *psdr, int rounding) +{ +   double      cval; +   int         lowraw, highraw, raw, maxraw, minraw, next_raw; +   int         analog_dfmt; + +   analog_dfmt = (psdr[20] >> 6) & 0x03; +   switch( analog_dfmt ) +   { +       case IpmiAnalogDataFormat1Compl: +            lowraw   = -127; +            highraw  = 127; +            minraw   = -127; +            maxraw   = 127; +            next_raw = 0; +            break; +       case IpmiAnalogDataFormat2Compl: +            lowraw   = -128; +            highraw  = 127; +            minraw   = -128; +            maxraw   = 127; +            next_raw = 0; +            break; +       case IpmiAnalogDataFormatUnsigned: +       default: +            lowraw   = 0; +            highraw  = 255; +            minraw   = 0; +            maxraw   = 255; +            next_raw = 128; +            break; +    } + +    /* do a binary search for the right nth root value */ +    do { +        raw = next_raw; +        cval = RawToFloat( (uchar)raw, psdr ); +        if ( cval < val ) { +            next_raw = ((highraw - raw) / 2) + raw; +            lowraw = raw; +        } else { +            next_raw = ((raw - lowraw) / 2) + lowraw; +            highraw = raw; +        } +    } while ( raw != next_raw ); +    +    /* Do rounding to get the final value */ +    switch( rounding ) { +       case 0:   /* Round Normal = Round to nearest value */ +            if ( val > cval ) { +                 if ( raw < maxraw ) { +                      double nval; +		      nval = RawToFloat((uchar)(raw+1),psdr); +                      nval = cval + ((nval - cval) / 2.0); +                      if ( val >= nval ) raw++; +                 } +            } else { +                 if ( raw > minraw ) { +                      double pval; +		      pval = RawToFloat((uchar)(raw-1),psdr); +                      pval = pval + ((cval - pval) / 2.0); +                      if ( val < pval ) raw--; +                 } +            } +            break; +       case 1:  /*Round Down*/ +            if ((val < cval) && (raw > minraw )) raw--; +            break; +       case 2:  /*Round Up*/ +            if ((val > cval) && (raw < maxraw)) raw++; +            break; +     } +     if ( analog_dfmt == IpmiAnalogDataFormat1Compl ) +        if ( raw < 0 ) raw -= 1; +    return((uchar)raw); +}  /*end FloatToRaw()*/ + +static int fill_thresholds(double *thrf, uchar *sdr) +{ +   int rv = 0; +   uchar *vals; +   uchar bits; + +   // snum = sdr[7]; +   bits = sdr[19]; /*which are settable*/ +   vals = &sdr[36]; +   if (fdebug)  +      printf("fill_thresholds: bits=%02x, values: %f>=%f>=%f, %f<=%f<=%f\n", +		bits, thrf[0],thrf[1],thrf[2], thrf[3],thrf[4],thrf[5]); +   if (thrf[0] == THR_EMPTY) { +	if ((bits & 0x01) != 0) { /*lo-noncrit*/ +	   thrf[0] = RawToFloat(vals[5],sdr); +           rv++; +        } else thrf[0] = 0; +   } +   if (thrf[1] == THR_EMPTY) {  +	if ((bits & 0x02) != 0) { /*lo-crit*/ +	   thrf[1] = RawToFloat(vals[4],sdr); +           rv++; +	} else thrf[1] = 0; +   } +   if (thrf[2] == THR_EMPTY) {  +	if ((bits & 0x04) != 0) { /*lo-unrec*/ +	   thrf[2] = RawToFloat(vals[3],sdr); +           rv++; +	} else thrf[2] = 0; +   } +   if (thrf[3] == THR_EMPTY) {  +	if ((bits & 0x08) != 0) { /*hi-noncrit*/ +	   thrf[3] = RawToFloat(vals[2],sdr); +           rv++; +	} else thrf[3] = 0; +   } +   if (thrf[4] == THR_EMPTY) {  +	if ((bits & 0x10) != 0) { /*hi-crit*/ +	   thrf[4] = RawToFloat(vals[1],sdr); +           rv++; +	} else thrf[4] = 0; +   } +   if (thrf[5] == THR_EMPTY) {  +	if ((bits & 0x20) != 0) { /*hi-unrec*/ +	   thrf[5] = RawToFloat(vals[0],sdr); +           rv++; +	} else thrf[5] = 0; +   } +   if (fdebug) +      printf("fill_thresholds: after rv=%d values: %f>=%f>=%f, %f<=%f<=%f\n", +	      rv,thrf[0],thrf[1],thrf[2], thrf[3],thrf[4],thrf[5]); +   return(rv);  +} + +char * +decode_itype(uchar itype) +{ +   char *retstr; +   int i; +   /* Decode the Interrupt Type from Entity Assoc records */ + +   retstr = tmpstr; +   if (itype <= 0x0f) sprintf(retstr,"IRQ_%d",itype); +   else if (itype <= 0x13) { +	strcpy(retstr,"PCI-A"); +	for (i=0x10;i<itype;i++) retstr[4]++; +	} +   else if (itype == 0x14) strcpy(retstr,"SMI"); +   else if (itype == 0x15) strcpy(retstr,"SCI"); +   else if (itype >= 0x20 && itype <= 0x5f)  +	sprintf(retstr,"SysInt_%d",itype-0x20); +   else if (itype == 0x60) strcpy(retstr,"ACPI/PnP"); +   else if (itype == 0xFF) strcpy(retstr,"NoInt"); +   else strcpy(retstr,"Invalid"); +   return(retstr); +} + +int decode_oem_sensor(uchar *sdr,uchar *reading,char *pstring,int slen) +{ +   int rv = -1; +#ifdef METACOMMAND +   switch(vend_id) { +      case VENDOR_INTEL:  +          rv = decode_sensor_intel(sdr, reading, pstring, slen); +          break; +      case VENDOR_KONTRON:  +          rv = decode_sensor_kontron(sdr, reading, pstring, slen); +          break; +      case VENDOR_FUJITSU: +          rv = decode_sensor_fujitsu(sdr,reading,pstring,slen); +          break; +      case VENDOR_SUN:  +          rv = decode_sensor_sun(sdr, reading, pstring, slen); +          break; +      case VENDOR_MAGNUM:  +      case VENDOR_SUPERMICRO:  +      case VENDOR_SUPERMICROX:  +          rv = decode_sensor_supermicro(sdr,reading,pstring,slen,fsimple,fdebug); +          break; +      case VENDOR_QUANTA:  +          rv = decode_sensor_quanta(sdr, reading, pstring, slen); +          break; +      case VENDOR_HP:  +          rv = decode_sensor_hp(sdr, reading, pstring, slen); +          break; +      case VENDOR_DELL:  +          rv = decode_sensor_dell(sdr, reading, pstring, slen); +          break; +      case VENDOR_IBM:  +      case VENDOR_LENOVO:  +      case VENDOR_LENOVO2:  +          rv = decode_sensor_lenovo(sdr, reading, pstring, slen); +          break; +      case VENDOR_ASUS:  +          rv = decode_sensor_asus(sdr, reading, pstring, slen); +          break; +      default: +	  break; +   } /*end-switch vend_id*/ +   if (fdebug) // && rv == 0) +      printf("decode_oem_sensor rv=%d vend=%x string=%s\n",rv,vend_id,pstring); +#endif +   return (rv); +} + +int show_oemsdr(int vend, uchar *sdr) +{ +   int rv = -1; +   int i, len; + +#ifdef METACOMMAND +   if (vend == VENDOR_INTEL) { +      show_oemsdr_intel(sdr); /*show subtypes for Intel BMC_TAM*/ +      rv = 0; +   } else if (vend == 4156) {  /*special HP/NewAccess OEM SDR*/ +      show_oemsdr_hp(sdr);     +      rv = 0; +   } else if (vend == VENDOR_QUANTA) { +      printf("Quanta: "); +      show_oemsdr_nm(sdr);  +      rv = 0; +   } +#endif +   if (rv != 0) { +      len = sdr[4] + 5; +      if (vend == VENDOR_FUJITSU) printf("Fujitsu: "); +      else if (vend == VENDOR_INTEL) printf("Intel: "); +      else printf("manuf=%d: ",vend); +      for (i = 8; i < len; i++) printf("%02x ",sdr[i]); +      printf("\n"); +   } +   return(rv); +} + +void +ShowThresh(int flg, uchar bits, uchar *vals, uchar *sdr) +{ +   char str[128] = ""; +   char part[24]; /* ~15 bytes used */ +   double ival; +   char sep[4]; +   char *tag; +   tag = ""; +   if (fsimple) { +	sprintf(sep,"%c ",bdelim); +	tag = "Thresholds"; +   } else sep[0] = 0; /*null string*/ +   if (fshowthr == 2) { +	double i0, i1, i2, i3, i4, i5; +        i0 = RawToFloat(vals[0],sdr); +        i1 = RawToFloat(vals[1],sdr); +        i2 = RawToFloat(vals[2],sdr); +        i3 = RawToFloat(vals[3],sdr); +        i4 = RawToFloat(vals[4],sdr); +        i5 = RawToFloat(vals[5],sdr); +	sprintf(str,"%.2f:%.2f:%.2f:%.2f:%.2f:%.2f",i0,i1,i2,i3,i4,i5); +	printf("\t%s%s%s%c",sep,"Thresh ",str,chEol); +   } else if (flg != 0) {  /* Compact, did GetThresholds, reverse order */ +	if (bits & 0x20) { +		ival = RawToFloat(vals[5],sdr); +		sprintf(part,"%shi-unrec %.2f ",sep,ival); +		strcat(str,part); +	} +	if (bits & 0x10) { +		ival = RawToFloat(vals[4],sdr); +		sprintf(part,"%shi-crit %.2f ", sep,ival); +		strcat(str,part); +	} +	if (bits & 0x08) { +		ival = RawToFloat(vals[3],sdr); +		sprintf(part,"%shi-noncr %.2f ",sep,ival); +		strcat(str,part); +	} +	if (bits & 0x01) { +		ival = RawToFloat(vals[0],sdr); +		sprintf(part,"%slo-noncr %.2f ",sep,ival); +		strcat(str,part); +	} +	if (bits & 0x02) { +		ival = RawToFloat(vals[1],sdr); +		sprintf(part,"%slo-crit %.2f ", sep,ival); +		strcat(str,part); +	} +	if (bits & 0x04) { +		ival = RawToFloat(vals[2],sdr); +		sprintf(part,"%slo-unrec %.2f ",sep,ival); +		strcat(str,part); +	} +	if (flg == 2) { +	   if (sens_verbose) tag = "Volatile "; +	   printf("\t%s%s%s%c",sep,tag,str,chEol); +	} else  +	   printf("\t%s%s%s%c",sep,tag,str,chEol); +   } else {  /*Full SDR*/ +	if (fdebug) printf("ShowThresh[%x]: bits=%02x, sdr18=%02x %02x\n", +				sdr[7],bits,sdr[18],sdr[19]); +	if (bits & 0x20) { +		ival = RawToFloat(vals[0],sdr); +		sprintf(part,"%shi-unrec %.2f ",sep,ival); +		strcat(str,part); +	} +	if (bits & 0x10) { +		ival = RawToFloat(vals[1],sdr); +		sprintf(part,"%shi-crit %.2f ",sep,ival); +		strcat(str,part); +	} +	if (bits & 0x08) { +		ival = RawToFloat(vals[2],sdr); +		sprintf(part,"%shi-noncr %.2f ",sep,ival); +		strcat(str,part); +	} +	if (bits & 0x01) { +		ival = RawToFloat(vals[5],sdr); +		sprintf(part,"%slo-noncr %.2f ",sep,ival); +		strcat(str,part); +	} +	if (bits & 0x02) { +		ival = RawToFloat(vals[4],sdr); +		sprintf(part,"%slo-crit %.2f ",sep,ival); +		strcat(str,part); +	} +	if (bits & 0x04) { +		ival = RawToFloat(vals[3],sdr); +		sprintf(part,"%slo-unrec %.2f ",sep,ival); +		strcat(str,part); +	} +	if (sens_verbose) tag = "SdrThres "; +	printf("\t%s%s%s%c",sep,tag,str,chEol); +	if (sens_verbose) +	{ 	/* show max/min  & hysteresis from full sdr */ +		str[0] = 0; +		ival = RawToFloat(sdr[31],sdr); +		sprintf(part,"%snom %.2f ",sep,ival); +		strcat(str,part); +		ival = RawToFloat(sdr[32],sdr); +		sprintf(part,"%snmax %.2f ",sep,ival); +		strcat(str,part); +		ival = RawToFloat(sdr[33],sdr); +		sprintf(part,"%snmin %.2f ",sep,ival); +		strcat(str,part); + +		ival = RawToFloat(sdr[34],sdr); +		sprintf(part,"%ssmax %.2f ",sep,ival); +		strcat(str,part); +	  +		ival = RawToFloat(sdr[35],sdr); +		sprintf(part,"%ssmin %.2f ",sep,ival); +		strcat(str,part); +	    +#ifdef OLD +		ival = RawToFloat(sdr[42],sdr); +		sprintf(part,"%s+hyst %.2f ",sep,ival); +		strcat(str,part); + +		ival = RawToFloat(sdr[43],sdr); +		sprintf(part,"%s-hyst %.2f ",sep,ival); +		strcat(str,part); +#endif +	 +		printf("\t%s%c",str,chEol); +	} +   }  /*endif full sdr*/ +} + +int decode_comp_generic(uchar type, uchar evtype, uchar num, ushort reading) +{ +	int istr = 0; +    uchar b; +	   /* decode via evtype */ +       switch(evtype) +	   { +	   case 0x02:	 +		  if (reading & 0x01) istr = 85; /* Active */ +		  if (reading & 0x02) istr = 86; /* Busy */ +		  else istr = 84;  /* Idle (OK)) */ +	   case 0x03: +		  if (reading & 0x01) istr = 13; /* Asserted */ +		  else istr = 0;  /* "OK" Deasserted */ +	      break; +	   case 0x04: +		  if (reading & 0x01) istr = 15; /* Predictive Failure */ +		  else istr = 0;  /* "OK" Deasserted */ +	      break; +	   case 0x05: +		  if (reading & 0x01) istr = 65; /* Limit Exceeded*/ +		  else istr = 0;  /* "OK" LimitNotExceeded*/ +	      break; +	   case 0x07:	/* transition */ +		  b = bitnum(reading); +		  switch(b) { +		  case 0: istr = 0; break; /*no bits set, OK*/ +		  case 1: istr = 87; break; /*transition up to Non-Critical*/ +		  case 2: istr = 88; break; /*transition up to Critical */ +		  case 3: istr = 89; break; /*transition up to Non-recoverable */ +		  case 4: istr = 87; break; /*transition down to Non-Critical */ +		  case 5: istr = 88; break; /*transition down to Critical */ +		  case 6: istr = 89; break; /*transition to Non-recoverable */ +		  case 7: istr = 90; break; /*Monitor*/ +		  case 8: istr = 91; break; /*Informational*/ +		  default: istr = 8; break; /*'OK*'*/ +		  } +	      break; +	   case 0x08: +		  if (reading & 0x01) istr = 9; /* Present */ +		  else istr = 10;  /*Absent*/ +	      break; +	   case 0x09:	/*  Availability event states */ +		  if (reading & 0x01) istr = 17; /* Enabled */ +		  else istr = 16;  /*Disabled*/ +	      break; +	   case 0x0A:	/* */ +		  b = (reading & 0x7f); +		  switch(b) { +		  case 0x00: istr = 8;  break; /* 00 'OK*'*/ +		  case 0x01: istr = 92; break; /* transition to Running */ +		  case 0x02: istr = 93; break; /* transition to In Test */ +		  case 0x04: istr = 94; break; /* transition to Power Off */ +		  case 0x08: istr = 95; break; /* transition to On Line */ +		  case 0x10: istr = 96; break; /* transition to Off Line */ +		  case 0x20: istr = 97; break; /* transition to Off Duty */ +		  case 0x40: istr = 98; break; /* transition to Degraded */ +		  case 0x80: istr = 99; break; /* transition to Power Save */ +		  default: istr = 100; break; /* Install Error */ +		  } +	      break; +	   case 0x0B:	/* Redundancy */ +		  b = (reading & 0x7f); +		  switch(b) { +		  case 0x00: istr = 8;  break; /* 00 'OK*'*/ +		  case 0x01: istr = 18; break; /* 01 Fully Redundant */ +		  case 0x02: istr = 19; break; /* 02 Redundancy Lost */ +		  case 0x04: istr = 20; break; /* 04 Redundancy Degraded */ +		  case 0x08: istr = 82; break; /* 08 Non-Redundant/Sufficient down */ +		  case 0x10: istr = 82; break; /* 10 Non-Redundant/Sufficient up*/ +		  case 0x20: istr = 83; break; /* 20 Non-Redundant/Insufficient */ +		  case 0x40: istr = 20; break; /* 40 Redundancy Degraded down */ +		  default: istr = 20; break; /* Redundancy Degraded up */ +		  } +	      break; +	   case 0x0C:	/* ACPI Power States */ +		  if (reading & 0x04)      istr = 21; /* D3, Off */ +		  else if (reading & 0x02) istr = 23; /* D2, Sleeping */ +		  else if (reading & 0x01) istr = 22; /* D1, Working */ +		  else istr = 24;  /*D0, On*/ +	      break; +	   default: +	      if (fdebug)  +		    printf("sensor[%x] et %02x type %02x not decoded, reading = %04x\n", +				   num,evtype,type,reading); +	      istr = STR_OTHER;  /* other " - " */ +	      break; +	   } +	return(istr); +} + +/*  + * decode_comp_reading + *  + * Decodes the readings from compact SDR sensors. + * Use sensor_dstatus array for sensor reading types and meaning strings. + * Refer to IPMI Table 36-1 and 36-2 for this. + *  + * Note that decoding should be based on sensor type and ev_type only, + * except for end cases. + *  + * Note reading1 = sens_reading[2], reading2 = sens_reading[3] + */ +int  +decode_comp_reading(uchar type, uchar evtype, uchar num,  +		    uchar reading1, uchar reading2) +{ +   int istr = 0;  /*string index into sensor_dstatus[] */ +   uchar b; +   ushort reading; +   static char customstr[35]; + +   /* usually reading2 has h.o. bit set (0x80). */ +   reading = reading1 | ((reading2 & 0x7f) << 8); + +   switch(type) +   { +	case 0x01:	/*Discrete Thermal, Temperature*/ +	   if (fdebug)  +	      printf("Discrete Thermal snum %x evtype=%x reading=%x\n", +				num,evtype,reading); +	   if (evtype == 0x07) { +		   b = bitnum(reading); +		   if (b == 0) istr = 8; /*no bits set, "OK*"*/ +		   else if (b < 3) istr = 0; /*bits 1,2 "OK"*/ +		   else istr = 65; /*transition to error, Limit Exceeded*/ +	   } else if (evtype == 0x05) { +		   /* see CPU1 VRD Temp on S5000, snum 0xc0 thru 0xcf */ +		   if (reading & 0x01) istr = 65; /* Limit Exceeded*/ +		   else istr = 0;  /* "OK" LimitNotExceeded*/ +	   } else if (evtype == 0x03) { +		   if (reading & 0x01) istr = 13; /* Asserted */ +		   else istr = 0;  /* "OK" Deasserted */ +	   } else {   /* evtype == other 0x05 */ +		   if (reading & 0x01) istr = 0; /* 8="OK*", 0="OK" */ +		   else istr = 5; /*state asserted, Crit-hi */ +	   }  +	   break; +	case 0x02:	/*Discrete Voltage*/ +	   { /* evtype == 0x05 for VBat, 0x03 for VR Watchdog */ +	      if (reading & 0x01) istr = 65; /*LimitExceeded, was Crit-hi*/ +              else istr = 0; /* "OK" LimitNotExceeded*/  +	   } +	   break; +	case 0x04:	/*Fan*/ +	   if (evtype == 0x0b) {  /*redundancy*/ +	      b = reading & 0x3f; +	      if (b == 0x00) istr = 16;   /*sensor disabled*/ +	      else if (b == 0x01) istr = 18;  /*fully redundant*/ +	      else if (b == 0x02) istr = 19; /*redundancy lost*/ +	      else if (b == 0x0b) istr = STR_AC_LOST; /*ac lost*/ +	      else istr = 20; /*redundancy degraded*/ +	   } else if (evtype == 0x08) {  /*presence*/ +              if (reading & 0x02) istr = 9;   /*Present/Inserted*/ +              else if (reading & 0x01) istr = 10; /*Absent/Removed*/ +              else /*reading==00*/ istr = 47; /*Unused*/ +	   } else if (evtype == 0x03) {  /*PS Fan Fail*/ +	      if (reading == 0) istr = 0; /*OK*/ +	      else istr = 12;  /*faulty*/ +	   } else {  /*other evtype*/ +	      b = reading & 0x0f; +	      if (b == 0) istr = 12;  /*faulty*/ +              else if (b & 0x01) istr = 11;  /*ready*/ +	      else istr = 41;   /*Unknown*/ +	   } +	   break; +	case 0x05:	/*Physical Security, Chassis */ +	   if (reading == 0) istr = 0; /*OK*/ +	   else if (reading & 0x01) istr = 38; /*chassis intrusion*/ +	   /* 0x02 Drive bay intrusion */ +	   /* 0x04 IO area intrusion */ +	   /* 0x08 Processor area intrusion */ +	   else if (reading & 0x10) istr = 37; /*lan leash lost*/ +	   /* 0x20 Dock/Undock */ +	   /* 0x40 Fan area intrusion */ +	   else istr = 41; /* Unknown, was bitnum(reading); */ +	   break; +	case 0x07:	/*Processor Status - 0x80 is OK/Present */ +	   b = bitnum(reading); +	   if (evtype == 0x03) { +              if (b <= 1) istr = 0; /*bit1 Deasserted, OK* */ +	      else istr = 13; /*bit2 Asserted*/   +	   } else {   /*usu 0x6f*/ +              if (b > 10) istr = 41; /*Unknown*/ +              else if (b == 0) istr = 0;  /*OK*/ +              else istr = 47 + b;  /*Proc strings 48 thru 57*/ +	   } +	   break; +	case 0x08:	/*Power Supply*/ +	   b = reading & 0x7f; +	   if (b == 0) istr = 10;  /*absent*/ +	   else if (b & 0x40) istr = STR_PS_CONFIG; /*Config Err*/ +	   else if (b & 0x08) istr = STR_AC_LOST; /*AC Lost*/ +	   else if (b & 0x04) istr = 15; /*Predictive Fail*/ +	   else if (b & 0x02) istr = STR_PS_FAIL; /*PS Fail*/ +	   else if (b & 0x01) istr =  9; /*present*/ +	   break; +	case 0x09:	/*Power Unit*/ +	   b = reading & 0x3f; +	   if (evtype == 0x0b) {  /*Power Redundancy*/ +	      if (b == 0x00) istr = 16;   /*sensor disabled*/ +	      else if (b == 0x01) istr = 18;  /*fully redundant*/ +	      else if (b == 0x02) istr = 19; /*redundancy lost*/ +	      else if (b == 0x0b) istr = STR_AC_LOST; /*ac lost*/ +	      else istr = 20; /*redundancy degraded*/ +	   } else {  /* Power Unit (evtype==0x6f or 0xef) */ +	      if (b == 0) istr = 17;   /*enabled*/ +	      else if ((b & 0x01) == 1) istr = 16;  /*disabled*/ +	   } +	   break; +	case 0x0C:	/* Memory */ +	   b = reading & 0x3f; +           if (b == 0) istr = 0;  /*OK*/ +           else if (b & 0x01) istr = 8;  /*Correctable ECC (OK*)*/ +           else if ((b & 0x02) || (b & 0x20)) istr = 39;  /*ECC Error*/ +           else if (b & 0x04) istr = 40;  /*Parity Error*/ +	   else istr = bitnum(b);  /* ECC or other error */ +	   break; +	case 0x0D:	/* drive slot - usually HSC sens_ownid == 0xc0 */ +	   if (fRomley || fGrantley) {  /* evtype==0x6f, has both status and presence */ +	      if (reading & 0x02) istr = 12; /*Faulty*/ +	      else if (reading & 0x80) istr = STR_REBUILDING; /*Rebuilding*/ +	      else if (reading & 0x01) istr = 9; /*Present (OK)*/ +	      else istr = 10; /*Absent*/ +	   } else { +	      if (evtype == 8) {  /* HSC slot presence sensors (num > 8)*/ +                 if (reading1 & 0x02) istr = 9;   /*Present/Inserted*/ +                 else if (reading1 & 0x01) istr = 10; /*Absent/Removed*/ +                 else /*reading1==00*/ istr = 47; /*Unused*/ +	      } else { /* HSC slot status sensors (evtype==0x6f)*/ +                 /* usually reading2 == 0x82 or 0x8E if healthy */ +                 if (reading2 & 0x01) istr = 12; /*state8=Rebuild stopped*/ +                 else if (reading2 & 0x02) istr = 11; /*state9=Inserted/Ready */ +                 else if (reading2 & 0x04) istr = 11; /*state10=Safe_to_Remove*/ +                 else if (reading2 & 0x08) istr = 11; /*state11=Ready */ +                 else if (reading2 == 0x80) istr = 47; /*no states, Unused*/ +                 else istr = 12;  /*faulty*/ +                 b = 8;  /*if no bits set, no raid state */ +                 if (reading1 & 0x01) { b = 0; } /*state0=Faulty*/ +                 else if (reading1 & 0x02) b = 1; /*state1=Rebuilding*/ +                 else if (reading1 & 0x04) b = 2; /*state2=InFailedArray*/ +                 else if (reading1 & 0x08) b = 3; /*state3=InCriticalArray*/ +                 else if (reading1 & 0x10) b = 4; /*state4=ParityCheck*/ +                 else if (reading1 & 0x20) b = 5; /*state5=PredictedFault*/ +                 else if (reading1 & 0x40) b = 6; /*state6=Un-configured*/ +                 else if (reading1 & 0x80) b = 7; /*state7=HotSpare*/ +                 if (b < 8) {  +		     /* also include a raid_state, via custom string */ +		     sprintf(customstr,"%s %s", +				sensor_dstatus[istr], raid_states[b]); +		     istr = STR_CUSTOM; +		     sensor_dstatus[istr] = customstr; +		     if (fdebug) printf("dstatus=%s\n",sensor_dstatus[istr]); +                 } +              } /*end-else-if HSC slot status (0x6f)*/ +           }  +	   break; +	case 0x10:	/*Event Logging*/ +	   /* usu evtype==0x6f*/ +	   b = bitnum(reading & 0x3f); +	   switch (b) { +	      case 0x00:  istr = 0; break; /*OK*/ +	      case 0x01:  istr = 59; break; /*MemLogDisabled*/ +	      case 0x02:  istr = 60; break; /*TypLogDisabled*/ +	      case 0x03:  istr = 61; break; /*LogCleared*/ +	      case 0x04:  istr = 62; break; /*AllLogDisabled*/ +	      case 0x05:  istr = 63; break; /*SelFull*/ +	      case 0x06:  istr = 64; break; /*SelNearFull*/ +	      default:  istr = 41; break;  /*Unknown*/ +	   } +	   break; +	case 0x12:	/*System Event*/ +	   if (reading == 0) istr = 0; +	   else istr = 13; /*Asserted*/   +	   break; +	case 0x13:	/*Critical Interrupt*/ +	   /* valid bits:  0x03FF */ +	   if (reading == 0) istr = 0;  /*OK*/ +	   else {    +	        b = bitnum(reading);  /* ECC or other error */ +		if (b > 10) b = 10; +		istr = 24 + b; +	   } +	   break; +	case 0x14:	/*Button*/ +	   if (reading == 0) istr = 0; /*OK*/ +	   else istr = 13; /*Asserted*/   +	   break; +	case 0x15:	/*Module/ Board */ +	   if (evtype == 0x08) {  /*presence*/ +              if (reading & 0x02) istr = 9;   /*Present/Inserted*/ +              else if (reading & 0x01) istr = 10; /*Absent/Removed*/ +              else /*reading==00*/ istr = 47; /*Unused*/ +	   } +	   break; +	case 0x16:	/* HSBP Status (esp. Romley) */ +	   if (reading & 0x010) istr = STR_HSC_OFF; /*Offline*/ +	   else istr = 0;  /*OK*/ +	   break; +	case 0x17:	/* ATCA CDM, Air Filter, Filter Tray */ +	   if (reading == 0) istr = 0; /*OK*/ +	   else if (reading & 0x01) istr = 10; /*Absent*/ +	   else istr = bitnum(reading);  /* other error, TODO: fix this */ +	   break; +	case 0x1C:	/*Terminator (usu SCSI)*/ +	   if (reading & 0x01) istr = 9; /*present*/ +	   else istr = 10;        /*missing,absent*/ +	   break; +	case 0x21:	/*DIMM memory slot*/ +	   if ((reading & 0x04) != 0) istr = 9; /*present*/ +	   else istr = 10; /*absent*/ +	   sprintf(customstr,"%s", sensor_dstatus[istr]); +	   if ((reading & 0x01) != 0) strcat(customstr,",Fault"); +	   if ((reading & 0x0100) != 0) strcat(customstr,",Disabled"); +	   istr = 58; /*use a custom string*/ +	   sensor_dstatus[istr] = customstr; +	   if (fdebug) printf("dstatus=%s\n",sensor_dstatus[istr]); +	   break; +	case 0x22:	/*ACPI Power State*/ +           b = bitnum(reading);  +           switch(b) { +	     case 0: istr = 0;  break; /*OK*/ +	     case 1: istr = 22;  break; /*Working*/ +	     case 2: +	     case 3: +	     case 4: +	     case 5: +	     case 9: +	     case 10: istr = 23;  break; /*Sleeping*/ +	     case 6:  +	     case 7:  +	     case 8:  +	     case 11:  +	     case 12: istr = 24;  break; /*On*/ +	     case 13: istr = 21;  break; /*Off*/ +	     default: istr = 41;   /*unknown*/ +           } +	   break; +	case 0x23:	/*Watchdog*/ +	   if (reading == 0) istr = 0; +	   else istr = 13; /*Asserted*/   +	   break; +	case 0x24:	/*Platform Alert*/ +           b = bitnum(reading);  +           switch(b) { +	     case 0: istr = 0;   break; /*OK, no bits set*/ +	     case 1: istr = 66;  break; /*Page, bit 0 set*/ +	     case 2: istr = 67;  break; /*LAN,  bit 1 set*/ +	     case 3: istr = 68;  break; /*PET*/ +	     case 4: istr = 69;  break; /*SNMP OEM*/ +	     default: istr = 70;   /*None*/ +           } +	   break; +	case 0x25:	/* Entity Presence */ +	   if (reading & 0x01) istr = 8;  /*Present*/ +	   else if (reading & 0x02) istr = 9;  /*Absent*/ +	   else if (reading & 0x04) istr = 16;  /*Disabled*/ +	   else istr = 42;  /* NotAvailable */ +	   break; +	case 0x28:	/* BMC FW Health */ +	   if (evtype == 0x6F) {  /*Sensor-specific*/ +	     if (reading == 0) istr = 0;  /*OK*/ +	     else istr = 12; /*Faulty*/ +	   } else {  /*use event/reading type*/ +	     istr = decode_comp_generic(type, evtype, num, reading); +	   } +	   break; +	case 0x29:	/* Battery */ +           switch(reading & 0x7f) { +	     case 0x00: istr = 0;  break; /*OK*/ +	     case 0x01: istr = 15; break; /*Predict Fail*/ +	     case 0x04: istr = 9;  break; /*Present*/ +	     case 0x02:  +	     default:   istr = 12; break; /*Failed/Faulty*/ +           } +	   break; +	case 0x2A:	/* Session Audit (IPMI 2.0) */ +	   if (reading == 0x00) istr = 45; /*Activated*/ +	   else istr = 46;                 /*Deactivated*/ +	   break; +	case 0x2B:	/* Version Change */ +	   b = bitnum(reading1);  +	   switch(b) { +	     case 0: istr = 0;   break; /*OK, no bits set*/ +	     case 1: istr = 72;  break; /*HW Changed, bit 0 set*/ +	     case 2: istr = 73;  break; /*SW Changed,  bit 1 set*/ +	     case 3: istr = 74;  break; /*HW incompatibility*/ +	     default: istr = 75; break; /*Change error*/ +	   } +	   break; + +        /* sensor types 0xC0 - 0xFF are OEM RESERVED */ +	case 0xF1:	/* ATCA IPMB-0 Sensor */ +	   if ((reading & 0x7fff) == 0x0008) istr = 0; /*OK*/ +	   else istr = bitnum(reading1);  /* other error, TODO: refine this */ +	   break; +	case 0xC0:	/* SMI State, NMI State */ +	case 0xD8:	/* BIST */ +	case 0xF0:	/* ATCA FRU HotSwap, TODO: refine this */ +	case 0xF2:	/* ATCA Module HotSwap, TODO: refine this */ +	case 0xF3:	/* SMI Timeout, etc. */ +	   if (reading & 0x01) istr = 13; /* Asserted */ +	   else istr = 0;  /* "OK", Deasserted */ +	   break; + +	case 0x60:	/* SCSI 1 Term Flt */ +	case 0x61:	/* SCSI 2 Term Flt */ +   	default: +	   istr = decode_comp_generic(type, evtype, num, reading); +	   break; +   } +   return(istr); +}  /* end decode_comp_reading */ + +#define STYPSZ  15 +static char *get_stype_str(uchar stype) +{   /*return sensor type string, with fixed length */ +    static char stype_str[STYPSZ+1]; +    char *tmpstr; +    int i, n; +    tmpstr = get_sensor_type_desc(stype);  +    n = strlen_(tmpstr); +    if (n > STYPSZ) n = STYPSZ; +    strncpy(stype_str,tmpstr,n); +    for (i = n; i < STYPSZ; i++) stype_str[i] = ' '; +    stype_str[i] = 0; +    tmpstr = stype_str; +    return(tmpstr); +} + +void +ShowSDR(char *tag, uchar *sdr) +{ +  SDR01REC *sdr01; +  SDR02REC *sdr02; +  SDR08REC *sdr08; +  SDR11REC *sdr11; +  SDR12REC *sdr12; +  SDR14REC *sdr14; +  SDRc0REC *sdrc0; +  char idstr[32]; +  char *typestr = NULL; +  int vend; +  int len, ilen, i, j; +  int ioff; +  uchar sens[4]; +  uchar sens_cap; +  uchar shar_cnt; +  int rc;  +  double val; +  char brearm; +  uchar sep[4]; +  char rdgstr[50]; + +  len = sdr[4] + 5; +  sens_cap = 0x80;  /*ignore*/ +  if (fdebug) printf("ShowSDR: len=%d, type=%x\n",len,sdr[3]); +  memset(sens,0,4); +  if (frawsdr || fdebug) { +	  /* raw is different than dump_buf */ +	  printf("raw SDR: "); +	  for (i = 0; i < len; i++) +		  printf("%02x ",sdr[i]); +	  printf("\n"); +  } +  strcpy(idstr,"INIT");  /*always set idstr to some initial string*/ +  switch(sdr[3]) +  { +    case 0x01:   /* Full sensor record */ +	sdr01 = (SDR01REC *)sdr; +	ioff = 48; +	if (ioff > len) { +		if (fdebug) printf("bad length: type=%x, len=%d, ioff=%d\n", +					sdr[3],len,ioff); +		fprintf(stderr,"Bad SDR Length %d, please apply the correct FRU/SDR diskette\n",len); +		return; +	} +	sens_cap = sdr[11];  /*sdr01->sens_capab*/ +	// ilen = (sdr[ioff] & 0x1f);  /*sdr01->id_typelen*/ +	ilen = len - ioff; +	if (fdebug) printf("SDR[%x] Full ioff=%d idTypLen=0x%02x ilen=%d\n",  +			sdr01->recid, ioff,sdr[ioff] ,ilen); +	if (ilen >= sizeof(idstr)) ilen = sizeof(idstr) - 1; +	if (ilen <= 0) {  /*bug if true*/ +	   fprintf(stderr,"Bad SDR Length %d, omits ID string\n",len); +	   ilen = 16;  /*less than sizeof(idstr)*/ +	} +	memcpy(idstr,&sdr[ioff],ilen); +	for (i=ilen; i<16; i++) { idstr[i] = ' '; ilen++; } +	idstr[ilen] = 0;  /* stringify */ +	if ((sdr01->sens_capab & 0x40) == 0) brearm = 'm'; /*manual rearm*/ +	else brearm = 'a';  /*automatic rearm*/ +	if (fdebug) printf("entity %d.%d, idlen=%d sizeof=%lu idstr0=%c s0=%x\n", +					sdr01->entity_id, sdr01->entity_inst,  +					ilen,sizeof(SDR01REC),idstr[0],sdr[ioff]); +	rc = GetSensorReading(sdr01->sens_num,sdr01,sens); +	if (rc != 0) { /* if rc != 0, leave sens values zero */ +	   i = 41;  /* Unknown */ +	   val = 0; +	   if (rc == 0xCB) {  /*sensor not present*/ +	        i = 10;  /* Absent */ +	        typestr = "na"; +	   } else typestr = decode_rv(rc); +	} else { +	   j = (sens[2] & 0x3f);   /*sensor reading state*/ +	   i = bitnum((ushort)j);  /*sensor_dstatus index*/ +	   if (fdebug)  +		printf("bitnum(%02x)=%d raw=%02x init=%x base/units=%x/%x\n", +			sens[2],i,sens[0],sens[1],sdr01->sens_base, +			sdr01->sens_units); +	   if ((sens[1] & 0x20) != 0) { i = 7; val = 0; } /* Init state */ +       else if (sdr01->sens_units == 0xC0) i = 42; /*reading NotAvailable*/ +	   else if (sens[2] == 0xc7) { i = 10; val = 0;  /* Absent (Intel) */ +			if (fdebug) printf("sensor[%x] is absent (c7), no reading\n",  +							sdr01->sens_num); +	   } +	   else val = RawToFloat(sens[0],sdr); +	   typestr = get_unit_type(sdr01->sens_units, sdr01->sens_base,  +					sdr01->sens_mod, fsimple); +#ifdef WRONG +	   if (is_romley(vend_id,prod_id) &&  +		(sdr01->sens_type == 0x0C) && (sdr01->sens_units & 0x01)) +	   { /* Intel Memory Thermal Throttling %, raw 0x01 == 0.5 % */ +               val = (val / 2);  /* handle MTT SDR errata */ +	   } /*correct solution is to fix the SDR m-value instead */ +#endif +	} +	rc = decode_oem_sensor(sdr,sens,oem_string,sizeof(oem_string)); +	if (rc == 0) { +	   if (fsimple) strncpy(rdgstr,oem_string,sizeof(rdgstr)); +	   else snprintf(rdgstr,sizeof(rdgstr),"%02x %s",sens[0],oem_string); +	} else { +	   if (fsimple)  +	      snprintf(rdgstr,sizeof(rdgstr),"%s %c %.2f %s", +			sensor_dstatus[i],bdelim,val,typestr); +	   else  +	      snprintf(rdgstr,sizeof(rdgstr),"%02x %s %.2f %s", +			sens[0], sensor_dstatus[i],val,typestr); +	} +	sep[0] = 0; /*null string*/ +    printf("%s", tag); +	if (fsimple) { +	   sprintf(sep,"%c ",bdelim); +	   printf("%04x %c Full    %c %s %c %02x %c %s %c %s%c", +			sdr01->recid, bdelim, bdelim, +			get_stype_str(sdr01->sens_type),  +			bdelim, sdr01->sens_num,bdelim, idstr, +			bdelim,rdgstr,chEol); +	} else +	   printf("%04x SDR Full %02x %02x %02x %c %02x snum %02x %s = %s%c", +		sdr01->recid, sdr01->rectype, sdr01->ev_type, +		sdr01->sens_ownid, brearm, sdr01->sens_type, sdr01->sens_num,  +		idstr, rdgstr, chEol); +	if (fdebug && fshowthr) +		   printf("cap=%02x settable=%02x, readable=%02x\n", +			  sens_cap,sdr[19],sdr[18]); +	if (sens_verbose)   /* if -v, also show Entity ID */ +	    printf("\t%sEntity ID %d.%d (%s), Capab: %s%c", +		   sep, sdr01->entity_id, sdr01->entity_inst,  +		   decode_entity_id(sdr01->entity_id), // sens_cap,  +		   decode_capab(sens_cap),chEol); +	if (fshowthr && (sens_cap & 0x0f) != 0x03) { +		uchar thresh[7]; +		/* Thresholds, so show them */ +		/* Use settable bits to show thresholds, since the  +		 * readable values will be off for Full SDRs.   +		 * If cant set any thresholds, only show SDR thresholds */ +		if (sdr[19] == 0) rc = 1;  +		else { +		   /* Show volatile thresholds. */ +		   rc = GetSensorThresholds(sdr01->sens_num,&thresh[0]); +		   if (rc == 0) ShowThresh(2,thresh[0],&thresh[1],sdr); +		} +		/* Show SDR non-volatile thresholds. */ +		if (sens_verbose || rc !=0) ShowThresh(0,sdr[18],&sdr[36],sdr);  +		// ShowThresh(0,0x3f,&sdr[36],sdr); /* to show all %%%% */ +	}  +	if (fwrap) {  /* (chEol != '\n') include time */ +		time_t ltime; +		time(<ime); +		if (fsimple)  +	 	   printf("%c %s",bdelim,ctime(<ime)); /*ctime has '\n' */ +		else +	 	   printf("at %s",ctime(<ime)); /*ctime has '\n' */ +	}  +	break; +    case 0x02:   /* Compact sensor record */ +	sdr02 = (SDR02REC *)sdr; +	ioff = 32; +	if (ioff > len) { +		if (fdebug) printf("bad length: type=%x, len=%d, ioff=%d\n", +					sdr[3],len,ioff); +		fprintf(stderr,"Bad SDR Length, please apply the correct FRU/SDR diskette\n"); +		return; +	} +	sens_cap = sdr[11];  /*sdr02->sens_capab*/ +	shar_cnt = sdr02->shar_cnt & 0x0f;  /*sdr[23]*/ +	ilen = len - ioff; +	if ((ilen+1) >= sizeof(idstr)) ilen = sizeof(idstr) - 2; +	memcpy(idstr,&sdr[ioff],ilen); +	if ((shar_cnt > 1) && (sdr02->shar_off & 0x80) != 0) { /*do shared SDR*/ +	   j = (sdr02->shar_off & 0x7f);  /*sdr[24] = modifier offset*/ +	   if (fdebug) printf("share count = %d, mod_offset = %d\n",shar_cnt,j); +	   if ((sdr02->shar_cnt & 0x10) != 0) { /*alpha*/  +	      idstr[ilen++] = 0x40 + j;  /* j=1 -> 'A' */ +	      idstr[ilen] = 0;  /* stringify */ +	   } else { /*numeric*/ +	      sprintf(&idstr[ilen],"%d",j); +	      ilen = strlen_(idstr); +	   } +	} /* else normal idstr */ +	for (i=ilen; i<16; i++) { idstr[i] = ' '; ilen++; } +	idstr[ilen] = 0;  /* stringify */ +        if ((sdr02->sens_capab & 0x40) == 0) brearm = 'm'; /*manual rearm*/ +        else brearm = 'a';  /*automatic rearm*/ +	if (fdebug) printf("ilen=%d, istr0=%c, sizeof=%zu, s0=%x\n", +				ilen,idstr[0],sizeof(SDR02REC),sdr[ioff]); +	memset(sens,0,sizeof(sens)); +	rc = GetSensorReading(sdr02->sens_num,sdr02,sens); +	if (rc != 0) { /* if rc != 0, leave sens values zero */ +	  i = 41;  /* Unknown */ +	  val = 0; +	  if (rc == 0xCB) {  /*sensor not present*/ +	        i = 10;  /* Absent */ +		typestr = "na"; +	  } else typestr = decode_rv(rc); +	} else { +          if ((sens[1] & 0x20) != 0) i = 42; /*init state, NotAvailable*/ +	  else { +	    rc = decode_oem_sensor(sdr,sens,oem_string,sizeof(oem_string)); +	    if (rc == 0) i = STR_OEM; +	    else i = decode_comp_reading(sdr02->sens_type,sdr02->ev_type, +					sdr02->sens_num,sens[2],sens[3]); +          } +        } +	if (fdebug)  +            printf("snum %x type %x evt %x reading %02x%02x i=%d rc=%d %s\n", +			sdr02->sens_num,sdr02->sens_type,sdr02->ev_type, +			sens[3],sens[2],i,rc, decode_rv(rc)); +	j = sens[2] | ((sens[3] & 0x7f) << 8); /*full reading, less h.o. bit*/ +	sep[0] = 0; /*null string*/ +        printf("%s", tag); +	if (fsimple) { +		sprintf(sep,"%c ",bdelim); +	        printf("%04x %c Compact %c %s %c %02x %c %s %c %s %c%c", +			sdr02->recid, bdelim, bdelim, +			get_stype_str(sdr02->sens_type),  +			bdelim, sdr02->sens_num, bdelim, idstr, +			bdelim, sensor_dstatus[i],bdelim,chEol); +	} else if (i == STR_OEM) { +	   // idstr[ilen] = 0; /*cut out padding in idstr*/ +	   printf("%04x SDR Comp %02x %02x %02x %c %02x snum %02x %s = %04x %s%c", +		sdr02->recid, sdr02->rectype, sdr02->ev_type, +		sdr02->sens_ownid, brearm, sdr02->sens_type, sdr02->sens_num,  +                idstr, j, sensor_dstatus[i],chEol); +                // sensor_dstatus[i] == oem_string +	} else { +	   printf("%04x SDR Comp %02x %02x %02x %c %02x snum %02x %s = %04x %s%c", +		sdr02->recid, sdr02->rectype, sdr02->ev_type, +		sdr02->sens_ownid, brearm, sdr02->sens_type, sdr02->sens_num,  +		idstr, j, sensor_dstatus[i],chEol); +                /* idstr, sens[0], sens[1], sens[2], sens[3], */  +	} +	if (fdebug && fshowthr) +		   printf("cap=%02x settable=%02x, readable=%02x\n", +			  sens_cap,sdr[19],sdr[18]); +	if (fshowthr)  /*also show Entity ID */ +	    printf("\t%sEntity ID %d.%d (%s), Capab: %s%c", +		   sep, sdr02->entity_id, sdr02->entity_inst,  +		   decode_entity_id(sdr02->entity_id), // sens_cap,  +		   decode_capab(sens_cap),chEol); +	if (fshowthr && +	    ((sens_cap & 0x80) == 0) && (sens_cap & 0x0C) != 0) { +		uchar thresh[7]; +		/* Thresholds, show them */ +		/* Use readable bits to get & show thresholds */ +		if (sdr[20] != 0) { +		   rc = GetSensorThresholds(sdr02->sens_num,&thresh[0]); +		   if (rc == 0) ShowThresh(1,thresh[0],&thresh[1],sdr); +		} +	} +	if (fwrap) {  /*include time and \n */ +		time_t ltime; +		time(<ime); +		if (fsimple)  +	 	   printf("%c %s",bdelim,ctime(<ime)); /*ctime has '\n' */ +		else +	 	   printf("at %s",ctime(<ime)); /*ctime has '\n' */ +	}  +	break; +    case 0x03:   /* Event-only sensor record, treat like Compact SDR */ +	sdr02 = (SDR02REC *)sdr; +	ioff = 17; +	if (ioff > len) { +		fprintf(stderr,"Bad SDR %x Length %d. Please apply the correct FRU/SDR diskette\n", +			sdr02->recid, len); +		return; +	} +	if (!fsimple) +	{ +	ilen = len - ioff; +	if (ilen >= sizeof(idstr)) ilen = sizeof(idstr) - 1; +	memcpy(idstr,&sdr[ioff],ilen); +	for (i=ilen; i<16; i++) { idstr[i] = ' '; ilen++; } +	idstr[ilen] = 0;  /* stringify */ +	sens_cap = sdr[11]; +	memset(sens,0,sizeof(sens)); +        if ((sdr02->sens_capab & 0x40) == 0) brearm = 'm'; /*manual rearm*/ +        else brearm = 'a';  /*automatic rearm*/ +	// rc = GetSensorReading(sdr02->sens_num,sdr02,sens); +	/* EvtOnly SDRs do not support readings.  +	 * GetSensorReading would return ccode=0xCB (not present),  +	 * but this skips error msg */ +	rc = 0xCB; +	i = bitnum((ushort)sens[2]); +	j = sens[2] | ((sens[3] & 0x7f) << 8); +        printf("%s",tag); +	printf("%04x SDR EvtO %02x %02x %02x %c %02x snum %02x %s = %04x %s\n", +		sdr02->recid, sdr02->rectype, sdr02->reclen,  +		sdr02->sens_ownid, 'a', sdr[10], sdr02->sens_num,  +		idstr, j,  sensor_dstatus[i]); +		// sens[0], sens[1], sens[2], sens[3], sensor_dstatus[i] +	} +	break; +    case 0x08:   /* Entity Association record */ +	sdr08 = (SDR08REC *)sdr; +	if (!fsimple) +	{ +        printf("%s",tag); +	printf("%04x SDR EntA %02x %02x %02x %02x %02x: ", +		sdr08->recid, sdr08->rectype, sdr08->reclen,  +		sdr08->contid, sdr08->continst, sdr08->flags); +	for (i = 0; i < 8; i++) printf("%02x ",sdr08->edata[i]); +	printf("\n"); +	} +	break; +    case 0x09:   /* Device-relative Entity Association record */ +        sdr08 = (SDR08REC *)sdr;  /*but SDR09 is 26 bytes*/ +        if (!fsimple) +        { +        printf("%s",tag); +        printf("%04x SDR DEnt %02x %02x %02x %02x %02x %02x %02x: ", +                sdr08->recid, sdr08->rectype, sdr08->reclen, +                sdr08->contid, sdr08->continst, sdr08->flags, +                sdr08->edata[0], sdr08->edata[1]); +        /*display 2 of 4 contained entity devices edata[2-10] */ +        for (i = 2; i < 8; i++) printf("%02x ",sdr08->edata[i]); +        printf("\n"); +        } +        break; +    case 0x10:   /* Generic Device Locator record */ +	sdr11 = (SDR11REC *)sdr; +	ioff = 16; +	if (ioff > len) {  +	    if (fdebug) printf("SDR %x bad length: type=%x, len=%d, ioff=%d\n", +				sdr11->recid, sdr[3],len,ioff); +            return; +        } +	if (!fsimple) +	{ +	ilen = len - ioff; +	if (ilen >= sizeof(idstr)) ilen = sizeof(idstr) - 1; +	memcpy(idstr,&sdr[ioff],ilen); +	idstr[ilen] = 0;  /* stringify */ +        printf("%s", tag); +	if (fsimple) +		printf("DevLocator record[%x]%c device %02x %c %s\n", +			sdr11->recid, bdelim,sdr11->dev_slave_adr,bdelim,idstr); +	else +	printf("%04x SDR DLoc %02x %02x dev: %02x %02x %02x %02x %02x %02x %s\n", +		sdr11->recid, sdr11->rectype, sdr11->reclen, +		sdr11->dev_access_adr, sdr11->dev_slave_adr,  +		sdr11->access_lun, sdr[8], sdr[10], sdr[11], +		idstr); +        } +	break; +    case 0x11:   /* FRU record */ +	sdr11 = (SDR11REC *)sdr; +	ioff = 16; +	if (ioff > len) { +	    if (fdebug) printf("SDR %x bad length: type=%x len=%d ioff=%d\n", +				sdr11->recid, sdr[3],len,ioff); +		printf("Please apply the correct FRU/SDR diskette\n"); +		return; +	} +	if (!fsimple) +	{ +	ilen = len - ioff; +	if (ilen >= sizeof(idstr)) ilen = sizeof(idstr) - 1; +	memcpy(idstr,&sdr[ioff],ilen); +	idstr[ilen] = 0;  /* stringify */ +	if (fdebug) printf("ilen=%d, istr0=%c, sizeof=%zu, s0=%x\n", +				ilen,idstr[0],sizeof(SDR11REC),sdr[ioff]); +        printf("%s", tag); +	if (fsimple) +		printf("FRU record[%x]: device %02x : %s\n", +			sdr11->recid, sdr11->dev_slave_adr,idstr); +	else +	printf("%04x SDR FRU  %02x %02x dev: %02x %02x %02x %02x %02x %02x %s\n", +		sdr11->recid, sdr11->rectype, sdr11->reclen, +		sdr11->dev_access_adr, sdr11->dev_slave_adr /*fru_id*/,  +		sdr11->access_lun, sdr11->chan_num, +		sdr11->entity_id, sdr11->entity_inst,  +		idstr); +	} +	break; +    case 0x12:   /* IPMB record */ +	sdr12 = (SDR12REC *)sdr; +	ioff = 16; +	if (ioff > len) { +		if (fdebug) printf("bad length: type=%x, len=%d, ioff=%d\n", +					sdr[3],len,ioff); +		printf("Please apply the correct FRU/SDR diskette\n"); +		return; +	} +	if (!fsimple) +	{ +	ilen = len - ioff; +	if (ilen >= sizeof(idstr)) ilen = sizeof(idstr) - 1; +	memcpy(idstr,&sdr[ioff],ilen); +	idstr[ilen] = 0;  /* stringify */ +	if (fdebug) printf("ilen=%d, istr0=%c, sizeof=%zu, s0=%x\n", +				ilen,idstr[0],sizeof(SDR12REC),sdr[ioff]); +        printf("%s", tag); +	if (fsimple) +		printf("IPMB record[%x]%c addr %02x %02x %c %s\n", +			sdr12->recid, bdelim,sdr12->dev_slave_adr,  +			sdr12->chan_num,bdelim,idstr); +	else +	printf("%04x SDR IPMB %02x %02x dev: %02x %02x %02x %02x %02x %s\n", +		sdr12->recid, sdr12->rectype, sdr12->reclen, +		sdr12->dev_slave_adr, sdr12->chan_num, sdr12->dev_capab, +		sdr12->entity_id, sdr12->entity_inst,  +		idstr); +	} +	break; +    case 0x14:   /* BMC Message Channel Info record */ +	sdr14 = (SDR14REC *)sdr; +	if(!fsimple){ +        printf("%s", tag); +	printf("%04x SDR BMsg %02x %02x: ", +		sdr14->recid, sdr14->rectype, sdr14->reclen ); +	for (i = 0; i < 8; i++) printf("%02x ",sdr14->mdata[i]); +	printf("%s %s %02x\n",decode_itype(sdr14->mint), +		decode_itype(sdr14->eint), sdr14->rsvd); +	} +	break; +    case 0xc0:   /* OEM SDR record (manuf_id 343. = Intel) */ +	sdrc0 = (SDRc0REC *)sdr; +	if(!fsimple) +	{ +	  vend = sdrc0->manuf_id[0] + (sdrc0->manuf_id[1] << 8)  +		+ (sdrc0->manuf_id[2] << 16); +          printf("%s",tag); +	  printf("%04x SDR OEM  %02x %02x ",  +		sdrc0->recid, sdrc0->rectype, sdrc0->reclen); +	  show_oemsdr(vend,sdr); +	} +	break; +    default: +	sdrc0 = (SDRc0REC *)sdr; +	/* also saw type = 0x08 & 0x14 on STL2s */ +	if (!fsimple){ +          printf("%s", tag); +	  printf("%04x SDR type=%02x ", sdrc0->recid, sdr[3]); +	  for (i = 0; i < len; i++) printf("%02x ",sdr[i]); +	  printf("\n"); +	} +  } +  return; +} + +static int +ShowPowerOnHours(void) +{ +	uchar resp[MAX_BUFFER_SIZE]; +	int sresp = MAX_BUFFER_SIZE; +	uchar cc; +	int rc = -1; +	int i; +	unsigned int hrs; +   +	if (fmBMC) return(0); +	if (fsimple) return(0); +	sresp = MAX_BUFFER_SIZE; +	memset(resp,0,6);  /* default response size is 5 */ +	rc = ipmi_cmd_mc(GET_POWERON_HOURS, NULL, 0, resp, &sresp, &cc, fdebug); +	if (rc == 0 && cc == 0) { +	   /* show the hours (32-bits) */ +	   hrs = resp[1] | (resp[2] << 8) | (resp[3] << 16) | (resp[4] << 24); +	   /*60=normal, more is OOB, so avoid div-by-zero*/  +	   if ((resp[0] <= 0) || (resp[0] >= 60)) i = 1;  +	   else { +		i = 60 / resp[0]; +		hrs = hrs / i; +	   } +	   printf("     SDR IPMI       sensor: Power On Hours \t   = %d hours\n", +				hrs); +	} +	if (fdebug) { +		   printf("PowerOnHours (rc=%d cc=%x len=%d): ",rc,cc,sresp); +		   if (rc == 0)  +		   for (i = 0; i < sresp; i++) printf("%02x ",resp[i]); +		   printf("\n"); +	} +	return(rc); +} + +int SaveThreshold(int id, int sensor_num, int sensor_lo, int sensor_hi,  +		 uchar *thr_set) +{ +    int rv = 0; +    char lostr[20]; +    char histr[20]; +    FILE *fd; + +    /* persist the thresholds by re-applying with ipmiutil sensor commands.*/ +    if (thr_set != NULL) { +      sprintf(lostr,"-u 0x%02x%02x%02x%02x%02x%02x", +		sensor_thr[0], sensor_thr[1], sensor_thr[2],  +		sensor_thr[3], sensor_thr[4], sensor_thr[5]); +      histr[0] = 0;  /*empty string*/ +    } else { +      if (sensor_lo != 0xff) { +	  sprintf(lostr,"-l 0x%02x",sensor_lo); +      } else      lostr[0] = 0; +      if (sensor_hi != 0xff) { +	  sprintf(histr,"-h 0x%02x",sensor_hi); +      } else      histr[0] = 0; +    } +    fd = fopen(savefile,"a+"); +    if (fd == NULL) return(-1); +    fprintf(fd, "ipmiutil sensor -i 0x%04x -n 0x%02x %s %s\n", id, sensor_num, +		lostr,histr); +    fclose(fd); +    return(rv); +} + +#ifdef NOT_USED +#define PICMG_GET_ADDR_INFO  0x01 +static int get_picmg_addrinfo(uchar a1, uchar a2, uchar *addrdata) +{ +   uchar idata[5]; +   uchar rdata[16]; +   int rlen; +   ushort icmd; +   uchar ilen, cc; +   int rv; +    +   idata[0] = 0x00; +   idata[1] = 0x00; +   idata[2] = 0x03; +   idata[3] = a1;  /* 01 thru 0f */ +   idata[4] = a2;  /* 00, 01 thru 09 */ +   ilen = 5; +   rlen = sizeof(rdata); +   icmd = PICMG_GET_ADDR_INFO | (NETFN_PICMG << 8); +   rv = ipmi_cmd_mc(icmd, idata, ilen, rdata, &rlen, &cc, fdebug); +   if (rv == 0 && cc != 0) rv = cc; +   if (rv == 0) { +       if (fdebug) { +	  printf("picmg_addr(%02x,%02x)",a1,a2); +	  dump_buf("picmg_addr",rdata,rlen,0); +       } +       memcpy(addrdata,rdata,rlen);  +   } +   return(rv); +} +#endif + +#ifdef WIN32 +static int get_filesize(char *fileName, ulong *psize) +{ +    int rv; +    WIN32_FILE_ATTRIBUTE_DATA   fileInfo; + +    if (fileName == NULL) return -1; +    if (psize == NULL) return -1; +    rv = GetFileAttributesEx(fileName, GetFileExInfoStandard, (void*)&fileInfo); +    if (!rv) return -1; +    *psize = (long)fileInfo.nFileSizeLow; +    return 0; +} +#endif + +int write_sdr_binfile(char *binfile) +{ +      uchar *pbuf = NULL; +      FILE *fp; +      int len, ret; +      ret = get_sdr_cache(&pbuf); /* sets nsdrs, sz_sdrs */ +      if (ret == 0) { +		fp = fopen(binfile,"wb"); +    	if (fp == NULL) { +    	   ret = get_LastError(); +    	   printf("Cannot open file %s for writing, error %d\n",binfile,ret); +    	} else { +    	   printf("Writing SDR size %d to %s  ...\n",sz_sdrs,binfile); +    	   len = (int)fwrite(pbuf, 1, sz_sdrs, fp); +    	   fclose(fp); +    	   if (len <= 0) { +    	      ret = get_LastError(); +    	      printf("Error %d writing file %s\n",ret,binfile); +    	   } else ret = 0; +    	} +    	free_sdr_cache(pbuf); +      } +      return(ret); +} + +int read_sdr_binfile(char *binfile, uchar **pbufret, int *buflen) +{ +      uchar *pbuf = NULL; +      FILE *fp; +      int len; +      int ret; +#ifdef WIN32 +      { +	 ulong flen; +	 ret = get_filesize(binfile, &flen); +	 if (ret == 0) len = flen; +	 else { +	   ret = get_LastError(); +	   printf("Cannot get file size for %s, error %d\n",binfile,ret); +	   return(ret); +	 }  +      } +#endif +      fp = fopen(binfile,"rb"); +      if (fp == NULL) { +    	 ret = get_LastError(); +    	 printf("Cannot open file %s, error %d\n",binfile,ret); +    	 return(ret); +      }  +      fseek(fp, 0L, SEEK_SET); +#ifndef WIN32 +      { /*not windows but Linux, etc.*/ +	 struct stat st; +	 /* use fstat to get file size and allocate buffer */ +	 ret = fstat(fileno(fp), &st); +	 len = st.st_size;  /*file size in bytes*/ +	 if (ret != 0) { +	    ret = get_LastError(); +	    printf("Cannot stat file %s, error %d\n",binfile,ret); +	    return(ret); +	 } +      } +#endif +      /* Could estimate size for nsdrs*SDR_SZ, but we don't yet know nsdrs. +       * It is better to use the real file size detected above. */ +      sz_sdrs = len; +      pbuf = malloc(len); +      if (fdebug) printf("sdr_binfile: malloc(%d) pbuf=%p\n",len,pbuf); +      if (pbuf == NULL) { +    	  ret = -2; +    	  fclose(fp); +    	  return(ret); +      } +      psdrcache = pbuf; +      /*ok, so proceed with restore*/ +      ret = 0; +      len = (int)fread(pbuf, 1, sz_sdrs, fp); +      if (len <= 0) { +    	 ret = get_LastError(); +    	 printf("Error %d reading file %s\n",ret,binfile); +    	 sz_sdrs = 0;  /*for safety*/ +      } else if (len < sz_sdrs) { +    	 /* Show error if this happens in Windows */ +    	 ret = get_LastError(); +    	 printf("truncated fread(%s): attempted %d, got %d, error %d\n", +    		binfile,sz_sdrs,len,ret); +         ret = 0; /*try to keep going*/ +      } +      fclose(fp); +      if (fdebug) { +		 printf("SDR buffer from file (len=%d,sz=%d)\n",len,sz_sdrs); +		 dump_buf("SDR buffer",pbuf,len,1); +      } +    *pbufret = pbuf; +    *buflen = len; +    return(ret); +} + +#ifdef ALONE +#ifdef WIN32 +int __cdecl  +#else +int  +#endif +main(int  argc, char **argv) +#else +/* METACOMMAND or libipmiutil */ +int i_sensor(int argc, char **argv) +#endif +{ +   int ret, rv; +   int c; +   int recid, recnext; +   uchar sdrdata[MAX_BUFFER_SIZE]; +   uchar devrec[16]; +   int sz, i, j; +   int fsetfound = 0; +   int iloop, irec; +   int ipass, npass; +   uchar *pset; +   char *p; +   char *s1; + +   printf("%s version %s\n",progname,progver); + +   while ( (c = getopt( argc, argv,"a:bcd:ef:g:h:i:j:k:l:m:n:opqrstu:vwxT:V:J:L:EYF:P:N:R:U:Z:?")) != EOF ) +      switch(c) { +	  case 'a':   /* reArm sensor number N */ +		if (strncmp(optarg,"0x",2) == 0) frearm = htoi(&optarg[2]); +		else frearm = htoi(optarg);  /*was atoi()*/ +		break; +	  case 'c': fsimple = 1;   break;  /* Canonical/simple output*/ +	  case 'd': fdump = 1;      /* Dump SDRs to a file*/ +		    binfile = optarg; break; +	  case 'b': fchild = 1;    break;  /* Bladed, so get child SDRs */    +	  case 'e': fchild = 1;    break;  /* Extra bladed child SDRs */    +	  case 'f': frestore = 1;      /* Restore SDRs from a file*/ +		    binfile = optarg; break; +	  case 's': fsimple = 1;   break;  /* Simple/canonical output */ +		    /*fcanonical==fsimple*/ +	  case 'g':  +		rv = get_group_id(optarg); +		if (rv < 0) {  +		    printf("Unrecognized sensor type group (%s)\n",optarg); +		    ret = ERR_BAD_PARAM; +		    goto do_exit; +		} else fshowgrp = rv; +		if (fdebug) printf("num sensor type groups = %d\n",fshowgrp); +		break; +	  case 'i':  +		fshowidx = 1;   +		get_idx_range(optarg); +		break; +	  case 'j': fjumpstart = 1;      /* Load SDR cache from a file*/ +		    binfile = optarg; break; +	  case 'k': loopsec = atoi(optarg); break;  /*N sec between loops*/ +	  case 'm': /* specific 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*/ +		    if (optarg[6] == 's') { +			     g_addrtype = ADDR_SMI;  s1 = "SMI"; +		    } else { g_addrtype = ADDR_IPMB; s1 = "IPMB"; } +		    fset_mc = 1; +		    printf("set MC at %s bus=%x sa=%x lun=%x\n", +			    s1,g_bus,g_sa,g_lun); +		    break; +	  case 'o':  +		fgetmem = 1; +		break; +	  case 'n':  +		if (strncmp(optarg,"0x",2) == 0) i = htoi(&optarg[2]); +		else i = htoi(optarg);      /*was atoi()*/ +		sensor_num = (uchar)i; +		printf("sensor_num = 0x%x\n",sensor_num); +		break; +	  case 'h':   /* highest threshold */ +		if (strncmp(optarg,"0x",2) == 0) { +			i = htoi(&optarg[2]); +			sensor_hi = (uchar)i; +			fsetthresh = 1; +		} else { +			sensor_hi_f = atof(optarg); +			fsetthresh = 2;  /*indicates float conversion*/ +		} +		break; +	  case 'l':    /* lowest threshold */ +		if (strncmp(optarg,"0x",2) == 0) { +			i = htoi(&optarg[2]); +			sensor_lo = (uchar)i; +			fsetthresh = 1; +		} else { +			sensor_lo_f = atof(optarg); +			fsetthresh = 2;  /*indicates float conversion*/ +		} +		break; +	  case 'p': fsavethresh = 1;  break; +	  case 'q': fshowthr = 2; fwrap = 1; break; +	  case 'r': frawsdr = 1;   break; +	  case 't': fshowthr = 1;  break; +	  case 'v': fshowthr = 1; sens_verbose = 1; break; +	  case 'u':    /* specify unique thresholds in hex or float */ +		/* raw hex format: 0xLNLCLUHNHCHU, all 6 required */ +		if (strncmp(optarg,"0x",2) == 0) {  /*raw hex thresholds*/ +		   sensor_thr[0] = htoi(&optarg[2]);  /*lo noncrit*/ +		   sensor_thr[1] = htoi(&optarg[4]);  /*lo crit*/ +		   sensor_thr[2] = htoi(&optarg[6]);  /*lo unrec*/ +		   sensor_thr[3] = htoi(&optarg[8]);  /*hi noncrit*/ +		   sensor_thr[4] = htoi(&optarg[10]); /*hi crit*/ +		   sensor_thr[5] = htoi(&optarg[12]); /*hi unrec*/ +		   /* validate sensor threshold ordering */ +		   rv = validate_thresholds(&sensor_thr[0],0,NULL); +		   if (rv == 0) { +		      sensor_lo = sensor_thr[0]; +		      sensor_hi = sensor_thr[3]; +		      fsetthresh = 3;  /*indicates unique raw thresholds */ +		   } else { +		      ret = ERR_BAD_PARAM; +		      goto do_exit; +		   } +		} else {   +		   /* assume float input thresholds, with ':' separator*/ +		   /* format LN:LC:LU:HN:HC:HU */ +		   sz = strlen_(optarg); +		   p = &optarg[0]; +		   for (i = 0; i < 6; i++) sensor_thrf[i] = THR_EMPTY; +		   j = 0; +		   for (i = 0; i <= sz; i++) { +		      if (j >= 6) break; +		      switch(optarg[i]) { +			case ':': +			case '\n': +			case '\0': +			   optarg[i] = 0; +			   if (p[0] == 0) sensor_thrf[j] = THR_EMPTY; +			   else sensor_thrf[j] = atof(p); +			   if (i+1 < sz) p = &optarg[i+1]; +			   j++; +			   break; +			default: +			   break; +		      } +		   } +		   /* validate sensor threshold ordering later */ +		   // rv = validate_thresholds(&sensor_thrf[0],1,NULL); +		   // if (rv == 0) { +		      sensor_lo_f = sensor_thrf[0]; +		      sensor_hi_f = sensor_thrf[3]; +		      fsetthresh = 4;  /*indicates unique float thresholds */ +		   // } else { +		      // ret = ERR_BAD_PARAM; +		      // goto do_exit; +		   // } +		} /*end-else -u float thresholds*/ +		break; +	  case 'w': fwrap = 1;   break; +	  case 'x': fdebug = 1;  break; +	  case 'L':      /* Loop */ +		nloops = atoi(optarg); +		fdoloop = 1; +		break; +	  case 'V':    /* priv level */ +		fprivset = 1; +	  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 'Y':    /* prompt for remote password */ +	  case 'Z':    /* set local MC address */ +		parse_lan_options(c,optarg,fdebug); +		break; +	  default:   /*usage*/ +	     printf("Usage: %s [-abcdefghijlmnprstuvwxL -NUPREFTVYZ]\n",progname); +	     printf("where -x      shows eXtra debug messages\n"); +	     printf("      -a snum reArms the sensor (snum) for events\n"); +	     printf("      -b      show Bladed child MCs for PICMG (same as -e)\n"); +	     printf("      -c      displays a simpler, Canonical output fmt\n"); +	     printf("      -d file Dump SDRs to a binary file\n"); +	     printf("      -e      show Every bladed child MC for PICMG\n"); +	//   printf("      -f file Restore SDRs from a binary dump file\n"); +	     printf("      -g fan  show only this sensor type group\n"); +	     printf("      -h tval specifies the Highest threshold to set\n"); +	     printf("      -i id   only show these sensor id numbers\n"); +	     printf("      -j file Jump-start SDR cache from a binary file\n"); +	     printf("      -k K    If -L, wait K sec between loops (default=1)\n"); +	     printf("      -l tval specifies the Lowest threshold to set\n"); +	     printf("      -m002000 specific MC (bus 00,sa 20,lun 00)\n"); +	     printf("      -n snum specifies the sensor Number to set hi/lo\n"); +	     printf("      -o      output memory DIMM information\n"); +	     printf("      -p      persist the threshold being set\n"); +	     printf("      -q      shows threshold values in d:d:d format\n"); +	     printf("      -r      show Raw SDR bytes\n"); +	     printf("      -s      displays a Simpler output format\n"); +	     printf("      -t      shows Threshold values in text format\n"); +	     printf("      -u thr  set Unique threshold values (e.g. 3:2:1:48:49:50)\n"); +	     printf("      -v      Verbose: thresholds, max/min, hysteresis\n"); +	     printf("      -w      Wrap thresholds on sensor line\n"); +	     printf("      -L n    Loop n times every k seconds (default k=1)\n"); +	     print_lan_opt_usage(0); +	     ret = ERR_USAGE; +	     goto do_exit; +      } +    if (fjumpstart && fchild) { +       printf("Cannot use -j jumpstart cache with -c child SDRs\n"); +       ret = ERR_BAD_PARAM; +       goto do_exit; +    } +    fremote = is_remote(); +#ifndef WIN32 +    if (fremote == 0) {   +	/* only run this as superuser for accessing IPMI devices. */ +	i = geteuid(); +	if (i > 1) { +	    printf("Not superuser (%d)\n", i); +	    /* Show warning, but could be ok if /dev/ipmi0 is accessible */ +	    //ret = ERR_NOT_ALLOWED; +	    //goto do_exit; +	} +    }  +#endif +    if (fremote) { +	if (!fprivset) { +	  /* on many systems, getting the SDR Reservation ID requires admin */ +	  /* if ((fsetthresh != 0) || (frearm != 0))  also require admin */ +	  parse_lan_options('V',"4",0); +	} +    } + +   ret = ipmi_getdeviceid(devrec,sizeof(devrec),fdebug); +   if (ret == 0) { +	uchar ipmi_maj; +	uchar ipmi_min; +	char *pstr; +	ipmi_maj = devrec[4] & 0x0f; +	ipmi_min = devrec[4] >> 4; +	if ((devrec[1] & 0x80) == 0x80) fdevsdrs = 1; +	vend_id = devrec[6] + (devrec[7] << 8) + (devrec[8] << 16); +	prod_id = devrec[9] + (devrec[10] << 8); +	if (vend_id == VENDOR_NSC) { /*NSC mBMC*/  +		pstr = "mBMC"; +		fmBMC = 1; +		fdevsdrs = 0; +	} else if (vend_id == VENDOR_INTEL) { /*Intel BMC*/  +		/*Intel Sahalee BMC */ +		pstr = "BMC"; +		fmBMC = 0; +		if (is_romley(vend_id,prod_id)) fRomley = 1; +		if (is_grantley(vend_id,prod_id)) fGrantley = 1; +		if (prod_id == 0x003E || fRomley || fGrantley)  /*Urbanna,CG2100*/ +		   set_max_kcs_loops(URNLOOPS); /*longer KCS timeout*/ +	} else if ((vend_id == VENDOR_SUPERMICRO) +                || (vend_id == VENDOR_SUPERMICROX)) { +                   set_max_kcs_loops(URNLOOPS); /*longer KCS timeout*/ +	} else if (vend_id == 16394) { /*Pigeon Point*/  +		fbadsdr = 1;   /* SDR has bad sa/mc value, so ignore it */ +	} else {   /* Other products */ +		pstr = "BMC"; +		fmBMC = 0; +		if (vend_id == VENDOR_NEC) fdevsdrs = 0; +	} +	show_devid( devrec[2],  devrec[3], ipmi_maj, ipmi_min); +		// "-- %s version %x.%x, IPMI version %d.%d \n", pstr, +   } else { +	goto do_exit; +   } + +   ret = ipmi_getpicmg( devrec, sizeof(devrec),fdebug); +   if (ret == 0) fpicmg = 1; +   /*if not PICMG, some vendors override to SDR Rep*/ +   fdevsdrs = use_devsdrs(fpicmg); +   if (fdevsdrs) printf("supports device sdrs\n"); +   npass = 1; +   if (g_sa != 0) { +      /* target a specific MC via IPMB (usu a picmg blade) */ +      ipmi_set_mc(g_bus,g_sa,g_lun,g_addrtype); +      fchild = 0;  /* no children, only the specified address */ +   } else {  +#ifdef PICMG_CHILD +      /* fchild set above if -b is specified to get Blade child SDRs */ +      /* npass = 2 will get both SdrRep & DevSdr passes on CMM */ +      if (fpicmg && fdevsdrs) { +	 npass = 2; +	 g_addrtype = ADDR_IPMB; +      } +#endif +      g_sa = BMC_SA; +   } + +   if (fgetmem) { +      if (fremote) printf("Cannot get memory DIMM information remotely.\n"); +      else { +	 int msz; +	 char desc[80]; +	 char szstr[25]; +	 ret = -1; +	 for (j = 0; j < 1; j++) { +	    for (i = 0; i < 16; i++) { +	       rv = get_MemDesc(j, i, desc,&msz); +	       if (rv == 0) { +		  if (msz == 0) strcpy(szstr,"not present"); +		  else if (msz & 0x8000) +		       sprintf(szstr,"size=%dKB",(msz & 0x7FFF)); +		  else sprintf(szstr,"size=%dMB",msz); +		  printf("Memory Device (%d,%d): %s : %s\n", +			 j,i,desc,szstr); +		  ret = 0; +	       } +	    } +	 } +      } /*end-else*/ +      goto do_exit; +   } + +   if (fdump) { +	  ret = write_sdr_binfile(binfile); +      goto do_exit; +   } /*endif fdump*/ + +   if (frestore) { +      uchar sdr[MAX_BUFFER_SIZE]; +      ushort id; +      int slen; +      uchar *pbuf = NULL; + +      ret = read_sdr_binfile(binfile,&pbuf,&slen); +      if (ret == 0) {   /*successful, so write SDRs */ +		 nsdrs = find_nsdrs(pbuf); +		 printf("Ready to restore %d SDRs\n",nsdrs); +		 set_reserve(1); +		 ret = sdr_clear_repo(fdevsdrs); +		 if (ret != 0) { +		    printf("SDR Clear Repository error %d\n",ret); +		    goto do_exit; +		 } +		 id = 0; +		 while(find_sdr_next(sdr,pbuf,id) == 0) { +		    id = sdr[0] + (sdr[1] << 8); +		    if (fdebug) printf("adding SDR[%x]\n",id); +		    set_reserve(1); +		    ret = sdr_add_record(sdr,fdevsdrs); +		    if (ret != 0) { +			printf("SDR[%x] add error %d\n",id,ret); +			break; +		    } +		 } /*end while sdr*/ +      } +      if (ret == 0) printf("Restored %d SDRs successfully.\n",nsdrs); +      free_sdr_cache(pbuf); /* does nothing if (pbuf == NULL) */ +      goto do_exit; +   } /*endif frestore*/ + +   if (fjumpstart) { +      uchar *pbuf = NULL; +      int slen; +      ret = read_sdr_binfile(binfile,&pbuf,&slen); +      if (ret != 0) {  +    	 /* Try to dump sdrs to this file if not there */ +	     ret = write_sdr_binfile(binfile); +         if (ret == 0)  +      		ret = read_sdr_binfile(binfile,&pbuf,&slen); +         if (ret != 0) { +    		fjumpstart = 0; /*cannot do jumpstart*/ +		 } +      } else {  /* set this as the SDR cache */ +    	 psdrcache = pbuf; +    	 sz_sdrs = slen; +    	 nsdrs = find_nsdrs(pbuf); +    	 if (fdebug) printf("jumpstart cache: nsdrs=%d size=%d\n",nsdrs,slen); +      } +   } /*endif fjumpstart*/ + +   for (ipass = 0; ipass < npass; ipass++) +   { +     if (fjumpstart) ; /*already got this above*/ +     else { +	ret = GetSDRRepositoryInfo(&j,&fdevsdrs); +	if (fdebug) printf("GetSDRRepositoryInfo: ret=%x nSDRs=%d\n",ret,j); +	if (ret == 0 && j == 0) { +	   printf("SDR Repository is empty\n"); +	   goto do_exit; +	} +	nsdrs = j; +     } + +     /* show header for SDR records */ +     if (fsimple)  +	printf(" ID  | SDRType | Type            |SNum| Name             |Status| Reading\n"); +     else  +	printf("_ID_ SDR_Type_xx ET Own Typ S_Num   Sens_Description   Hex & Interp Reading\n"); + +     if (fwrap) chEol = ' '; +     if (!fdoloop) nloops = 1; +     for (iloop = 0; iloop < nloops; iloop++) +     { +       if (fshowidx) recid = sensor_idx1; +       else recid = 0; +	   irec = 0; /*first sdr record*/ +       while (recid != 0xffff)  +       { +	 if (fjumpstart) { +	   if (irec == 0)  /*need sdr_by_id if fshowid recid>0*/ +	        ret = find_sdr_by_id(sdrdata,psdrcache,recid); +	   else ret = find_sdr_next(sdrdata,psdrcache,recid); +	   if (ret != 0) {  /*end of sdrs*/ +		if (fdebug) printf("find_sdr_next(%04x): ret = %d\n", recid,ret); +		ret = 0; break;  +	   } +	   recnext = sdrdata[0] + (sdrdata[1] << 8);  /*same as recid*/ +	   if (fdebug) printf("find_sdr_next(%04x): ret = %d, next=%04x\n", +				recid,ret,recnext); +	   if (recid > 0 && recnext == 0) { +		if (fdebug) printf("Error recid=%04x recnext=%04x\n",recid,recnext); +		ret = 0; break;  +	   } +	   sz = sdrdata[4] + 5; +	 } else { +	   int try; +           for (try = 0; try < 10; try++) { +             ret = GetSDR(recid,&recnext,sdrdata,sizeof(sdrdata),&sz); +             if (fdebug) +               printf("GetSDR[%04x]: ret = %x, next=%x\n",recid,ret,recnext); +             if (ret != 0) { +               if (ret == 0xC5) {  /* lost Reservation ID, retry */ +                 /*fprintf(stderr,"%04x lost reservation retrying to get, try: %d,  %d, rlen = %d\n", recid,try,ret,sz);*/ +                 os_usleep((rand() & 3000),0); +                 fDoReserve = 1; +               } +               else { +                 fprintf(stderr,"%04x GetSDR error %d, rlen = %d\n", recid,ret,sz); +                 break; +               } +             } +             else { +               break; +             } +             if (try==9){ +               sz=0; +              fprintf(stderr,"%04x GetSDR error %d, rlen = %d\n", recid,ret,sz); +             } +           } +           if (sz < MIN_SDR_SZ) {  /* don't have recnext, so abort */ +             break; +           } /* else fall through & continue */ +	 } /*end-else*/ +	 if (ret == 0) {  /* (ret == 0) OK, got full SDR */ +	   if (fdebug) { +		dump_buf("got SDR",sdrdata,sz,0); +	   } +	   if (sz < MIN_SDR_SZ) goto NextSdr; +	   /* if recid == 0, get real record id */ +	   if (recid == 0) recid = sdrdata[0] + (sdrdata[1] << 8); +	   if (fshowgrp > 0) { +	      for (i = 0; i < fshowgrp; i++) { +		uchar styp; +		if (sdrdata[3] == 0x03) styp = sdrdata[10]; /*EvtOnly*/ +		else styp = sdrdata[12]; +		if (fdebug) printf("sdrt=%02x styp=%02x sgrp[%d]=%02x\n", +				sdrdata[3],styp,i,sensor_grps[i]); +		if (sdrdata[3] == 0xc0) continue; /*skip OEM SDRs*/ +		if (styp == sensor_grps[i]) break; +	      } +	      if (i >= fshowgrp) goto NextSdr; +	   } + +	   if ((sensor_num == INIT_SNUM) || (sdrdata[7] == sensor_num)  +	      || fsetthresh) { +	       /* if -n not set or if -n matches, parse and show the SDR */ +	       ShowSDR("",sdrdata); +	   }  /* else filter SDRs if not matching -n sensor_num */ + +#ifdef PICMG_CHILD +	   /* +	    * Special logic for blade child MCs in PICMG ATCA systems  +	    * if fchild, try all child MCs within the chassis. +	    * SDR type 12 capabilities bits (sdrdata[8]): +	    *    80 = Chassis Device +	    *    40 = Bridge +	    *    20 = IPMB Event Generator +	    *    10 = IPMB Event Receiver +	    *    08 = FRU Device +	    *    04 = SEL Device +	    *    02 = SDR Repository Device +	    *    01 = Sensor Device +	    *    But all child MCs use Device SDRs anyway. +	    */ +	   if (fpicmg && fchild && (sdrdata[3] == 0x12)) { /* PICMG MC DLR */ +	      int   _recid, _recnext, _sz; +	      uchar _sdrdata[MAX_SDR_SIZE]; +	      int   devsdrs_save; +	      uchar cc; + +	      /* save the BMC globals, use IPMB MC */ +	      devsdrs_save  = fdevsdrs; +	      fdevsdrs = 1;   /* use Device SDRs for the children*/ +	      if (fdebug) +		printf(" --- IPMB MC (sa=%02x cap=%02x id=%02x devsdrs=%d):\n", +		       sdrdata[5],sdrdata[8],sdrdata[12],fdevsdrs); +	      fDoReserve = 1;  /* get a new SDR Reservation ID */ +	      ipmi_set_mc(PICMG_SLAVE_BUS,sdrdata[5],sdrdata[6],g_addrtype); + +	      _sz = 16; +	      ret = ipmi_cmd_mc(GET_DEVICE_ID,NULL,0,_sdrdata,&_sz,&cc,fdebug); +	      if (ret == 0 && cc == 0) { +		/* Get the SDRs from the IPMB MC */ +		_recid = 0; +		while (_recid != 0xffff)  +		{ +		  ret = GetSDR(_recid,&_recnext,_sdrdata,sizeof(_sdrdata),&_sz); +		  if (ret != 0) { +		     fprintf(stderr,"%04x GetSDR error %d, rlen = %d\n",_recid,ret,_sz); +		     break; +		  } +		  else if (_sz >= MIN_SDR_SZ)  +		     ShowSDR(" ",_sdrdata); + +		  if (_recnext == _recid) _recid = 0xffff; +		  else _recid = _recnext; +		} /*end while*/ +	      } /*endif ret==0*/ + +	      /* restore BMC globals */ +	      fdevsdrs = devsdrs_save; +	      ipmi_restore_mc(); +	      fDoReserve = 1;  /* get a new SDR Reservation ID */ +	   }  /*endif fpicmg && fchild*/ +#endif + +	   if (fdebug) printf("fsetthresh=%d snum=%02x(%02x) sa=%02x(%02x)\n", +			    fsetthresh,sdrdata[7],sensor_num,sdrdata[5],g_sa); +	   if (fsetthresh && (sdrdata[7] == sensor_num)  +		&& (sdrdata[5] == g_sa))  /*g_sa usu is BMC_SA*/ +	   { +	     /* setting threshold, compute threshold raw values */ +	     if (fsetthresh == 2) {   /*set from float*/ +		if (fdebug)  +		   printf("lof=%.2f hif=%.2f\n", sensor_lo_f,sensor_hi_f); +		if (sensor_lo_f != 0)  +		   sensor_lo = FloatToRaw(sensor_lo_f,sdrdata,0); +		if (sensor_hi_f != 0)  +		   sensor_hi = FloatToRaw(sensor_hi_f,sdrdata,0); +	     } else if (fsetthresh == 1) {  /*raw thresholds*/ +		if (sensor_hi != 0xff) +		   sensor_hi_f = RawToFloat(sensor_hi,sdrdata); +		if (sensor_lo != 0xff) +		   sensor_lo_f = RawToFloat(sensor_lo,sdrdata); +	     } else if (fsetthresh == 3) {  /*unique raw thresholds*/ +		if (sensor_hi != 0xff) +		   sensor_hi_f = RawToFloat(sensor_hi,sdrdata); +		if (sensor_lo != 0xff) +		   sensor_lo_f = RawToFloat(sensor_lo,sdrdata); +	     } else if (fsetthresh == 4) {   /*set unique from float*/ +		i = fill_thresholds(&sensor_thrf[0], sdrdata);  +		/* if (i > 0) ;  * filled in some thresholds */ +		{  /* always set lo/hi if any are non-zero */ +		   for (j = 0; j < 3; j++) { +		      if (sensor_thrf[j] != 0) { +			  sensor_lo_f = sensor_thrf[j]; break; } +		   } +		   for (j = 3; j < 6; j++) { +		      if (sensor_thrf[j] != 0) { +			  sensor_hi_f = sensor_thrf[j]; break; } +		   } +		} +		if (fdebug)  +		   printf("lof=%.2f hif=%.2f\n", sensor_lo_f,sensor_hi_f); +		/* convert thrf (float) to thr (raw) */ +		if (sensor_lo_f != 0) { +		   sensor_lo = FloatToRaw(sensor_lo_f,sdrdata,0); +		   sensor_thr[0] = FloatToRaw(sensor_thrf[0],sdrdata,0); +		   sensor_thr[1] = FloatToRaw(sensor_thrf[1],sdrdata,0); +		   sensor_thr[2] = FloatToRaw(sensor_thrf[2],sdrdata,0); +		} +		if (sensor_hi_f != 0) { +		   sensor_hi = FloatToRaw(sensor_hi_f,sdrdata,0); +		   sensor_thr[3] = FloatToRaw(sensor_thrf[3],sdrdata,0); +		   sensor_thr[4] = FloatToRaw(sensor_thrf[4],sdrdata,0); +		   sensor_thr[5] = FloatToRaw(sensor_thrf[5],sdrdata,0); +		} +		/* validate threshold ordering */ +		if (validate_thresholds(sensor_thrf,1,sdrdata) != 0) { +		   ret = ERR_BAD_PARAM; +		   goto do_exit;  +		} +	     } +	     { +		printf("\tSetting SDR %04x sensor %02x to lo=%02x hi=%02x\n", +			    recid,sensor_num,sensor_lo,sensor_hi); +		if (recid == 0) fsetfound = 1; +		else fsetfound = recid; +	     } +	   } /*endif fsetthresh */ +	 }  /*endif ok, got full SDR */ + +NextSdr: +	 if (ret == ERR_SDR_MALFORMED) break; +	 if (fjumpstart) recid = recnext; +	 else { +		if (recnext == recid) recid = 0xffff; /*break;*/ +		else recid = recnext; +	 } +	 if (fshowidx) { +		/* if we have already read the last in the range, done. */ +		if (recid >= sensor_idxN) break; // recnext = 0xffff; // break; +	 } +	     irec++; +       } /*end while recid*/ +       if (fdoloop && (nloops > 1)) { +     	 printf("\n"); /* output an empty separator line */ +     	 os_usleep(loopsec,0); /*delay 1 sec between loops*/ +       } +     } /*end for nloops*/ + +     if (npass > 1) {   /* npass==2 for PICMG */ +	/* Switch fdevsdrs from Device to Repository */ +	if (fdevsdrs == 0) fdevsdrs = 1; +	else fdevsdrs = 0; +	fDoReserve = 1;  /* get a new SDR Reservation ID */ +     } +   } /*end for npass*/ + +   if ((fshowidx == 0) && (fshowgrp == 0)) { +      /* use local rv, errors are ignored for POH */ +      rv = ShowPowerOnHours(); +   } + +   if (frearm != 0) { +	ret = RearmSensor((uchar)frearm); +	printf("RearmSensor(0x%02x) ret = %d\n",frearm,ret); +   } + +   if (fsetthresh != 0) { +	uchar tdata[7]; +	if (fsetfound == 0) { +	   printf("Did not find sensor number %02x.\nPlease enter the sensor number parameter in hex, as it is displayed above.\n",sensor_num); +	} +	ret = GetSensorThresholds(sensor_num,tdata); +	if (ret != 0) goto do_exit;  +#ifdef TEST +	printf("thresh(%02x): %02x %02x %02x %02x %02x %02x %02x %02x\n", +		sensor_num, sensor_num, tdata[0], tdata[1], tdata[2], +		tdata[3], tdata[4], tdata[5], tdata[6]); +	printf("   set(%02x):          %02x       %02x \n", +		sensor_num,sensor_lo,sensor_hi); +#endif +	if (fsetthresh == 3 || fsetthresh == 4) {   +	   /* apply unique sensor thresholds */ +	   pset = &sensor_thr[0]; +	} else pset = NULL;  /* use just hi/lo */ +	ret = SetSensorThresholds(sensor_num,sensor_hi,sensor_lo,tdata,pset); +	printf("SetSensorThreshold[%02x] to lo=%02x(%4.3f) hi=%02x(%4.3f), ret = %d\n", +		sensor_num,sensor_lo,sensor_lo_f,sensor_hi,sensor_hi_f,ret); +	if (fsavethresh && ret == 0) { +	    recid = fsetfound; +	    rv = SaveThreshold(recid,sensor_num,sensor_lo,sensor_hi,pset); +	    if (rv == 0)  +		printf("Saved thresholds for sensor %02x\n",sensor_num); +	} +	fsetthresh = 0;  /*only set threshold once*/ +   } + +do_exit: +   // if (fjumpstart)  +   free_sdr_cache(psdrcache); /* does nothing if ==NULL*/ +   /* show_outcome(progname,ret); *handled in ipmiutil.c*/ +   ipmi_close_(); +   return(ret);   +} + +/* end isensor.c */ diff --git a/util/mem_if.c b/util/mem_if.c index 3fcc139..c7ca677 100644 --- a/util/mem_if.c +++ b/util/mem_if.c @@ -8,6 +8,7 @@   * 02/26/08 ARCress - decode type 15 log structure   * 07/21/08 ARCress - fixed for 64-bit memory model   * 08/12/08 ARCress - trim out extra stuff, consolidated + * 01/09/23 ARCress - try UEFI_MEM_RANGE_BASE  0x6d5a7000 if error   *----------------------------------------------------------------------*/  /*----------------------------------------------------------------------*  The BSD License  @@ -74,6 +75,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  #endif  #define	DOS_MEM_RANGE_BASE   0xF0000  //starting memory range for smbios tables +#define	UEFI_MEM_RANGE_BASE  0x6d5a7000  //starting memory range for UEFI tables  #define	DOS_NUM_BYTES_TO_MAP 0x0FFFE  //number bytes to map for smbios tables  //smbios defines @@ -416,8 +418,13 @@ int  getSmBiosTables(UCHAR **ptableAddress)  	    * unless in debug mode. */  	   if (fsm_debug)   #endif -		fprintf(stderr, "Cannot map memory.\n"); -	        return ulSmBiosLen; /*==0*/ +		fprintf(stderr, "Cannot map SMBIOS memory.\n"); +	   	/* Try UEFI address */ +		tdStartAddress = UEFI_MEM_RANGE_BASE; +		if (!MapPhysicalMemory(tdStartAddress,ulSize,&tdVirtualAddress)) { +		   fprintf(stderr, "Cannot map UEFI SMBIOS memory.\n"); +	           return ulSmBiosLen; /*==0*/ +		}  	}  	//now find the entry point for smbios | 
